@alfadocs/ui-kit 1.44.0 → 1.45.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.
@@ -0,0 +1,103 @@
1
+ import { useState as v, useEffect as _, useCallback as e } from "react";
2
+ import { u as k } from "./use-prefers-reduced-motion-BMwIQRjB.js";
3
+ const y = {
4
+ intro: 3200,
5
+ landed: 2800
6
+ }, g = {
7
+ intro: "ds:animate-[ai-pill-shimmer_calc(var(--animation-duration)*6)_var(--ease-in-out)_1]",
8
+ working: "ds:animate-[ai-pill-shimmer_calc(var(--animation-duration)*6)_var(--ease-in-out)_infinite]",
9
+ landed: "ds:animate-[ai-pill-shimmer_calc(var(--animation-duration)*4)_var(--ease-out)_1]"
10
+ }, S = {
11
+ intro: "ds:animate-[ai-comet-orbit_calc(var(--animation-duration)*7)_var(--ease-in-out)_1_both]",
12
+ working: "ds:animate-[ai-comet-orbit_calc(var(--animation-duration)*8)_linear_infinite]",
13
+ landed: "ds:animate-[ai-comet-orbit_calc(var(--animation-duration)*5)_var(--ease-out)_1_both]"
14
+ }, w = {
15
+ intro: "ds:[--sparkle-base:8] ds:animate-[ai-sparkle-burst_calc(var(--animation-duration)*5)_var(--ease-in-out)_1_both]",
16
+ working: "ds:[--sparkle-base:0] ds:animate-[ai-sparkle-twinkle_calc(var(--animation-duration)*8)_var(--ease-in-out)_infinite]",
17
+ landed: "ds:[--sparkle-base:6] ds:animate-[ai-sparkle-burst_calc(var(--animation-duration)*5)_var(--ease-in-out)_1_both]"
18
+ }, s = "ds:absolute ds:opacity-0 ds:text-[color:var(--ai-sparkle)] ds:fill-current ds:drop-shadow-[0_0_var(--spacing-2xs)_var(--ai-sparkle)] ds:[animation-delay:calc(var(--animation-duration)*(var(--sparkle-base)+var(--sparkle-stagger)))]", z = [
19
+ {
20
+ key: "start",
21
+ className: `${s} ds:[--sparkle-stagger:0] ds:size-3 ds:[inset-block-start:calc(var(--spacing-xs)*-1)] ds:[inset-inline-start:calc(var(--spacing-2xs)*-1)]`
22
+ },
23
+ {
24
+ key: "top",
25
+ className: `${s} ds:[--sparkle-stagger:0.5] ds:size-4 ds:[inset-block-start:calc(var(--spacing-sm)*-1)] ds:[inset-inline-start:40%]`
26
+ },
27
+ {
28
+ key: "end",
29
+ className: `${s} ds:[--sparkle-stagger:1] ds:size-3 ds:[inset-block-start:calc(var(--spacing-xs)*-1)] ds:[inset-inline-end:var(--spacing-md)]`
30
+ },
31
+ {
32
+ key: "side",
33
+ className: `${s} ds:[--sparkle-stagger:1.5] ds:size-2 ds:[inset-block-start:40%] ds:[inset-inline-end:calc(var(--spacing-sm)*-1)]`
34
+ },
35
+ {
36
+ key: "below",
37
+ className: `${s} ds:[--sparkle-stagger:2] ds:size-3 ds:[inset-block-end:calc(var(--spacing-xs)*-1)] ds:[inset-inline-start:25%]`
38
+ }
39
+ ], h = "ds:pointer-events-none ds:absolute ds:[inset-block-start:0] ds:[inset-inline-start:0] ds:opacity-0 ds:[offset-path:inset(0_round_var(--radius-full))] ds:[offset-rotate:0deg]", C = [
40
+ {
41
+ key: 1,
42
+ lag: "ds:[animation-delay:calc(var(--animation-duration)*0.2)]",
43
+ dot: "ds:size-2.5 ds:opacity-[var(--opacity-90)]"
44
+ },
45
+ {
46
+ key: 2,
47
+ lag: "ds:[animation-delay:calc(var(--animation-duration)*0.4)]",
48
+ dot: "ds:size-2 ds:opacity-[var(--opacity-70)]"
49
+ },
50
+ {
51
+ key: 3,
52
+ lag: "ds:[animation-delay:calc(var(--animation-duration)*0.6)]",
53
+ dot: "ds:size-2 ds:opacity-[var(--opacity-50)]"
54
+ },
55
+ {
56
+ key: 4,
57
+ lag: "ds:[animation-delay:calc(var(--animation-duration)*0.8)]",
58
+ dot: "ds:size-1.5 ds:opacity-[var(--opacity-30)]"
59
+ },
60
+ {
61
+ key: 5,
62
+ lag: "ds:[animation-delay:calc(var(--animation-duration)*1)]",
63
+ dot: "ds:size-1.5 ds:opacity-[var(--opacity-20)]"
64
+ },
65
+ {
66
+ key: 6,
67
+ lag: "ds:[animation-delay:calc(var(--animation-duration)*1.2)]",
68
+ dot: "ds:size-1 ds:opacity-[var(--opacity-10)]"
69
+ }
70
+ ];
71
+ function A(o = {}) {
72
+ const { enabled: r = !0, reducedMotion: d = "auto" } = o, c = k(), n = d === "off" ? !1 : c, [a, i] = v(
73
+ r ? "intro" : null
74
+ );
75
+ _(() => {
76
+ if (a !== "intro" && a !== "landed") return;
77
+ const t = n ? 0 : y[a], p = window.setTimeout(() => i(null), t);
78
+ return () => window.clearTimeout(p);
79
+ }, [a, n]);
80
+ const l = e(() => i("working"), []), m = e(() => i("landed"), []), u = e(() => {
81
+ i((t) => t === "working" ? null : t);
82
+ }, []);
83
+ return {
84
+ state: a,
85
+ props: {
86
+ "data-ai-sparkle": a ?? void 0,
87
+ className: a ? g[a] : ""
88
+ },
89
+ start: l,
90
+ land: m,
91
+ reset: u
92
+ };
93
+ }
94
+ export {
95
+ w as B,
96
+ C,
97
+ z as S,
98
+ h as a,
99
+ S as b,
100
+ g as c,
101
+ A as u
102
+ };
103
+ //# sourceMappingURL=use-ai-sparkle-CyQSRTCe.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "packageVersion": "1.44.0",
3
+ "packageVersion": "1.45.0",
4
4
  "components": [
5
5
  {
6
6
  "kind": "component",
@@ -0,0 +1,24 @@
1
+ import { type AiSparkleState } from '../../hooks/use-ai-sparkle';
2
+ export type { AiSparkleState };
3
+ export interface AiSparkleProps {
4
+ /**
5
+ * The current phase, from `useAiSparkle`. Renders nothing when `null` —
6
+ * callers don't need to guard the mount themselves.
7
+ */
8
+ state: AiSparkleState | null;
9
+ }
10
+ /**
11
+ * The AI pill's comet + burst sparkle: a comet with a six-dot tail riding
12
+ * the host's rounded outline, plus five staggered stars that burst (intro,
13
+ * landed) or twinkle (working) around it.
14
+ *
15
+ * Purely decorative (`aria-hidden`) and stateless — pass the `state` from
16
+ * `useAiSparkle`. The shimmer layer (a light sweep across the host itself)
17
+ * is not part of this component: it needs no extra DOM, so it travels as
18
+ * a class string on `useAiSparkle(...).props.className` instead. Position
19
+ * this component's host with `relative` (or `absolute`) sizing that matches
20
+ * the surface the sparkle decorates — it fills `inset-0` of its offset
21
+ * parent via the comet's `offset-path`.
22
+ */
23
+ export declare const AiSparkle: import("react").ForwardRefExoticComponent<AiSparkleProps & import("react").RefAttributes<HTMLSpanElement>>;
24
+ //# sourceMappingURL=ai-sparkle.d.ts.map
@@ -0,0 +1,3 @@
1
+ export { AiSparkle, type AiSparkleProps } from './ai-sparkle';
2
+ export type { AiSparkleState } from '../../hooks/use-ai-sparkle';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,5 @@
1
+ import { A as e } from "../../_chunks/ai-sparkle-DXeP_6a0.js";
2
+ export {
3
+ e as AiSparkle
4
+ };
5
+ //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
- export { usePrefersReducedMotion, useMediaQuery, useScrollToFirstError, useLocale, useTheme, resolveTheme, themeClassList, THEME_CLASS, THEME_STORAGE_KEY, ACCESSIBILITY_STORAGE_KEY, useSigningSession, useZoomDrilldown, ZOOM_DRILLDOWN_TRANSITION_CLASS, } from '../hooks';
2
- export type { LocaleDir, UseLocaleReturn, UseScrollToFirstErrorOptions, ThemePreference, AccessibilityPreference, ResolvedTheme, UseThemeReturn, SigningField, SigningFieldBase, UseSigningSessionReturn, UseZoomDrilldownOptions, UseZoomDrilldownReturn, } from '../hooks';
1
+ export { usePrefersReducedMotion, useMediaQuery, useScrollToFirstError, useLocale, useTheme, resolveTheme, themeClassList, THEME_CLASS, THEME_STORAGE_KEY, ACCESSIBILITY_STORAGE_KEY, useSigningSession, useZoomDrilldown, ZOOM_DRILLDOWN_TRANSITION_CLASS, useAiSparkle, } from '../hooks';
2
+ export type { LocaleDir, UseLocaleReturn, UseScrollToFirstErrorOptions, ThemePreference, AccessibilityPreference, ResolvedTheme, UseThemeReturn, SigningField, SigningFieldBase, UseSigningSessionReturn, UseZoomDrilldownOptions, UseZoomDrilldownReturn, AiSparkleState, UseAiSparkleOptions, UseAiSparkleReturn, } from '../hooks';
3
3
  export * from './button';
4
4
  export * from './button-group';
5
5
  export * from './floating-action-button';
@@ -161,6 +161,7 @@ export * from './unit-converter';
161
161
  export * from './visually-hidden';
162
162
  export * from './chart';
163
163
  export * from './ai-prompt-input';
164
+ export * from './ai-sparkle';
164
165
  export * from './audio-recorder';
165
166
  export * from './audio-visualiser';
166
167
  export * from './chat-container';
@@ -1,4 +1,4 @@
1
- import { N as a } from "../../_chunks/notes-panel-CY4KmDo-.js";
1
+ import { N as a } from "../../_chunks/notes-panel-Dkk9QPPX.js";
2
2
  export {
3
3
  a as NotesPanel
4
4
  };
@@ -1,4 +1,4 @@
1
- import { R as a, r as e, w as i } from "../../_chunks/rich-text-editor-BYE6kK4u.js";
1
+ import { R as a, r as e, w as i } from "../../_chunks/rich-text-editor-BrAvNajV.js";
2
2
  export {
3
3
  a as RichTextEditor,
4
4
  e as richTextEditorAgent,
@@ -30,4 +30,5 @@ export { usePresenceTransition, type PresencePhase, type UsePresenceTransitionOp
30
30
  export { useListReflow, REFLOW_ROW_CLASS, type UseListReflowOptions, type UseListReflowReturn, } from './use-list-reflow';
31
31
  export { useClampOverflow } from './use-clamp-overflow';
32
32
  export { useScrollOverflow, type UseScrollOverflowReturn, } from './use-scroll-overflow';
33
+ export { useAiSparkle, SHIMMER_CLASS as AI_SPARKLE_SHIMMER_CLASS, COMET_CLASS as AI_SPARKLE_COMET_CLASS, BURST_CLASS as AI_SPARKLE_BURST_CLASS, SPARKLE_GLYPHS as AI_SPARKLE_GLYPHS, COMET_TAIL as AI_SPARKLE_COMET_TAIL, COMET_WRAPPER_CLASS as AI_SPARKLE_COMET_WRAPPER_CLASS, type AiSparkleState, type UseAiSparkleOptions, type UseAiSparkleProps, type UseAiSparkleReturn, } from './use-ai-sparkle';
33
34
  //# sourceMappingURL=index.d.ts.map
@@ -1,40 +1,41 @@
1
- import { u as h } from "../_chunks/use-prefers-reduced-motion-BMwIQRjB.js";
2
- import { u as y } from "../_chunks/use-media-query-CcAx5SMM.js";
3
- import { Z as D, u as R, a as _, b as F } from "../_chunks/use-zoom-drilldown-qCX34w9I.js";
4
- import { u as g } from "../_chunks/use-count-up-BLLetaZ8.js";
5
- import { u as k } from "../_chunks/use-locale-BkCIHujH.js";
6
- import { A as M, T as V, a as W, r as H, t as N, u as Y } from "../_chunks/use-theme-CAuo6EYT.js";
7
- import { u as q } from "../_chunks/use-controllable-state-BiY4xTzM.js";
8
- import { u as G } from "../_chunks/use-copy-to-clipboard-Cyfc_dlv.js";
1
+ import { u as R } from "../_chunks/use-prefers-reduced-motion-BMwIQRjB.js";
2
+ import { u as I } from "../_chunks/use-media-query-CcAx5SMM.js";
3
+ import { Z as h, u as v, a as y, b as w } from "../_chunks/use-zoom-drilldown-qCX34w9I.js";
4
+ import { u as K } from "../_chunks/use-count-up-BLLetaZ8.js";
5
+ import { u as M } from "../_chunks/use-locale-BkCIHujH.js";
6
+ import { A as k, T as H, a as W, r as B, t as V, u as Y } from "../_chunks/use-theme-CAuo6EYT.js";
7
+ import { u as N } from "../_chunks/use-controllable-state-BiY4xTzM.js";
8
+ import { u as Z } from "../_chunks/use-copy-to-clipboard-Cyfc_dlv.js";
9
9
  import { u as j } from "../_chunks/use-debounced-callback-BisrB-Fq.js";
10
- import { useState as b, useRef as x, useEffect as E } from "react";
10
+ import { useState as A, useRef as S, useEffect as E } from "react";
11
11
  import { u as Q, a as J } from "../_chunks/use-direction-Dp8h70PP.js";
12
12
  import { u as $ } from "../_chunks/use-persistent-state-nZwZAnE9.js";
13
13
  import { u as te } from "../_chunks/use-isomorphic-layout-effect-BGfaCOP1.js";
14
- import { u as oe, a as ue } from "../_chunks/use-scroll-overflow-UbLrUfBo.js";
14
+ import { u as oe, a as se } from "../_chunks/use-scroll-overflow-UbLrUfBo.js";
15
15
  import { c as ne, u as ae } from "../_chunks/use-priority-overflow-c9SjxZkZ.js";
16
16
  import { u as ce } from "../_chunks/use-web-otp-D_utzp6S.js";
17
17
  import { u as fe } from "../_chunks/use-visual-viewport-pin-ChurOsHM.js";
18
18
  import { u as de } from "../_chunks/use-edge-resize-BHesP0kg.js";
19
- import { u as xe } from "../_chunks/use-countdown-Yd6ts0_a.js";
20
- import { u as be } from "../_chunks/use-check-animation--I3cS00X.js";
21
- import { R as Te, u as Ce, a as Le } from "../_chunks/use-list-reflow-Cw43nxw5.js";
22
- import { u as Oe } from "../_chunks/use-presence-transition-cDwWUXV-.js";
23
- import { u as ve } from "../_chunks/use-clamp-overflow-DQE2kwZ9.js";
24
- function C(e, o) {
25
- const [t, i] = b(e), u = x(null);
19
+ import { u as Se } from "../_chunks/use-countdown-Yd6ts0_a.js";
20
+ import { u as Ae } from "../_chunks/use-check-animation--I3cS00X.js";
21
+ import { R as Le, u as _e, a as Ce } from "../_chunks/use-list-reflow-Cw43nxw5.js";
22
+ import { u as be } from "../_chunks/use-presence-transition-cDwWUXV-.js";
23
+ import { u as Oe } from "../_chunks/use-clamp-overflow-DQE2kwZ9.js";
24
+ import { B as Pe, b as he, C as ve, a as ye, S as we, c as De, u as Ke } from "../_chunks/use-ai-sparkle-CyQSRTCe.js";
25
+ function _(e, o) {
26
+ const [t, i] = A(e), s = S(null);
26
27
  return E(() => {
27
28
  if (o <= 0) {
28
- u.current !== null && (clearTimeout(u.current), u.current = null), i(e);
29
+ s.current !== null && (clearTimeout(s.current), s.current = null), i(e);
29
30
  return;
30
31
  }
31
32
  const n = setTimeout(() => {
32
- i(e), u.current = null;
33
+ i(e), s.current = null;
33
34
  }, o);
34
- return u.current = n, () => clearTimeout(n);
35
+ return s.current = n, () => clearTimeout(n);
35
36
  }, [e, o]), t;
36
37
  }
37
- const S = [
38
+ const x = [
38
39
  "a[href]",
39
40
  "button:not([disabled])",
40
41
  'input:not([disabled]):not([type="hidden"])',
@@ -47,7 +48,7 @@ const S = [
47
48
  ].join(",");
48
49
  function p(e) {
49
50
  return Array.from(
50
- e.querySelectorAll(S)
51
+ e.querySelectorAll(x)
51
52
  ).filter((o) => {
52
53
  if (o.hidden) return !1;
53
54
  let t = o;
@@ -58,75 +59,82 @@ function p(e) {
58
59
  return !0;
59
60
  });
60
61
  }
61
- function L(e, o = {}) {
62
- const { enabled: t = !0, autoFocus: i = !0, restoreFocus: u = !0 } = o, n = x(null);
62
+ function C(e, o = {}) {
63
+ const { enabled: t = !0, autoFocus: i = !0, restoreFocus: s = !0 } = o, n = S(null);
63
64
  E(() => {
64
65
  if (!t) return;
65
66
  const a = e.current;
66
67
  if (!a) return;
67
68
  if (n.current = typeof document < "u" && document.activeElement instanceof HTMLElement ? document.activeElement : null, i) {
68
- const s = p(a)[0] ?? (a.tabIndex >= -1 ? a : null);
69
- s == null || s.focus();
69
+ const u = p(a)[0] ?? (a.tabIndex >= -1 ? a : null);
70
+ u == null || u.focus();
70
71
  }
71
72
  function f(r) {
72
73
  if (r.key !== "Tab") return;
73
- const s = e.current;
74
- if (!s) return;
75
- const c = p(s);
74
+ const u = e.current;
75
+ if (!u) return;
76
+ const c = p(u);
76
77
  if (c.length === 0) {
77
78
  r.preventDefault();
78
79
  return;
79
80
  }
80
81
  const m = c[0], d = c[c.length - 1], l = document.activeElement;
81
- r.shiftKey ? (l === m || !s.contains(l)) && (r.preventDefault(), d.focus()) : (l === d || !s.contains(l)) && (r.preventDefault(), m.focus());
82
+ r.shiftKey ? (l === m || !u.contains(l)) && (r.preventDefault(), d.focus()) : (l === d || !u.contains(l)) && (r.preventDefault(), m.focus());
82
83
  }
83
84
  return a.addEventListener("keydown", f), () => {
84
- if (a.removeEventListener("keydown", f), u && n.current) {
85
+ if (a.removeEventListener("keydown", f), s && n.current) {
85
86
  const r = n.current;
86
87
  requestAnimationFrame(() => {
87
88
  r.isConnected && r.focus();
88
89
  });
89
90
  }
90
91
  };
91
- }, [t, i, u, e]);
92
+ }, [t, i, s, e]);
92
93
  }
93
94
  export {
94
- M as ACCESSIBILITY_STORAGE_KEY,
95
- Te as REFLOW_ROW_CLASS,
96
- V as THEME_CLASS,
95
+ k as ACCESSIBILITY_STORAGE_KEY,
96
+ Pe as AI_SPARKLE_BURST_CLASS,
97
+ he as AI_SPARKLE_COMET_CLASS,
98
+ ve as AI_SPARKLE_COMET_TAIL,
99
+ ye as AI_SPARKLE_COMET_WRAPPER_CLASS,
100
+ we as AI_SPARKLE_GLYPHS,
101
+ De as AI_SPARKLE_SHIMMER_CLASS,
102
+ Le as REFLOW_ROW_CLASS,
103
+ H as THEME_CLASS,
97
104
  W as THEME_STORAGE_KEY,
98
- D as ZOOM_DRILLDOWN_TRANSITION_CLASS,
105
+ h as ZOOM_DRILLDOWN_TRANSITION_CLASS,
99
106
  ne as computePriorityLayout,
100
- H as resolveTheme,
101
- N as themeClassList,
102
- be as useCheckAnimation,
103
- ve as useClampOverflow,
104
- q as useControllableState,
105
- G as useCopyToClipboard,
106
- g as useCountUp,
107
- xe as useCountdown,
107
+ B as resolveTheme,
108
+ V as themeClassList,
109
+ Ke as useAiSparkle,
110
+ Ae as useCheckAnimation,
111
+ Oe as useClampOverflow,
112
+ N as useControllableState,
113
+ Z as useCopyToClipboard,
114
+ K as useCountUp,
115
+ Se as useCountdown,
108
116
  j as useDebouncedCallback,
109
- C as useDebouncedValue,
117
+ _ as useDebouncedValue,
110
118
  Q as useDirection,
111
119
  J as useDocumentDirection,
112
120
  de as useEdgeResize,
113
- Ce as useExitTransition,
114
- L as useFocusTrap,
121
+ _e as useExitTransition,
122
+ C as useFocusTrap,
115
123
  te as useIsomorphicLayoutEffect,
116
- Le as useListReflow,
117
- k as useLocale,
118
- y as useMediaQuery,
124
+ Ce as useListReflow,
125
+ M as useLocale,
126
+ I as useMediaQuery,
119
127
  oe as useOverflowCollapse,
120
128
  $ as usePersistentState,
121
- h as usePrefersReducedMotion,
122
- Oe as usePresenceTransition,
129
+ R as usePrefersReducedMotion,
130
+ be as usePresenceTransition,
123
131
  ae as usePriorityOverflow,
124
- ue as useScrollOverflow,
125
- R as useScrollToFirstError,
126
- _ as useSigningSession,
132
+ se as useScrollOverflow,
133
+ v as useScrollToFirstError,
134
+ y as useSigningSession,
127
135
  Y as useTheme,
128
136
  fe as useVisualViewportPin,
129
137
  ce as useWebOtp,
130
- F as useZoomDrilldown
138
+ w as useZoomDrilldown
131
139
  };
132
140
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,109 @@
1
+ /** Where the sparkle is: on first show, while an action runs, as it lands. */
2
+ export type AiSparkleState = 'intro' | 'working' | 'landed';
3
+ export declare const SHIMMER_CLASS: Record<AiSparkleState, string>;
4
+ export declare const COMET_CLASS: Record<AiSparkleState, string>;
5
+ export declare const BURST_CLASS: Record<AiSparkleState, string>;
6
+ export declare const SPARKLE_GLYPHS: readonly [{
7
+ readonly key: "start";
8
+ readonly className: "ds:absolute ds:opacity-0 ds:text-[color:var(--ai-sparkle)] ds:fill-current ds:drop-shadow-[0_0_var(--spacing-2xs)_var(--ai-sparkle)] ds:[animation-delay:calc(var(--animation-duration)*(var(--sparkle-base)+var(--sparkle-stagger)))] ds:[--sparkle-stagger:0] ds:size-3 ds:[inset-block-start:calc(var(--spacing-xs)*-1)] ds:[inset-inline-start:calc(var(--spacing-2xs)*-1)]";
9
+ }, {
10
+ readonly key: "top";
11
+ readonly className: "ds:absolute ds:opacity-0 ds:text-[color:var(--ai-sparkle)] ds:fill-current ds:drop-shadow-[0_0_var(--spacing-2xs)_var(--ai-sparkle)] ds:[animation-delay:calc(var(--animation-duration)*(var(--sparkle-base)+var(--sparkle-stagger)))] ds:[--sparkle-stagger:0.5] ds:size-4 ds:[inset-block-start:calc(var(--spacing-sm)*-1)] ds:[inset-inline-start:40%]";
12
+ }, {
13
+ readonly key: "end";
14
+ readonly className: "ds:absolute ds:opacity-0 ds:text-[color:var(--ai-sparkle)] ds:fill-current ds:drop-shadow-[0_0_var(--spacing-2xs)_var(--ai-sparkle)] ds:[animation-delay:calc(var(--animation-duration)*(var(--sparkle-base)+var(--sparkle-stagger)))] ds:[--sparkle-stagger:1] ds:size-3 ds:[inset-block-start:calc(var(--spacing-xs)*-1)] ds:[inset-inline-end:var(--spacing-md)]";
15
+ }, {
16
+ readonly key: "side";
17
+ readonly className: "ds:absolute ds:opacity-0 ds:text-[color:var(--ai-sparkle)] ds:fill-current ds:drop-shadow-[0_0_var(--spacing-2xs)_var(--ai-sparkle)] ds:[animation-delay:calc(var(--animation-duration)*(var(--sparkle-base)+var(--sparkle-stagger)))] ds:[--sparkle-stagger:1.5] ds:size-2 ds:[inset-block-start:40%] ds:[inset-inline-end:calc(var(--spacing-sm)*-1)]";
18
+ }, {
19
+ readonly key: "below";
20
+ readonly className: "ds:absolute ds:opacity-0 ds:text-[color:var(--ai-sparkle)] ds:fill-current ds:drop-shadow-[0_0_var(--spacing-2xs)_var(--ai-sparkle)] ds:[animation-delay:calc(var(--animation-duration)*(var(--sparkle-base)+var(--sparkle-stagger)))] ds:[--sparkle-stagger:2] ds:size-3 ds:[inset-block-end:calc(var(--spacing-xs)*-1)] ds:[inset-inline-start:25%]";
21
+ }];
22
+ export declare const COMET_WRAPPER_CLASS = "ds:pointer-events-none ds:absolute ds:[inset-block-start:0] ds:[inset-inline-start:0] ds:opacity-0 ds:[offset-path:inset(0_round_var(--radius-full))] ds:[offset-rotate:0deg]";
23
+ export declare const COMET_TAIL: readonly [{
24
+ readonly key: 1;
25
+ readonly lag: "ds:[animation-delay:calc(var(--animation-duration)*0.2)]";
26
+ readonly dot: "ds:size-2.5 ds:opacity-[var(--opacity-90)]";
27
+ }, {
28
+ readonly key: 2;
29
+ readonly lag: "ds:[animation-delay:calc(var(--animation-duration)*0.4)]";
30
+ readonly dot: "ds:size-2 ds:opacity-[var(--opacity-70)]";
31
+ }, {
32
+ readonly key: 3;
33
+ readonly lag: "ds:[animation-delay:calc(var(--animation-duration)*0.6)]";
34
+ readonly dot: "ds:size-2 ds:opacity-[var(--opacity-50)]";
35
+ }, {
36
+ readonly key: 4;
37
+ readonly lag: "ds:[animation-delay:calc(var(--animation-duration)*0.8)]";
38
+ readonly dot: "ds:size-1.5 ds:opacity-[var(--opacity-30)]";
39
+ }, {
40
+ readonly key: 5;
41
+ readonly lag: "ds:[animation-delay:calc(var(--animation-duration)*1)]";
42
+ readonly dot: "ds:size-1.5 ds:opacity-[var(--opacity-20)]";
43
+ }, {
44
+ readonly key: 6;
45
+ readonly lag: "ds:[animation-delay:calc(var(--animation-duration)*1.2)]";
46
+ readonly dot: "ds:size-1 ds:opacity-[var(--opacity-10)]";
47
+ }];
48
+ export interface UseAiSparkleOptions {
49
+ /**
50
+ * Whether the sparkle is available at all. Read once, at mount, to seed
51
+ * the initial `'intro'` phase — matches how the RichTextEditor's
52
+ * `aiSparkle` prop only ever gated the very first render. Default `true`.
53
+ */
54
+ enabled?: boolean;
55
+ /**
56
+ * `'auto'` (default) reads `prefers-reduced-motion` via
57
+ * `usePrefersReducedMotion`. `'off'` forces full motion regardless of the
58
+ * OS preference — useful for a story that wants to show the animated
59
+ * states side by side with a reduced one.
60
+ */
61
+ reducedMotion?: 'auto' | 'off';
62
+ }
63
+ export interface UseAiSparkleProps {
64
+ /** Spread (or picked) onto the host element as a pure styling hook. */
65
+ 'data-ai-sparkle': AiSparkleState | undefined;
66
+ /**
67
+ * The shimmer animation class for the current state — empty when at rest.
68
+ * Layer it over the host's own base positioning classes; the comet and
69
+ * burst layers need real DOM and live in the `AiSparkle` component instead.
70
+ */
71
+ className: string;
72
+ }
73
+ export interface UseAiSparkleReturn {
74
+ /** `null` at rest — nothing to render for the comet/burst layers either. */
75
+ state: AiSparkleState | null;
76
+ props: UseAiSparkleProps;
77
+ /** An AI action started: swap to the looping `'working'` phase. */
78
+ start: () => void;
79
+ /** An action's result landed: swap to the one-off `'landed'` phase. */
80
+ land: () => void;
81
+ /**
82
+ * Settle after an action ends. Clears back to rest only when still
83
+ * `'working'` (the action errored or was cancelled before `land()`);
84
+ * leaves `'landed'` alone so the one-off animation gets to play out.
85
+ */
86
+ reset: () => void;
87
+ }
88
+ /**
89
+ * Drives the AI-pill sparkle: lit on first show, looping while an action
90
+ * runs, and a one-off flourish as the result lands.
91
+ *
92
+ * The hook owns the state machine and the timing only — it paints nothing.
93
+ * `props['data-ai-sparkle']` is a plain styling hook for the host element;
94
+ * `props.className` carries the shimmer layer's animation class from the
95
+ * same lookup table the RichTextEditor's pill originally inlined. The
96
+ * comet and burst layers need actual DOM (a tail of dots, five staggered
97
+ * glyphs), so they live in the sibling `AiSparkle` component, keyed off the
98
+ * same `state`.
99
+ *
100
+ * Both `intro` and `landed` are one-off: this hook clears them back to
101
+ * `null` on a timer sized to the comet's lap plus the burst and its
102
+ * stagger, at the default 200ms `--animation-duration`. Under reduced
103
+ * motion (`prefers-reduced-motion` or `reducedMotion: 'auto'`'s system
104
+ * read) the CSS animations already collapse to 0ms, so the clear fires at
105
+ * the next tick instead of waiting out the full lap — the pill still gets
106
+ * its `data-ai-sparkle` attribute for a moment, but nothing visibly moves.
107
+ */
108
+ export declare function useAiSparkle(options?: UseAiSparkleOptions): UseAiSparkleReturn;
109
+ //# sourceMappingURL=use-ai-sparkle.d.ts.map