@blakesteve/roster 5.1.0 → 5.2.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.
Files changed (30) hide show
  1. package/README.md +57 -3
  2. package/dist/components/atoms/Input/Input.cjs +1 -1
  3. package/dist/components/atoms/Input/Input.js +46 -41
  4. package/dist/components/atoms/Spinner/Spinner.cjs +1 -1
  5. package/dist/components/atoms/Spinner/Spinner.d.ts +6 -1
  6. package/dist/components/atoms/Spinner/Spinner.js +9 -8
  7. package/dist/components/molecules/Carousel/Carousel.cjs +1 -0
  8. package/dist/components/molecules/Carousel/Carousel.d.ts +146 -0
  9. package/dist/components/molecules/Carousel/Carousel.js +363 -0
  10. package/dist/components/molecules/Carousel/carousel-layout.cjs +1 -0
  11. package/dist/components/molecules/Carousel/carousel-layout.d.ts +23 -0
  12. package/dist/components/molecules/Carousel/carousel-layout.js +22 -0
  13. package/dist/components/molecules/Carousel/carousel-math.cjs +1 -0
  14. package/dist/components/molecules/Carousel/carousel-math.d.ts +60 -0
  15. package/dist/components/molecules/Carousel/carousel-math.js +58 -0
  16. package/dist/components/molecules/EmptyState/EmptyState.cjs +1 -1
  17. package/dist/components/molecules/EmptyState/EmptyState.d.ts +7 -1
  18. package/dist/components/molecules/EmptyState/EmptyState.js +18 -14
  19. package/dist/components/organisms/Sheet/Sheet.cjs +1 -1
  20. package/dist/components/organisms/Sheet/Sheet.d.ts +8 -5
  21. package/dist/components/organisms/Sheet/Sheet.js +122 -121
  22. package/dist/components/organisms/Sheet/sheet-title.cjs +1 -0
  23. package/dist/components/organisms/Sheet/sheet-title.d.ts +10 -0
  24. package/dist/components/organisms/Sheet/sheet-title.js +17 -0
  25. package/dist/index.d.ts +1 -0
  26. package/dist/meta.json +3 -3
  27. package/dist/roster.cjs +1 -1
  28. package/dist/roster.css +1 -1
  29. package/dist/roster.js +55 -53
  30. package/package.json +1 -1
