@blakesteve/roster 5.1.0 → 5.2.1

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.
Files changed (47) hide show
  1. package/README.md +57 -3
  2. package/dist/components/atoms/Combobox/Combobox.cjs +1 -1
  3. package/dist/components/atoms/Combobox/Combobox.js +63 -62
  4. package/dist/components/atoms/Input/Input.cjs +1 -1
  5. package/dist/components/atoms/Input/Input.js +41 -39
  6. package/dist/components/atoms/MultiSelect/MultiSelect.cjs +1 -1
  7. package/dist/components/atoms/MultiSelect/MultiSelect.js +69 -68
  8. package/dist/components/atoms/Select/Select.cjs +1 -1
  9. package/dist/components/atoms/Select/Select.js +52 -51
  10. package/dist/components/atoms/Spinner/Spinner.cjs +1 -1
  11. package/dist/components/atoms/Spinner/Spinner.d.ts +6 -1
  12. package/dist/components/atoms/Spinner/Spinner.js +9 -8
  13. package/dist/components/atoms/Textarea/Textarea.cjs +1 -1
  14. package/dist/components/atoms/Textarea/Textarea.js +36 -34
  15. package/dist/components/molecules/Carousel/Carousel.cjs +1 -0
  16. package/dist/components/molecules/Carousel/Carousel.d.ts +146 -0
  17. package/dist/components/molecules/Carousel/Carousel.js +363 -0
  18. package/dist/components/molecules/Carousel/carousel-layout.cjs +1 -0
  19. package/dist/components/molecules/Carousel/carousel-layout.d.ts +23 -0
  20. package/dist/components/molecules/Carousel/carousel-layout.js +22 -0
  21. package/dist/components/molecules/Carousel/carousel-math.cjs +1 -0
  22. package/dist/components/molecules/Carousel/carousel-math.d.ts +60 -0
  23. package/dist/components/molecules/Carousel/carousel-math.js +58 -0
  24. package/dist/components/molecules/CheckboxGroup/CheckboxGroup.cjs +1 -1
  25. package/dist/components/molecules/CheckboxGroup/CheckboxGroup.d.ts +5 -3
  26. package/dist/components/molecules/CheckboxGroup/CheckboxGroup.js +61 -59
  27. package/dist/components/molecules/EmptyState/EmptyState.cjs +1 -1
  28. package/dist/components/molecules/EmptyState/EmptyState.d.ts +7 -1
  29. package/dist/components/molecules/EmptyState/EmptyState.js +18 -14
  30. package/dist/components/molecules/RadioGroup/RadioGroup.cjs +1 -1
  31. package/dist/components/molecules/RadioGroup/RadioGroup.d.ts +4 -3
  32. package/dist/components/molecules/RadioGroup/RadioGroup.js +48 -47
  33. package/dist/components/organisms/Sheet/Sheet.cjs +1 -1
  34. package/dist/components/organisms/Sheet/Sheet.d.ts +8 -5
  35. package/dist/components/organisms/Sheet/Sheet.js +122 -121
  36. package/dist/components/organisms/Sheet/sheet-title.cjs +1 -0
  37. package/dist/components/organisms/Sheet/sheet-title.d.ts +10 -0
  38. package/dist/components/organisms/Sheet/sheet-title.js +17 -0
  39. package/dist/index.d.ts +1 -0
  40. package/dist/internal/field-invalid.cjs +1 -0
  41. package/dist/internal/field-invalid.d.ts +37 -0
  42. package/dist/internal/field-invalid.js +13 -0
  43. package/dist/meta.json +3 -3
  44. package/dist/roster.cjs +1 -1
  45. package/dist/roster.css +1 -1
  46. package/dist/roster.js +55 -53
  47. package/package.json +1 -1
