@blakesteve/roster 5.10.0 → 5.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +202 -11
- package/dist/components/atoms/Chip/chip-variants.cjs +1 -1
- package/dist/components/atoms/Chip/chip-variants.js +8 -2
- package/dist/components/atoms/Combobox/Combobox.cjs +1 -1
- package/dist/components/atoms/Combobox/Combobox.js +20 -18
- package/dist/components/atoms/MultiSelect/MultiSelect.cjs +1 -1
- package/dist/components/atoms/MultiSelect/MultiSelect.js +22 -20
- package/dist/components/atoms/PasswordInput/PasswordInput.cjs +1 -1
- package/dist/components/atoms/PasswordInput/PasswordInput.js +5 -5
- package/dist/components/atoms/Select/Select.cjs +1 -1
- package/dist/components/atoms/Select/Select.js +19 -17
- package/dist/components/atoms/Select/select-variants.cjs +1 -1
- package/dist/components/atoms/Select/select-variants.js +11 -2
- package/dist/components/molecules/Carousel/Carousel.cjs +1 -1
- package/dist/components/molecules/Carousel/Carousel.js +31 -29
- package/dist/components/molecules/FileUpload/FileUpload.cjs +1 -1
- package/dist/components/molecules/FileUpload/FileUpload.js +21 -19
- package/dist/components/molecules/LiquidTabs/LiquidTabs.cjs +1 -1
- package/dist/components/molecules/LiquidTabs/LiquidTabs.js +22 -20
- package/dist/components/molecules/Menu/Menu.cjs +1 -1
- package/dist/components/molecules/Menu/Menu.js +133 -124
- package/dist/components/molecules/RadioGroup/RadioGroup.cjs +1 -1
- package/dist/components/molecules/RadioGroup/RadioGroup.js +23 -21
- package/dist/components/molecules/RangeSlider/RangeSlider.cjs +1 -0
- package/dist/components/molecules/RangeSlider/RangeSlider.d.ts +79 -0
- package/dist/components/molecules/RangeSlider/RangeSlider.js +166 -0
- package/dist/components/molecules/Slider/Slider.cjs +1 -0
- package/dist/components/molecules/Slider/Slider.d.ts +91 -0
- package/dist/components/molecules/Slider/Slider.js +130 -0
- package/dist/components/molecules/Slider/track-parts.cjs +1 -0
- package/dist/components/molecules/Slider/track-parts.d.ts +65 -0
- package/dist/components/molecules/Slider/track-parts.js +121 -0
- package/dist/components/molecules/Slider/track.cjs +1 -0
- package/dist/components/molecules/Slider/track.d.ts +115 -0
- package/dist/components/molecules/Slider/track.js +152 -0
- package/dist/components/organisms/Dialog/Dialog.cjs +1 -1
- package/dist/components/organisms/Dialog/Dialog.js +19 -17
- package/dist/components/organisms/ModerationQueue/ModerationQueue.cjs +1 -1
- package/dist/components/organisms/ModerationQueue/ModerationQueue.js +45 -43
- package/dist/components/organisms/Navbar/Navbar.cjs +1 -1
- package/dist/components/organisms/Navbar/Navbar.js +24 -22
- package/dist/components/organisms/Sheet/Sheet.cjs +1 -1
- package/dist/components/organisms/Sheet/Sheet.js +25 -23
- package/dist/index.d.ts +2 -0
- package/dist/internal/key-focus.cjs +1 -0
- package/dist/internal/key-focus.d.ts +7 -0
- package/dist/internal/key-focus.js +60 -0
- package/dist/internal/popup.cjs +1 -1
- package/dist/internal/popup.d.ts +15 -1
- package/dist/internal/popup.js +17 -12
- package/dist/meta.json +3 -3
- package/dist/roster.cjs +1 -1
- package/dist/roster.css +1 -1
- package/dist/roster.js +67 -63
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -543,6 +543,39 @@ The band matters more than it looks. Without it the ring sits directly on the
|
|
|
543
543
|
fill, and a `primary-500` ring on a `primary-600` button is 1.37:1 — which is
|
|
544
544
|
why the ring and its offset are a pair rather than two independent knobs.
|
|
545
545
|
|
|
546
|
+
**A row in a popup marks focus with the ring too.** The focused row in `Menu`,
|
|
547
|
+
`Select`, `Combobox` and `MultiSelect` keeps its soft primary tint and adds a
|
|
548
|
+
2px inset ring in `--roster-ring`. The tint alone was the indicator until
|
|
549
|
+
5.11.0, and it measured 1.17:1 against the panel in light and 1.03:1 in dark
|
|
550
|
+
on Roster's own defaults: a keyboard user couldn't see where they were. The
|
|
551
|
+
ring follows the token you already set against your own surfaces, so it holds
|
|
552
|
+
wherever the panel is: 6.37:1 and 5.61:1 on the defaults. If you set
|
|
553
|
+
`--roster-popover-bg` to a surface `--roster-ring` doesn't contrast with, set
|
|
554
|
+
the ring with it. In `Menu` the ring shows for keyboard focus only, because the
|
|
555
|
+
pointer moves focus there too. Headless UI's popups mark the keys' row and the
|
|
556
|
+
pointer's alike, so in theirs it shows on hover as well.
|
|
557
|
+
|
|
558
|
+
**Keyboard focus shows in Safari too.** Every ring is drawn on Roster's
|
|
559
|
+
`focus-visible` variant, which matches the engine's own `:focus-visible` or an
|
|
560
|
+
element marked `data-key-focus`. WebKit doesn't match `:focus-visible` on an
|
|
561
|
+
element a script focuses in answer to a key once the page has been clicked.
|
|
562
|
+
Escape handing focus back to a menu's or a select's trigger, or to a dialog's
|
|
563
|
+
opener, and a radio group's or tabs' arrows all drew no ring in Safari after
|
|
564
|
+
a click. A small internal tracker marks those elements: keyboard mode starts on a navigation key (Tab, Option+Tab, the
|
|
565
|
+
arrows, Escape, Enter, Space, Home, End, PageUp, PageDown) and ends on pointer
|
|
566
|
+
input, and it marks only what Chromium's own `:focus-visible` already matches,
|
|
567
|
+
so Chromium's rings are unchanged. It runs while a component that moves focus
|
|
568
|
+
is mounted (Menu, the select family, Dialog, Sheet, RadioGroup, LiquidTabs,
|
|
569
|
+
Slider and the rest), on one set of document listeners.
|
|
570
|
+
|
|
571
|
+
Your own components' rings come from your Tailwind, not Roster's, so they
|
|
572
|
+
don't follow the mark on their own. To have them do the same, redefine the
|
|
573
|
+
variant in your stylesheet as Roster does:
|
|
574
|
+
|
|
575
|
+
```css
|
|
576
|
+
@custom-variant focus-visible (&:is(:focus-visible, [data-key-focus]));
|
|
577
|
+
```
|
|
578
|
+
|
|
546
579
|
### Motion
|
|
547
580
|
|
|
548
581
|
Two hand-rolled utilities, both of which stop for `prefers-reduced-motion`.
|
|
@@ -732,11 +765,10 @@ opens are also legitimately different surfaces in plenty of palettes.
|
|
|
732
765
|
**Set these at `:root`, not on a container.** The menu and the tooltip bubble
|
|
733
766
|
are portaled to `<body>`, so they are not descendants of whatever you rendered
|
|
734
767
|
the component inside: properties set on a wrapper reach the trigger and stop
|
|
735
|
-
there
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
same reason the control family needs both.
|
|
768
|
+
there, and the result is a themed trigger opening an unthemed panel, which is
|
|
769
|
+
the exact problem this family exists to fix. Any ancestor of `<body>` works:
|
|
770
|
+
`:root`, `html.dark`, or inline on `<html>` all reach every panel. Set them in
|
|
771
|
+
both scopes too, for the same reason the control family needs both.
|
|
740
772
|
|
|
741
773
|
Where each component takes them, and why not everywhere:
|
|
742
774
|
|
|
@@ -773,6 +805,8 @@ Every field therefore has a second prop, **named for the element it reaches**:
|
|
|
773
805
|
| `Combobox` | `className` | `inputClassName` | `optionsClassName` |
|
|
774
806
|
| `CheckboxGroup`| `className` | — | `optionsClassName` |
|
|
775
807
|
| `RadioGroup` | `className` | `radioClassName` | `optionsClassName`, `optionClassName`, `labelClassName`, `optionLabelClassName`, `descriptionClassName`, `messageClassName` |
|
|
808
|
+
| `Slider` | `className` | `trackClassName` | `thumbClassName`, `chipClassName`, `labelClassName`, `messageClassName` |
|
|
809
|
+
| `RangeSlider` | `className` | `thumbClassName` | `trackClassName`, `chipClassName`, `labelClassName`, `messageClassName` |
|
|
776
810
|
|
|
777
811
|
`CheckboxGroup` and `RadioGroup` have no single "control" to reach, since they
|
|
778
812
|
hold one per option, so `RadioGroup`'s `radioClassName` lands on every radio
|
|
@@ -925,9 +959,16 @@ look like oversights until you know why:
|
|
|
925
959
|
variable that inline rule reads:
|
|
926
960
|
`optionsClassName="rst:[--anchor-max-height:20rem]"`.
|
|
927
961
|
- **The panel is portaled to `<body>`**, so a `.dark` scoped to part of your
|
|
928
|
-
page does not reach it.
|
|
929
|
-
|
|
930
|
-
|
|
962
|
+
page does not reach it. The panel carries `.dark` itself in that case, and
|
|
963
|
+
only then: when `.dark` is on `<html>` or `<body>` the panel is already
|
|
964
|
+
inside it, and carrying the class would re-declare Roster's palette on the
|
|
965
|
+
panel over your own. Every portaled surface does the same (`Menu`, `Sheet`
|
|
966
|
+
and the toasts too). Custom properties are not carried: set
|
|
967
|
+
`--roster-popover-*` on an ancestor of `<body>`.
|
|
968
|
+
- **A row is a click target, and focus is a ring.** Every option row shows
|
|
969
|
+
the pointer cursor, as `Menu`'s items do (a disabled one, `not-allowed`).
|
|
970
|
+
A focused row keeps its tint and adds an inset `--roster-ring`, which is
|
|
971
|
+
what reaches 3:1 against the panel ([Focus](#focus)).
|
|
931
972
|
- **`Menu` shares the panel, not the anchoring.** Its panel takes the same
|
|
932
973
|
surface, tokens and dark carry, but `Menu` places itself (see
|
|
933
974
|
[Menu](#menu)), writing its own inline `max-height`. It reads the same
|
|
@@ -1584,8 +1625,10 @@ import { Menu, MenuButton, MenuItems, MenuItem, MenuSeparator } from "@blakestev
|
|
|
1584
1625
|
- **Styling.** `className` on `MenuItems` and on each item merges last, so a
|
|
1585
1626
|
fill such as `bg-gray-100` takes; the scroll shadows are drawn over it. Its
|
|
1586
1627
|
ring and separators follow `--roster-border-width`. Items show the pointer
|
|
1587
|
-
cursor, a disabled one `not-allowed`.
|
|
1588
|
-
|
|
1628
|
+
cursor, a disabled one `not-allowed`. Keyboard focus adds an inset ring in
|
|
1629
|
+
`--roster-ring` to the item's tint, which alone doesn't reach 3:1 against
|
|
1630
|
+
the panel ([Focus](#focus)). In forced colors the focused item gets an
|
|
1631
|
+
outline, since its fill and ring are dropped.
|
|
1589
1632
|
- **Targets.** Every item is at least 44px tall, and `MenuButton` at least 44
|
|
1590
1633
|
by 44 whatever its size. `MenuButton plain` renders a bare `<button>` for a
|
|
1591
1634
|
trigger drawn its own way; keep its target at least 44 by 44 with a hit
|
|
@@ -1599,6 +1642,126 @@ that its rows are 44px tall rather than 36, and that with neither an inbox nor
|
|
|
1599
1642
|
a theme row it no longer draws an empty band and rule at the top. It keeps its
|
|
1600
1643
|
own white fill, whatever `--roster-popover-bg` says.
|
|
1601
1644
|
|
|
1645
|
+
### Slider
|
|
1646
|
+
|
|
1647
|
+
A value picked along a track: tapped, dragged, stepped with the keys, or set
|
|
1648
|
+
from a named snap point.
|
|
1649
|
+
|
|
1650
|
+
```tsx
|
|
1651
|
+
import { Slider } from "@blakesteve/roster";
|
|
1652
|
+
|
|
1653
|
+
<Slider
|
|
1654
|
+
label="How sure are you?"
|
|
1655
|
+
value={sure}
|
|
1656
|
+
onChange={setSure}
|
|
1657
|
+
snapPoints={[{ value: 100, label: "Certain" }, { value: 75, label: "Likely" }, { value: 50, label: "Toss-up" }]}
|
|
1658
|
+
formatValue={(v) => `${v}%`}
|
|
1659
|
+
/>;
|
|
1660
|
+
```
|
|
1661
|
+
|
|
1662
|
+
- **It starts with a thumb**, in the middle of the range by default.
|
|
1663
|
+
`startValue` moves where it starts, and `defaultValue` sets it outright:
|
|
1664
|
+
`defaultValue={0}` starts it at the low end.
|
|
1665
|
+
- **Not set** is opt-in: `defaultValue={null}`, or `value={null}` when
|
|
1666
|
+
controlled, leaves the track empty with no thumb until the first input. A
|
|
1667
|
+
form takes it as a valid answer: under `name` it submits an empty string.
|
|
1668
|
+
Controlled, `value` can go back to `null`, which is how a consumer offers a
|
|
1669
|
+
clear.
|
|
1670
|
+
- **Snap points** are named stops, any values and labels: a selectable
|
|
1671
|
+
`Chip` under the track for each, in the track's order, moves the thumb
|
|
1672
|
+
there, and a bead on the rail shows where. They're shortcuts, so dragging
|
|
1673
|
+
still lands anywhere between them. A chip shows as pressed (solid rather
|
|
1674
|
+
than outline) while the value is exactly its value, and pressing it again
|
|
1675
|
+
leaves it there. A point outside `min` to `max` is left out.
|
|
1676
|
+
- **The label** is a string or a node, so it can carry markup; the slider is
|
|
1677
|
+
named by reference to it, so what's read is its text. A consumer's own
|
|
1678
|
+
`aria-labelledby` names it instead, as when the visible label is shared and
|
|
1679
|
+
each slider needs its own name.
|
|
1680
|
+
- **The number** shows beside the label (`formatValue` writes it). A screen
|
|
1681
|
+
reader hears it with the nearest snap point's name, "72%, Likely", and
|
|
1682
|
+
"Not set" while there's no value, never a number. Every string is in
|
|
1683
|
+
`labels`.
|
|
1684
|
+
- **In range.** A value outside `min` to `max` shows, and is said, at the
|
|
1685
|
+
end it's past. A controlled owner that turns a change down (a clamp, say)
|
|
1686
|
+
leaves the next key stepping from the value it kept.
|
|
1687
|
+
- **Pointer.** A tap on the track sets the value there; a press on the thumb
|
|
1688
|
+
takes it without a jump, and commits only if the drag moved it. On touch
|
|
1689
|
+
the track waits to see which way a finger goes: across is a drag, down the
|
|
1690
|
+
page scrolls it and sets nothing (and takes no focus), and a tap sets on
|
|
1691
|
+
lift. A pointermove with no press, which WebKit sends when content scrolls
|
|
1692
|
+
under a resting pointer, sets nothing. A second finger is left alone.
|
|
1693
|
+
- **Keys.** The arrows step by `step`, PageUp and PageDown by `pageStep` (a
|
|
1694
|
+
tenth of the range by default), Home and End go to the ends. **On an empty
|
|
1695
|
+
slider an arrow or Page key places the thumb at `startValue`, the middle
|
|
1696
|
+
by default**; it doesn't step from anywhere. A key at an end does nothing.
|
|
1697
|
+
From a value between steps, a key goes to the next step that way. Keys
|
|
1698
|
+
always step from the value last set, never from where the thumb is drawn
|
|
1699
|
+
while it eases there, so a burst of presses counts every one. A key the
|
|
1700
|
+
consumer's own `onKeyDown` handled (`preventDefault`) is left to it.
|
|
1701
|
+
- **Focus.** By keyboard, the ring is round the thumb; an empty slider rings
|
|
1702
|
+
the track. A disabled slider takes no focus at all.
|
|
1703
|
+
- **Form.** Under `name` it submits its value, or an empty string while not
|
|
1704
|
+
set; disabled, nothing, as a disabled input submits nothing. A form's
|
|
1705
|
+
reset puts an uncontrolled slider back where it started.
|
|
1706
|
+
- **Targets.** The track is 44px tall and its rail stops 22px short of each
|
|
1707
|
+
end, so the thumb's 44 by 44 target stays on it at every value. Each chip
|
|
1708
|
+
has Chip's 44px-tall target and is at least 44 wide, and the chip row sits
|
|
1709
|
+
8px under the track so its targets never take the thumb's. Under reduced
|
|
1710
|
+
motion the thumb moves without easing. Under `dir="rtl"` the track runs
|
|
1711
|
+
from the right.
|
|
1712
|
+
- **Look.** The rail is a light surface edged in `--roster-control-border`,
|
|
1713
|
+
which carries a control edge's 3:1 when there's no thumb to show the
|
|
1714
|
+
slider. Snap points are beads set in the rail, the edge's color on the bare
|
|
1715
|
+
rail and the page's on the fill.
|
|
1716
|
+
|
|
1717
|
+
One thumb. Two, for a range, is [RangeSlider](#rangeslider), on the same
|
|
1718
|
+
track, so `value` here stays a number.
|
|
1719
|
+
|
|
1720
|
+
### RangeSlider
|
|
1721
|
+
|
|
1722
|
+
A low and a high along one track: `Slider`'s track, with two thumbs.
|
|
1723
|
+
|
|
1724
|
+
```tsx
|
|
1725
|
+
import { RangeSlider } from "@blakesteve/roster";
|
|
1726
|
+
|
|
1727
|
+
<RangeSlider
|
|
1728
|
+
label="Price"
|
|
1729
|
+
min={0}
|
|
1730
|
+
max={500}
|
|
1731
|
+
step={5}
|
|
1732
|
+
value={price}
|
|
1733
|
+
onChange={setPrice}
|
|
1734
|
+
formatValue={(v) => `$${v}`}
|
|
1735
|
+
/>;
|
|
1736
|
+
```
|
|
1737
|
+
|
|
1738
|
+
- **It starts at the whole range**, `[min, max]`, unless `defaultValue`
|
|
1739
|
+
says otherwise. `value` is `[low, high]`, always low first: a pair given
|
|
1740
|
+
the wrong way round is shown the right way. There's no not-set state; the
|
|
1741
|
+
whole range is what "any" looks like.
|
|
1742
|
+
- **Each thumb is a slider** to the keyboard and a screen reader: its own
|
|
1743
|
+
tab stop, named for the slider and its end ("Price Minimum", "Price
|
|
1744
|
+
Maximum", both in `labels`), whose `aria-valuemin` and `aria-valuemax`
|
|
1745
|
+
run to the other thumb. The thumbs meet and never cross: End on the low
|
|
1746
|
+
thumb takes it to the high one. The whole is a group named by the label.
|
|
1747
|
+
- **Pointer.** A press takes the nearer thumb: a tap on the track moves it
|
|
1748
|
+
there, a drag carries it. Two thumbs on one spot part by the way the drag
|
|
1749
|
+
first moves, up the range taking the high one. Touch, the resting
|
|
1750
|
+
pointer, the second finger and the keys work as `Slider`'s do.
|
|
1751
|
+
- **Snap points** put a bead on the rail and a `Chip` under it, which does
|
|
1752
|
+
what a tap on its mark does: moves the nearer thumb there (halfway, the
|
|
1753
|
+
low one). A chip shows as pressed while either thumb is on it.
|
|
1754
|
+
- **The label** takes a node too, and names the group and each thumb by
|
|
1755
|
+
reference; a consumer's `aria-labelledby` names them instead.
|
|
1756
|
+
- **The number** beside the label shows both, "$120 – $340"
|
|
1757
|
+
(`labels.range`). Each thumb says its own value with the nearest snap
|
|
1758
|
+
point's name.
|
|
1759
|
+
- **Form.** Under `name` both values are submitted, low then high, as a
|
|
1760
|
+
multiple select's are: read them with `formData.getAll(name)`.
|
|
1761
|
+
- **Focus, targets, motion, RTL and look** as `Slider`'s: the ring is round
|
|
1762
|
+
the focused thumb, each thumb's 44 by 44 target stays on the track at
|
|
1763
|
+
every value.
|
|
1764
|
+
|
|
1602
1765
|
### Pagination
|
|
1603
1766
|
|
|
1604
1767
|
Moves through pages of a list, built for a long list browsed on a phone.
|
|
@@ -1886,6 +2049,8 @@ function App() {
|
|
|
1886
2049
|
| `StepProgress` | Named steps: a stepper with markers and connectors, or a compact segmented "Step x of y" |
|
|
1887
2050
|
| `Pullquote` | A line lifted out of prose, as `<figure>` + `<blockquote>` + `<figcaption>` |
|
|
1888
2051
|
| `RadioGroup` | Radio set reporting one `string`; descriptions, error, 44px targets |
|
|
2052
|
+
| `Slider` | A value along a track, starting in the middle or not set on request; named snap-point chips, a visible number, the full keyboard, 44px targets (see [Slider](#slider)) |
|
|
2053
|
+
| `RangeSlider` | A low and a high on one track: two thumbs that meet and never cross, each its own slider to the keyboard (see [RangeSlider](#rangeslider)) |
|
|
1889
2054
|
| `Toast` | Transient floating notice; `Toaster` + the imperative `toast` handle |
|
|
1890
2055
|
|
|
1891
2056
|
### Organisms
|
|
@@ -1997,6 +2162,32 @@ such as `AvatarStrip`'s `ringClass`, stays exactly as they wrote it.
|
|
|
1997
2162
|
|
|
1998
2163
|
`npm run build` fails if any unprefixed class reaches `dist/roster.css`.
|
|
1999
2164
|
|
|
2165
|
+
## Authoring components: cursors
|
|
2166
|
+
|
|
2167
|
+
**If it's clickable, it's the pointer.** Every element that does something
|
|
2168
|
+
when it's clicked shows `cursor: pointer`, and says so in its classes. A
|
|
2169
|
+
browser gives a button the arrow; Tailwind v3's preflight gave it the pointer
|
|
2170
|
+
and v4's doesn't, so a `<button>` with no cursor class shows the arrow. Until 5.11.0 the option rows
|
|
2171
|
+
in `Select`, `Combobox` and `MultiSelect` showed the arrow while `Menu`'s
|
|
2172
|
+
showed the pointer, and `PasswordInput`'s reveal button showed the arrow too.
|
|
2173
|
+
|
|
2174
|
+
- A disabled control shows `not-allowed`.
|
|
2175
|
+
- A busy one may say so: `Button`'s `loading` shows `progress`.
|
|
2176
|
+
- A text field's label keeps the arrow, as a native one does: clicking it puts
|
|
2177
|
+
the caret in the field rather than doing something.
|
|
2178
|
+
|
|
2179
|
+
Three things keep another cursor, because they aren't click targets:
|
|
2180
|
+
|
|
2181
|
+
- **`Breadcrumbs`' current crumb** is the page you're on, not a link:
|
|
2182
|
+
`default`.
|
|
2183
|
+
- **`Tooltip`'s trigger wrapper** isn't necessarily clickable: `default`. A
|
|
2184
|
+
control inside it brings its own pointer.
|
|
2185
|
+
- **A drag surface** says what it does: `Carousel`'s track and `Sheet`'s drag
|
|
2186
|
+
handle show `grab`, then `grabbing`.
|
|
2187
|
+
|
|
2188
|
+
`src/internal/popups.checks.stories.tsx` reads the computed cursor on a row in
|
|
2189
|
+
each popup, with a disabled row as its twin.
|
|
2190
|
+
|
|
2000
2191
|
## Development
|
|
2001
2192
|
|
|
2002
2193
|
Storybook is the component playground. Each component has dedicated stories covering all variants, props, and light/dark mode.
|
|
@@ -2128,7 +2319,7 @@ like a file count but counts `describe` blocks — 166 against 92 real files.
|
|
|
2128
2319
|
Pull requests are welcome. Please:
|
|
2129
2320
|
|
|
2130
2321
|
1. Open an issue or discussion first for significant changes
|
|
2131
|
-
2. Follow the existing code style (CVA variants, forwardRef, Storybook stories, unit tests)
|
|
2322
|
+
2. Follow the existing code style (CVA variants, forwardRef, Storybook stories, unit tests) and the authoring rules above: the `rst:` prefix and cursors
|
|
2132
2323
|
3. Fill out the pull request template checklist before requesting review
|
|
2133
2324
|
|
|
2134
2325
|
## License
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("../../../node_modules/class-variance-authority/dist/index.cjs"),t=r.cva("rst:font-ui rst:inline-flex rst:items-center rst:rounded-full rst:font-medium rst:whitespace-nowrap rst:align-middle rst:transition-colors",{variants:{colorScheme:{primary:"",success:"",error:"",amber:"",info:"",neutral:""},variant:{soft:"",outline:"rst:bg-transparent
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("../../../node_modules/class-variance-authority/dist/index.cjs"),t=r.cva("rst:font-ui rst:inline-flex rst:items-center rst:rounded-full rst:border rst:border-transparent rst:font-medium rst:whitespace-nowrap rst:align-middle rst:transition-colors",{variants:{colorScheme:{primary:"",success:"",error:"",amber:"",info:"",neutral:""},variant:{soft:"",outline:"rst:bg-transparent",solid:""},size:{sm:"rst:text-xs rst:px-2.5 rst:py-0.5 rst:gap-1.5",md:"rst:text-sm rst:px-3 rst:py-1 rst:gap-2"},disabled:{true:"rst:opacity-50 rst:cursor-not-allowed",false:""}},compoundVariants:[{variant:"soft",colorScheme:"primary",className:"rst:bg-primary-50 rst:text-primary-700 rst:dark:bg-primary-500/15 rst:dark:text-primary-300"},{variant:"soft",colorScheme:"success",className:"rst:bg-success-50 rst:text-success-700 rst:dark:bg-success-500/15 rst:dark:text-success-300"},{variant:"soft",colorScheme:"error",className:"rst:bg-error-50 rst:text-error-700 rst:dark:bg-error-500/15 rst:dark:text-error-300"},{variant:"soft",colorScheme:"amber",className:"rst:bg-amber-50 rst:text-amber-800 rst:dark:bg-amber-500/15 rst:dark:text-amber-300"},{variant:"soft",colorScheme:"info",className:"rst:bg-info-50 rst:text-info-700 rst:dark:bg-info-500/15 rst:dark:text-info-300"},{variant:"soft",colorScheme:"neutral",className:"rst:bg-gray-100 rst:text-gray-700 rst:dark:bg-gray-500/15 rst:dark:text-gray-300"},{variant:"outline",colorScheme:"primary",className:"rst:border-primary-600 rst:text-primary-700 rst:dark:border-primary-400 rst:dark:text-primary-300"},{variant:"outline",colorScheme:"success",className:"rst:border-success-600 rst:text-success-700 rst:dark:border-success-400 rst:dark:text-success-300"},{variant:"outline",colorScheme:"error",className:"rst:border-error-600 rst:text-error-700 rst:dark:border-error-400 rst:dark:text-error-300"},{variant:"outline",colorScheme:"amber",className:"rst:border-amber-600 rst:text-amber-800 rst:dark:border-amber-400 rst:dark:text-amber-300"},{variant:"outline",colorScheme:"info",className:"rst:border-info-600 rst:text-info-700 rst:dark:border-info-400 rst:dark:text-info-300"},{variant:"outline",colorScheme:"neutral",className:"rst:border-gray-600 rst:text-gray-700 rst:dark:border-gray-400 rst:dark:text-gray-300"},{variant:"solid",colorScheme:"primary",className:"rst:bg-primary-500 rst:text-primary-500-ink"},{variant:"solid",colorScheme:"success",className:"rst:bg-success-500 rst:text-success-500-ink"},{variant:"solid",colorScheme:"error",className:"rst:bg-error-500 rst:text-error-500-ink"},{variant:"solid",colorScheme:"amber",className:"rst:bg-amber-500 rst:text-amber-500-ink"},{variant:"solid",colorScheme:"info",className:"rst:bg-info-500 rst:text-info-500-ink"},{variant:"solid",colorScheme:"neutral",className:"rst:bg-gray-600 rst:dark:bg-gray-500 rst:text-gray-600-ink rst:dark:text-gray-500-ink"}],defaultVariants:{colorScheme:"neutral",variant:"soft",size:"md",disabled:!1}});exports.chipVariants=t;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { cva as r } from "../../../node_modules/class-variance-authority/dist/index.js";
|
|
2
2
|
const s = /* @__PURE__ */ r(
|
|
3
|
-
|
|
3
|
+
/* A border on every variant, transparent where the variant draws none, so
|
|
4
|
+
every variant is one size. Only `outline` had one, so a chip that swaps
|
|
5
|
+
`outline` for `solid` when selected, as a filter row and a slider's snap
|
|
6
|
+
chips do, lost the border's width on both sides at the press and the row
|
|
7
|
+
jumped. A transparent border costs nothing to see: the fill paints under
|
|
8
|
+
it. Its width is `--roster-border-width`, like every edge. */
|
|
9
|
+
"rst:font-ui rst:inline-flex rst:items-center rst:rounded-full rst:border rst:border-transparent rst:font-medium rst:whitespace-nowrap rst:align-middle rst:transition-colors",
|
|
4
10
|
{
|
|
5
11
|
variants: {
|
|
6
12
|
colorScheme: {
|
|
@@ -13,7 +19,7 @@ const s = /* @__PURE__ */ r(
|
|
|
13
19
|
},
|
|
14
20
|
variant: {
|
|
15
21
|
soft: "",
|
|
16
|
-
outline: "rst:bg-transparent
|
|
22
|
+
outline: "rst:bg-transparent",
|
|
17
23
|
solid: ""
|
|
18
24
|
},
|
|
19
25
|
size: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),j=require("react"),a=require("../../../node_modules/@headlessui/react/dist/components/combobox/combobox.cjs"),_=require("../../../node_modules/@headlessui/react/dist/components/description/description.cjs"),L=require("../../../node_modules/@headlessui/react/dist/components/field/field.cjs"),R=require("../../../node_modules/@headlessui/react/dist/components/label/label.cjs"),T=require("../../../node_modules/@headlessui/react/dist/components/transition/transition.cjs"),U=require("../../../node_modules/@fortawesome/react-fontawesome/dist/index.cjs"),A=require("../../../node_modules/@fortawesome/free-solid-svg-icons/index.cjs"),i=require("../../../lib/utils.cjs"),h=require("../../../internal/field-invalid.cjs"),V=require("../Input/input-variants.cjs"),E=require("../../../internal/PopupOption.cjs"),c=require("../../../internal/popup.cjs"),H=require("../../../internal/key-focus.cjs");function B(t){const s=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const r in t)if(r!=="default"){const n=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(s,r,n.get?n:{enumerable:!0,get:()=>t[r]})}}return s.default=t,Object.freeze(s)}const K=B(j),Q=(t,s)=>{const r=s.trim().toLowerCase();return r?t.filter(n=>n.label.toLowerCase().includes(r)):t},W=({options:t,value:s,onChange:r,placeholder:n="Search...",disabled:x=!1,variant:m,size:l,error:P,label:p,helperText:b,errorMessage:u,className:q,inputClassName:O,optionsClassName:g,emptyMessage:N="No matches",filter:C=Q,...f})=>{H.useKeyFocus();const[k,v]=K.useState(""),{ref:F,inDarkScope:w}=c.useDarkScope(),d=!!u||P,D=h.isFieldInvalid(d,f),I=h.withoutInvalidProps(f),y=C(t,k),S=t.find(o=>o.value===s)??null;return e.jsxs(L.Field,{disabled:x,className:i.cn("rst:flex rst:flex-col rst:gap-1.5",q),...I,children:[p&&e.jsx(R.Label,{className:"rst:block rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)] rst:text-left",children:p}),e.jsx(a.Combobox,{value:s??null,onChange:r,disabled:x,children:e.jsxs("div",{ref:F,className:"rst:relative",children:[e.jsx(a.ComboboxInput,{"aria-invalid":D||void 0,className:i.cn(V.inputVariants({variant:m,size:l,error:d}),O,"rst:pr-9"),placeholder:n,displayValue:()=>S?.label??"",onChange:o=>v(o.target.value)}),e.jsx(a.ComboboxButton,{className:i.cn("rst:absolute rst:inset-y-0 rst:right-0 rst:flex rst:w-11 rst:cursor-pointer rst:items-center rst:justify-end",l==="sm"?"rst:pr-2.5":"rst:pr-3"),children:e.jsx(U.FontAwesomeIcon,{icon:A.faChevronDown,className:"rst:h-3.5 rst:w-3.5 rst:text-gray-400 rst:dark:text-gray-500","aria-hidden":"true"})}),e.jsx(T.Transition,{as:j.Fragment,leave:"rst:transition rst:ease-in rst:duration-100",leaveFrom:"rst:opacity-100",leaveTo:"rst:opacity-0",afterLeave:()=>v(""),children:e.jsx(a.ComboboxOptions,{anchor:c.POPUP_ANCHOR,className:i.cn(c.popupInDarkPalette(w,m)&&"dark",c.POPUP_PANEL,c.POPUP_WIDTH_OF_INPUT,g),children:y.length===0?e.jsx(a.ComboboxOption,{value:"",disabled:!0,className:i.cn("rst:px-4 rst:py-2.5 rst:text-sm rst:opacity-70",l==="sm"&&"rst:px-3 rst:py-2"),children:N}):y.map(o=>e.jsx(E.PopupOption,{as:a.ComboboxOption,value:o.value,disabled:o.disabled,size:l,children:o.label},o.value))})})]})}),(b||u)&&e.jsx(_.Description,{className:i.cn("rst:text-xs rst:text-left",d?"rst:text-error-600 rst:dark:text-error-400 rst:font-medium":"rst:text-gray-500 rst:dark:text-gray-400"),children:u||b})]})};exports.Combobox=W;
|
|
@@ -8,16 +8,17 @@ import { Field as T } from "../../../node_modules/@headlessui/react/dist/compone
|
|
|
8
8
|
import { Label as q } from "../../../node_modules/@headlessui/react/dist/components/label/label.js";
|
|
9
9
|
import { Transition as B } from "../../../node_modules/@headlessui/react/dist/components/transition/transition.js";
|
|
10
10
|
import { FontAwesomeIcon as E } from "../../../node_modules/@fortawesome/react-fontawesome/dist/index.js";
|
|
11
|
-
import { faChevronDown as
|
|
11
|
+
import { faChevronDown as K } from "../../../node_modules/@fortawesome/free-solid-svg-icons/index.js";
|
|
12
12
|
import { cn as e } from "../../../lib/utils.js";
|
|
13
|
-
import { isFieldInvalid as
|
|
13
|
+
import { isFieldInvalid as V, withoutInvalidProps as W } from "../../../internal/field-invalid.js";
|
|
14
14
|
import { inputVariants as Q } from "../Input/input-variants.js";
|
|
15
15
|
import { PopupOption as Z } from "../../../internal/PopupOption.js";
|
|
16
16
|
import { useDarkScope as G, POPUP_ANCHOR as J, POPUP_WIDTH_OF_INPUT as X, POPUP_PANEL as Y, popupInDarkPalette as $ } from "../../../internal/popup.js";
|
|
17
|
-
|
|
17
|
+
import { useKeyFocus as M } from "../../../internal/key-focus.js";
|
|
18
|
+
const z = (s, o) => {
|
|
18
19
|
const a = o.trim().toLowerCase();
|
|
19
20
|
return a ? s.filter((l) => l.label.toLowerCase().includes(a)) : s;
|
|
20
|
-
},
|
|
21
|
+
}, xt = ({
|
|
21
22
|
options: s,
|
|
22
23
|
value: o,
|
|
23
24
|
onChange: a,
|
|
@@ -25,23 +26,24 @@ const M = (s, o) => {
|
|
|
25
26
|
disabled: c = !1,
|
|
26
27
|
variant: d,
|
|
27
28
|
size: i,
|
|
28
|
-
error:
|
|
29
|
+
error: y,
|
|
29
30
|
label: p,
|
|
30
31
|
helperText: f,
|
|
31
|
-
errorMessage:
|
|
32
|
-
className:
|
|
32
|
+
errorMessage: m,
|
|
33
|
+
className: P,
|
|
33
34
|
inputClassName: N,
|
|
34
35
|
optionsClassName: C,
|
|
35
36
|
emptyMessage: k = "No matches",
|
|
36
|
-
filter: g =
|
|
37
|
+
filter: g = z,
|
|
37
38
|
...u
|
|
38
39
|
}) => {
|
|
39
|
-
|
|
40
|
+
M();
|
|
41
|
+
const [F, x] = U.useState(""), { ref: O, inDarkScope: w } = G(), n = !!m || y, I = V(n, u), D = W(u), h = g(s, F), L = s.find((r) => r.value === o) ?? null;
|
|
40
42
|
return /* @__PURE__ */ b(
|
|
41
43
|
T,
|
|
42
44
|
{
|
|
43
45
|
disabled: c,
|
|
44
|
-
className: e("rst:flex rst:flex-col rst:gap-1.5",
|
|
46
|
+
className: e("rst:flex rst:flex-col rst:gap-1.5", P),
|
|
45
47
|
...D,
|
|
46
48
|
children: [
|
|
47
49
|
p && /* @__PURE__ */ t(q, { className: "rst:block rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)] rst:text-left", children: p }),
|
|
@@ -51,13 +53,13 @@ const M = (s, o) => {
|
|
|
51
53
|
value: o ?? null,
|
|
52
54
|
onChange: a,
|
|
53
55
|
disabled: c,
|
|
54
|
-
children: /* @__PURE__ */ b("div", { ref:
|
|
56
|
+
children: /* @__PURE__ */ b("div", { ref: O, className: "rst:relative", children: [
|
|
55
57
|
/* @__PURE__ */ t(
|
|
56
58
|
S,
|
|
57
59
|
{
|
|
58
60
|
"aria-invalid": I || void 0,
|
|
59
61
|
className: e(
|
|
60
|
-
Q({ variant: d, size: i, error:
|
|
62
|
+
Q({ variant: d, size: i, error: n }),
|
|
61
63
|
N,
|
|
62
64
|
"rst:pr-9"
|
|
63
65
|
),
|
|
@@ -76,7 +78,7 @@ const M = (s, o) => {
|
|
|
76
78
|
children: /* @__PURE__ */ t(
|
|
77
79
|
E,
|
|
78
80
|
{
|
|
79
|
-
icon:
|
|
81
|
+
icon: K,
|
|
80
82
|
className: "rst:h-3.5 rst:w-3.5 rst:text-gray-400 rst:dark:text-gray-500",
|
|
81
83
|
"aria-hidden": "true"
|
|
82
84
|
}
|
|
@@ -96,7 +98,7 @@ const M = (s, o) => {
|
|
|
96
98
|
{
|
|
97
99
|
anchor: J,
|
|
98
100
|
className: e(
|
|
99
|
-
$(
|
|
101
|
+
$(w, d) && "dark",
|
|
100
102
|
Y,
|
|
101
103
|
/* `--input-width`, not `--button-width`: the button here is
|
|
102
104
|
the chevron, so matching it renders a 20px sliver. */
|
|
@@ -132,14 +134,14 @@ const M = (s, o) => {
|
|
|
132
134
|
] })
|
|
133
135
|
}
|
|
134
136
|
),
|
|
135
|
-
(f ||
|
|
137
|
+
(f || m) && /* @__PURE__ */ t(
|
|
136
138
|
R,
|
|
137
139
|
{
|
|
138
140
|
className: e(
|
|
139
141
|
"rst:text-xs rst:text-left",
|
|
140
|
-
|
|
142
|
+
n ? "rst:text-error-600 rst:dark:text-error-400 rst:font-medium" : "rst:text-gray-500 rst:dark:text-gray-400"
|
|
141
143
|
),
|
|
142
|
-
children:
|
|
144
|
+
children: m || f
|
|
143
145
|
}
|
|
144
146
|
)
|
|
145
147
|
]
|
|
@@ -147,5 +149,5 @@ const M = (s, o) => {
|
|
|
147
149
|
);
|
|
148
150
|
};
|
|
149
151
|
export {
|
|
150
|
-
|
|
152
|
+
xt as Combobox
|
|
151
153
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),F=require("react"),K=require("../../../node_modules/@headlessui/react/dist/components/description/description.cjs"),W=require("../../../node_modules/@headlessui/react/dist/components/field/field.cjs"),X=require("../../../node_modules/@headlessui/react/dist/components/label/label.cjs"),h=require("../../../node_modules/@headlessui/react/dist/components/listbox/listbox.cjs"),G=require("../../../node_modules/@headlessui/react/dist/components/transition/transition.cjs"),T=require("../../../node_modules/@fortawesome/react-fontawesome/dist/index.cjs"),R=require("../../../node_modules/@fortawesome/free-solid-svg-icons/index.cjs"),n=require("../../../lib/utils.cjs"),_=require("../../../internal/field-invalid.cjs"),J=require("../Select/select-variants.cjs"),D=require("../Chip/Chip.cjs"),Q=require("../../../internal/PopupOption.cjs"),c=require("../../../internal/popup.cjs"),Z=require("../../../internal/key-focus.cjs"),z=({options:x,value:i,onChange:m,placeholder:v="Select options",disabled:l=!1,variant:f,size:o,error:L,className:A,triggerClassName:E,optionsClassName:U,helperText:b,errorMessage:p,label:g,display:u="chips",maxChips:N,clearable:j=!1,chipColorScheme:k="neutral",chipVariant:w="outline",clearLabel:$="Clear selection",removeLabel:C=e=>`Remove ${e}`,countLabel:y=e=>`${e} selected`,...I})=>{Z.useKeyFocus();const e=!!p||L,V=_.isFieldInvalid(e,I),B=_.withoutInvalidProps(I),a=i.length>0,P=new Map(x.map((r,s)=>[r.value,s])),d=i.map(r=>({value:r,label:x.find(s=>s.value===r)?.label??String(r)})).sort((r,s)=>(P.get(r.value)??Number.POSITIVE_INFINITY)-(P.get(s.value)??Number.POSITIVE_INFINITY)),q=N===void 0?d:d.slice(0,N),O=d.length-q.length,{ref:H,inDarkScope:M}=c.useDarkScope(),S=F.useRef(null);return t.jsxs(W.Field,{disabled:l,className:n.cn("rst:flex rst:flex-col rst:gap-1.5",A),...B,children:[g&&t.jsx(X.Label,{className:"rst:block rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)] rst:text-left",children:g}),t.jsx(h.Listbox,{value:i,onChange:m,disabled:l,multiple:!0,children:t.jsxs("div",{ref:H,className:"rst:relative",children:[t.jsxs("div",{className:n.cn(J.selectTriggerVariants({variant:f,size:o,error:e}),"rst:h-auto rst:flex-wrap rst:items-center rst:gap-1.5 rst:py-1.5",o==="sm"?"rst:min-h-9":o==="lg"?"rst:min-h-11":"rst:min-h-10",j&&a&&"rst:pr-16","rst:focus-within:ring-[length:calc(var(--roster-border-width,1px)+1px)] rst:focus-within:ring-ring",l&&"rst:opacity-50 rst:cursor-not-allowed",E),children:[t.jsx(h.ListboxButton,{ref:S,"aria-invalid":V||void 0,className:"rst:absolute rst:inset-0 rst:h-full rst:w-full rst:cursor-pointer rst:rounded-md rst:focus:outline-hidden rst:disabled:cursor-not-allowed",children:t.jsx("span",{className:"rst:sr-only",children:a?u==="count"?y(i.length):d.map(r=>r.label).join(", "):v})}),!a&&t.jsx("span",{"aria-hidden":"true",className:"rst:pointer-events-none rst:relative rst:block rst:truncate rst:text-gray-500 rst:dark:text-gray-400",children:v}),a&&u==="count"&&t.jsx("span",{"aria-hidden":"true",className:"rst:pointer-events-none rst:relative rst:block rst:truncate",children:y(i.length)}),a&&u==="chips"&&q.map((r,s)=>t.jsx(D.Chip,{size:"sm",variant:w,colorScheme:k,disabled:l,onRemove:()=>m(i.filter(Y=>Y!==r.value)),removeLabel:C(r.label),className:n.cn("rst:relative rst:max-w-[12rem] rst:pointer-events-none","rst:[&_button]:pointer-events-auto","rst:text-inherit rst:border-current/70 rst:dark:text-inherit rst:dark:border-current/70"),children:t.jsx("span",{className:"rst:block rst:truncate",children:r.label})},`${s}-${String(r.value)}`)),O>0&&u==="chips"&&t.jsxs(D.Chip,{size:"sm",variant:w,colorScheme:k,"aria-hidden":"true",className:"rst:pointer-events-none rst:relative rst:text-inherit rst:border-current/70 rst:dark:text-inherit rst:dark:border-current/70",children:["+",O]}),t.jsx("span",{className:n.cn("rst:pointer-events-none rst:absolute rst:inset-y-0 rst:right-0 rst:flex rst:items-center",o==="sm"?"rst:pr-2.5":"rst:pr-3"),children:t.jsx(T.FontAwesomeIcon,{icon:R.faChevronDown,className:"rst:h-3.5 rst:w-3.5 rst:text-gray-400 rst:dark:text-gray-500","aria-hidden":"true"})}),j&&a&&t.jsx("button",{type:"button",disabled:l,onClick:()=>{m([]),S.current?.focus()},"aria-label":$,className:n.cn("rst:absolute rst:inset-y-0 rst:flex rst:w-6 rst:items-center rst:justify-center","rst:cursor-pointer rst:disabled:cursor-not-allowed","rst:text-current rst:opacity-70 rst:hover:opacity-100 rst:disabled:opacity-40","rst:focus:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:rounded-sm",o==="sm"?"rst:right-7":"rst:right-8"),children:t.jsx(T.FontAwesomeIcon,{icon:R.faXmark,className:"rst:h-3.5 rst:w-3.5","aria-hidden":"true"})})]}),t.jsx(G.Transition,{as:F.Fragment,leave:"rst:transition rst:ease-in rst:duration-100",leaveFrom:"rst:opacity-100",leaveTo:"rst:opacity-0",children:t.jsx(h.ListboxOptions,{anchor:c.POPUP_ANCHOR,className:n.cn(c.popupInDarkPalette(M,f)&&"dark",c.POPUP_PANEL,c.POPUP_WIDTH_OF_BUTTON,U),children:x.map(r=>t.jsx(Q.PopupOption,{as:h.ListboxOption,value:r.value,disabled:r.disabled,size:o,children:r.label},r.value))})})]})}),(b||p)&&t.jsx(K.Description,{className:n.cn("rst:text-xs rst:text-left",e?"rst:text-error-600 rst:dark:text-error-400 rst:font-medium":"rst:text-gray-500 rst:dark:text-gray-400"),children:p||b})]})};exports.MultiSelect=z;
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs as d, jsx as r } from "react/jsx-runtime";
|
|
3
|
-
import
|
|
4
|
-
import { Description as
|
|
5
|
-
import { Field as
|
|
6
|
-
import { Label as
|
|
3
|
+
import K, { Fragment as V } from "react";
|
|
4
|
+
import { Description as W } from "../../../node_modules/@headlessui/react/dist/components/description/description.js";
|
|
5
|
+
import { Field as Y } from "../../../node_modules/@headlessui/react/dist/components/field/field.js";
|
|
6
|
+
import { Label as C } from "../../../node_modules/@headlessui/react/dist/components/label/label.js";
|
|
7
7
|
import { Listbox as X, ListboxButton as Z, ListboxOptions as q, ListboxOption as G } from "../../../node_modules/@headlessui/react/dist/components/listbox/listbox.js";
|
|
8
8
|
import { Transition as J } from "../../../node_modules/@headlessui/react/dist/components/transition/transition.js";
|
|
9
|
-
import { FontAwesomeIcon as
|
|
9
|
+
import { FontAwesomeIcon as F } from "../../../node_modules/@fortawesome/react-fontawesome/dist/index.js";
|
|
10
10
|
import { faChevronDown as Q, faXmark as z } from "../../../node_modules/@fortawesome/free-solid-svg-icons/index.js";
|
|
11
11
|
import { cn as n } from "../../../lib/utils.js";
|
|
12
12
|
import { isFieldInvalid as tt, withoutInvalidProps as rt } from "../../../internal/field-invalid.js";
|
|
13
13
|
import { selectTriggerVariants as et } from "../Select/select-variants.js";
|
|
14
|
-
import { Chip as
|
|
14
|
+
import { Chip as T } from "../Chip/Chip.js";
|
|
15
15
|
import { PopupOption as st } from "../../../internal/PopupOption.js";
|
|
16
16
|
import { useDarkScope as nt, POPUP_ANCHOR as ot, POPUP_WIDTH_OF_BUTTON as it, POPUP_PANEL as at, popupInDarkPalette as lt } from "../../../internal/popup.js";
|
|
17
|
-
|
|
17
|
+
import { useKeyFocus as ct } from "../../../internal/key-focus.js";
|
|
18
|
+
const Ot = ({
|
|
18
19
|
options: u,
|
|
19
20
|
value: o,
|
|
20
21
|
onChange: p,
|
|
@@ -37,22 +38,23 @@ const Pt = ({
|
|
|
37
38
|
clearLabel: E = "Clear selection",
|
|
38
39
|
removeLabel: U = (e) => `Remove ${e}`,
|
|
39
40
|
countLabel: I = (e) => `${e} selected`,
|
|
40
|
-
...
|
|
41
|
+
...y
|
|
41
42
|
}) => {
|
|
42
|
-
|
|
43
|
+
ct();
|
|
44
|
+
const e = !!h || R, $ = tt(e, y), A = rt(y), a = o.length > 0, P = new Map(u.map((t, s) => [t.value, s])), m = o.map((t) => ({
|
|
43
45
|
value: t,
|
|
44
46
|
label: u.find((s) => s.value === t)?.label ?? String(t)
|
|
45
47
|
})).sort(
|
|
46
|
-
(t, s) => (
|
|
47
|
-
), O = g === void 0 ? m : m.slice(0, g), S = m.length - O.length, { ref: B, inDarkScope: M } = nt(), _ =
|
|
48
|
+
(t, s) => (P.get(t.value) ?? Number.POSITIVE_INFINITY) - (P.get(s.value) ?? Number.POSITIVE_INFINITY)
|
|
49
|
+
), O = g === void 0 ? m : m.slice(0, g), S = m.length - O.length, { ref: B, inDarkScope: M } = nt(), _ = K.useRef(null);
|
|
48
50
|
return /* @__PURE__ */ d(
|
|
49
|
-
|
|
51
|
+
Y,
|
|
50
52
|
{
|
|
51
53
|
disabled: l,
|
|
52
54
|
className: n("rst:flex rst:flex-col rst:gap-1.5", D),
|
|
53
55
|
...A,
|
|
54
56
|
children: [
|
|
55
|
-
b && /* @__PURE__ */ r(
|
|
57
|
+
b && /* @__PURE__ */ r(C, { className: "rst:block rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)] rst:text-left", children: b }),
|
|
56
58
|
/* @__PURE__ */ r(X, { value: o, onChange: p, disabled: l, multiple: !0, children: /* @__PURE__ */ d("div", { ref: B, className: "rst:relative", children: [
|
|
57
59
|
/* @__PURE__ */ d(
|
|
58
60
|
"div",
|
|
@@ -98,7 +100,7 @@ const Pt = ({
|
|
|
98
100
|
}
|
|
99
101
|
),
|
|
100
102
|
a && c === "chips" && O.map((t, s) => /* @__PURE__ */ r(
|
|
101
|
-
|
|
103
|
+
T,
|
|
102
104
|
{
|
|
103
105
|
size: "sm",
|
|
104
106
|
variant: w,
|
|
@@ -116,7 +118,7 @@ const Pt = ({
|
|
|
116
118
|
`${s}-${String(t.value)}`
|
|
117
119
|
)),
|
|
118
120
|
S > 0 && c === "chips" && /* @__PURE__ */ d(
|
|
119
|
-
|
|
121
|
+
T,
|
|
120
122
|
{
|
|
121
123
|
size: "sm",
|
|
122
124
|
variant: w,
|
|
@@ -137,7 +139,7 @@ const Pt = ({
|
|
|
137
139
|
i === "sm" ? "rst:pr-2.5" : "rst:pr-3"
|
|
138
140
|
),
|
|
139
141
|
children: /* @__PURE__ */ r(
|
|
140
|
-
|
|
142
|
+
F,
|
|
141
143
|
{
|
|
142
144
|
icon: Q,
|
|
143
145
|
className: "rst:h-3.5 rst:w-3.5 rst:text-gray-400 rst:dark:text-gray-500",
|
|
@@ -167,7 +169,7 @@ const Pt = ({
|
|
|
167
169
|
i === "sm" ? "rst:right-7" : "rst:right-8"
|
|
168
170
|
),
|
|
169
171
|
children: /* @__PURE__ */ r(
|
|
170
|
-
|
|
172
|
+
F,
|
|
171
173
|
{
|
|
172
174
|
icon: z,
|
|
173
175
|
className: "rst:h-3.5 rst:w-3.5",
|
|
@@ -182,7 +184,7 @@ const Pt = ({
|
|
|
182
184
|
/* @__PURE__ */ r(
|
|
183
185
|
J,
|
|
184
186
|
{
|
|
185
|
-
as:
|
|
187
|
+
as: V,
|
|
186
188
|
leave: "rst:transition rst:ease-in rst:duration-100",
|
|
187
189
|
leaveFrom: "rst:opacity-100",
|
|
188
190
|
leaveTo: "rst:opacity-0",
|
|
@@ -213,7 +215,7 @@ const Pt = ({
|
|
|
213
215
|
)
|
|
214
216
|
] }) }),
|
|
215
217
|
(x || h) && /* @__PURE__ */ r(
|
|
216
|
-
|
|
218
|
+
W,
|
|
217
219
|
{
|
|
218
220
|
className: n(
|
|
219
221
|
"rst:text-xs rst:text-left",
|
|
@@ -227,5 +229,5 @@ const Pt = ({
|
|
|
227
229
|
);
|
|
228
230
|
};
|
|
229
231
|
export {
|
|
230
|
-
|
|
232
|
+
Ot as MultiSelect
|
|
231
233
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),i=require("react"),j=require("../../../node_modules/@fortawesome/react-fontawesome/dist/index.cjs"),c=require("../../../node_modules/@fortawesome/free-solid-svg-icons/index.cjs"),a=require("../../../lib/utils.cjs"),S=require("../Input/Input.cjs"),u=i.forwardRef(({revealable:l=!0,defaultRevealed:d=!1,revealed:r,onRevealChange:p,showLabel:y="Show password",hideLabel:f="Hide password",disabled:s,variant:m,error:w,errorMessage:h,className:v,...x},g)=>{const[I,q]=i.useState(d),o=r!==void 0,t=o?r:I,b=()=>{const n=!t;o||q(n),p?.(n)};return e.jsx(S.Input,{ref:g,type:t?"text":"password",disabled:s,variant:m,error:w,errorMessage:h,className:a.cn("rst:[&_input::-ms-reveal]:hidden",v),endIcon:l?e.jsx("button",{type:"button",onClick:b,disabled:s,"aria-label":t?f:y,"aria-pressed":t,className:a.cn("rst:-m-1 rst:flex rst:items-center rst:rounded-sm rst:p-1 rst:transition-opacity","rst:opacity-70 rst:hover:opacity-100","rst:focus:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring",s?"rst:cursor-not-allowed rst:opacity-40 rst:hover:opacity-40":"rst:cursor-pointer"),children:e.jsx(j.FontAwesomeIcon,{icon:t?c.faEyeSlash:c.faEye,className:"rst:h-4 rst:w-4","aria-hidden":"true"})}):void 0,...x})});u.displayName="PasswordInput";exports.PasswordInput=u;
|