@blakesteve/roster 5.16.0 → 5.18.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 (33) hide show
  1. package/README.md +227 -2
  2. package/dist/components/molecules/RadioTileGroup/RadioTileGroup.cjs +1 -0
  3. package/dist/components/molecules/RadioTileGroup/RadioTileGroup.d.ts +101 -0
  4. package/dist/components/molecules/RadioTileGroup/RadioTileGroup.js +142 -0
  5. package/dist/components/molecules/RadioTileGroup/radio-tile-group-variants.cjs +1 -0
  6. package/dist/components/molecules/RadioTileGroup/radio-tile-group-variants.d.ts +49 -0
  7. package/dist/components/molecules/RadioTileGroup/radio-tile-group-variants.js +34 -0
  8. package/dist/components/molecules/StepProgress/StepProgress.cjs +1 -1
  9. package/dist/components/molecules/StepProgress/StepProgress.js +29 -42
  10. package/dist/components/molecules/Timeline/Timeline.cjs +1 -0
  11. package/dist/components/molecules/Timeline/Timeline.d.ts +86 -0
  12. package/dist/components/molecules/Timeline/Timeline.js +217 -0
  13. package/dist/components/organisms/Dialog/Dialog.cjs +1 -1
  14. package/dist/components/organisms/Dialog/Dialog.d.ts +58 -6
  15. package/dist/components/organisms/Dialog/Dialog.js +82 -59
  16. package/dist/components/organisms/Sheet/Sheet.cjs +1 -1
  17. package/dist/components/organisms/Sheet/Sheet.d.ts +2 -1
  18. package/dist/components/organisms/Sheet/Sheet.js +90 -87
  19. package/dist/index.d.ts +3 -0
  20. package/dist/internal/leave-watchdog.cjs +1 -0
  21. package/dist/internal/leave-watchdog.d.ts +62 -0
  22. package/dist/internal/leave-watchdog.js +64 -0
  23. package/dist/internal/step-check.cjs +1 -0
  24. package/dist/internal/step-check.d.ts +2 -0
  25. package/dist/internal/step-check.js +6 -0
  26. package/dist/internal/step-marker.cjs +1 -0
  27. package/dist/internal/step-marker.d.ts +10 -0
  28. package/dist/internal/step-marker.js +12 -0
  29. package/dist/meta.json +3 -3
  30. package/dist/roster.cjs +1 -1
  31. package/dist/roster.css +1 -1
  32. package/dist/roster.js +155 -147
  33. package/package.json +1 -1
@@ -1,39 +1,40 @@
1
1
  "use client";
2
- import { jsxs as l, Fragment as H, jsx as n } from "react/jsx-runtime";
2
+ import { jsxs as l, Fragment as Z, jsx as n } from "react/jsx-runtime";
3
3
  import * as s from "react";
4
- import { Description as J } from "../../../node_modules/@headlessui/react/dist/components/description/description.js";
5
- import { Dialog as Z, DialogBackdrop as W, DialogPanel as O, DialogTitle as tt } from "../../../node_modules/@headlessui/react/dist/components/dialog/dialog.js";
6
- import { TransitionChild as et } from "../../../node_modules/@headlessui/react/dist/components/transition/transition.js";
4
+ import { Description as O } from "../../../node_modules/@headlessui/react/dist/components/description/description.js";
5
+ import { Dialog as tt, DialogBackdrop as et, DialogPanel as rt, DialogTitle as st } from "../../../node_modules/@headlessui/react/dist/components/dialog/dialog.js";
6
+ import { TransitionChild as nt } from "../../../node_modules/@headlessui/react/dist/components/transition/transition.js";
7
7
  import { cn as d } from "../../../lib/utils.js";