@@ -0,0 +1,22 @@
1
+ const a = ["base", "sm", "md", "lg", "xl"];
2
+ function n(t) {
3
+ const r = Math.ceil(t) - 1;
4
+ return `calc((100% + ${Number.isInteger(t) ? 0 : 1} * var(--rst-cv-gutter) - ${r} * var(--rst-cv-gap)) / ${t})`;
5
+ }
6
+ function o(t) {
7
+ const r = typeof t == "number" ? { base: t } : t, s = {};
8
+ let c;
9
+ for (const e of a) {
10
+ const v = r[e];
11
+ v !== void 0 && v > 0 && (c = v), c !== void 0 && (s[`--rst-cv-w-${e}`] = n(c));
12
+ }
13
+ return s;
14
+ }
15
+ const l = "var(--rst-cv-w)", w = "rst:[--rst-cv-w:var(--rst-cv-w-base)] rst:sm:[--rst-cv-w:var(--rst-cv-w-sm)] rst:md:[--rst-cv-w:var(--rst-cv-w-md)] rst:lg:[--rst-cv-w:var(--rst-cv-w-lg)] rst:xl:[--rst-cv-w:var(--rst-cv-w-xl)]";
16
+ export {
17
+ a as BREAKPOINTS,
18
+ w as FLUID_CLASSES,
19
+ l as FLUID_ITEM_WIDTH,
20
+ n as fluidItemWidth,
21
+ o as perViewVars
22
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=6,i=1;function a(t){return Math.max(0,t.scrollWidth-t.clientWidth)}function h(t){return a(t)>i}function S(t){return t.scrollLeft>i}function L(t){return t.scrollLeft<a(t)-i}function s(t,e){const n=t.items[e];if(!n)return 0;const r=t.align==="start"?n.start-t.paddingStart:(n.start+n.end)/2-(t.paddingStart+(t.clientWidth-t.paddingStart-t.paddingEnd)/2);return Math.min(Math.max(0,r),a(t))}function u(t){const e=t.scrollLeft-i,n=t.scrollLeft+t.clientWidth+i,r=[];return t.items.forEach((l,c)=>{l.start>=e&&l.end<=n&&r.push(c)}),r}function f(t){let e=0,n=1/0;return t.items.forEach((r,l)=>{const c=Math.abs(s(t,l)-t.scrollLeft);c<n&&(e=l,n=c)}),e}function m(t){const e=u(t);return e.length?e[0]:f(t)}function x(t,e){const n=t.items.length;if(!n)return 0;const r=u(t),l=r.length?r[0]:f(t),c=Math.max(1,r.length);let o=Math.min(n-1,Math.max(0,l+e*c));for(;o>0&&o<n-1&&Math.abs(s(t,o)-t.scrollLeft)<=i;)o+=e;return s(t,o)}exports.CAROUSEL_DRAG_THRESHOLD=d;exports.CAROUSEL_TOLERANCE=i;exports.canScrollNext=L;exports.canScrollPrev=S;exports.currentIndex=m;exports.fullyVisible=u;exports.maxScroll=a;exports.nearestIndex=f;exports.overflows=h;exports.pageTarget=x;exports.snapPosition=s;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Where a carousel's row is, and where it should go.
3
+ *
4
+ * Pure, and kept out of the component so paging and snapping can be tested
5
+ * with literal numbers. jsdom has no layout, so a test that read positions
6
+ * from the DOM would be testing zero; the stories measure the real thing.
7
+ *
8
+ * Every position is in the scroller's own coordinates, the space `scrollLeft`
9
+ * is measured in: an item's `start` is how far `scrollLeft` would have to be
10
+ * for the item's leading edge to sit at the scroller's leading edge.
11
+ */
12
+ export interface CarouselItemBox {
13
+ start: number;
14
+ end: number;
15
+ }
16
+ export interface CarouselGeometry {
17
+ items: readonly CarouselItemBox[];
18
+ scrollLeft: number;
19
+ clientWidth: number;
20
+ scrollWidth: number;
21
+ /** `scroll-padding-inline-start`: the gutter a snapped item lines up with. */
22
+ paddingStart: number;
23
+ /** `scroll-padding-inline-end`. */
24
+ paddingEnd: number;
25
+ align: "start" | "center";
26
+ }
27
+ /** Movement past this, in px, makes a mouse press a drag, and its click is dropped. */
28
+ export declare const CAROUSEL_DRAG_THRESHOLD = 6;
29
+ /** Sub-pixel layout leaves fractions; anything closer than this is "at". */
30
+ export declare const CAROUSEL_TOLERANCE = 1;
31
+ export declare function maxScroll(g: CarouselGeometry): number;
32
+ /** Whether the row is wider than its box at all. */
33
+ export declare function overflows(g: CarouselGeometry): boolean;
34
+ export declare function canScrollPrev(g: CarouselGeometry): boolean;
35
+ export declare function canScrollNext(g: CarouselGeometry): boolean;
36
+ /**
37
+ * The `scrollLeft` that snaps item `i` into place, clamped to what the row can
38
+ * reach. The last items of a row that can't align to the start land at the
39
+ * end, which is also where the browser's own snapping puts them.
40
+ */
41
+ export declare function snapPosition(g: CarouselGeometry, i: number): number;
42
+ /** Indices of the items wholly inside the box at the current scroll. */
43
+ export declare function fullyVisible(g: CarouselGeometry): number[];
44
+ /** The item whose snap position is nearest the current scroll. */
45
+ export declare function nearestIndex(g: CarouselGeometry): number;
46
+ /**
47
+ * The first item wholly in view, which is what the row reports as its index.
48
+ * An item wider than the box is never wholly in view, so then it is the item
49
+ * the row is snapped nearest to.
50
+ */
51
+ export declare function currentIndex(g: CarouselGeometry): number;
52
+ /**
53
+ * Where a previous or next arrow should take the row: a page, which is as many
54
+ * items as are wholly in view (at least one), landing on an item's snap point.
55
+ * Measured every time rather than a fixed pixel step, so it holds whatever the
56
+ * items' widths and however many are in view.
57
+ *
58
+ * Returns the target `scrollLeft`.
59
+ */
60
+ export declare function pageTarget(g: CarouselGeometry, direction: 1 | -1): number;
@@ -0,0 +1,58 @@
1
+ const E = 6, u = 1;
2
+ function a(t) {
3
+ return Math.max(0, t.scrollWidth - t.clientWidth);
4
+ }
5
+ function L(t) {
6
+ return a(t) > 1;
7
+ }
8
+ function h(t) {
9
+ return t.scrollLeft > 1;
10
+ }
11
+ function d(t) {
12
+ return t.scrollLeft < a(t) - 1;
13
+ }
14
+ function o(t, e) {
15
+ const n = t.items[e];
16
+ if (!n) return 0;
17
+ const r = t.align === "start" ? n.start - t.paddingStart : (n.start + n.end) / 2 - (t.paddingStart + (t.clientWidth - t.paddingStart - t.paddingEnd) / 2);
18
+ return Math.min(Math.max(0, r), a(t));
19
+ }
20
+ function l(t) {
21
+ const e = t.scrollLeft - 1, n = t.scrollLeft + t.clientWidth + 1, r = [];
22
+ return t.items.forEach((i, s) => {
23
+ i.start >= e && i.end <= n && r.push(s);
24
+ }), r;
25
+ }
26
+ function f(t) {
27
+ let e = 0, n = 1 / 0;
28
+ return t.items.forEach((r, i) => {
29
+ const s = Math.abs(o(t, i) - t.scrollLeft);
30
+ s < n && (e = i, n = s);
31
+ }), e;
32
+ }
33
+ function R(t) {
34
+ const e = l(t);
35
+ return e.length ? e[0] : f(t);
36
+ }
37
+ function A(t, e) {
38
+ const n = t.items.length;
39
+ if (!n) return 0;
40
+ const r = l(t), i = r.length ? r[0] : f(t), s = Math.max(1, r.length);
41
+ let c = Math.min(n - 1, Math.max(0, i + e * s));
42
+ for (; c > 0 && c < n - 1 && Math.abs(o(t, c) - t.scrollLeft) <= 1; )
43
+ c += e;
44
+ return o(t, c);
45
+ }
46
+ export {
47
+ E as CAROUSEL_DRAG_THRESHOLD,
48
+ u as CAROUSEL_TOLERANCE,
49
+ d as canScrollNext,
50
+ h as canScrollPrev,
51
+ R as currentIndex,
52
+ l as fullyVisible,
53
+ a as maxScroll,
54
+ f as nearestIndex,
55
+ L as overflows,
56
+ A as pageTarget,
57
+ o as snapPosition
58
+ };
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),A=require("react"),B=require("../../../node_modules/@headlessui/react/dist/components/description/description.cjs"),D=require("../../../node_modules/@headlessui/react/dist/components/field/field.cjs"),y=require("../../../node_modules/@headlessui/react/dist/components/fieldset/fieldset.cjs"),F=require("../../../node_modules/@headlessui/react/dist/components/label/label.cjs"),g=require("../../../node_modules/@headlessui/react/dist/components/legend/legend.cjs"),e=require("../../../lib/utils.cjs"),P=require("../../atoms/Checkbox/Checkbox.cjs"),R=require("../../atoms/Eyebrow/Eyebrow.cjs"),h=require("./checkbox-group-variants.cjs"),V=t=>t.length>0&&Array.isArray(t[0].options),Z={sm:"rst:text-xs",md:"rst:text-sm",lg:"rst:text-base"},_=({options:t,value:a,onChange:p,label:b,helperText:o,errorMessage:i,maxHeight:u,disabled:n=!1,variant:v,size:c="md",columns:j,colorScheme:k,className:N,optionsClassName:q,panelClassName:w,"aria-describedby":G,"aria-invalid":C,...E})=>{const l=!!i,d=u!==void 0,m=A.useId(),L=[G,o||i?m:void 0].filter(Boolean).join(" ")||void 0,I=(s,x)=>{p(x?[...a,s]:a.filter(S=>S!==s))},O=s=>r.jsxs(D.Field,{disabled:n||s.disabled,className:"rst:flex rst:items-start rst:gap-2",children:[r.jsx(P.Checkbox,{size:c??"md",colorScheme:k,checked:a.includes(s.value),onChange:x=>I(s.value,x),className:"rst:mt-0.5 rst:shrink-0"}),r.jsxs("div",{className:"rst:flex rst:min-w-0 rst:flex-col",children:[r.jsx(F.Label,{className:e.cn("rst:cursor-pointer rst:select-none rst:px-1 rst:py-0.5","rst:text-[var(--roster-control-text)]","rst:data-disabled:cursor-not-allowed rst:data-disabled:opacity-50",Z[c??"md"]),children:s.label}),s.description&&r.jsx(B.Description,{className:"rst:px-1 rst:text-xs rst:text-gray-500 rst:dark:text-gray-400 rst:data-disabled:opacity-50",children:s.description})]})]},s.value),f=s=>r.jsx("div",{className:e.cn(h.checkboxGroupOptionsVariants({columns:j,size:c})),children:s.map(O)});return r.jsxs(y.Fieldset,{disabled:n,className:e.cn("rst:font-ui rst:flex rst:flex-col rst:gap-1.5 rst:min-w-0",N),...E,"aria-invalid":l||C||void 0,"aria-describedby":L,children:[b&&r.jsx(g.Legend,{className:"rst:block rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)] rst:text-left rst:data-disabled:opacity-50",children:b}),r.jsx("div",{className:e.cn(h.checkboxGroupPanelVariants({variant:v,size:c,error:l}),d&&"rst:overflow-y-auto rst:custom-scrollbar rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:focus-visible:ring-offset-2 rst:ring-offset-background",w,q),style:d?{maxHeight:u}:void 0,tabIndex:d?0:void 0,children:V(t)?t.map(s=>r.jsxs(y.Fieldset,{className:"rst:flex rst:flex-col rst:gap-2",children:[r.jsx(g.Legend,{as:R.Eyebrow,weight:"semibold",tone:"default",className:"rst:border-b rst:border-gray-200 rst:pb-1 rst:dark:border-gray-800",children:s.category}),f(s.options)]},s.category)):f(t)}),(o||i)&&r.jsx("p",{id:m,className:e.cn("rst:text-xs rst:text-left",l?"rst:text-error-600 rst:dark:text-error-400 rst:font-medium":"rst:text-gray-500 rst:dark:text-gray-400",n&&"rst:opacity-50"),children:i||o})]})};exports.CheckboxGroup=_;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),B=require("react"),D=require("../../../node_modules/@headlessui/react/dist/components/description/description.cjs"),R=require("../../../node_modules/@headlessui/react/dist/components/field/field.cjs"),g=require("../../../node_modules/@headlessui/react/dist/components/fieldset/fieldset.cjs"),V=require("../../../node_modules/@headlessui/react/dist/components/label/label.cjs"),h=require("../../../node_modules/@headlessui/react/dist/components/legend/legend.cjs"),e=require("../../../lib/utils.cjs"),p=require("../../../internal/field-invalid.cjs"),Z=require("../../atoms/Checkbox/Checkbox.cjs"),_=require("../../atoms/Eyebrow/Eyebrow.cjs"),j=require("./checkbox-group-variants.cjs"),J=t=>t.length>0&&Array.isArray(t[0].options),K={sm:"rst:text-xs",md:"rst:text-sm",lg:"rst:text-base"},Q=({options:t,value:c,onChange:k,label:u,helperText:o,errorMessage:i,maxHeight:b,disabled:n=!1,variant:q,size:a="md",columns:N,colorScheme:w,className:I,optionsClassName:G,panelClassName:C,"aria-describedby":E,"aria-invalid":L,...m})=>{const l=!!i,f=p.isFieldInvalid(l,{...m,"aria-invalid":L}),F=p.withoutInvalidProps(m),d=b!==void 0,v=B.useId(),O=[E,o||i?v:void 0].filter(Boolean).join(" ")||void 0,P=(r,x)=>{k(x?[...c,r]:c.filter(A=>A!==r))},S=r=>s.jsxs(R.Field,{disabled:n||r.disabled,className:"rst:flex rst:items-start rst:gap-2",children:[s.jsx(Z.Checkbox,{size:a??"md",colorScheme:w,checked:c.includes(r.value),onChange:x=>P(r.value,x),"aria-invalid":f||void 0,className:"rst:mt-0.5 rst:shrink-0"}),s.jsxs("div",{className:"rst:flex rst:min-w-0 rst:flex-col",children:[s.jsx(V.Label,{className:e.cn("rst:cursor-pointer rst:select-none rst:px-1 rst:py-0.5","rst:text-[var(--roster-control-text)]","rst:data-disabled:cursor-not-allowed rst:data-disabled:opacity-50",K[a??"md"]),children:r.label}),r.description&&s.jsx(D.Description,{className:"rst:px-1 rst:text-xs rst:text-gray-500 rst:dark:text-gray-400 rst:data-disabled:opacity-50",children:r.description})]})]},r.value),y=r=>s.jsx("div",{className:e.cn(j.checkboxGroupOptionsVariants({columns:N,size:a})),children:r.map(S)});return s.jsxs(g.Fieldset,{disabled:n,className:e.cn("rst:font-ui rst:flex rst:flex-col rst:gap-1.5 rst:min-w-0",I),...F,"aria-invalid":f||void 0,"aria-describedby":O,children:[u&&s.jsx(h.Legend,{className:"rst:block rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)] rst:text-left rst:data-disabled:opacity-50",children:u}),s.jsx("div",{className:e.cn(j.checkboxGroupPanelVariants({variant:q,size:a,error:l}),d&&"rst:overflow-y-auto rst:custom-scrollbar rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:focus-visible:ring-offset-2 rst:ring-offset-background",C,G),style:d?{maxHeight:b}:void 0,tabIndex:d?0:void 0,children:J(t)?t.map(r=>s.jsxs(g.Fieldset,{className:"rst:flex rst:flex-col rst:gap-2",children:[s.jsx(h.Legend,{as:_.Eyebrow,weight:"semibold",tone:"default",className:"rst:border-b rst:border-gray-200 rst:pb-1 rst:dark:border-gray-800",children:r.category}),y(r.options)]},r.category)):y(t)}),(o||i)&&s.jsx("p",{id:v,className:e.cn("rst:text-xs rst:text-left",l?"rst:text-error-600 rst:dark:text-error-400 rst:font-medium":"rst:text-gray-500 rst:dark:text-gray-400",n&&"rst:opacity-50"),children:i||o})]})};exports.CheckboxGroup=Q;
@@ -30,13 +30,15 @@ export interface CheckboxGroupProps extends Omit<React.HTMLAttributes<HTMLFieldS
30
30
  helperText?: string;