@@ -0,0 +1,363 @@
1
+ "use client";
2
+ import { jsxs as y, jsx as c, Fragment as $t } from "react/jsx-runtime";
3
+ import * as n from "react";
4
+ import { Button as Bt } from "../../atoms/Button/Button.js";
5
+ import { cn as w } from "../../../lib/utils.js";
6
+ import { prefersReducedMotion as Ht } from "../../../internal/motion.js";
7
+ import { currentIndex as jt, canScrollNext as zt, canScrollPrev as Ut, overflows as Vt, pageTarget as Wt, snapPosition as U, nearestIndex as qt, CAROUSEL_DRAG_THRESHOLD as Xt } from "./carousel-math.js";
8
+ import { perViewVars as Gt, FLUID_ITEM_WIDTH as Jt, FLUID_CLASSES as Kt } from "./carousel-layout.js";
9
+ const Qt = (a) => Math.min(3e3, 500 + a * 0.35), Yt = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]), [contenteditable]:not([contenteditable="false"])', V = (a) => typeof a == "number" ? `${a}px` : a;
10
+ function nt(a) {
11
+ const d = parseFloat(a);
12
+ return Number.isFinite(d) ? d : 0;
13
+ }
14
+ const Zt = "rst:hidden rst:[@media(any-hover:hover)]:inline-flex", te = "rst:hidden rst:[@media(any-hover:hover)]:flex";
15
+ function st({ direction: a }) {
16
+ return /* @__PURE__ */ c(
17
+ "svg",
18
+ {
19
+ "aria-hidden": "true",
20
+ focusable: "false",
21
+ viewBox: "0 0 20 20",
22
+ className: "rst:h-5 rst:w-5",
23
+ fill: "none",
24
+ stroke: "currentColor",
25
+ strokeWidth: "2",
26
+ strokeLinecap: "round",
27
+ strokeLinejoin: "round",
28
+ children: /* @__PURE__ */ c("path", { d: a === "prev" ? "M12.5 4.5 7 10l5.5 5.5" : "M7.5 4.5 13 10l-5.5 5.5" })
29
+ }
30
+ );
31
+ }
32
+ const ot = {
33
+ overflowing: null,
34
+ canScrollPrev: !1,
35
+ canScrollNext: !1,
36
+ index: 0
37
+ }, ce = n.forwardRef(function({
38
+ "aria-label": d,
39
+ "aria-labelledby": N,
40
+ children: W,
41
+ itemWidth: I,
42
+ perView: R,
43
+ gap: q = 12,
44
+ gutter: X = 16,
45
+ bleed: lt = !1,
46
+ snap: L = "start",
47
+ snapStrictness: ct = "mandatory",
48
+ oneAtATime: at = !1,
49
+ arrows: P = "hover",
50
+ arrowPlacement: M = "controls",
51
+ renderArrows: T,
52
+ prevLabel: it,
53
+ nextLabel: ut,
54
+ prevIcon: dt,
55
+ nextIcon: ft,
56
+ arrowButtonProps: gt,
57
+ fade: vt = !1,
58
+ scrollbar: pt = !1,
59
+ showPosition: G = !1,
60
+ onIndexChange: J,
61
+ onScrollStateChange: K,
62
+ itemClassName: mt,
63
+ listClassName: bt,
64
+ className: xt,
65
+ style: ht,
66
+ ...St
67
+ }, yt) {
68
+ const f = n.useRef(null), Q = `${n.useId()}-list`, Y = n.Children.toArray(W), E = Y.length, [o, wt] = n.useState(ot), Z = n.useRef(ot), [Nt, It] = n.useState(""), [Tt, Et] = n.useState(!1), D = n.useRef({ onIndexChange: J, onScrollStateChange: K });
69
+ n.useEffect(() => {
70
+ D.current = { onIndexChange: J, onScrollStateChange: K };
71
+ });
72
+ const i = n.useCallback(() => {
73
+ const t = f.current;
74
+ if (!t) return null;
75
+ const e = t.getBoundingClientRect(), r = getComputedStyle(t), s = e.left + t.clientLeft - t.scrollLeft;
76
+ return {
77
+ items: Array.from(t.children).map((u) => {
78
+ const p = u.getBoundingClientRect();
79
+ return { start: p.left - s, end: p.right - s };
80
+ }),
81
+ scrollLeft: t.scrollLeft,
82
+ clientWidth: t.clientWidth,
83
+ scrollWidth: t.scrollWidth,
84
+ paddingStart: nt(r.scrollPaddingInlineStart || r.scrollPaddingLeft),
85
+ paddingEnd: nt(r.scrollPaddingInlineEnd || r.scrollPaddingRight),
86
+ align: L
87
+ };
88
+ }, [L]), m = n.useCallback(() => {
89
+ const t = i();
90
+ if (!t) return;
91
+ const e = {
92
+ overflowing: Vt(t),
93
+ canScrollPrev: Ut(t),
94
+ canScrollNext: zt(t),
95
+ index: t.items.length ? jt(t) : 0
96
+ }, r = Z.current;
97
+ r.overflowing === e.overflowing && r.canScrollPrev === e.canScrollPrev && r.canScrollNext === e.canScrollNext && r.index === e.index || (Z.current = e, wt(e), r.index !== e.index && D.current.onIndexChange?.(e.index), (r.canScrollPrev !== e.canScrollPrev || r.canScrollNext !== e.canScrollNext) && D.current.onScrollStateChange?.({
98
+ canScrollPrev: e.canScrollPrev,
99
+ canScrollNext: e.canScrollNext
100
+ }));
101
+ }, [i]), Ct = JSON.stringify([q, X, I, R]);
102
+ n.useLayoutEffect(() => {
103
+ const t = f.current;
104
+ if (!t) return;
105
+ m();
106
+ let e = 0;
107
+ const r = () => {
108
+ e || (e = requestAnimationFrame(() => {
109
+ e = 0, m();
110
+ }));
111
+ };
112
+ t.addEventListener("scroll", r, { passive: !0 });
113
+ const s = typeof ResizeObserver > "u" ? null : new ResizeObserver(() => m()), l = () => {
114
+ s?.observe(t), Array.from(t.children).forEach((p) => s?.observe(p));
115
+ };
116
+ l();
117
+ const u = typeof MutationObserver > "u" ? null : new MutationObserver(() => {
118
+ l(), m();
119
+ });
120
+ return u?.observe(t, { childList: !0 }), () => {
121
+ t.removeEventListener("scroll", r), s?.disconnect(), u?.disconnect(), e && cancelAnimationFrame(e);
122
+ };
123
+ }, [m, E, Ct]), n.useLayoutEffect(() => {
124
+ const t = f.current;
125
+ if (t && (Et(!t.querySelector(Yt)), N)) {
126
+ const e = N.split(/\s+/).map((r) => document.getElementById(r)?.textContent?.trim() ?? "").filter(Boolean).join(" ");
127
+ It(e);
128
+ }
129
+ }, [W, N]);
130
+ const b = n.useRef(null), g = n.useCallback(() => {
131
+ const t = f.current, e = b.current;
132
+ e && (b.current = null, window.clearTimeout(e.timer), t?.removeEventListener("scrollend", e.done), t && (t.style.scrollSnapType = "", delete t.dataset.settling));
133
+ }, []), v = n.useCallback(
134
+ (t, e) => {
135
+ const r = f.current;
136
+ if (!r) return;
137
+ if (g(), e !== "smooth" || Ht() || Math.abs(r.scrollLeft - t) < 1) {
138
+ r.style.scrollSnapType = "none", r.scrollTo({ left: t, behavior: "instant" }), r.style.scrollSnapType = "";
139
+ return;
140
+ }
141
+ r.style.scrollSnapType = "none", r.dataset.settling = "";
142
+ const l = () => g();
143
+ b.current = {
144
+ timer: window.setTimeout(l, Qt(Math.abs(r.scrollLeft - t))),
145
+ done: l,
146
+ target: t
147
+ }, r.addEventListener("scrollend", l, { once: !0 }), r.scrollTo({ left: t, behavior: "smooth" });
148
+ },
149
+ [g]
150
+ ), C = n.useCallback(
151
+ (t) => {
152
+ const e = i();
153
+ if (!e) return;
154
+ const r = b.current ? { ...e, scrollLeft: b.current.target } : e;
155
+ v(Wt(r, t), "smooth");
156
+ },
157
+ [i, v]
158
+ );
159
+ n.useImperativeHandle(
160
+ yt,
161
+ () => ({
162
+ scrollToIndex: (t, e) => {
163
+ const r = i();
164
+ if (!r || !r.items.length) return;
165
+ const s = Math.min(Math.max(0, Math.round(t)), r.items.length - 1);
166
+ v(U(r, s), e?.behavior ?? "smooth");
167
+ },
168
+ scrollPrev: () => C(-1),
169
+ scrollNext: () => C(1)
170
+ }),
171
+ [i, C, v]
172
+ ), n.useEffect(() => g, [g]);
173
+ const O = n.useRef(null), A = n.useRef(null), F = n.useRef(null);
174
+ n.useLayoutEffect(() => {
175
+ const t = F.current;
176
+ if (!t) return;
177
+ const e = t === "prev" ? O.current : A.current, r = t === "prev" ? A.current : O.current, s = t === "prev" ? !o.canScrollPrev : !o.canScrollNext, l = document.activeElement;
178
+ s && (l !== e && l !== document.body && l !== null || r && !r.disabled && r.focus());
179
+ }, [o.canScrollPrev, o.canScrollNext]);
180
+ const x = n.useRef(null), h = n.useRef(!1), kt = (t) => {
181
+ t.pointerType !== "mouse" || t.button !== 0 || o.overflowing && (g(), h.current = !1, x.current = {
182
+ pointerId: t.pointerId,
183
+ x0: t.clientX,
184
+ scroll0: t.currentTarget.scrollLeft,
185
+ dragging: !1
186
+ });
187
+ }, Rt = (t) => {
188
+ const e = x.current;
189
+ if (!e || t.pointerId !== e.pointerId) return;
190
+ const r = t.currentTarget, s = t.clientX - e.x0;
191
+ if (!e.dragging) {
192
+ if (Math.abs(s) <= Xt) return;
193
+ e.dragging = !0, r.dataset.dragging = "", r.style.scrollSnapType = "none", window.getSelection?.()?.removeAllRanges();
194
+ try {
195
+ r.setPointerCapture(t.pointerId);
196
+ } catch {
197
+ }
198
+ }
199
+ r.scrollLeft = e.scroll0 - s;
200
+ }, _ = (t) => {
201
+ const e = x.current;
202
+ if (!e || t.pointerId !== e.pointerId || (x.current = null, !e.dragging)) return;
203
+ const r = t.currentTarget;
204
+ delete r.dataset.dragging, h.current = t.type === "pointerup", window.setTimeout(() => {
205
+ h.current = !1;
206
+ }, 0);
207
+ const s = i();
208
+ s ? v(U(s, qt(s)), "smooth") : r.style.scrollSnapType = "";
209
+ }, Lt = (t) => {
210
+ !h.current || t.detail === 0 || (h.current = !1, t.preventDefault(), t.stopPropagation());
211
+ }, Pt = (t) => {
212
+ o.overflowing && t.preventDefault();
213
+ }, Mt = (t) => {
214
+ const e = t.currentTarget, r = t.target;
215
+ if (r === e || x.current?.dragging) return;
216
+ let s = !1;
217
+ try {
218
+ s = r.matches(":focus-visible");
219
+ } catch {
220
+ s = !1;
221
+ }
222
+ if (!s) return;
223
+ const l = r.closest("[data-carousel-item]");
224
+ if (!l || l.parentElement !== e) return;
225
+ const u = i();
226
+ if (!u) return;
227
+ const p = Array.prototype.indexOf.call(e.children, l);
228
+ v(U(u, p), "instant");
229
+ }, [Dt, Ot] = n.useState(0);
230
+ n.useEffect(() => {
231
+ const t = window.setTimeout(() => Ot(o.index), 150);
232
+ return () => window.clearTimeout(t);
233
+ }, [o.index]);
234
+ const tt = d ?? Nt, et = (t) => tt ? `${t} ${tt}` : t, $ = P !== "none" && o.overflowing !== !1, At = P === "hover" ? Zt : "rst:inline-flex", rt = (t) => {
235
+ const e = t === "prev", { className: r, ...s } = gt ?? {};
236
+ return /* @__PURE__ */ c(
237
+ Bt,
238
+ {
239
+ type: "button",
240
+ variant: "outline",
241
+ colorScheme: "neutral",
242
+ size: "icon",
243
+ ...s,
244
+ "aria-label": e ? it ?? et("Previous") : ut ?? et("Next"),
245
+ "aria-controls": Q,
246
+ disabled: e ? !o.canScrollPrev : !o.canScrollNext,
247
+ onClick: () => C(e ? -1 : 1),
248
+ ref: e ? O : A,
249
+ onFocus: () => {
250
+ F.current = t;
251
+ },
252
+ onBlur: (l) => {
253
+ l.relatedTarget && (F.current = null);
254
+ },
255
+ "data-carousel-arrow": t,
256
+ className: w(
257
+ /* 44px, the target size, whatever the Button's own icon size is. */
258
+ "rst:size-11 rst:shrink-0 rst:rounded-full",
259
+ /* Over the row, a disabled arrow would sit on top of the first or
260
+ last item for nothing, so it hides. Hidden is also out of the tab
261
+ order and the accessibility tree, as disabled already was. */
262
+ M === "overlay" && !T && "rst:bg-[var(--roster-popover-bg)] rst:elevation-raised rst:hover:bg-[var(--roster-popover-bg)] rst:disabled:invisible",
263
+ At,
264
+ r
265
+ ),
266
+ children: e ? dt ?? /* @__PURE__ */ c(st, { direction: "prev" }) : ft ?? /* @__PURE__ */ c(st, { direction: "next" })
267
+ }
268
+ );
269
+ }, k = $ ? rt("prev") : null, B = $ ? rt("next") : null, S = G && E ? (
270
+ /* `font-ui` here and not on the root: the readout is the only text the
271
+ carousel owns. The items are the host's content, and not Roster's to
272
+ restyle. */
273
+ /* @__PURE__ */ y("p", { "aria-live": "polite", className: "rst:font-ui rst:m-0 rst:text-sm rst:tabular-nums rst:opacity-75", "data-carousel-position": "", children: [
274
+ Dt + 1,
275
+ " of ",
276
+ E
277
+ ] })
278
+ ) : null;
279
+ let H = null;
280
+ T ? H = T({ prev: k, next: B, position: S }) : M === "controls" && (k || S) && (H = /* @__PURE__ */ y(
281
+ "div",
282
+ {
283
+ className: w(
284
+ "rst:mb-2 rst:items-center rst:justify-end rst:gap-2",
285
+ /* A line with only arrows in it takes no room where they can't show. */
286
+ !S && P === "hover" ? te : "rst:flex"
287
+ ),
288
+ "data-carousel-controls": "",
289
+ children: [
290
+ S && /* @__PURE__ */ c("div", { className: "rst:mr-auto", children: S }),
291
+ k,
292
+ B
293
+ ]
294
+ }
295
+ ));
296
+ const j = vt && o.overflowing && (o.canScrollPrev || o.canScrollNext) ? `linear-gradient(to right, ${o.canScrollPrev ? "transparent, black 48px" : "black"}, ${o.canScrollNext ? "black calc(100% - 48px), transparent" : "black"})` : void 0, z = I === void 0 && R !== void 0, Ft = {
297
+ "--rst-cv-gap": V(q),
298
+ "--rst-cv-gutter": V(X),
299
+ ...z ? Gt(R) : {},
300
+ ...j ? { maskImage: j, WebkitMaskImage: j } : {}
301
+ }, _t = I !== void 0 ? { width: V(I) } : z ? { width: Jt } : void 0;
302
+ return /* @__PURE__ */ y("div", { className: w("rst:min-w-0", xt), style: ht, ...St, children: [
303
+ H,
304
+ /* @__PURE__ */ y("div", { className: "rst:relative", children: [
305
+ /* @__PURE__ */ c(
306
+ "ul",
307
+ {
308
+ ref: f,
309
+ id: Q,
310
+ role: "list",
311
+ "aria-label": d,
312
+ "aria-labelledby": d ? void 0 : N,
313
+ tabIndex: Tt && o.overflowing ? 0 : void 0,
314
+ "data-overflowing": o.overflowing ? "" : void 0,
315
+ onPointerDown: kt,
316
+ onPointerMove: Rt,
317
+ onPointerUp: _,
318
+ onPointerCancel: _,
319
+ onLostPointerCapture: _,
320
+ onClickCapture: Lt,
321
+ onDragStart: Pt,
322
+ onFocus: Mt,
323
+ style: Ft,
324
+ className: w(
325
+ "rst:m-0 rst:flex rst:list-none rst:overflow-x-auto rst:overflow-y-hidden",
326
+ "rst:gap-(--rst-cv-gap) rst:px-(--rst-cv-gutter) rst:py-1 rst:scroll-px-(--rst-cv-gutter)",
327
+ "rst:overscroll-x-contain",
328
+ ct === "mandatory" ? "rst:snap-x rst:snap-mandatory" : "rst:snap-x rst:snap-proximity",
329
+ lt && "rst:-mx-(--rst-cv-gutter)",
330
+ !pt && "rst:[scrollbar-width:none] rst:[&::-webkit-scrollbar]:hidden",
331
+ z && Kt,
332
+ "rst:data-overflowing:cursor-grab rst:data-dragging:cursor-grabbing rst:data-dragging:select-none",
333
+ "rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:focus-visible:ring-inset",
334
+ bt
335
+ ),
336
+ children: Y.map((t, e) => /* @__PURE__ */ c(
337
+ "li",
338
+ {
339
+ "data-carousel-item": "",
340
+ "aria-label": G ? `${e + 1} of ${E}` : void 0,
341
+ style: _t,
342
+ className: w(
343
+ "rst:shrink-0",
344
+ L === "start" ? "rst:snap-start" : "rst:snap-center",
345
+ at && "rst:snap-always",
346
+ mt
347
+ ),
348
+ children: t
349
+ },
350
+ n.isValidElement(t) && t.key != null ? t.key : e
351
+ ))
352
+ }
353
+ ),
354
+ !T && M === "overlay" && $ && /* @__PURE__ */ y($t, { children: [
355
+ /* @__PURE__ */ c("div", { className: "rst:pointer-events-none rst:absolute rst:inset-y-0 rst:start-1 rst:flex rst:items-center", children: /* @__PURE__ */ c("div", { className: "rst:pointer-events-auto", children: k }) }),
356
+ /* @__PURE__ */ c("div", { className: "rst:pointer-events-none rst:absolute rst:inset-y-0 rst:end-1 rst:flex rst:items-center", children: /* @__PURE__ */ c("div", { className: "rst:pointer-events-auto", children: B }) })
357
+ ] })
358
+ ] })
359
+ ] });
360
+ });
361
+ export {
362
+ ce as Carousel
363
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=["base","sm","md","lg","xl"];function o(t){const r=Math.ceil(t)-1;return`calc((100% + ${Number.isInteger(t)?0:1} * var(--rst-cv-gutter) - ${r} * var(--rst-cv-gap)) / ${t})`}function n(t){const r=typeof t=="number"?{base:t}:t,s={};let c;for(const v of a){const e=r[v];e!==void 0&&e>0&&(c=e),c!==void 0&&(s[`--rst-cv-w-${v}`]=o(c))}return s}const i="var(--rst-cv-w)",l="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)]";exports.BREAKPOINTS=a;exports.FLUID_CLASSES=l;exports.FLUID_ITEM_WIDTH=i;exports.fluidItemWidth=o;exports.perViewVars=n;
@@ -0,0 +1,23 @@
1
+ import { CarouselPerView } from './Carousel';
2
+ /**
3
+ * Fluid mode's sizing. The items-per-view table becomes one item width per
4
+ * breakpoint, set as custom properties on the list, and five short classes
5
+ * pick the one for the current width. The server render is already the right
6
+ * size, and nothing measures before it paints.
7
+ *
8
+ * Every breakpoint is filled in, carrying the one below it up, so the CSS
9
+ * needs no fallback chain, and a row nested in another fluid row never
10
+ * inherits the outer row's widths. Kept small on purpose: Roster's stylesheet
11
+ * ships to every consumer, carousel or not.
12
+ */
13
+ export declare const BREAKPOINTS: readonly ["base", "sm", "md", "lg", "xl"];
14
+ /**
15
+ * One item's width for `n` items per view. A fraction is the peek, and the
16
+ * peek runs into the trailing gutter, out to the edge. A whole number of items
17
+ * fits between the gutters instead, so a one-per-view gallery sits centered.
18
+ * `100%` is the list's content box, resolved where the width is used.
19
+ */
20
+ export declare function fluidItemWidth(n: number): string;
21
+ export declare function perViewVars(perView: number | CarouselPerView): Record<string, string>;
22
+ export declare const FLUID_ITEM_WIDTH = "var(--rst-cv-w)";
23
+ export declare const FLUID_CLASSES = "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)]";
@@ -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 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
  };