8
- import { withLabels as rt } from "../../../lib/labels.js";
9
- import { useDarkScope as st } from "../../../internal/popup.js";
10
- import { useReducedMotion as nt } from "../../../internal/motion.js";
11
- import { lockPage as ot } from "../../../internal/page-inert.js";
12
- import { sheetDragOutcome as at, sheetReleaseVelocity as it, exceedsSheetTapSlop as ct } from "./sheet-drag.js";
13
- import { titleSignature as ut } from "./sheet-title.js";
14
- import { useKeyFocus as lt } from "../../../internal/key-focus.js";
15
- const dt = { close: "Close" }, ft = "rst:transition-transform rst:duration-(--roster-sheet-enter-duration) rst:ease-(--roster-sheet-enter-easing) rst:data-leave:duration-(--roster-sheet-leave-duration) rst:data-leave:ease-(--roster-sheet-leave-easing) rst:data-closed:translate-y-full", pt = "rst:transition-opacity rst:duration-(--roster-sheet-fade-duration) rst:ease-out rst:data-closed:opacity-0", mt = "rst:transition-opacity rst:duration-(--roster-sheet-enter-duration) rst:ease-out rst:data-leave:duration-(--roster-sheet-leave-duration) rst:data-closed:opacity-0", ht = "rst:transition-opacity rst:duration-(--roster-sheet-fade-duration) rst:ease-out rst:data-closed:opacity-0", gt = [
8
+ import { withLabels as ot } from "../../../lib/labels.js";
9
+ import { useDarkScope as at } from "../../../internal/popup.js";
10
+ import { useReducedMotion as it } from "../../../internal/motion.js";
11
+ import { lockPage as ct } from "../../../internal/page-inert.js";
12
+ import { useLeaveWatchdog as ut } from "../../../internal/leave-watchdog.js";
13
+ import { sheetDragOutcome as lt, sheetReleaseVelocity as dt, exceedsSheetTapSlop as ft } from "./sheet-drag.js";
14
+ import { titleSignature as pt } from "./sheet-title.js";
15
+ import { useKeyFocus as mt } from "../../../internal/key-focus.js";
16
+ const ht = { close: "Close" }, gt = "rst:transition-transform rst:duration-(--roster-sheet-enter-duration) rst:ease-(--roster-sheet-enter-easing) rst:data-leave:duration-(--roster-sheet-leave-duration) rst:data-leave:ease-(--roster-sheet-leave-easing) rst:data-closed:translate-y-full", yt = "rst:transition-opacity rst:duration-(--roster-sheet-fade-duration) rst:ease-out rst:data-closed:opacity-0", bt = "rst:transition-opacity rst:duration-(--roster-sheet-enter-duration) rst:ease-out rst:data-leave:duration-(--roster-sheet-leave-duration) rst:data-closed:opacity-0", vt = "rst:transition-opacity rst:duration-(--roster-sheet-fade-duration) rst:ease-out rst:data-closed:opacity-0", Y = { slide: 200, fade: 150 }, xt = [
16
17
  "input:not([type=checkbox]):not([type=radio]):not([type=button]):not([type=submit]):not([type=reset]):not([type=range]):not([type=color]):not([type=file]):not([type=image])",
17
18
  "textarea",
18
19
  "select",
19
20
  "[contenteditable]:not([contenteditable=false])"
20
21
  ].join(",");
21
- function yt(r) {
22
+ function Et(r) {
22
23
  return r ? "current" in r ? r.current : r : null;
23
24
  }
24
- function bt({ target: r }) {
25
+ function Rt({ target: r }) {
25
26
  const u = s.useRef(r), f = s.useRef(!1);
26
27
  return s.useEffect(() => {
27
28
  u.current = r;
28
29
  }), s.useEffect(() => (f.current = !1, () => {
29
30
  f.current = !0, queueMicrotask(() => {
30
31
  if (!f.current) return;
31
- const p = yt(u.current);
32
+ const p = Et(u.current);
32
33
  p?.isConnected && p.focus();
33
34
  });
34
35
  }), []), null;
35
36
  }
36
- function vt() {
37
+ function kt() {
37
38
  return /* @__PURE__ */ n(
38
39
  "svg",
39
40
  {
@@ -49,74 +50,74 @@ function vt() {
49
50
  }
50
51
  );
51
52
  }
52
- const Mt = ({
53
+ const Bt = ({
53
54
  isOpen: r,
54
55
  onClose: u,
55
56
  onAfterClose: f,
56
57
  title: p,
57
- hideTitle: z = !1,
58
- description: C,
59
- actions: N,
58
+ hideTitle: _ = !1,
59
+ description: N,
60
+ actions: D,
60
61
  maxWidth: v = 560,
61
62
  initialFocus: x,
62
- returnFocus: B,
63
+ returnFocus: T,
63
64
  busy: m = !1,
64
65
  dragToDismiss: E = !0,
65
66
  contentKey: h,
66
- labels: Y,
67
- className: T,
68
- children: _
67
+ labels: q,
68
+ className: V,
69
+ children: $
69
70
  }) => {
70
- lt();
71
- const q = rt(dt, Y), { ref: R, inDarkScope: $ } = st(), D = nt();
71
+ mt();
72
+ const K = ot(ht, q), { ref: R, inDarkScope: U } = at(), k = it(), I = s.useRef(null), i = s.useRef(null), S = ut(I, i, r, k ? Y.fade : Y.slide, f);
72
73
  s.useLayoutEffect(() => {
73
74
  if (r)
74
- return ot(R.current);
75
+ return ct(R.current);
75
76
  }, [r, R]);
76
- const i = s.useRef(null), I = s.useRef(null), w = s.useRef(null), k = s.useRef(null), L = s.useRef(null), S = s.useId(), g = ut(p), P = s.useRef({ signature: g, contentKey: h, open: r, busy: m });
77
+ const w = s.useRef(null), P = s.useRef(null), L = s.useRef(null), C = s.useRef(null), M = s.useId(), g = pt(p), A = s.useRef({ signature: g, contentKey: h, open: r, busy: m });
77
78
  s.useEffect(() => {
78
- const t = P.current;
79
- if (P.current = { signature: g, contentKey: h, open: r, busy: m }, !t.open || !r) return;
79
+ const t = A.current;
80
+ if (A.current = { signature: g, contentKey: h, open: r, busy: m }, !t.open || !r) return;
80
81
  const e = t.contentKey !== h, o = t.signature !== g && !t.busy;
81
- !e && !o || (w.current?.focus(), L.current && (L.current.scrollTop = 0));
82
+ !e && !o || (P.current?.focus(), C.current && (C.current.scrollTop = 0));
82
83
  }, [g, h, r, m]), s.useEffect(() => {
83
84
  if (!r) return;
84
85
  const t = requestAnimationFrame(() => {
85
86
  const e = i.current, o = document.activeElement;
86
- !e || o && e.contains(o) || (x?.current ?? k.current)?.focus();
87
+ !e || o && e.contains(o) || (x?.current ?? L.current)?.focus();
87
88
  });
88
89
  return () => cancelAnimationFrame(t);
89
90
  }, [r, x]);
90
- const [M, A] = s.useState(null);
91
+ const [F, j] = s.useState(null);
91
92
  s.useEffect(() => {
92
93
  if (!r) return;
93
94
  const t = window.visualViewport;
94
95
  if (!t) return;
95
96
  const e = () => {
96
- const o = document.activeElement, c = !!o && !!i.current?.contains(o) && o.matches(gt);
97
- A(c ? Math.round(t.height) : null);
97
+ const o = document.activeElement, c = !!o && !!i.current?.contains(o) && o.matches(xt);
98
+ j(c ? Math.round(t.height) : null);
98
99
  };
99
100
  return t.addEventListener("resize", e), document.addEventListener("focusin", e), document.addEventListener("focusout", e), () => {
100
- t.removeEventListener("resize", e), document.removeEventListener("focusin", e), document.removeEventListener("focusout", e), A(null);
101
+ t.removeEventListener("resize", e), document.removeEventListener("focusin", e), document.removeEventListener("focusout", e), j(null);
101
102
  };
102
103
  }, [r]);
103
- const a = s.useRef(null), y = s.useRef(!1), F = s.useRef(r);
104
+ const a = s.useRef(null), y = s.useRef(!1), z = s.useRef(r);
104
105
  s.useEffect(() => {
105
- F.current = r;
106
+ z.current = r;
106
107
  }, [r]);
107
108
  const b = (t) => {
108
109
  i.current?.style.setProperty("--rst-sheet-drag", `${t}px`);
109
- }, j = (t) => {
110
+ }, B = (t) => {
110
111
  const e = i.current;
111
112
  a.current = null, e && (delete e.dataset.dragging, t === "close" ? (u(), requestAnimationFrame(() => {
112
- F.current && !a.current && b(0);
113
+ z.current && !a.current && b(0);
113
114
  })) : b(0));
114
115
  };
115
116
  s.useEffect(() => {
116
117
  !r && a.current && (a.current = null, i.current && delete i.current.dataset.dragging), r && !a.current && b(0);
117
118
  }, [r]);
118
- const K = (t) => {
119
- a.current || (y.current = !1, !(!E || !r) && (t.pointerType === "mouse" && (t.button !== 0 || !I.current?.contains(t.target)) || (a.current = {
119
+ const X = (t) => {
120
+ a.current || (y.current = !1, !(!E || !r) && (t.pointerType === "mouse" && (t.button !== 0 || !w.current?.contains(t.target)) || (a.current = {
120
121
  pointerId: t.pointerId,
121
122
  x0: t.clientX,
122
123
  y0: t.clientY,
@@ -124,12 +125,12 @@ const Mt = ({
124
125
  phase: "pending",
125
126
  samples: [{ t: t.timeStamp, y: t.clientY }]
126
127
  })));
127
- }, U = (t) => {
128
+ }, G = (t) => {
128
129
  const e = a.current;
129
130
  if (!e || t.pointerId !== e.pointerId) return;
130
131
  const o = t.clientX - e.x0, c = t.clientY - e.y0;
131
132
  if (e.phase === "pending") {
132
- if (!ct(o, c)) return;
133
+ if (!ft(o, c)) return;
133
134
  if (Math.abs(o) > Math.abs(c)) {
134
135
  e.phase = "ignored";
135
136
  return;
@@ -142,7 +143,7 @@ const Mt = ({
142
143
  i.current && (i.current.dataset.dragging = "");
143
144
  }
144
145
  e.phase === "dragging" && (e.dy = c, e.samples.push({ t: t.timeStamp, y: t.clientY }), e.samples.length > 32 && e.samples.shift(), b(Math.max(0, c)));
145
- }, V = (t) => {
146
+ }, Q = (t) => {
146
147
  const e = a.current;
147
148
  if (!e || t.pointerId !== e.pointerId) return;
148
149
  if (e.phase !== "dragging") {
@@ -151,46 +152,47 @@ const Mt = ({
151
152
  }
152
153
  e.samples.push({ t: t.timeStamp, y: t.clientY });
153
154
  const o = t.clientY - e.y0, c = i.current?.getBoundingClientRect().height ?? 0;
154
- j(at(o, c, it(e.samples)));
155
- }, X = (t) => {
155
+ B(lt(o, c, dt(e.samples)));
156
+ }, H = (t) => {
156
157
  const e = a.current;
157
- !e || t.pointerId !== e.pointerId || (e.phase === "dragging" ? j("stay") : a.current = null);
158
- }, G = (t) => {
158
+ !e || t.pointerId !== e.pointerId || (e.phase === "dragging" ? B("stay") : a.current = null);
159
+ }, J = (t) => {
159
160
  !y.current || t.detail === 0 || (y.current = !1, t.preventDefault(), t.stopPropagation());
160
- }, Q = {
161
+ }, W = {
161
162
  "--rst-sheet-max-width": typeof v == "number" ? `${v}px` : v,
162
- ...M !== null && { "--rst-sheet-keyboard-cap": `${M}px` }
163
+ ...F !== null && { "--rst-sheet-keyboard-cap": `${F}px` }
163
164
  };
164
- return /* @__PURE__ */ l(H, { children: [
165
+ return /* @__PURE__ */ l(Z, { children: [
165
166
  /* @__PURE__ */ n("span", { ref: R, hidden: !0 }),
166
167
  /* @__PURE__ */ l(
167
- Z,
168
+ tt,
168
169
  {
170
+ ref: I,
169
171
  open: r,
170
172
  as: "div",
171
173
  onClose: u,
172
- initialFocus: x ?? k,
174
+ initialFocus: x ?? L,
173
175
  className: d(
174
- "rst:font-ui rst:relative rst:z-50 rst:focus:outline-hidden",
175
- $ && "dark"
176
+ "rst:font-ui rst:fixed rst:inset-0 rst:z-50 rst:focus:outline-hidden",
177
+ U && "dark"
176
178
  ),
177
179
  children: [
178
180
  /* @__PURE__ */ n(
179
- W,
181
+ et,
180
182
  {
181
183
  transition: !0,
182
184
  "data-testid": "sheet-backdrop",
183
185
  className: d(
184
186
  "rst:fixed rst:inset-0 rst:bg-[var(--roster-backdrop,var(--roster-sheet-backdrop))]",
185
- D ? ht : mt
187
+ k ? vt : bt
186
188
  )
187
189
  }
188
190
  ),
189
- /* @__PURE__ */ n("div", { className: "rst:fixed rst:inset-0 rst:flex rst:items-end rst:justify-center", children: /* @__PURE__ */ n(et, { afterLeave: f, children: /* @__PURE__ */ l(
190
- O,
191
+ /* @__PURE__ */ n("div", { className: "rst:fixed rst:inset-0 rst:flex rst:items-end rst:justify-center", children: /* @__PURE__ */ n(nt, { afterLeave: S.afterLeave, children: /* @__PURE__ */ l(
192
+ rt,
191
193
  {
192
194
  ref: i,
193
- style: Q,
195
+ style: W,
194
196
  "data-testid": "sheet-panel",
195
197
  className: d(
196
198
  /* 92dvh, or the visual viewport while the keyboard is up,
@@ -204,9 +206,9 @@ const Mt = ({
204
206
  "rst:[--roster-ring-offset:var(--roster-popover-bg)]",
205
207
  "rst:pb-[env(safe-area-inset-bottom)]",
206
208
  "rst:translate-y-[var(--rst-sheet-drag,0px)]",
207
- D ? pt : ft,
209
+ k ? yt : gt,
208
210
  "rst:data-dragging:transition-none",
209
- T
211
+ V
210
212
  ),
211
213
  children: [
212
214
  /* @__PURE__ */ l(
@@ -214,16 +216,16 @@ const Mt = ({
214
216
  {
215
217
  "data-testid": "sheet-drag-zone",
216
218
  className: d("rst:shrink-0", E && "rst:touch-none"),
217
- onPointerDown: K,
218
- onPointerMove: U,
219
- onPointerUp: V,
220
- onPointerCancel: X,
221
- onClickCapture: G,
219
+ onPointerDown: X,
220
+ onPointerMove: G,
221
+ onPointerUp: Q,
222
+ onPointerCancel: H,
223
+ onClickCapture: J,
222
224
  children: [
223
225
  /* @__PURE__ */ n(
224
226
  "div",
225
227
  {
226
- ref: I,
228
+ ref: w,
227
229
  "aria-hidden": "true",
228
230
  "data-testid": "sheet-handle",
229
231
  className: d(
@@ -241,40 +243,40 @@ const Mt = ({
241
243
  /* @__PURE__ */ l("div", { className: "rst:-mt-3 rst:flex rst:items-start rst:gap-2 rst:px-5 rst:pb-4", children: [
242
244
  /* @__PURE__ */ l("div", { className: "rst:min-w-0 rst:flex-1 rst:pt-2", children: [
243
245
  /* @__PURE__ */ n(
244
- tt,
246
+ st,
245
247
  {
246
248
  as: "h2",
247
- id: S,
248
- ref: w,
249
+ id: M,
250
+ ref: P,
249
251
  tabIndex: -1,
250
252
  className: d(
251
253
  "rst:text-lg rst:font-semibold rst:text-inherit rst:focus:outline-hidden",
252
- z && "rst:sr-only"
254
+ _ && "rst:sr-only"
253
255
  ),
254
256
  children: p
255
257
  }
256
258
  ),
257
- C && /* @__PURE__ */ n(
258
- J,
259
+ N && /* @__PURE__ */ n(
260
+ O,
259
261
  {
260
262
  as: "p",
261
263
  className: "rst:mt-1 rst:text-sm rst:text-inherit rst:opacity-75",
262
- children: C
264
+ children: N
263
265
  }
264
266
  )
265
267
  ] }),
266
- N && /* 44px tall like the close button, so actions of any
268
+ D && /* 44px tall like the close button, so actions of any
267
269
  height center on the same line as it. */
268
- /* @__PURE__ */ n("div", { className: "rst:flex rst:h-11 rst:shrink-0 rst:items-center rst:gap-1", children: N }),
270
+ /* @__PURE__ */ n("div", { className: "rst:flex rst:h-11 rst:shrink-0 rst:items-center rst:gap-1", children: D }),
269
271
  /* @__PURE__ */ n(
270
272
  "button",
271
273
  {
272
- ref: k,
274
+ ref: L,
273
275
  type: "button",
274
276
  onClick: u,
275
- "aria-label": q.close,
277
+ "aria-label": K.close,
276
278
  className: "rst:inline-flex rst:size-11 rst:shrink-0 rst:-mr-2 rst:cursor-pointer rst:items-center rst:justify-center rst:rounded-md rst:bg-transparent rst:text-inherit rst:opacity-60 rst:transition-opacity rst:hover:opacity-100 rst:focus:outline-hidden rst:focus-visible:opacity-100 rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:focus-visible:ring-offset-2 rst:ring-offset-background",
277
- children: /* @__PURE__ */ n(vt, {})
279
+ children: /* @__PURE__ */ n(kt, {})
278
280
  }
279
281
  )
280
282
  ] })
@@ -284,25 +286,26 @@ const Mt = ({
284
286
  /* @__PURE__ */ n(
285
287
  "div",
286
288
  {
287
- ref: L,
289
+ ref: C,
288
290
  role: "region",
289
- "aria-labelledby": S,
291
+ "aria-labelledby": M,
290
292
  tabIndex: 0,
291
293
  "data-testid": "sheet-content",
292
294
  "aria-busy": m || void 0,
293
295
  className: "rst:min-h-0 rst:flex-1 rst:overflow-y-auto rst:overscroll-contain rst:px-5 rst:pb-4 rst:focus:outline-hidden rst:ring-inset rst:focus-visible:ring-2 rst:focus-visible:ring-ring",
294
- children: _
296
+ children: $
295
297
  }
296
298
  ),
297
- /* @__PURE__ */ n(bt, { target: B })
299
+ /* @__PURE__ */ n(Rt, { target: T })
298
300
  ]
299
301
  }
300
302
  ) }) })
301
303
  ]
302
- }
304
+ },
305
+ S.key
303
306
  )
304
307
  ] });
305
308
  };
306
309
  export {
307
- Mt as Sheet
310
+ Bt as Sheet
308
311
  };
package/dist/index.d.ts CHANGED
@@ -58,6 +58,8 @@ export * from './components/molecules/CheckboxGroup/CheckboxGroup';
58
58
  export * from './components/molecules/CheckboxGroup/checkbox-group-variants';
59
59
  export * from './components/molecules/RadioGroup/RadioGroup';
60
60
  export * from './components/molecules/RadioGroup/radio-group-variants';
61
+ export * from './components/molecules/RadioTileGroup/RadioTileGroup';
62
+ export * from './components/molecules/RadioTileGroup/radio-tile-group-variants';
61
63
  export * from './components/molecules/Breadcrumbs/Breadcrumbs';
62
64
  export * from './components/molecules/Breadcrumbs/breadcrumb-variants';
63
65
  export * from './components/molecules/Tabs/Tabs';
@@ -79,6 +81,7 @@ export * from './components/molecules/Pagination/Pagination';
79
81
  export * from './components/molecules/SkeletonPresets/SkeletonPresets';
80
82
  export * from './components/molecules/ProgressField/ProgressField';
81
83
  export * from './components/molecules/StepProgress/StepProgress';
84
+ export * from './components/molecules/Timeline/Timeline';
82
85
  export * from './components/molecules/ErrorState/ErrorState';
83
86
  export * from './components/molecules/ErrorState/error-state-variants';
84
87
  export * from './components/molecules/MatchupCard/MatchupCard';
@@ -0,0 +1 @@
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("react");function w(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const n in e)if(n!=="default"){const u=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,u.get?u:{enumerable:!0,get:()=>e[n]})}}return t.default=e,Object.freeze(t)}const c=w(v),l=300;function g(e,t){return typeof e.getAnimations!="function"?!1:e.getAnimations({subtree:!0}).some(n=>{if(!("transitionProperty"in n)||n.playState!=="running")return!1;const u=n.effect?.target;return!(u&&t&&u!==t&&t.contains(u))})}const E=16;function y(e,t){e.reported||(e.reported=!0,t?.())}function L(e,t,n,u,d){const[m,b]=c.useState(0),f=c.useRef({onAfterClose:d,leaveMs:u});c.useEffect(()=>{f.current={onAfterClose:d,leaveMs:u}});const o=c.useRef(null),a=c.useRef(n),S=c.useCallback(()=>{const r=o.current;if(!r)return;const s=()=>{if(o.current!==r||r.reported)return;const i=e.current;if(i?.isConnected&&g(i,t.current)){window.setTimeout(s,E);return}y(r,f.current.onAfterClose)};s()},[e,t]);return c.useEffect(()=>{if(n){a.current=!0;return}if(!a.current)return;a.current=!1;const r={timer:0,reported:!1,removed:!1};o.current=r;const s=()=>{const i=e.current;if(i?.isConnected){if(g(i,t.current)){r.timer=window.setTimeout(s,l);return}r.removed=!0,b(p=>p+1)}};return r.timer=window.setTimeout(s,f.current.leaveMs+l),()=>{window.clearTimeout(r.timer),o.current===r&&(o.current=null)}},[n,e,t]),c.useLayoutEffect(()=>{const r=o.current;r?.removed&&(o.current=null,y(r,f.current.onAfterClose))},[m]),{key:m,afterLeave:S}}exports.LEAVE_MARGIN_MS=l;exports.useLeaveWatchdog=L;
@@ -0,0 +1,62 @@
1
+ import * as React from "react";
2
+ /**
3
+ * Makes sure a closed `Dialog` or `Sheet` leaves the page, and says so once.
4
+ *
5
+ * Internal, and not exported from the package.
6
+ *
7
+ * Headless UI removes a dialog when its leave transition has ended, and it
8
+ * finds that end by reading the panel's transitions once, a frame after the
9
+ * classes change, then waiting for those. A close that arrives during the
10
+ * entrance doesn't start a leave: it turns the entrance around. When that
11
+ * turned-around transition ends, Headless UI 2.2.9 checks once more, and if
12
+ * any transition on the element is still unfinished it returns without
13
+ * waiting for it and never checks again. The dialog stays mounted, closed,
14
+ * over the page, taking every click, and `afterLeave` never comes. Rare, and
15
+ * commoner the busier the machine: in real Escapes during the entrance, 2
16
+ * stuck in 1,800 at a load of 13 to 20, none in 2,700 at 3 to 5.
17
+ *
18
+ * Upstream, this is Headless UI's issue #3902
19
+ * (https://github.com/tailwindlabs/headlessui/issues/3902). PR #3895
20
+ * (https://github.com/tailwindlabs/headlessui/pull/3895), open and unreviewed
21
+ * on 29 Oct 2026, reads the transitions again each time a batch of them
22
+ * settles, which covers this. When a Headless UI release carries that fix,
23
+ * the removal can come out. The wait in `afterLeave` (below) stays until a
24
+ * release also stops ending a leave before it has run, which #3895 doesn't
25
+ * (https://github.com/tailwindlabs/headlessui/issues/3902#issuecomment-6511980829).
26
+ *
27
+ * So each close is watched. A leave that ends goes as it always has: Headless
28
+ * UI calls `afterLeave`, then removes the dialog. If the dialog is still
29
+ * mounted `leaveMs` plus a margin after the close, with no transition running
30
+ * inside it, nothing is going to remove it, and Roster does: `key` changes,
31
+ * which remounts Headless UI's `Dialog` closed, and the stuck tree goes with
32
+ * the old one. A transition still running (a leave made longer than its
33
+ * default, say) is waited out, then checked again.
34
+ *
35
+ * Remounted rather than rendered only while open, so the way a dialog opens
36
+ * is untouched: Headless UI's helper that finds the page behind is in place
37
+ * before the open, as it always was, and a dialog open on its first render
38
+ * behaves as it did.
39
+ *
40
+ * `onAfterClose` fires once for each close: after `afterLeave`, once no
41
+ * transition runs on the dialog's own parts or it has gone (Headless UI can
42
+ * call `afterLeave` with the leave still to run), or, when `afterLeave` never
43
+ * came, once the stuck dialog is gone. A watched close that ends with `afterLeave` stays
44
+ * watched until the dialog leaves the page, because the backdrop has its own
45
+ * transition and can be the part left behind. Reopening during the leave ends
46
+ * the watch, and that close never reports; so does unmounting.
47
+ */
48
+ /** How long past its leave a closed dialog may stay mounted, with nothing running, before it counts as stuck. */
49
+ export declare const LEAVE_MARGIN_MS = 300;
50
+ export interface LeaveWatchdog {
51
+ /** For Headless UI's `Dialog`: changes when a stuck dialog is removed. */
52
+ key: number;
53
+ /** For the panel's `TransitionChild`, in place of `onAfterClose`. */
54
+ afterLeave: () => void;
55
+ }
56
+ /**
57
+ * `ref` is on Headless UI's `Dialog`, the element that holds the backdrop and
58
+ * the panel, `panelRef` is on its `DialogPanel`, and `open` is what that
59
+ * `Dialog` is given. `leaveMs` is the leave's default length, the panel's and
60
+ * the backdrop's, whichever is longer.
61
+ */
62
+ export declare function useLeaveWatchdog(ref: React.RefObject<HTMLElement | null>, panelRef: React.RefObject<HTMLElement | null>, open: boolean, leaveMs: number, onAfterClose?: () => void): LeaveWatchdog;
@@ -0,0 +1,64 @@
1
+ "use client";
2
+ import * as n from "react";
3
+ const d = 300;
4
+ function w(t, r) {
5
+ return typeof t.getAnimations != "function" ? !1 : t.getAnimations({ subtree: !0 }).some((u) => {
6
+ if (!("transitionProperty" in u) || u.playState !== "running") return !1;
7
+ const o = u.effect?.target;
8
+ return !(o && r && o !== r && r.contains(o));
9
+ });
10
+ }
11
+ const y = 16;
12
+ function g(t, r) {
13
+ t.reported || (t.reported = !0, r?.());
14
+ }
15
+ function T(t, r, u, o, l) {
16
+ const [m, E] = n.useState(0), f = n.useRef({ onAfterClose: l, leaveMs: o });
17
+ n.useEffect(() => {
18
+ f.current = { onAfterClose: l, leaveMs: o };
19
+ });
20
+ const c = n.useRef(null), a = n.useRef(u), L = n.useCallback(() => {
21
+ const e = c.current;
22
+ if (!e) return;
23
+ const s = () => {
24
+ if (c.current !== e || e.reported) return;
25
+ const i = t.current;
26
+ if (i?.isConnected && w(i, r.current)) {
27
+ window.setTimeout(s, y);
28
+ return;
29
+ }
30
+ g(e, f.current.onAfterClose);
31
+ };
32
+ s();
33
+ }, [t, r]);
34
+ return n.useEffect(() => {
35
+ if (u) {
36
+ a.current = !0;
37
+ return;
38
+ }
39
+ if (!a.current) return;
40
+ a.current = !1;
41
+ const e = { timer: 0, reported: !1, removed: !1 };
42
+ c.current = e;
43
+ const s = () => {
44
+ const i = t.current;
45
+ if (i?.isConnected) {
46
+ if (w(i, r.current)) {
47
+ e.timer = window.setTimeout(s, d);
48
+ return;
49
+ }
50
+ e.removed = !0, E((v) => v + 1);
51
+ }
52
+ };
53
+ return e.timer = window.setTimeout(s, f.current.leaveMs + d), () => {
54
+ window.clearTimeout(e.timer), c.current === e && (c.current = null);
55
+ };
56
+ }, [u, t, r]), n.useLayoutEffect(() => {
57
+ const e = c.current;
58
+ e?.removed && (c.current = null, g(e, f.current.onAfterClose));
59
+ }, [m]), { key: m, afterLeave: L };
60
+ }
61
+ export {
62
+ d as LEAVE_MARGIN_MS,
63
+ T as useLeaveWatchdog
64
+ };
@@ -0,0 +1 @@
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=()=>e.jsx("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"none",stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("path",{d:"M20 6 9 17l-5-5"})});exports.StepCheck=t;
@@ -0,0 +1,2 @@
1
+ /** The check a finished step's marker shows in place of its number. */
2
+ export declare const StepCheck: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ "use client";
2
+ import { jsx as e } from "react/jsx-runtime";
3
+ const r = () => /* @__PURE__ */ e("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ e("path", { d: "M20 6 9 17l-5-5" }) });
4
+ export {
5
+ r as StepCheck
6
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("../lib/utils.cjs"),s=r=>t.cn("rst:relative rst:z-10 rst:flex rst:h-8 rst:w-8 rst:items-center rst:justify-center rst:rounded-full rst:text-sm rst:font-semibold rst:tabular-nums",r==="done"&&"rst:bg-primary-600 rst:text-primary-600-ink rst:dark:bg-primary-400 rst:dark:text-gray-950 rst:forced-colors:forced-color-adjust-none rst:forced-colors:bg-[Highlight] rst:forced-colors:text-[HighlightText]",r==="current"&&"rst:border-2 rst:border-primary-600 rst:bg-[var(--roster-card-bg)] rst:text-primary-600 rst:dark:border-primary-400 rst:dark:text-primary-400",r==="upcoming"&&"rst:bg-[var(--roster-skeleton)] rst:text-gray-600 rst:dark:text-gray-300 rst:forced-colors:border");exports.stepMarkerClass=s;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * A step's marker, shared by `StepProgress` and `Timeline`, so a finished,
3
+ * current or upcoming step looks the same in both. The check it shows when
4
+ * done is `StepCheck`, in `step-check.tsx`.
5
+ *
6
+ * Internal, and not exported from the package.
7
+ */
8
+ export type StepState = "done" | "current" | "upcoming";
9
+ /** The marker's classes: a 32px circle, filled when done, ringed when current. */
10
+ export declare const stepMarkerClass: (state: StepState) => string;
@@ -0,0 +1,12 @@
1
+ import { cn as t } from "../lib/utils.js";
2
+ const e = (r) => t(
3
+ "rst:relative rst:z-10 rst:flex rst:h-8 rst:w-8 rst:items-center rst:justify-center rst:rounded-full rst:text-sm rst:font-semibold rst:tabular-nums",
4
+ r === "done" && "rst:bg-primary-600 rst:text-primary-600-ink rst:dark:bg-primary-400 rst:dark:text-gray-950 rst:forced-colors:forced-color-adjust-none rst:forced-colors:bg-[Highlight] rst:forced-colors:text-[HighlightText]",
5
+ /* A border, not a ring: forced colors keep a border and drop the shadow a
6
+ ring is drawn with. */
7
+ r === "current" && "rst:border-2 rst:border-primary-600 rst:bg-[var(--roster-card-bg)] rst:text-primary-600 rst:dark:border-primary-400 rst:dark:text-primary-400",
8
+ r === "upcoming" && "rst:bg-[var(--roster-skeleton)] rst:text-gray-600 rst:dark:text-gray-300 rst:forced-colors:border"
9
+ );
10
+ export {
11
+ e as stepMarkerClass
12
+ };
package/dist/meta.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.16.0",
3
- "tests": 2564,
4
- "testFiles": 651
2
+ "version": "5.18.0",
3
+ "tests": 2701,
4
+ "testFiles": 699
5
5
  }