31
31
  /**
32
32
  * The message for an invalid selection. Implies the error state, so a caller
33
- * cannot color the text red and forget to say why.
33
+ * can not color the text red and forget to say why.
34
34
  *
35
35
  * What it repaints depends on `variant`, and the difference is worth
36
36
  * knowing: `panel` gets an error border, `plain` has no boundary to repaint
37
37
  * and so the message *is* the whole error state. Narrower than `Input`'s or
38
- * `Select`'s, which both ring the control itself — a checkbox is not the
39
- * thing that is invalid here, the selection is.
38
+ * `Select`'s, which both ring the control itself: what is invalid here is
39
+ * the selection. Each checkbox is still announced as invalid, though, since
40
+ * a checkbox is what a screen reader focuses
41
+ * (`src/internal/field-invalid.ts`).
40
42
  */
41
43
  errorMessage?: string;
42
44
  /**
@@ -1,68 +1,70 @@
1
1
  "use client";
2
- import { jsxs as i, jsx as t } from "react/jsx-runtime";
3
- import O from "react";
2
+ import { jsxs as o, jsx as t } from "react/jsx-runtime";
3
+ import P from "react";
4
4
  import { Description as _ } from "../../../node_modules/@headlessui/react/dist/components/description/description.js";
5
- import { Field as F } from "../../../node_modules/@headlessui/react/dist/components/field/field.js";
6
- import { Fieldset as y } from "../../../node_modules/@headlessui/react/dist/components/fieldset/fieldset.js";
7
- import { Label as S } from "../../../node_modules/@headlessui/react/dist/components/label/label.js";
8
- import { Legend as h } from "../../../node_modules/@headlessui/react/dist/components/legend/legend.js";
5
+ import { Field as S } from "../../../node_modules/@headlessui/react/dist/components/field/field.js";
6
+ import { Fieldset as h } from "../../../node_modules/@headlessui/react/dist/components/fieldset/fieldset.js";
7
+ import { Label as Z } from "../../../node_modules/@headlessui/react/dist/components/label/label.js";
8
+ import { Legend as g } from "../../../node_modules/@headlessui/react/dist/components/legend/legend.js";
9
9
  import { cn as e } from "../../../lib/utils.js";
10
- import { Checkbox as Z } from "../../atoms/Checkbox/Checkbox.js";
11
- import { Eyebrow as P } from "../../atoms/Eyebrow/Eyebrow.js";
12
- import { checkboxGroupPanelVariants as R, checkboxGroupOptionsVariants as V } from "./checkbox-group-variants.js";
13
- const W = (s) => s.length > 0 && Array.isArray(s[0].options), q = {
10
+ import { isFieldInvalid as R, withoutInvalidProps as V } from "../../../internal/field-invalid.js";
11
+ import { Checkbox as W } from "../../atoms/Checkbox/Checkbox.js";
12
+ import { Eyebrow as q } from "../../atoms/Eyebrow/Eyebrow.js";
13
+ import { checkboxGroupPanelVariants as J, checkboxGroupOptionsVariants as K } from "./checkbox-group-variants.js";
14
+ const Q = (s) => s.length > 0 && Array.isArray(s[0].options), U = {
14
15
  sm: "rst:text-xs",
15
16
  md: "rst:text-sm",
16
17
  lg: "rst:text-base"
17
- }, tr = ({
18
+ }, or = ({
18
19
  options: s,
19
- value: c,
20
- onChange: v,
20
+ value: d,
21
+ onChange: k,
21
22
  label: x,
22
- helperText: d,
23
- errorMessage: a,
23
+ helperText: c,
24
+ errorMessage: i,
24
25
  maxHeight: b,
25
26
  disabled: l = !1,
26
- variant: g,
27
- size: o = "md",
28
- columns: k,
29
- colorScheme: N,
30
- className: w,
31
- optionsClassName: I,
32
- panelClassName: E,
33
- "aria-describedby": G,
34
- "aria-invalid": L,
35
- ...j
27
+ variant: N,
28
+ size: a = "md",
29
+ columns: w,
30
+ colorScheme: I,
31
+ className: E,
32
+ optionsClassName: G,
33
+ panelClassName: L,
34
+ "aria-describedby": j,
35
+ "aria-invalid": A,
36
+ ...p
36
37
  }) => {
37
- const n = !!a, m = b !== void 0, p = O.useId(), A = [G, d || a ? p : void 0].filter(Boolean).join(" ") || void 0, B = (r, f) => {
38
- v(
39
- f ? [...c, r] : c.filter((D) => D !== r)
38
+ const n = !!i, v = R(n, { ...p, "aria-invalid": A }), B = V(p), m = b !== void 0, u = P.useId(), C = [j, c || i ? u : void 0].filter(Boolean).join(" ") || void 0, D = (r, f) => {
39
+ k(
40
+ f ? [...d, r] : d.filter((O) => O !== r)
40
41
  );
41
- }, C = (r) => /* @__PURE__ */ i(
42
- F,
42
+ }, F = (r) => /* @__PURE__ */ o(
43
+ S,
43
44
  {
44
45
  disabled: l || r.disabled,
45
46
  className: "rst:flex rst:items-start rst:gap-2",
46
47
  children: [
47
48
  /* @__PURE__ */ t(
48
- Z,
49
+ W,
49
50
  {
50
- size: o ?? "md",
51
- colorScheme: N,
52
- checked: c.includes(r.value),
53
- onChange: (f) => B(r.value, f),
51
+ size: a ?? "md",
52
+ colorScheme: I,
53
+ checked: d.includes(r.value),
54
+ onChange: (f) => D(r.value, f),
55
+ "aria-invalid": v || void 0,
54
56
  className: "rst:mt-0.5 rst:shrink-0"
55
57
  }
56
58
  ),
57
- /* @__PURE__ */ i("div", { className: "rst:flex rst:min-w-0 rst:flex-col", children: [
59
+ /* @__PURE__ */ o("div", { className: "rst:flex rst:min-w-0 rst:flex-col", children: [
58
60
  /* @__PURE__ */ t(
59
- S,
61
+ Z,
60
62
  {
61
63
  className: e(
62
64
  "rst:cursor-pointer rst:select-none rst:px-1 rst:py-0.5",
63
65
  "rst:text-[var(--roster-control-text)]",
64
66
  "rst:data-disabled:cursor-not-allowed rst:data-disabled:opacity-50",
65
- q[o ?? "md"]
67
+ U[a ?? "md"]
66
68
  ),
67
69
  children: r.label
68
70
  }
@@ -72,33 +74,33 @@ const W = (s) => s.length > 0 && Array.isArray(s[0].options), q = {
72
74
  ]
73
75
  },
74
76
  r.value
75
- ), u = (r) => /* @__PURE__ */ t("div", { className: e(V({ columns: k, size: o })), children: r.map(C) });
76
- return /* @__PURE__ */ i(
77
- y,
77
+ ), y = (r) => /* @__PURE__ */ t("div", { className: e(K({ columns: w, size: a })), children: r.map(F) });
78
+ return /* @__PURE__ */ o(
79
+ h,
78
80
  {
79
81
  disabled: l,
80
82
  className: e(
81
83
  "rst:font-ui rst:flex rst:flex-col rst:gap-1.5 rst:min-w-0",
82
- w
84
+ E
83
85
  ),
84
- ...j,
85
- "aria-invalid": n || L || void 0,
86
- "aria-describedby": A,
86
+ ...B,
87
+ "aria-invalid": v || void 0,
88
+ "aria-describedby": C,
87
89
  children: [
88
- x && /* @__PURE__ */ t(h, { className: "rst:block rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)] rst:text-left rst:data-disabled:opacity-50", children: x }),
90
+ x && /* @__PURE__ */ t(g, { className: "rst:block rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)] rst:text-left rst:data-disabled:opacity-50", children: x }),
89
91
  /* @__PURE__ */ t(
90
92
  "div",
91
93
  {
92
94
  className: e(
93
- R({ variant: g, size: o, error: n }),
95
+ J({ variant: N, size: a, error: n }),
94
96
  m && "rst:overflow-y-auto rst:custom-scrollbar rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:focus-visible:ring-offset-2 rst:ring-offset-background",
95
97
  /* Deprecated name first, so the current one wins when both are set. */
96
- E,
97
- I
98
+ L,
99
+ G
98
100
  ),
99
101
  style: m ? { maxHeight: b } : void 0,
100
102
  tabIndex: m ? 0 : void 0,
101
- children: W(s) ? s.map((r) => (
103
+ children: Q(s) ? s.map((r) => (
102
104
  /* Nested fieldset per category, so the heading is the group's
103
105
  accessible name rather than decoration a screen reader walks
104
106
  straight past. Nesting is valid HTML, the inner
@@ -109,32 +111,32 @@ const W = (s) => s.length > 0 && Array.isArray(s[0].options), q = {
109
111
  `as={Eyebrow}` overrides Legend's own `as="div"` — it is
110
112
  spread after — so these render as <span>. The registration is
111
113
  what matters and it is unchanged. */
112
- /* @__PURE__ */ i(y, { className: "rst:flex rst:flex-col rst:gap-2", children: [
114
+ /* @__PURE__ */ o(h, { className: "rst:flex rst:flex-col rst:gap-2", children: [
113
115
  /* @__PURE__ */ t(
114
- h,
116
+ g,
115
117
  {
116
- as: P,
118
+ as: q,
117
119
  weight: "semibold",
118
120
  tone: "default",
119
121
  className: "rst:border-b rst:border-gray-200 rst:pb-1 rst:dark:border-gray-800",
120
122
  children: r.category
121
123
  }
122
124
  ),
123
- u(r.options)
125
+ y(r.options)
124
126
  ] }, r.category)
125
- )) : u(s)
127
+ )) : y(s)
126
128
  }
127
129
  ),
128
- (d || a) && /* @__PURE__ */ t(
130
+ (c || i) && /* @__PURE__ */ t(
129
131
  "p",
130
132
  {
131
- id: p,
133
+ id: u,
132
134
  className: e(
133
135
  "rst:text-xs rst:text-left",
134
136
  n ? "rst:text-error-600 rst:dark:text-error-400 rst:font-medium" : "rst:text-gray-500 rst:dark:text-gray-400",
135
137
  l && "rst:opacity-50"
136
138
  ),
137
- children: a || d
139
+ children: i || c
138
140
  }
139
141
  )
140
142
  ]
@@ -142,5 +144,5 @@ const W = (s) => s.length > 0 && Array.isArray(s[0].options), q = {
142
144
  );
143
145
  };
144
146
  export {
145
- tr as CheckboxGroup
147
+ or as CheckboxGroup
146
148
  };
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime");require("react");const c=require("../../../lib/utils.cjs"),n=require("./empty-state-variants.cjs"),d=({title:a,description:r,icon:s,action:e,variant:l,className:i,...m})=>t.jsxs("div",{className:c.cn(n.emptyStateVariants({variant:l}),i),...m,children:[s&&t.jsx("div",{className:"rst:mb-4 rst:flex rst:h-12 rst:w-12 rst:items-center rst:justify-center rst:rounded-full rst:bg-gray-100 rst:text-gray-400 rst:dark:bg-gray-800 rst:dark:text-gray-500",children:t.jsx("div",{className:"rst:h-6 rst:w-6 rst:[&>svg]:h-full rst:[&>svg]:w-full",children:s})}),t.jsx("h3",{className:"rst:text-lg rst:font-semibold rst:text-gray-900 rst:dark:text-gray-100",children:a}),r&&t.jsx("p",{className:"rst:mt-1 rst:max-w-sm rst:text-sm rst:text-gray-500 rst:dark:text-gray-400",children:r}),e&&t.jsx("div",{className:"rst:mt-6",children:e})]});exports.EmptyState=d;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime");require("react");const d=require("../../../lib/utils.cjs"),x=require("./empty-state-variants.cjs"),g=({title:a,description:s,icon:r,action:e,headingLevel:l=3,variant:i,className:n,...c})=>{const m=`h${l}`;return t.jsxs("div",{className:d.cn(x.emptyStateVariants({variant:i}),n),...c,children:[r&&t.jsx("div",{className:"rst:mb-4 rst:flex rst:h-12 rst:w-12 rst:items-center rst:justify-center rst:rounded-full rst:bg-gray-100 rst:text-gray-400 rst:dark:bg-gray-800 rst:dark:text-gray-500",children:t.jsx("div",{className:"rst:h-6 rst:w-6 rst:[&>svg]:h-full rst:[&>svg]:w-full",children:r})}),t.jsx(m,{className:"rst:text-lg rst:font-semibold rst:text-gray-900 rst:dark:text-gray-100",children:a}),s&&t.jsx("p",{className:"rst:mt-1 rst:max-w-sm rst:text-sm rst:text-gray-500 rst:dark:text-gray-400",children:s}),e&&t.jsx("div",{className:"rst:mt-6",children:e})]})};exports.EmptyState=g;
@@ -6,6 +6,12 @@ export interface EmptyStateProps extends React.HTMLAttributes<HTMLDivElement>, V
6
6
  description?: string;
7
7
  icon?: React.ReactNode;
8
8
  action?: React.ReactNode;
9
+ /**
10
+ * The title's heading level. `3` by default; set it to follow the heading
11
+ * the empty state sits under, so the page's outline doesn't skip a level.
12
+ * Only the element changes; its classes are the same at every level.
13
+ */
14
+ headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;
9
15
  }
10
- declare const EmptyState: ({ title, description, icon, action, variant, className, ...props }: EmptyStateProps) => import("react/jsx-runtime").JSX.Element;
16
+ declare const EmptyState: ({ title, description, icon, action, headingLevel, variant, className, ...props }: EmptyStateProps) => import("react/jsx-runtime").JSX.Element;
11
17
  export { EmptyState };
@@ -1,22 +1,26 @@
1
1
  "use client";
2
- import { jsxs as i, jsx as t } from "react/jsx-runtime";
2
+ import { jsxs as g, jsx as t } from "react/jsx-runtime";
3
3
  import "react";
4
- import { cn as c } from "../../../lib/utils.js";
5
- import { emptyStateVariants as g } from "./empty-state-variants.js";
6
- const f = ({
4
+ import { cn as n } from "../../../lib/utils.js";
5
+ import { emptyStateVariants as x } from "./empty-state-variants.js";
6
+ const p = ({
7
7
  title: a,
8
8
  description: r,
9
9
  icon: s,
10
10
  action: e,
11
- variant: m,
12
- className: l,
13
- ...d
14
- }) => /* @__PURE__ */ i("div", { className: c(g({ variant: m }), l), ...d, children: [
15
- s && /* @__PURE__ */ t("div", { className: "rst:mb-4 rst:flex rst:h-12 rst:w-12 rst:items-center rst:justify-center rst:rounded-full rst:bg-gray-100 rst:text-gray-400 rst:dark:bg-gray-800 rst:dark:text-gray-500", children: /* @__PURE__ */ t("div", { className: "rst:h-6 rst:w-6 rst:[&>svg]:h-full rst:[&>svg]:w-full", children: s }) }),
16
- /* @__PURE__ */ t("h3", { className: "rst:text-lg rst:font-semibold rst:text-gray-900 rst:dark:text-gray-100", children: a }),
17
- r && /* @__PURE__ */ t("p", { className: "rst:mt-1 rst:max-w-sm rst:text-sm rst:text-gray-500 rst:dark:text-gray-400", children: r }),
18
- e && /* @__PURE__ */ t("div", { className: "rst:mt-6", children: e })
19
- ] });
11
+ headingLevel: m = 3,
12
+ variant: l,
13
+ className: d,
14
+ ...i
15
+ }) => {
16
+ const c = `h${m}`;
17
+ return /* @__PURE__ */ g("div", { className: n(x({ variant: l }), d), ...i, children: [
18
+ s && /* @__PURE__ */ t("div", { className: "rst:mb-4 rst:flex rst:h-12 rst:w-12 rst:items-center rst:justify-center rst:rounded-full rst:bg-gray-100 rst:text-gray-400 rst:dark:bg-gray-800 rst:dark:text-gray-500", children: /* @__PURE__ */ t("div", { className: "rst:h-6 rst:w-6 rst:[&>svg]:h-full rst:[&>svg]:w-full", children: s }) }),
19
+ /* @__PURE__ */ t(c, { className: "rst:text-lg rst:font-semibold rst:text-gray-900 rst:dark:text-gray-100", children: a }),
20
+ r && /* @__PURE__ */ t("p", { className: "rst:mt-1 rst:max-w-sm rst:text-sm rst:text-gray-500 rst:dark:text-gray-400", children: r }),
21
+ e && /* @__PURE__ */ t("div", { className: "rst:mt-6", children: e })
22
+ ] });
23
+ };
20
24
  export {
21
- f as EmptyState
25
+ p as EmptyState
22
26
  };
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime");require("react");const u=require("../../../node_modules/@headlessui/react/dist/components/description/description.cjs"),w=require("../../../node_modules/@headlessui/react/dist/components/field/field.cjs"),m=require("../../../node_modules/@headlessui/react/dist/components/label/label.cjs"),p=require("../../../node_modules/@headlessui/react/dist/components/radio-group/radio-group.cjs"),r=require("../../../lib/utils.cjs"),c=require("./radio-group-variants.cjs"),L={sm:"rst:text-xs",md:"rst:text-sm",lg:"rst:text-base"},D=({options:f,value:v,onChange:y,label:n,helperText:d,errorMessage:l,disabled:e=!1,size:j="md",orientation:i="vertical",colorScheme:b,className:N,optionsClassName:h,optionClassName:q,radioClassName:g,labelClassName:G,optionLabelClassName:z,descriptionClassName:R,messageClassName:S,"aria-invalid":V,...k})=>{const x=!!l,a=j??"md";return t.jsxs(p.RadioGroup,{value:v,onChange:y,disabled:e,className:r.cn("rst:font-ui rst:flex rst:flex-col rst:gap-1.5 rst:min-w-0",N),...k,"aria-invalid":x||V||void 0,"aria-orientation":i,children:[n&&t.jsx(m.Label,{className:r.cn("rst:block rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)] rst:text-left",e&&"rst:opacity-50",G),children:n}),t.jsx("div",{className:r.cn(c.radioGroupOptionsVariants({size:a,orientation:i}),h),children:f.map(s=>t.jsxs(w.Field,{disabled:e||s.disabled,className:r.cn(c.radioOptionVariants({orientation:i,size:a}),q),children:[t.jsx(p.Radio,{value:s.value,className:({checked:o})=>r.cn(c.radioVariants({colorScheme:b,size:a,checked:o}),"rst:self-start",e||s.disabled?"rst:opacity-50 rst:cursor-not-allowed":"rst:cursor-pointer",g),children:({checked:o})=>t.jsx("span",{className:r.cn(c.radioDotVariants({size:a}),o?"rst:opacity-100":"rst:opacity-0")})}),t.jsxs("div",{className:r.cn("rst:flex rst:min-w-0 rst:flex-col",i==="vertical"&&"rst:flex-1"),children:[t.jsx(m.Label,{className:r.cn("rst:cursor-pointer rst:select-none","rst:text-[var(--roster-control-text)]","rst:data-disabled:cursor-not-allowed rst:data-disabled:opacity-50",L[a],z),children:s.label}),s.description&&t.jsx(u.Description,{className:r.cn("rst:text-xs rst:text-gray-500 rst:dark:text-gray-400 rst:data-disabled:opacity-50",R),children:s.description})]})]},s.value))}),(d||l)&&t.jsx(u.Description,{as:"p",className:r.cn("rst:text-xs rst:text-left",x?"rst:text-error-600 rst:dark:text-error-400 rst:font-medium":"rst:text-gray-500 rst:dark:text-gray-400",e&&"rst:opacity-50",S),children:l||d})]})};exports.RadioGroup=D;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime");require("react");const m=require("../../../node_modules/@headlessui/react/dist/components/description/description.cjs"),D=require("../../../node_modules/@headlessui/react/dist/components/field/field.cjs"),p=require("../../../node_modules/@headlessui/react/dist/components/label/label.cjs"),v=require("../../../node_modules/@headlessui/react/dist/components/radio-group/radio-group.cjs"),r=require("../../../lib/utils.cjs"),f=require("../../../internal/field-invalid.cjs"),c=require("./radio-group-variants.cjs"),E={sm:"rst:text-xs",md:"rst:text-sm",lg:"rst:text-base"},O=({options:y,value:j,onChange:b,label:n,helperText:d,errorMessage:l,disabled:e=!1,size:h="md",orientation:i="vertical",colorScheme:N,className:q,optionsClassName:g,optionClassName:G,radioClassName:w,labelClassName:z,optionLabelClassName:R,descriptionClassName:S,messageClassName:V,"aria-invalid":k,...x})=>{const u=!!l,I=f.isFieldInvalid(u,{...x,"aria-invalid":k}),L=f.withoutInvalidProps(x),a=h??"md";return t.jsxs(v.RadioGroup,{value:j,onChange:b,disabled:e,className:r.cn("rst:font-ui rst:flex rst:flex-col rst:gap-1.5 rst:min-w-0",q),...L,"aria-invalid":I||void 0,"aria-orientation":i,children:[n&&t.jsx(p.Label,{className:r.cn("rst:block rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)] rst:text-left",e&&"rst:opacity-50",z),children:n}),t.jsx("div",{className:r.cn(c.radioGroupOptionsVariants({size:a,orientation:i}),g),children:y.map(s=>t.jsxs(D.Field,{disabled:e||s.disabled,className:r.cn(c.radioOptionVariants({orientation:i,size:a}),G),children:[t.jsx(v.Radio,{value:s.value,className:({checked:o})=>r.cn(c.radioVariants({colorScheme:N,size:a,checked:o}),"rst:self-start",e||s.disabled?"rst:opacity-50 rst:cursor-not-allowed":"rst:cursor-pointer",w),children:({checked:o})=>t.jsx("span",{className:r.cn(c.radioDotVariants({size:a}),o?"rst:opacity-100":"rst:opacity-0")})}),t.jsxs("div",{className:r.cn("rst:flex rst:min-w-0 rst:flex-col",i==="vertical"&&"rst:flex-1"),children:[t.jsx(p.Label,{className:r.cn("rst:cursor-pointer rst:select-none","rst:text-[var(--roster-control-text)]","rst:data-disabled:cursor-not-allowed rst:data-disabled:opacity-50",E[a],R),children:s.label}),s.description&&t.jsx(m.Description,{className:r.cn("rst:text-xs rst:text-gray-500 rst:dark:text-gray-400 rst:data-disabled:opacity-50",S),children:s.description})]})]},s.value))}),(d||l)&&t.jsx(m.Description,{as:"p",className:r.cn("rst:text-xs rst:text-left",u?"rst:text-error-600 rst:dark:text-error-400 rst:font-medium":"rst:text-gray-500 rst:dark:text-gray-400",e&&"rst:opacity-50",V),children:l||d})]})};exports.RadioGroup=O;
@@ -45,9 +45,10 @@ export interface RadioGroupProps extends Omit<React.HTMLAttributes<HTMLDivElemen
45
45
  * `aria-describedby` is one of the props Headless UI controls on a
46
46
  * `RadioGroup`, and a controlled prop is spread last. Passing one is
47
47
  * therefore a no-op rather than an addition. `aria-invalid` is not one of
48
- * Headless UI's, so a caller's survives its spread — and is then outranked
49
- * by this component's own error state, which is a different thing from the
50
- * token-list merge `CheckboxGroup` does for `aria-describedby`.
48
+ * Headless UI's: a caller's is read by the rule every Roster field follows
49
+ * (`src/internal/field-invalid.ts`), so any value but "false" marks the
50
+ * group invalid, as `"true"`, and an error message marks it invalid whatever
51
+ * the caller passed.
51
52
  */
52
53
  errorMessage?: string;
53
54
  /** Disables every option, and dims the label and helper text with them. */