@alfadocs/ui-kit-debug 0.57.0 → 0.58.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "packageVersion": "0.57.0",
3
+ "packageVersion": "0.58.0",
4
4
  "components": [
5
5
  {
6
6
  "kind": "component",
@@ -19,4 +19,5 @@ export { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect';
19
19
  export { useWebOtp, type UseWebOtpOptions } from './use-web-otp';
20
20
  export { useEdgeResize, type UseEdgeResizeOptions, type UseEdgeResizeReturn, type EdgeResizeSeparatorProps, } from './use-edge-resize';
21
21
  export { useSigningSession, type SigningField, type SigningFieldBase, type UseSigningSessionReturn, } from './use-signing-session';
22
+ export { useCountdown, type UseCountdownOptions, type UseCountdownReturn, } from './use-countdown';
22
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,YAAY,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,yBAAyB,EACzB,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,SAAS,EACT,eAAe,EACf,uBAAuB,EACvB,aAAa,EACb,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,KAAK,2BAA2B,GACjC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,GAC9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,oBAAoB,EACpB,KAAK,iBAAiB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,KAAK,SAAS,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,YAAY,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,yBAAyB,EACzB,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,SAAS,EACT,eAAe,EACf,uBAAuB,EACvB,aAAa,EACb,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,KAAK,2BAA2B,GACjC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,GAC9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,oBAAoB,EACpB,KAAK,iBAAiB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,KAAK,SAAS,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,YAAY,EACZ,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,iBAAiB,CAAC"}
@@ -1,32 +1,32 @@
1
- import { u as v } from "../_chunks/use-prefers-reduced-motion-BMwIQRjB.js";
2
- import { u as D } from "../_chunks/use-media-query-CcAx5SMM.js";
3
- import { u as g, a as _ } from "../_chunks/use-signing-session-CyOZWinp.js";
4
- import { u as O } from "../_chunks/use-count-up-BLLetaZ8.js";
5
- import { u as k } from "../_chunks/use-locale-BkCIHujH.js";
6
- import { A as K, T as H, a as M, r as Y, t as q, u as B } from "../_chunks/use-theme-CAuo6EYT.js";
7
- import { u as P } from "../_chunks/use-controllable-state-BiY4xTzM.js";
8
- import { u as V } from "../_chunks/use-copy-to-clipboard-Cyfc_dlv.js";
9
- import { u as z } from "../_chunks/use-debounced-callback-BisrB-Fq.js";
10
- import { useState as x, useRef as b, useEffect as E } from "react";
11
- import { u as W, a as J } from "../_chunks/use-direction-Dp8h70PP.js";
12
- import { u as X } from "../_chunks/use-persistent-state-i23OWy6G.js";
13
- import { u as $ } from "../_chunks/use-isomorphic-layout-effect-BGfaCOP1.js";
14
- import { u as te } from "../_chunks/use-web-otp-D_utzp6S.js";
15
- import { u as oe } from "../_chunks/use-edge-resize-ZnGG7gyO.js";
16
- function h(e, o) {
17
- const [t, i] = x(e), u = b(null);
18
- return E(() => {
19
- if (o <= 0) {
20
- u.current !== null && (clearTimeout(u.current), u.current = null), i(e);
1
+ import { u as L } from "../_chunks/use-prefers-reduced-motion-BMwIQRjB.js";
2
+ import { u as F } from "../_chunks/use-media-query-CcAx5SMM.js";
3
+ import { u as R, a as _ } from "../_chunks/use-signing-session-CyOZWinp.js";
4
+ import { u as w } from "../_chunks/use-count-up-BLLetaZ8.js";
5
+ import { u as K } from "../_chunks/use-locale-BkCIHujH.js";
6
+ import { A as H, T as Y, a as q, r as B, t as G, u as P } from "../_chunks/use-theme-CAuo6EYT.js";
7
+ import { u as V } from "../_chunks/use-controllable-state-BiY4xTzM.js";
8
+ import { u as z } from "../_chunks/use-copy-to-clipboard-Cyfc_dlv.js";
9
+ import { u as W } from "../_chunks/use-debounced-callback-BisrB-Fq.js";
10
+ import { useState as b, useRef as E, useEffect as m, useCallback as x } from "react";
11
+ import { u as N, a as X } from "../_chunks/use-direction-Dp8h70PP.js";
12
+ import { u as $ } from "../_chunks/use-persistent-state-i23OWy6G.js";
13
+ import { u as te } from "../_chunks/use-isomorphic-layout-effect-BGfaCOP1.js";
14
+ import { u as ne } from "../_chunks/use-web-otp-D_utzp6S.js";
15
+ import { u as ue } from "../_chunks/use-edge-resize-ZnGG7gyO.js";
16
+ function C(e, u) {
17
+ const [r, i] = b(e), n = E(null);
18
+ return m(() => {
19
+ if (u <= 0) {
20
+ n.current !== null && (clearTimeout(n.current), n.current = null), i(e);
21
21
  return;
22
22
  }
23
23
  const s = setTimeout(() => {
24
- i(e), u.current = null;
25
- }, o);
26
- return u.current = s, () => clearTimeout(s);
27
- }, [e, o]), t;
24
+ i(e), n.current = null;
25
+ }, u);
26
+ return n.current = s, () => clearTimeout(s);
27
+ }, [e, u]), r;
28
28
  }
29
- const T = [
29
+ const S = [
30
30
  "a[href]",
31
31
  "button:not([disabled])",
32
32
  'input:not([disabled]):not([type="hidden"])',
@@ -37,74 +37,96 @@ const T = [
37
37
  "audio[controls]",
38
38
  "video[controls]"
39
39
  ].join(",");
40
- function p(e) {
40
+ function T(e) {
41
41
  return Array.from(
42
- e.querySelectorAll(T)
43
- ).filter((o) => {
44
- if (o.hidden) return !1;
45
- let t = o;
46
- for (; t; ) {
47
- if (t.hasAttribute("inert") || t.getAttribute("aria-hidden") === "true") return !1;
48
- t = t.parentElement;
42
+ e.querySelectorAll(S)
43
+ ).filter((u) => {
44
+ if (u.hidden) return !1;
45
+ let r = u;
46
+ for (; r; ) {
47
+ if (r.hasAttribute("inert") || r.getAttribute("aria-hidden") === "true") return !1;
48
+ r = r.parentElement;
49
49
  }
50
50
  return !0;
51
51
  });
52
52
  }
53
- function C(e, o = {}) {
54
- const { enabled: t = !0, autoFocus: i = !0, restoreFocus: u = !0 } = o, s = b(null);
55
- E(() => {
56
- if (!t) return;
57
- const a = e.current;
58
- if (!a) return;
53
+ function v(e, u = {}) {
54
+ const { enabled: r = !0, autoFocus: i = !0, restoreFocus: n = !0 } = u, s = E(null);
55
+ m(() => {
56
+ if (!r) return;
57
+ const o = e.current;
58
+ if (!o) return;
59
59
  if (s.current = typeof document < "u" && document.activeElement instanceof HTMLElement ? document.activeElement : null, i) {
60
- const n = p(a)[0] ?? (a.tabIndex >= -1 ? a : null);
61
- n == null || n.focus();
60
+ const a = T(o)[0] ?? (o.tabIndex >= -1 ? o : null);
61
+ a == null || a.focus();
62
62
  }
63
- function f(r) {
64
- if (r.key !== "Tab") return;
65
- const n = e.current;
66
- if (!n) return;
67
- const c = p(n);
68
- if (c.length === 0) {
69
- r.preventDefault();
63
+ function l(t) {
64
+ if (t.key !== "Tab") return;
65
+ const a = e.current;
66
+ if (!a) return;
67
+ const f = T(a);
68
+ if (f.length === 0) {
69
+ t.preventDefault();
70
70
  return;
71
71
  }
72
- const d = c[0], m = c[c.length - 1], l = document.activeElement;
73
- r.shiftKey ? (l === d || !n.contains(l)) && (r.preventDefault(), m.focus()) : (l === m || !n.contains(l)) && (r.preventDefault(), d.focus());
72
+ const c = f[0], d = f[f.length - 1], p = document.activeElement;
73
+ t.shiftKey ? (p === c || !a.contains(p)) && (t.preventDefault(), d.focus()) : (p === d || !a.contains(p)) && (t.preventDefault(), c.focus());
74
74
  }
75
- return a.addEventListener("keydown", f), () => {
76
- if (a.removeEventListener("keydown", f), u && s.current) {
77
- const r = s.current;
75
+ return o.addEventListener("keydown", l), () => {
76
+ if (o.removeEventListener("keydown", l), n && s.current) {
77
+ const t = s.current;
78
78
  requestAnimationFrame(() => {
79
- r.isConnected && r.focus();
79
+ t.isConnected && t.focus();
80
80
  });
81
81
  }
82
82
  };
83
- }, [t, i, u, e]);
83
+ }, [r, i, n, e]);
84
+ }
85
+ function g(e, u = {}) {
86
+ const { autoStart: r = !0, onElapsed: i } = u, [n, s] = b(e), [o, l] = b(r), t = E(i);
87
+ m(() => {
88
+ t.current = i;
89
+ }, [i]);
90
+ const a = x(() => {
91
+ s(e), l(!0);
92
+ }, [e]), f = x(() => {
93
+ s(e), l(!1);
94
+ }, [e]);
95
+ return m(() => {
96
+ if (!o) return;
97
+ const c = setInterval(() => {
98
+ s((d) => Math.max(0, d - 1));
99
+ }, 1e3);
100
+ return () => clearInterval(c);
101
+ }, [o]), m(() => {
102
+ var c;
103
+ o && n <= 0 && (l(!1), (c = t.current) == null || c.call(t));
104
+ }, [o, n]), { remaining: n, isRunning: o, start: a, reset: f };
84
105
  }
85
106
  export {
86
- K as ACCESSIBILITY_STORAGE_KEY,
87
- H as THEME_CLASS,
88
- M as THEME_STORAGE_KEY,
89
- Y as resolveTheme,
90
- q as themeClassList,
91
- P as useControllableState,
92
- V as useCopyToClipboard,
93
- O as useCountUp,
94
- z as useDebouncedCallback,
95
- h as useDebouncedValue,
96
- W as useDirection,
97
- J as useDocumentDirection,
98
- oe as useEdgeResize,
99
- C as useFocusTrap,
100
- $ as useIsomorphicLayoutEffect,
101
- k as useLocale,
102
- D as useMediaQuery,
103
- X as usePersistentState,
104
- v as usePrefersReducedMotion,
105
- g as useScrollToFirstError,
107
+ H as ACCESSIBILITY_STORAGE_KEY,
108
+ Y as THEME_CLASS,
109
+ q as THEME_STORAGE_KEY,
110
+ B as resolveTheme,
111
+ G as themeClassList,
112
+ V as useControllableState,
113
+ z as useCopyToClipboard,
114
+ w as useCountUp,
115
+ g as useCountdown,
116
+ W as useDebouncedCallback,
117
+ C as useDebouncedValue,
118
+ N as useDirection,
119
+ X as useDocumentDirection,
120
+ ue as useEdgeResize,
121
+ v as useFocusTrap,
122
+ te as useIsomorphicLayoutEffect,
123
+ K as useLocale,
124
+ F as useMediaQuery,
125
+ $ as usePersistentState,
126
+ L as usePrefersReducedMotion,
127
+ R as useScrollToFirstError,
106
128
  _ as useSigningSession,
107
- B as useTheme,
108
- te as useWebOtp
129
+ P as useTheme,
130
+ ne as useWebOtp
109
131
  };
110
132
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/hooks/use-debounced-value.ts","../../src/hooks/use-focus-trap.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\n/**\n * Returns a value that lags `input` by `delayMs`. Each new `input`\n * resets the timer; the returned value updates once `input` has been\n * stable for `delayMs` ms.\n *\n * Companion to `useDebouncedCallback` — use this when you want the\n * debounced *value* (to drive a derived effect, query, or render),\n * and use the callback hook when you want the debounced *action*.\n *\n * @example\n * const [query, setQuery] = useState('');\n * const debouncedQuery = useDebouncedValue(query, 250);\n * useEffect(() => { void search(debouncedQuery); }, [debouncedQuery]);\n */\nexport function useDebouncedValue<T>(input: T, delayMs: number): T {\n const [value, setValue] = useState<T>(input);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (delayMs <= 0) {\n // Flush any pending timer so a stale queued value can't land\n // after the synchronous update below.\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n setValue(input);\n return;\n }\n const timer = setTimeout(() => {\n setValue(input);\n timerRef.current = null;\n }, delayMs);\n timerRef.current = timer;\n return () => clearTimeout(timer);\n }, [input, delayMs]);\n\n return value;\n}\n","import { useEffect, useRef, type RefObject } from 'react';\n\n/* -------------------------------------------------------------------- */\n/* Focus trap */\n/* */\n/* Lightweight focus-trap hook for components that compose a Radix */\n/* primitive without the overlay primitive (Dialog, AlertDialog, Sheet) */\n/* — those handle focus trapping for free via `@radix-ui/react-dialog`. */\n/* */\n/* This hook is intentionally NOT a Radix `<FocusScope>` re-export — it */\n/* is a hook so it composes inside `forwardRef` components without */\n/* nesting another wrapper element. If you need the full Radix */\n/* contract (return-focus management, loop, asChild), use */\n/* `@radix-ui/react-focus-scope` directly. */\n/* -------------------------------------------------------------------- */\n\nexport interface UseFocusTrapOptions {\n /** When `false` the trap is inert. Defaults to `true`. */\n enabled?: boolean;\n /**\n * When `true`, focus initial autofocus into the first focusable\n * descendant on mount / enable. @default true\n */\n autoFocus?: boolean;\n /**\n * When `true`, restores focus to the previously-focused element on\n * unmount / disable. @default true\n */\n restoreFocus?: boolean;\n}\n\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled]):not([type=\"hidden\"])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]',\n 'audio[controls]',\n 'video[controls]',\n].join(',');\n\nfunction getFocusable(container: HTMLElement): HTMLElement[] {\n return Array.from(\n container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),\n ).filter((el) => {\n if (el.hidden) return false;\n // `inert` and `aria-hidden=\"true\"` block focus on the element AND\n // all its descendants — walk the chain to catch either ancestor.\n let node: HTMLElement | null = el;\n while (node) {\n if (node.hasAttribute('inert')) return false;\n if (node.getAttribute('aria-hidden') === 'true') return false;\n node = node.parentElement;\n }\n return true;\n });\n}\n\n/**\n * Constrain Tab navigation to descendants of `containerRef`. Wraps Tab\n * forward from the last focusable to the first, and Shift+Tab back from\n * the first to the last. Optionally autofocuses on enable and restores\n * focus on disable.\n *\n * Use this for inline modal patterns or focus zones that don't ship\n * with their own Radix overlay. Don't stack it inside Dialog / Sheet —\n * Radix already traps focus in those.\n *\n * @example\n * const ref = useRef<HTMLDivElement>(null);\n * useFocusTrap(ref, { enabled: open });\n * return <div ref={ref}>…</div>;\n */\nexport function useFocusTrap<T extends HTMLElement>(\n containerRef: RefObject<T | null>,\n options: UseFocusTrapOptions = {},\n): void {\n const { enabled = true, autoFocus = true, restoreFocus = true } = options;\n const previouslyFocused = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (!enabled) return;\n const container = containerRef.current;\n if (!container) return;\n\n previouslyFocused.current =\n typeof document !== 'undefined' &&\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n\n if (autoFocus) {\n const focusable = getFocusable(container);\n // Container itself is the fallback focus target — needs `tabIndex`\n // to receive focus, but `-1` is fine.\n const target =\n focusable[0] ?? (container.tabIndex >= -1 ? container : null);\n target?.focus();\n }\n\n function onKeyDown(event: KeyboardEvent) {\n if (event.key !== 'Tab') return;\n const root = containerRef.current;\n if (!root) return;\n const focusable = getFocusable(root);\n if (focusable.length === 0) {\n event.preventDefault();\n return;\n }\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const active = document.activeElement;\n\n if (event.shiftKey) {\n if (active === first || !root.contains(active)) {\n event.preventDefault();\n last.focus();\n }\n } else {\n if (active === last || !root.contains(active)) {\n event.preventDefault();\n first.focus();\n }\n }\n }\n\n container.addEventListener('keydown', onKeyDown);\n\n return () => {\n container.removeEventListener('keydown', onKeyDown);\n if (restoreFocus && previouslyFocused.current) {\n // rAF lets parent unmounts settle before refocus — a microtask\n // fires too early and can throw on a detached node.\n const target = previouslyFocused.current;\n requestAnimationFrame(() => {\n if (target.isConnected) target.focus();\n });\n }\n };\n }, [enabled, autoFocus, restoreFocus, containerRef]);\n}\n"],"names":["useDebouncedValue","input","delayMs","value","setValue","useState","timerRef","useRef","useEffect","timer","FOCUSABLE_SELECTOR","getFocusable","container","el","node","useFocusTrap","containerRef","options","enabled","autoFocus","restoreFocus","previouslyFocused","target","onKeyDown","event","root","focusable","first","last","active"],"mappings":";;;;;;;;;;;;;;;AAgBO,SAASA,EAAqBC,GAAUC,GAAoB;AACjE,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAAYJ,CAAK,GACrCK,IAAWC,EAA6C,IAAI;AAElE,SAAAC,EAAU,MAAM;AACd,QAAIN,KAAW,GAAG;AAGhB,MAAII,EAAS,YAAY,SACvB,aAAaA,EAAS,OAAO,GAC7BA,EAAS,UAAU,OAErBF,EAASH,CAAK;AACd;AAAA,IACF;AACA,UAAMQ,IAAQ,WAAW,MAAM;AAC7B,MAAAL,EAASH,CAAK,GACdK,EAAS,UAAU;AAAA,IACrB,GAAGJ,CAAO;AACV,WAAAI,EAAS,UAAUG,GACZ,MAAM,aAAaA,CAAK;AAAA,EACjC,GAAG,CAACR,GAAOC,CAAO,CAAC,GAEZC;AACT;ACTA,MAAMO,IAAqB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG;AAEV,SAASC,EAAaC,GAAuC;AAC3D,SAAO,MAAM;AAAA,IACXA,EAAU,iBAA8BF,CAAkB;AAAA,EAAA,EAC1D,OAAO,CAACG,MAAO;AACf,QAAIA,EAAG,OAAQ,QAAO;AAGtB,QAAIC,IAA2BD;AAC/B,WAAOC,KAAM;AAEX,UADIA,EAAK,aAAa,OAAO,KACzBA,EAAK,aAAa,aAAa,MAAM,OAAQ,QAAO;AACxD,MAAAA,IAAOA,EAAK;AAAA,IACd;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAiBO,SAASC,EACdC,GACAC,IAA+B,IACzB;AACN,QAAM,EAAE,SAAAC,IAAU,IAAM,WAAAC,IAAY,IAAM,cAAAC,IAAe,OAASH,GAC5DI,IAAoBd,EAA2B,IAAI;AAEzD,EAAAC,EAAU,MAAM;AACd,QAAI,CAACU,EAAS;AACd,UAAMN,IAAYI,EAAa;AAC/B,QAAI,CAACJ,EAAW;AAQhB,QANAS,EAAkB,UAChB,OAAO,WAAa,OACpB,SAAS,yBAAyB,cAC9B,SAAS,gBACT,MAEFF,GAAW;AAIb,YAAMG,IAHYX,EAAaC,CAAS,EAI5B,CAAC,MAAMA,EAAU,YAAY,KAAKA,IAAY;AAC1D,MAAAU,KAAA,QAAAA,EAAQ;AAAA,IACV;AAEA,aAASC,EAAUC,GAAsB;AACvC,UAAIA,EAAM,QAAQ,MAAO;AACzB,YAAMC,IAAOT,EAAa;AAC1B,UAAI,CAACS,EAAM;AACX,YAAMC,IAAYf,EAAac,CAAI;AACnC,UAAIC,EAAU,WAAW,GAAG;AAC1B,QAAAF,EAAM,eAAA;AACN;AAAA,MACF;AACA,YAAMG,IAAQD,EAAU,CAAC,GACnBE,IAAOF,EAAUA,EAAU,SAAS,CAAC,GACrCG,IAAS,SAAS;AAExB,MAAIL,EAAM,YACJK,MAAWF,KAAS,CAACF,EAAK,SAASI,CAAM,OAC3CL,EAAM,eAAA,GACNI,EAAK,MAAA,MAGHC,MAAWD,KAAQ,CAACH,EAAK,SAASI,CAAM,OAC1CL,EAAM,eAAA,GACNG,EAAM,MAAA;AAAA,IAGZ;AAEA,WAAAf,EAAU,iBAAiB,WAAWW,CAAS,GAExC,MAAM;AAEX,UADAX,EAAU,oBAAoB,WAAWW,CAAS,GAC9CH,KAAgBC,EAAkB,SAAS;AAG7C,cAAMC,IAASD,EAAkB;AACjC,8BAAsB,MAAM;AAC1B,UAAIC,EAAO,eAAaA,EAAO,MAAA;AAAA,QACjC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,GAAG,CAACJ,GAASC,GAAWC,GAAcJ,CAAY,CAAC;AACrD;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/hooks/use-debounced-value.ts","../../src/hooks/use-focus-trap.ts","../../src/hooks/use-countdown.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\n/**\n * Returns a value that lags `input` by `delayMs`. Each new `input`\n * resets the timer; the returned value updates once `input` has been\n * stable for `delayMs` ms.\n *\n * Companion to `useDebouncedCallback` — use this when you want the\n * debounced *value* (to drive a derived effect, query, or render),\n * and use the callback hook when you want the debounced *action*.\n *\n * @example\n * const [query, setQuery] = useState('');\n * const debouncedQuery = useDebouncedValue(query, 250);\n * useEffect(() => { void search(debouncedQuery); }, [debouncedQuery]);\n */\nexport function useDebouncedValue<T>(input: T, delayMs: number): T {\n const [value, setValue] = useState<T>(input);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (delayMs <= 0) {\n // Flush any pending timer so a stale queued value can't land\n // after the synchronous update below.\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n setValue(input);\n return;\n }\n const timer = setTimeout(() => {\n setValue(input);\n timerRef.current = null;\n }, delayMs);\n timerRef.current = timer;\n return () => clearTimeout(timer);\n }, [input, delayMs]);\n\n return value;\n}\n","import { useEffect, useRef, type RefObject } from 'react';\n\n/* -------------------------------------------------------------------- */\n/* Focus trap */\n/* */\n/* Lightweight focus-trap hook for components that compose a Radix */\n/* primitive without the overlay primitive (Dialog, AlertDialog, Sheet) */\n/* — those handle focus trapping for free via `@radix-ui/react-dialog`. */\n/* */\n/* This hook is intentionally NOT a Radix `<FocusScope>` re-export — it */\n/* is a hook so it composes inside `forwardRef` components without */\n/* nesting another wrapper element. If you need the full Radix */\n/* contract (return-focus management, loop, asChild), use */\n/* `@radix-ui/react-focus-scope` directly. */\n/* -------------------------------------------------------------------- */\n\nexport interface UseFocusTrapOptions {\n /** When `false` the trap is inert. Defaults to `true`. */\n enabled?: boolean;\n /**\n * When `true`, focus initial autofocus into the first focusable\n * descendant on mount / enable. @default true\n */\n autoFocus?: boolean;\n /**\n * When `true`, restores focus to the previously-focused element on\n * unmount / disable. @default true\n */\n restoreFocus?: boolean;\n}\n\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled]):not([type=\"hidden\"])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]',\n 'audio[controls]',\n 'video[controls]',\n].join(',');\n\nfunction getFocusable(container: HTMLElement): HTMLElement[] {\n return Array.from(\n container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),\n ).filter((el) => {\n if (el.hidden) return false;\n // `inert` and `aria-hidden=\"true\"` block focus on the element AND\n // all its descendants — walk the chain to catch either ancestor.\n let node: HTMLElement | null = el;\n while (node) {\n if (node.hasAttribute('inert')) return false;\n if (node.getAttribute('aria-hidden') === 'true') return false;\n node = node.parentElement;\n }\n return true;\n });\n}\n\n/**\n * Constrain Tab navigation to descendants of `containerRef`. Wraps Tab\n * forward from the last focusable to the first, and Shift+Tab back from\n * the first to the last. Optionally autofocuses on enable and restores\n * focus on disable.\n *\n * Use this for inline modal patterns or focus zones that don't ship\n * with their own Radix overlay. Don't stack it inside Dialog / Sheet —\n * Radix already traps focus in those.\n *\n * @example\n * const ref = useRef<HTMLDivElement>(null);\n * useFocusTrap(ref, { enabled: open });\n * return <div ref={ref}>…</div>;\n */\nexport function useFocusTrap<T extends HTMLElement>(\n containerRef: RefObject<T | null>,\n options: UseFocusTrapOptions = {},\n): void {\n const { enabled = true, autoFocus = true, restoreFocus = true } = options;\n const previouslyFocused = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (!enabled) return;\n const container = containerRef.current;\n if (!container) return;\n\n previouslyFocused.current =\n typeof document !== 'undefined' &&\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n\n if (autoFocus) {\n const focusable = getFocusable(container);\n // Container itself is the fallback focus target — needs `tabIndex`\n // to receive focus, but `-1` is fine.\n const target =\n focusable[0] ?? (container.tabIndex >= -1 ? container : null);\n target?.focus();\n }\n\n function onKeyDown(event: KeyboardEvent) {\n if (event.key !== 'Tab') return;\n const root = containerRef.current;\n if (!root) return;\n const focusable = getFocusable(root);\n if (focusable.length === 0) {\n event.preventDefault();\n return;\n }\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const active = document.activeElement;\n\n if (event.shiftKey) {\n if (active === first || !root.contains(active)) {\n event.preventDefault();\n last.focus();\n }\n } else {\n if (active === last || !root.contains(active)) {\n event.preventDefault();\n first.focus();\n }\n }\n }\n\n container.addEventListener('keydown', onKeyDown);\n\n return () => {\n container.removeEventListener('keydown', onKeyDown);\n if (restoreFocus && previouslyFocused.current) {\n // rAF lets parent unmounts settle before refocus — a microtask\n // fires too early and can throw on a detached node.\n const target = previouslyFocused.current;\n requestAnimationFrame(() => {\n if (target.isConnected) target.focus();\n });\n }\n };\n }, [enabled, autoFocus, restoreFocus, containerRef]);\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseCountdownOptions {\n /** Begin counting down on mount. Default `true`. */\n autoStart?: boolean;\n /** Called exactly once when the countdown reaches zero. */\n onElapsed?: () => void;\n}\n\nexport interface UseCountdownReturn {\n /** Whole seconds remaining; counts down to 0. */\n remaining: number;\n /** Whether the countdown is actively ticking. */\n isRunning: boolean;\n /** (Re)start from the full duration. */\n start: () => void;\n /** Stop and reset to the full duration without firing `onElapsed`. */\n reset: () => void;\n}\n\n/**\n * A pure, render-friendly seconds countdown. It owns no side effects — when\n * it reaches zero it calls `onElapsed` and the CONSUMER decides what to do\n * (close the tab, redirect, …). Same \"no I/O\" contract as `useSigningSession`.\n *\n * `onElapsed` is read through a ref, so changing the callback doesn't restart\n * the timer. SSR-safe: the timer only ticks inside an effect (client-only).\n *\n * @example\n * const { remaining } = useCountdown(10, {\n * onElapsed: () => {\n * window.close(); // best-effort — blocked for user-opened tabs\n * window.location.assign('https://www.alfadocs.com'); // fallback\n * },\n * });\n */\nexport function useCountdown(\n seconds: number,\n options: UseCountdownOptions = {},\n): UseCountdownReturn {\n const { autoStart = true, onElapsed } = options;\n const [remaining, setRemaining] = useState(seconds);\n const [isRunning, setIsRunning] = useState(autoStart);\n\n const onElapsedRef = useRef(onElapsed);\n useEffect(() => {\n onElapsedRef.current = onElapsed;\n }, [onElapsed]);\n\n const start = useCallback(() => {\n setRemaining(seconds);\n setIsRunning(true);\n }, [seconds]);\n\n const reset = useCallback(() => {\n setRemaining(seconds);\n setIsRunning(false);\n }, [seconds]);\n\n // A single interval keyed on `isRunning` (NOT `remaining`) so each second\n // ticks regardless of re-renders — a setTimeout re-scheduled per render\n // misbehaves under fake timers and drops ticks.\n useEffect(() => {\n if (!isRunning) return undefined;\n const id = setInterval(() => {\n setRemaining((r) => Math.max(0, r - 1));\n }, 1000);\n return () => clearInterval(id);\n }, [isRunning]);\n\n // Fire `onElapsed` once when the counter reaches zero, then stop (which\n // tears down the interval above). Gated on `isRunning` so it can't re-fire.\n useEffect(() => {\n if (isRunning && remaining <= 0) {\n setIsRunning(false);\n onElapsedRef.current?.();\n }\n }, [isRunning, remaining]);\n\n return { remaining, isRunning, start, reset };\n}\n"],"names":["useDebouncedValue","input","delayMs","value","setValue","useState","timerRef","useRef","useEffect","timer","FOCUSABLE_SELECTOR","getFocusable","container","el","node","useFocusTrap","containerRef","options","enabled","autoFocus","restoreFocus","previouslyFocused","target","onKeyDown","event","root","focusable","first","last","active","useCountdown","seconds","autoStart","onElapsed","remaining","setRemaining","isRunning","setIsRunning","onElapsedRef","start","useCallback","reset","id","r","_a"],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ export interface UseCountdownOptions {
2
+ /** Begin counting down on mount. Default `true`. */
3
+ autoStart?: boolean;
4
+ /** Called exactly once when the countdown reaches zero. */
5
+ onElapsed?: () => void;
6
+ }
7
+ export interface UseCountdownReturn {
8
+ /** Whole seconds remaining; counts down to 0. */
9
+ remaining: number;
10
+ /** Whether the countdown is actively ticking. */
11
+ isRunning: boolean;
12
+ /** (Re)start from the full duration. */
13
+ start: () => void;
14
+ /** Stop and reset to the full duration without firing `onElapsed`. */
15
+ reset: () => void;
16
+ }
17
+ /**
18
+ * A pure, render-friendly seconds countdown. It owns no side effects — when
19
+ * it reaches zero it calls `onElapsed` and the CONSUMER decides what to do
20
+ * (close the tab, redirect, …). Same "no I/O" contract as `useSigningSession`.
21
+ *
22
+ * `onElapsed` is read through a ref, so changing the callback doesn't restart
23
+ * the timer. SSR-safe: the timer only ticks inside an effect (client-only).
24
+ *
25
+ * @example
26
+ * const { remaining } = useCountdown(10, {
27
+ * onElapsed: () => {
28
+ * window.close(); // best-effort — blocked for user-opened tabs
29
+ * window.location.assign('https://www.alfadocs.com'); // fallback
30
+ * },
31
+ * });
32
+ */
33
+ export declare function useCountdown(seconds: number, options?: UseCountdownOptions): UseCountdownReturn;
34
+ //# sourceMappingURL=use-countdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-countdown.d.ts","sourceRoot":"","sources":["../../src/hooks/use-countdown.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,SAAS,EAAE,OAAO,CAAC;IACnB,wCAAwC;IACxC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,sEAAsE;IACtE,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,mBAAwB,GAChC,kBAAkB,CAyCpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfadocs/ui-kit-debug",
3
- "version": "0.57.0",
3
+ "version": "0.58.0",
4
4
  "type": "module",
5
5
  "description": "AlfaDocs shared design system — tokens, components, patterns, and translations for platform, booking, and alfascribe. (debug build — identical runtime to @alfadocs/ui-kit, ships source maps for symbolication).",
6
6
  "license": "BUSL-1.1",