@qredence/fleet 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/web/client/assets/action-swap-roll-COzQ86wm.js +1 -0
  3. package/dist/web/client/assets/agent-activity-svETLf_5.js +1 -0
  4. package/dist/web/client/assets/agent-disclosure-DAMuuGcM.js +1 -0
  5. package/dist/web/client/assets/analytics-stub-B6zGMuSV.js +1 -0
  6. package/dist/web/client/assets/{artifacts-panel-CJ75gQub.js → artifacts-panel-HVjqBMyx.js} +1 -1
  7. package/dist/web/client/assets/button-C5wFDY5_.js +1 -0
  8. package/dist/web/client/assets/card-DA3Vnqay.js +1 -0
  9. package/dist/web/client/assets/chat-BhYseKd6.js +52 -0
  10. package/dist/web/client/assets/{chat-command-palette-CkISHfKE.js → chat-command-palette-LILDO_vG.js} +1 -1
  11. package/dist/web/client/assets/{citations-C_tPOJE_.js → citations-BPv8HIpf.js} +2 -2
  12. package/dist/web/client/assets/command-PhicLCoO.js +1 -0
  13. package/dist/web/client/assets/dialog-pBGUjAQ7.js +1 -0
  14. package/dist/web/client/assets/{fleet-message-queue-BCno4XP-.js → fleet-message-queue-fbYYwMj0.js} +1 -1
  15. package/dist/web/client/assets/{fleet-pi-tool-renderer-BEDIO3al.js → fleet-pi-tool-renderer-BRgNnmaJ.js} +28 -28
  16. package/dist/web/client/assets/fleet-reasoning-panel-CjA2dwUJ.js +1 -0
  17. package/dist/web/client/assets/{fork-picker-dialog-ByBOGVsa.js → fork-picker-dialog-B7NNpVmW.js} +1 -1
  18. package/dist/web/client/assets/globals-CuIiqOTg.css +2 -0
  19. package/dist/web/client/assets/horizontal-resize-Cp3iHMH7.js +1 -0
  20. package/dist/web/client/assets/index-CSGplyr_.js +12 -0
  21. package/dist/web/client/assets/{input-0wwjWjKq.js → input-PcdubeKn.js} +1 -1
  22. package/dist/web/client/assets/input-group-C2HJEZvl.js +1 -0
  23. package/dist/web/client/assets/ipython-tool-CyuMOxz1.js +3 -0
  24. package/dist/web/client/assets/{markdown-code-CuQcR3UO.js → markdown-code-xNyjdZ4g.js} +1 -1
  25. package/dist/web/client/assets/{markdown-DInPmRUG.js → markdown-lvexwooo.js} +2 -2
  26. package/dist/web/client/assets/{model-selector-list-Ch05B2nZ.js → model-selector-list-CoXX358G.js} +1 -1
  27. package/dist/web/client/assets/{notify-DgMKgZZW.js → notify-DxL0VD7Z.js} +1 -1
  28. package/dist/web/client/assets/openui-renderer-TLNe5e_Q.js +378 -0
  29. package/dist/web/client/assets/prompt-input-fwP8TsgQ.js +1 -0
  30. package/dist/web/client/assets/{prompt-suggestions-Cc--lSNR.js → prompt-suggestions-BlGXmWS7.js} +1 -1
  31. package/dist/web/client/assets/provider-catalog-DYMFdbKc.js +1 -0
  32. package/dist/web/client/assets/provider-label-B4q5mI65.js +1 -0
  33. package/dist/web/client/assets/{repl-panel-DsPX04Xr.js → repl-panel-C5om8MGU.js} +1 -1
  34. package/dist/web/client/assets/{right-panel-registry-Dp8yX-oL.js → right-panel-registry-BBlxLxnx.js} +2 -2
  35. package/dist/web/client/assets/routes-XGsAIqBJ.js +16 -0
  36. package/dist/web/client/assets/settings-dialog-BSBasR3o.js +2 -0
  37. package/dist/web/client/assets/{subagent-chat-panel-Yujplxpb.js → subagent-chat-panel-oeLDPDAK.js} +1 -1
  38. package/dist/web/client/assets/{subagent-transcript-CnI-mqN0.js → subagent-transcript-DaVHjNUH.js} +1 -1
  39. package/dist/web/client/assets/{subagents-panel-CjXEdimj.js → subagents-panel-D_aVgSCi.js} +1 -1
  40. package/dist/web/client/assets/surfaces-BhAXz9So.js +1 -0
  41. package/dist/web/client/assets/{switch-9rTeg6J6.js → switch-WhXeJNNY.js} +1 -1
  42. package/dist/web/client/assets/{toast-Bt9p2OL4.js → toast-D3c9XeGe.js} +1 -1
  43. package/dist/web/client/assets/{tool-result-DfnPN0FQ.js → tool-result-Cki8WUNc.js} +3 -3
  44. package/dist/web/client/assets/virtualized-turn-list-CdMa-ydT.js +6 -0
  45. package/dist/web/client/assets/workspace-panel-77bDbprs.js +1 -0
  46. package/dist/web/client/bundle-budget.json +5 -5
  47. package/dist/web/launcher.mjs +10 -1
  48. package/dist/web/server/{_tanstack-start-manifest_v-DS_CSIFQ-WB3VTKF3.js → _tanstack-start-manifest_v-0L7fqnH4-KMVGUFE4.js} +24 -24
  49. package/dist/web/server/{agent-activity-CS2rbF_C-A3R26CYH.js → agent-activity-BuEE6iVw-CDZLK4D2.js} +4 -4
  50. package/dist/web/server/{artifacts-panel-CaKrX2XC-R37I4BHF.js → artifacts-panel-D3ySO--V-XSL53CXL.js} +18 -18
  51. package/dist/web/server/{chat-command-palette-7gbqEnm9-6XICQZN7.js → chat-command-palette-kAbXhWVg-TJWXH2WW.js} +9 -9
  52. package/dist/web/server/{chunk-CNXJN5HN.js → chunk-2DDWXTVG.js} +5 -5
  53. package/dist/web/server/{chunk-TWYHHG5N.js → chunk-2JHTYWD5.js} +15 -15
  54. package/dist/web/server/{chunk-EAE2QXRK.js → chunk-3TIMGWWI.js} +1 -2
  55. package/dist/web/server/{chunk-AGFRJQZ7.js → chunk-4WBFCB4O.js} +257 -257
  56. package/dist/web/server/{chunk-P6UMR32I.js → chunk-5UCAJBAH.js} +4 -4
  57. package/dist/web/server/{chunk-DZ2IC3FH.js → chunk-D27LRYVT.js} +42 -42
  58. package/dist/web/server/{chunk-YXXRP3NS.js → chunk-DLUZFOG3.js} +5 -5
  59. package/dist/web/server/{chunk-K3BXQG3N.js → chunk-EBG3XFGQ.js} +60 -60
  60. package/dist/web/server/{chunk-2ATMSG7U.js → chunk-EJEPDVK6.js} +3 -3
  61. package/dist/web/server/{chunk-IJPCV6DH.js → chunk-FYDQK6UX.js} +1 -1
  62. package/dist/web/server/{chunk-WHBVQJ4K.js → chunk-HF7DG7PC.js} +73 -73
  63. package/dist/web/server/{chunk-WYL2DW5R.js → chunk-JTCCQZLN.js} +2 -2
  64. package/dist/web/server/{chunk-UAPNEWCA.js → chunk-KP2PNDGL.js} +6 -6
  65. package/dist/web/server/{chunk-7SR6WDM2.js → chunk-MNBGB2SP.js} +2 -2
  66. package/dist/web/server/{chunk-HSJMLO36.js → chunk-MNPHMZU7.js} +3 -3
  67. package/dist/web/server/{chunk-JQDLJ7KI.js → chunk-NGCQJ33Y.js} +1134 -1134
  68. package/dist/web/server/{chunk-7SD2ZSEA.js → chunk-NIDBN7BQ.js} +1 -1
  69. package/dist/web/server/{chunk-ZJFA4F5X.js → chunk-NIZBFVJF.js} +2 -2
  70. package/dist/web/server/{chunk-PIOFZUOU.js → chunk-NJ4QEZHK.js} +3 -4
  71. package/dist/web/server/{chunk-WM4PUT6M.js → chunk-NNKJTKOQ.js} +234 -234
  72. package/dist/web/server/{chunk-N6NOTURM.js → chunk-NWDI3OWB.js} +4 -4
  73. package/dist/web/server/{chunk-KELEYPVK.js → chunk-O3HDELZ2.js} +74826 -74825
  74. package/dist/web/server/{chunk-YNUWKMNQ.js → chunk-PLYZ7P2Y.js} +1 -152
  75. package/dist/web/server/{chunk-LXJD6IGW.js → chunk-QFRCJWQQ.js} +7 -7
  76. package/dist/web/server/{chunk-NXJ32VFR.js → chunk-QIULBRTU.js} +13 -13
  77. package/dist/web/server/{chunk-DI7XRK2H.js → chunk-RIP3PBWT.js} +3 -3
  78. package/dist/web/server/{chunk-YKVGQBZA.js → chunk-S5LFXXDY.js} +625 -622
  79. package/dist/web/server/{chunk-XLNCWZMZ.js → chunk-UCUFC553.js} +3 -1
  80. package/dist/web/server/{chunk-KOUEJ3NU.js → chunk-UL2725KQ.js} +3 -3
  81. package/dist/web/server/{chunk-HFQTI7AX.js → chunk-VPKX7QRU.js} +3 -3
  82. package/dist/web/server/{chunk-LZ4Q5KUJ.js → chunk-WNCAL4HN.js} +133 -133
  83. package/dist/web/server/{chunk-C5X6G26O.js → chunk-XIB6XNUX.js} +436 -436
  84. package/dist/web/server/{chunk-EH4BZ6QM.js → chunk-YGYOBX7G.js} +2 -2
  85. package/dist/web/server/{chunk-BBBS5AS7.js → chunk-ZIFSJ3HQ.js} +626 -626
  86. package/dist/web/server/{fleet-message-queue-BS-cZ56r-GLZXUKDF.js → fleet-message-queue-D_w8lSeY-T3HB7HVQ.js} +5 -5
  87. package/dist/web/server/{fleet-pi-tool-renderer-umKunT3K-O4GBH35V.js → fleet-pi-tool-renderer-qwc-qZFq-4U556N5Q.js} +12 -12
  88. package/dist/web/server/{fleet-reasoning-panel-BxC2COxi-GPLMQSTT.js → fleet-reasoning-panel-DG_vuvv0-NCZWEEIT.js} +26 -26
  89. package/dist/web/server/{fleet-subagent-list-CpSYzCIq-JDH2LHSS.js → fleet-subagent-list-BGb0PjhF-2X67FMUV.js} +1 -1
  90. package/dist/web/server/{fleet-tool-timeline-IB36_PB2-XJENTO6I.js → fleet-tool-timeline-D6yM4ZMz-ZSFVRRRI.js} +1 -1
  91. package/dist/web/server/{fork-picker-dialog-DlINz9UQ-UWIXFDJX.js → fork-picker-dialog-Ds6Tgtu3-DIBWN7MV.js} +5 -5
  92. package/dist/web/server/{model-selector-list-jBTZc2Mu-OXJOS5NA.js → model-selector-list-DxeGZoD2-P6S6FSJH.js} +9 -9
  93. package/dist/web/server/{openui-renderer-Biyyjhjn-SJOEKPTJ.js → openui-renderer-MKFv6LlH-MDRSVFEY.js} +11 -11
  94. package/dist/web/server/{prompt-suggestions-D4AEEY7K-RZSP7PWV.js → prompt-suggestions-BOItmGnD-YQA7RHLG.js} +2 -2
  95. package/dist/web/server/{repl-panel-D5KsoJik-BQKO53JO.js → repl-panel-CuyF8wt5-CHDT2Q3N.js} +2 -2
  96. package/dist/web/server/{router-DWALoX_M-I5CBL7FQ.js → router-Dg72SESP-PCWKLFRG.js} +16 -16
  97. package/dist/web/server/{routes-BBVirYfL-5WXMOT7M.js → routes-BGrVtPYF-SURPAJN6.js} +6432 -6413
  98. package/dist/web/server/server.js +2 -2
  99. package/dist/web/server/{settings-dialog-DndPbM-v-RFNXXEAN.js → settings-dialog-CK0FJlTg-HZRBAXDZ.js} +1392 -1402
  100. package/dist/web/server/{subagent-chat-panel-C0RpnXav-J7VYO7QY.js → subagent-chat-panel-gzamnTgK-PQ2TLLJF.js} +21 -21
  101. package/dist/web/server/{subagents-panel-jDqIn9Nh-YEV6QLUY.js → subagents-panel-Berjd7HJ-EI5ZKC6V.js} +20 -20
  102. package/dist/web/server/{workspace-panel-CX_Vo6As-EWO6AMPI.js → workspace-panel-CBBa_3UO-B4PPFPMA.js} +45 -20
  103. package/package.json +1 -1
  104. package/dist/web/client/assets/action-swap-roll-BB8DFMuf.js +0 -1
  105. package/dist/web/client/assets/agent-activity-CwMDU7aP.js +0 -1
  106. package/dist/web/client/assets/agent-disclosure-B8SnhQXL.js +0 -1
  107. package/dist/web/client/assets/analytics-stub-Cas1He0w.js +0 -1
  108. package/dist/web/client/assets/button-BR2WWrFo.js +0 -1
  109. package/dist/web/client/assets/card-BKl76a3R.js +0 -1
  110. package/dist/web/client/assets/chat-Ci2cEQrR.js +0 -52
  111. package/dist/web/client/assets/command-_WjnervL.js +0 -1
  112. package/dist/web/client/assets/dialog-BEZuZhzk.js +0 -1
  113. package/dist/web/client/assets/fleet-reasoning-panel-CbkO7u-v.js +0 -1
  114. package/dist/web/client/assets/globals-B_I1Eq1u.css +0 -2
  115. package/dist/web/client/assets/horizontal-resize-CwoDojST.js +0 -1
  116. package/dist/web/client/assets/index-DJ1fFbQu.js +0 -12
  117. package/dist/web/client/assets/input-group-Tb5TYbzi.js +0 -1
  118. package/dist/web/client/assets/ipython-tool-ldJ9F1Cw.js +0 -3
  119. package/dist/web/client/assets/openui-renderer-Bf60nxNi.js +0 -378
  120. package/dist/web/client/assets/prompt-input-qPIXZ-Rb.js +0 -1
  121. package/dist/web/client/assets/provider-catalog-D8G66gwc.js +0 -1
  122. package/dist/web/client/assets/provider-label-DDLRnZyC.js +0 -1
  123. package/dist/web/client/assets/routes-DpgMJZ5n.js +0 -16
  124. package/dist/web/client/assets/settings-dialog-YJkvt5EB.js +0 -2
  125. package/dist/web/client/assets/surfaces-DI-U-_2a.js +0 -1
  126. package/dist/web/client/assets/virtualized-turn-list--Vynre4D.js +0 -6
  127. package/dist/web/client/assets/workspace-panel-CPPIznT9.js +0 -1
@@ -6,14 +6,17 @@ import {
6
6
  } from "./chunk-PVJCTQFK.js";
7
7
  import {
8
8
  useHoverCapable
9
- } from "./chunk-N6NOTURM.js";
9
+ } from "./chunk-NWDI3OWB.js";
10
+ import {
11
+ elevatedMenu
12
+ } from "./chunk-UCUFC553.js";
10
13
  import {
11
14
  LoaderCircle
12
15
  } from "./chunk-TNL4YV63.js";
13
16
  import {
14
17
  AnimatePresence,
15
18
  useReducedMotion
16
- } from "./chunk-ZJFA4F5X.js";
19
+ } from "./chunk-NIZBFVJF.js";
17
20
  import {
18
21
  EASE_OUT,
19
22
  MotionConfigContext,
@@ -24,7 +27,7 @@ import {
24
27
  m,
25
28
  useConstant,
26
29
  useIsomorphicLayoutEffect
27
- } from "./chunk-K3BXQG3N.js";
30
+ } from "./chunk-EBG3XFGQ.js";
28
31
  import {
29
32
  JSAnimation,
30
33
  cancelFrame,
@@ -50,7 +53,7 @@ import {
50
53
  cn
51
54
  } from "./chunk-DJMHPJBP.js";
52
55
 
53
- // web/app/dist/server/assets/prompt-input-CQuyIgBz.js
56
+ // web/app/dist/server/assets/prompt-input-BhmLC9Jj.js
54
57
  import { cloneElement, createContext, forwardRef, isValidElement, useCallback, useContext, useEffect, useEffectEvent, useId, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
55
58
  import { jsx, jsxs } from "react/jsx-runtime";
56
59
  import { createPortal } from "react-dom";
@@ -215,402 +218,68 @@ function useSpring(source, options = {}) {
215
218
  ...options
216
219
  });
217
220
  }
218
- var VARIANT_CLASS = {
219
- primary: "bg-primary text-primary-foreground hover:bg-primary/90",
220
- secondary: "border border-border bg-card text-foreground hover:border-border",
221
- ghost: "text-muted-foreground hover:text-foreground hover:bg-primary/5",
222
- outline: "border border-border bg-transparent text-foreground hover:bg-primary/5"
223
- };
224
- var SIZE_CLASS = {
225
- sm: "h-8 px-3 text-xs gap-1.5 rounded-full",
226
- md: "h-10 px-5 text-sm gap-2 rounded-full",
227
- lg: "h-12 px-6 text-base gap-2 rounded-full",
228
- icon: "h-8 w-8 rounded-lg"
221
+ var INSTANT_TRANSITION = { duration: 0 };
222
+ var CHEVRON_TRANSITION = {
223
+ type: "spring",
224
+ duration: 0.4,
225
+ bounce: 0.3
229
226
  };
230
- var Button = forwardRef(function Button2({ variant = "primary", size = "md", pressScale = 0.93, ripple = false, className, children, onPointerDown, ...rest }, ref) {
231
- const reduce = useReducedMotion();
232
- const canHover = useHoverCapable();
233
- const [ripples, setRipples] = useState([]);
234
- const nextId = useRef(0);
235
- const handlePointerDown = useCallback((event) => {
236
- if (ripple && !reduce) {
237
- const rect = event.currentTarget.getBoundingClientRect();
238
- const size2 = Math.max(rect.width, rect.height) * 2;
239
- const id = nextId.current++;
240
- setRipples((prev) => [...prev, {
241
- id,
242
- x: event.clientX - rect.left,
243
- y: event.clientY - rect.top,
244
- size: size2
245
- }]);
246
- }
247
- onPointerDown?.(event);
248
- }, [
249
- ripple,
250
- reduce,
251
- onPointerDown
252
- ]);
253
- return /* @__PURE__ */ jsxs(m.button, {
254
- ref,
255
- type: "button",
256
- whileTap: reduce ? void 0 : { scale: pressScale },
257
- whileHover: reduce || !canHover ? void 0 : { scale: 1.02 },
258
- transition: SPRING_PRESS,
259
- onPointerDown: handlePointerDown,
260
- className: cn("inline-flex items-center justify-center font-medium select-none", "transition-colors", "disabled:pointer-events-none disabled:opacity-50", ripple && "relative overflow-hidden", VARIANT_CLASS[variant], SIZE_CLASS[size], className),
261
- ...rest,
262
- children: [/* @__PURE__ */ jsx("span", {
263
- className: cn("pointer-events-none absolute inset-0 overflow-hidden rounded-[inherit]", !ripple && "hidden"),
264
- children: /* @__PURE__ */ jsx(AnimatePresence, { children: ripple && !reduce ? ripples.map((r) => /* @__PURE__ */ jsx(m.span, {
265
- className: "absolute rounded-full bg-current",
266
- style: {
267
- left: r.x,
268
- top: r.y,
269
- width: r.size,
270
- height: r.size,
271
- x: "-50%",
272
- y: "-50%"
273
- },
274
- initial: {
275
- scale: 0.05,
276
- opacity: 0.3
277
- },
278
- animate: {
279
- scale: 1,
280
- opacity: 0
281
- },
282
- exit: { opacity: 0 },
283
- transition: {
284
- duration: 1.6,
285
- ease: EASE_OUT
286
- },
287
- onAnimationComplete: () => setRipples((prev) => prev.filter((x) => x.id !== r.id))
288
- }, r.id)) : null })
289
- }), children]
290
- });
291
- });
292
- forwardRef(function ButtonLink({ variant = "primary", size = "md", pressScale = 0.93, className, children, ...rest }, ref) {
293
- const reduce = useReducedMotion();
294
- const canHover = useHoverCapable();
295
- return /* @__PURE__ */ jsx(m.a, {
296
- ref,
297
- whileTap: reduce ? void 0 : { scale: pressScale },
298
- whileHover: reduce || !canHover ? void 0 : { scale: 1.02 },
299
- transition: SPRING_PRESS,
300
- className: cn("inline-flex items-center justify-center font-medium select-none", "transition-colors", VARIANT_CLASS[variant], SIZE_CLASS[size], className),
301
- ...rest,
302
- children
303
- });
304
- });
305
- function Magnetic({ children, strength = 0.35, className }) {
306
- const ref = useRef(null);
307
- const reduce = useReducedMotion();
308
- const canHover = useHoverCapable();
309
- const enabled = !reduce && canHover;
310
- const x = useMotionValue(0);
311
- const y = useMotionValue(0);
312
- const sx = useSpring(x, SPRING_MOUSE);
313
- const sy = useSpring(y, SPRING_MOUSE);
314
- const onMove = (e) => {
315
- const el = ref.current;
316
- if (!el || !enabled) return;
317
- const rect = el.getBoundingClientRect();
318
- x.set((e.clientX - rect.left - rect.width / 2) * strength);
319
- y.set((e.clientY - rect.top - rect.height / 2) * strength);
320
- };
321
- const onLeave = () => {
322
- x.set(0);
323
- y.set(0);
324
- };
325
- return /* @__PURE__ */ jsx(m.div, {
326
- ref,
327
- onMouseMove: onMove,
328
- onMouseLeave: onLeave,
329
- style: {
330
- x: sx,
331
- y: sy
332
- },
333
- className: cn("inline-block", className),
334
- children
335
- });
336
- }
337
- forwardRef(function MagneticButton({ strength = 0.25, magneticClassName, children, ...rest }, ref) {
338
- return /* @__PURE__ */ jsx(Magnetic, {
339
- strength,
340
- className: magneticClassName,
341
- children: /* @__PURE__ */ jsx(Button, {
342
- ref,
343
- ...rest,
344
- children
345
- })
346
- });
347
- });
348
- var CASCADE_STAGGER = 0.025;
349
- var ROLL_BLUR = "blur(6px)";
350
- var CASCADE_LETTER_VARIANTS = {
351
- initial: {
352
- opacity: 0,
353
- y: "105%",
354
- filter: ROLL_BLUR
355
- },
356
- animate: (delay = 0) => ({
357
- opacity: 1,
358
- y: "0%",
359
- filter: "blur(0px)",
360
- transition: {
361
- ...SPRING_SWAP,
362
- delay
363
- }
364
- }),
365
- exit: (delay = 0) => ({
366
- opacity: 0,
367
- y: "-105%",
368
- filter: ROLL_BLUR,
369
- transition: {
370
- duration: 0.16,
371
- ease: EASE_OUT,
372
- delay: delay * 0.5
373
- }
374
- })
227
+ var LIST_VARIANTS = {
228
+ hidden: {},
229
+ show: { transition: {
230
+ staggerChildren: 0.035,
231
+ delayChildren: 0.05
232
+ } }
375
233
  };
376
- var ICON_VARIANTS = {
377
- initial: {
234
+ var ITEM_VARIANTS = {
235
+ hidden: {
378
236
  opacity: 0,
379
- width: 0,
380
- scale: 0.7,
381
- filter: ROLL_BLUR
237
+ y: -6,
238
+ filter: "blur(3px)"
382
239
  },
383
- animate: {
240
+ show: {
384
241
  opacity: 1,
385
- width: "1.5rem",
386
- scale: 1,
387
- filter: "blur(0px)",
388
- transition: SPRING_SWAP
389
- },
390
- exit: {
391
- opacity: 0,
392
- width: 0,
393
- scale: 0.7,
394
- filter: ROLL_BLUR,
395
- transition: {
396
- duration: 0.16,
397
- ease: EASE_OUT
398
- }
242
+ y: 0,
243
+ filter: "blur(0px)"
399
244
  }
400
245
  };
401
- function IconSlot({ keyId, children }) {
402
- const reduce = useReducedMotion();
403
- return /* @__PURE__ */ jsx(m.span, {
404
- variants: ICON_VARIANTS,
405
- initial: reduce ? { opacity: 0 } : "initial",
406
- animate: reduce ? { opacity: 1 } : "animate",
407
- exit: reduce ? { opacity: 0 } : "exit",
408
- transition: reduce ? { duration: 0.15 } : void 0,
409
- className: "inline-grid shrink-0 place-items-center overflow-hidden",
410
- children
411
- }, keyId);
246
+ var AnimatedSelectContext = createContext(null);
247
+ function useAnimatedSelectContext(component) {
248
+ const ctx = useContext(AnimatedSelectContext);
249
+ if (!ctx) throw new Error(`${component} must be used within <AnimatedSelect>`);
250
+ return ctx;
412
251
  }
413
- function TextSlot({ value, children }) {
414
- const reduce = useReducedMotion();
415
- const measureRef = useRef(null);
416
- const [width, setWidth] = useState();
417
- const label = typeof children === "string" ? children : null;
418
- const cascade = label !== null && !reduce;
419
- useLayoutEffect(() => {
420
- const nextWidth = measureRef.current?.offsetWidth;
421
- if (!nextWidth) return;
422
- setWidth((current) => current === nextWidth ? current : nextWidth);
423
- });
424
- return /* @__PURE__ */ jsxs(m.span, {
425
- initial: false,
426
- layout: "size",
427
- style: { width },
428
- transition: reduce ? { duration: 0 } : SPRING_SWAP,
429
- className: "relative inline-block overflow-hidden whitespace-nowrap align-bottom",
430
- children: [
431
- /* @__PURE__ */ jsx("span", {
432
- ref: measureRef,
433
- "aria-hidden": true,
434
- className: "invisible inline-block whitespace-nowrap",
435
- children: cascade ? label.split("").map((char, index) => /* @__PURE__ */ jsx("span", {
436
- className: "inline-block whitespace-pre",
437
- children: char
438
- }, index)) : children
439
- }),
440
- cascade ? /* @__PURE__ */ jsx("span", {
441
- className: "sr-only",
442
- children: label
443
- }) : null,
444
- /* @__PURE__ */ jsx(AnimatePresence, {
445
- initial: false,
446
- children: cascade ? /* @__PURE__ */ jsx(m.span, {
447
- "aria-hidden": true,
448
- initial: "initial",
449
- animate: "animate",
450
- exit: "exit",
451
- className: "absolute left-0 top-0 inline-block whitespace-pre",
452
- children: label.split("").map((char, index) => /* @__PURE__ */ jsx(m.span, {
453
- custom: index * CASCADE_STAGGER,
454
- variants: CASCADE_LETTER_VARIANTS,
455
- className: "inline-block whitespace-pre",
456
- children: char
457
- }, index))
458
- }, `cascade-${value}`) : /* @__PURE__ */ jsx(m.span, {
459
- initial: reduce ? { opacity: 0 } : {
460
- opacity: 0,
461
- y: 14,
462
- filter: ROLL_BLUR
463
- },
464
- animate: reduce ? { opacity: 1 } : {
465
- opacity: 1,
466
- y: 0,
467
- filter: "blur(0px)"
468
- },
469
- exit: reduce ? { opacity: 0 } : {
470
- opacity: 0,
471
- y: -14,
472
- filter: ROLL_BLUR
473
- },
474
- transition: reduce ? { duration: 0.15 } : SPRING_SWAP,
475
- className: "absolute left-0 top-0 inline-block",
476
- children
477
- }, `text-${value}`)
478
- })
479
- ]
480
- });
481
- }
482
- forwardRef(function StatefulButton({ state = "idle", children, loadingText = "Loading", successText = "Done", errorText = "Try again", icon, disabled, ...rest }, ref) {
483
- const isBusy = state === "loading";
484
- const stateText = state === "loading" ? loadingText : state === "success" ? successText : state === "error" ? errorText : children;
485
- const textKey = typeof stateText === "string" ? `${state}-${stateText}` : state;
486
- return /* @__PURE__ */ jsx(Button, {
487
- ref,
488
- disabled: disabled || isBusy,
489
- "aria-busy": isBusy,
490
- whileHover: void 0,
491
- ...rest,
492
- children: /* @__PURE__ */ jsxs("span", {
493
- "aria-live": "polite",
494
- className: "relative inline-flex items-center justify-center overflow-hidden",
495
- children: [
496
- /* @__PURE__ */ jsxs(AnimatePresence, {
497
- initial: false,
498
- children: [
499
- state === "loading" ? /* @__PURE__ */ jsx(IconSlot, {
500
- keyId: "loading-icon",
501
- children: /* @__PURE__ */ jsx(LoaderCircle, { className: "size-4 animate-spin" })
502
- }) : null,
503
- state === "success" ? /* @__PURE__ */ jsx(IconSlot, {
504
- keyId: "success-icon",
505
- children: /* @__PURE__ */ jsx(Check, { className: "size-4" })
506
- }) : null,
507
- state === "error" ? /* @__PURE__ */ jsx(IconSlot, {
508
- keyId: "error-icon",
509
- children: /* @__PURE__ */ jsx(X, { className: "size-4" })
510
- }) : null
511
- ]
512
- }),
513
- /* @__PURE__ */ jsx(TextSlot, {
514
- value: textKey,
515
- children: stateText
516
- }),
517
- /* @__PURE__ */ jsx(AnimatePresence, {
518
- initial: false,
519
- children: state === "idle" && icon ? /* @__PURE__ */ jsx(IconSlot, {
520
- keyId: "idle-icon",
521
- children: icon
522
- }) : null
523
- })
524
- ]
525
- })
526
- });
527
- });
528
- function sameLayout(a, b) {
529
- return a?.trigger.left === b.trigger.left && a.trigger.top === b.trigger.top && a.trigger.width === b.trigger.width && a.trigger.height === b.trigger.height && a.content.width === b.content.width && a.content.height === b.content.height;
530
- }
531
- function usePopoverPortalPosition(triggerRef, contentRef, active) {
532
- const [layout, setLayout] = useState(null);
533
- const update = useCallback(() => {
534
- const trigger = triggerRef.current;
535
- const content = contentRef.current;
536
- if (!trigger || !content) return;
537
- const rect = trigger.getBoundingClientRect();
538
- const next = {
539
- trigger: {
540
- left: rect.left,
541
- top: rect.top,
542
- width: rect.width,
543
- height: rect.height
544
- },
545
- content: {
546
- width: content.offsetWidth,
547
- height: content.offsetHeight
548
- }
549
- };
550
- setLayout((current) => sameLayout(current, next) ? current : next);
551
- }, [contentRef, triggerRef]);
552
- useLayoutEffect(() => {
553
- update();
554
- if (!active) return;
555
- const trigger = triggerRef.current;
556
- const content = contentRef.current;
557
- const observer = new ResizeObserver(update);
558
- if (trigger) observer.observe(trigger);
559
- if (content) observer.observe(content);
560
- window.addEventListener("scroll", update, true);
561
- window.addEventListener("resize", update);
562
- return () => {
563
- observer.disconnect();
564
- window.removeEventListener("scroll", update, true);
565
- window.removeEventListener("resize", update);
566
- };
567
- }, [
568
- active,
569
- contentRef,
570
- triggerRef,
571
- update
572
- ]);
573
- return layout;
574
- }
575
- function subscribe() {
576
- return () => {
577
- };
578
- }
579
- function getSnapshot() {
580
- return true;
581
- }
582
- function getServerSnapshot() {
583
- return false;
584
- }
585
- function useHydrated() {
586
- return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
587
- }
588
- var MorphContext = createContext(null);
589
- function useMorphContext(component) {
590
- const ctx = useContext(MorphContext);
591
- if (!ctx) throw new Error(`${component} must be used within <MorphPopover>`);
592
- return ctx;
593
- }
594
- function MorphPopover({ children, open: controlledOpen, defaultOpen = false, onOpenChange, className }) {
252
+ function AnimatedSelect({ value, defaultValue, onValueChange, disabled = false, className, children }) {
253
+ const reduce = useReducedMotion() ?? false;
595
254
  const baseId = useId();
596
255
  const rootRef = useRef(null);
597
- const triggerRef = useRef(null);
598
- const contentRef = useRef(null);
599
- const [internalOpen, setInternalOpen] = useState(defaultOpen);
600
- const controlled = controlledOpen !== void 0;
601
- const open = controlled ? controlledOpen : internalOpen;
602
- const setOpen = useCallback((next) => {
603
- if (!controlled) setInternalOpen(next);
604
- onOpenChange?.(next);
605
- }, [controlled, onOpenChange]);
606
- const toggle = useCallback(() => setOpen(!open), [setOpen, open]);
607
- const setOpenEvent = useEffectEvent(setOpen);
256
+ const [open, setOpen] = useState(false);
257
+ const [internal, setInternal] = useState(defaultValue);
258
+ const [labels, setLabels] = useState(/* @__PURE__ */ new Map());
259
+ const [placement, setPlacement] = useState("bottom");
260
+ const controlled = value !== void 0;
261
+ const current = controlled ? value : internal;
262
+ const select = useCallback((next) => {
263
+ if (!controlled) setInternal(next);
264
+ onValueChange?.(next);
265
+ setOpen(false);
266
+ }, [controlled, onValueChange]);
267
+ const register = useCallback((v, label) => {
268
+ setLabels((m2) => m2.get(v) === label ? m2 : new Map(m2).set(v, label));
269
+ }, []);
270
+ const unregister = useCallback((v) => {
271
+ setLabels((m2) => {
272
+ if (!m2.has(v)) return m2;
273
+ const next = new Map(m2);
274
+ next.delete(v);
275
+ return next;
276
+ });
277
+ }, []);
608
278
  useEffect(() => {
609
279
  if (!open) return;
610
- const onKey = (e) => e.key === "Escape" && setOpenEvent(false);
280
+ const onKey = (e) => e.key === "Escape" && setOpen(false);
611
281
  const onPointer = (e) => {
612
- const target = e.target;
613
- if (rootRef.current && !rootRef.current.contains(target) && !contentRef.current?.contains(target)) setOpenEvent(false);
282
+ if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
614
283
  };
615
284
  window.addEventListener("keydown", onKey);
616
285
  window.addEventListener("pointerdown", onPointer);
@@ -620,255 +289,71 @@ function MorphPopover({ children, open: controlledOpen, defaultOpen = false, onO
620
289
  };
621
290
  }, [open]);
622
291
  const ctx = useMemo(() => ({
292
+ value: current,
623
293
  open,
624
294
  setOpen,
625
- toggle,
295
+ select,
296
+ register,
297
+ unregister,
298
+ labelFor: (v) => v === void 0 ? void 0 : labels.get(v),
299
+ reduce,
626
300
  triggerId: `${baseId}-trigger`,
627
- contentId: `${baseId}-content`,
628
- triggerRef,
629
- contentRef
301
+ listId: `${baseId}-list`,
302
+ disabled,
303
+ placement,
304
+ setPlacement
630
305
  }), [
306
+ current,
631
307
  open,
632
- setOpen,
633
- toggle,
634
- baseId
308
+ select,
309
+ register,
310
+ unregister,
311
+ labels,
312
+ reduce,
313
+ baseId,
314
+ disabled,
315
+ placement
635
316
  ]);
636
- return /* @__PURE__ */ jsx(MorphContext.Provider, {
317
+ return /* @__PURE__ */ jsx(AnimatedSelectContext.Provider, {
637
318
  value: ctx,
638
319
  children: /* @__PURE__ */ jsx("div", {
639
320
  ref: rootRef,
640
- className: cn("relative inline-flex", className),
321
+ className: cn("relative", className),
641
322
  children
642
323
  })
643
324
  });
644
325
  }
645
- function mergeRefs(...refs) {
646
- return (node) => {
647
- for (const ref of refs) if (typeof ref === "function") ref(node);
648
- else if (ref && typeof ref === "object") ref.current = node;
326
+ function AnimatedSelectTrigger({ className, children }) {
327
+ const ctx = useAnimatedSelectContext("AnimatedSelectTrigger");
328
+ const isTop = ctx.placement === "top";
329
+ const kf = ctx.open ? [
330
+ 0,
331
+ 0,
332
+ 12
333
+ ] : [
334
+ 12,
335
+ 0,
336
+ 12
337
+ ];
338
+ const kfT = ctx.reduce ? { duration: 0 } : ctx.open ? {
339
+ duration: 0.6,
340
+ times: [
341
+ 0,
342
+ 0.4,
343
+ 1
344
+ ],
345
+ ease: EASE_OUT
346
+ } : {
347
+ duration: 0.42,
348
+ times: [
349
+ 0,
350
+ 0.5,
351
+ 1
352
+ ],
353
+ ease: EASE_OUT
649
354
  };
650
- }
651
- function MorphPopoverTrigger({ children }) {
652
- const ctx = useMorphContext("MorphPopoverTrigger");
653
- if (!isValidElement(children)) return children;
654
- const child = children;
655
- const childOnClick = child.props.onClick;
656
- const childRef = child.props.ref;
657
- return cloneElement(child, {
658
- id: ctx.triggerId,
659
- ref: mergeRefs(childRef, (node) => {
660
- ctx.triggerRef.current = node;
661
- }),
662
- onClick: (e) => {
663
- childOnClick?.(e);
664
- ctx.toggle();
665
- },
666
- "aria-haspopup": "dialog",
667
- "aria-expanded": ctx.open,
668
- "aria-controls": ctx.open ? ctx.contentId : void 0
669
- });
670
- }
671
- var originFor = (side, align) => `${side === "bottom" ? "top" : "bottom"} ${align === "end" ? "right" : "left"}`;
672
- function clipHidden(side, align, radius) {
673
- return `inset(${side === "bottom" ? "0%" : "92%"} ${align === "end" ? "0%" : "92%"} ${side === "bottom" ? "92%" : "0%"} ${align === "end" ? "92%" : "0%"} round ${radius}px)`;
674
- }
675
- var clipShown = (radius) => `inset(0% 0% 0% 0% round ${radius}px)`;
676
- var MORPH_CLIP_TRANSITION = {
677
- duration: 0.32,
678
- ease: EASE_OUT
679
- };
680
- function MorphPopoverContent({ children, side = "bottom", align = "end", sideOffset = 8, radius = 16, className }) {
681
- const ctx = useMorphContext("MorphPopoverContent");
682
- const reduce = useReducedMotion() ?? false;
683
- const portalReady = useHydrated();
684
- const layout = usePopoverPortalPosition(ctx.triggerRef, ctx.contentRef, portalReady && ctx.open);
685
- const left = layout ? align === "end" ? layout.trigger.left + layout.trigger.width - layout.content.width : layout.trigger.left : 0;
686
- const top = layout ? side === "bottom" ? layout.trigger.top + layout.trigger.height + sideOffset : layout.trigger.top - layout.content.height - sideOffset : 0;
687
- const wrap = reduce ? void 0 : {
688
- hidden: {
689
- opacity: 0,
690
- scale: 0.96,
691
- transition: SPRING_PANEL
692
- },
693
- show: {
694
- opacity: 1,
695
- scale: 1,
696
- transition: SPRING_PANEL
697
- }
698
- };
699
- const clip = reduce ? void 0 : {
700
- hidden: {
701
- clipPath: clipHidden(side, align, radius),
702
- transition: MORPH_CLIP_TRANSITION
703
- },
704
- show: {
705
- clipPath: clipShown(radius),
706
- transition: MORPH_CLIP_TRANSITION
707
- }
708
- };
709
- if (!portalReady) return null;
710
- return createPortal(/* @__PURE__ */ jsx(AnimatePresence, { children: ctx.open ? /* @__PURE__ */ jsx(m.div, {
711
- "data-morph-popover-portal": "",
712
- variants: wrap,
713
- initial: reduce ? { opacity: 0 } : "hidden",
714
- animate: reduce ? { opacity: 1 } : "show",
715
- exit: reduce ? { opacity: 0 } : "hidden",
716
- transition: reduce ? { duration: 0.12 } : void 0,
717
- style: {
718
- left,
719
- top,
720
- visibility: layout ? "visible" : "hidden",
721
- transformOrigin: originFor(side, align)
722
- },
723
- className: "fixed z-[9999] [filter:drop-shadow(0_10px_18px_rgba(0,0,0,0.14))]",
724
- children: /* @__PURE__ */ jsx(m.div, {
725
- ref: ctx.contentRef,
726
- id: ctx.contentId,
727
- role: "dialog",
728
- "aria-labelledby": ctx.triggerId,
729
- variants: clip,
730
- style: { borderRadius: radius },
731
- className: cn("overflow-hidden border border-border bg-background", className),
732
- children
733
- })
734
- }) : null }), document.body);
735
- }
736
- var INSTANT_TRANSITION = { duration: 0 };
737
- var CHEVRON_TRANSITION = {
738
- type: "spring",
739
- duration: 0.4,
740
- bounce: 0.3
741
- };
742
- var LIST_VARIANTS = {
743
- hidden: {},
744
- show: { transition: {
745
- staggerChildren: 0.035,
746
- delayChildren: 0.05
747
- } }
748
- };
749
- var ITEM_VARIANTS = {
750
- hidden: {
751
- opacity: 0,
752
- y: -6,
753
- filter: "blur(3px)"
754
- },
755
- show: {
756
- opacity: 1,
757
- y: 0,
758
- filter: "blur(0px)"
759
- }
760
- };
761
- var AnimatedSelectContext = createContext(null);
762
- function useAnimatedSelectContext(component) {
763
- const ctx = useContext(AnimatedSelectContext);
764
- if (!ctx) throw new Error(`${component} must be used within <AnimatedSelect>`);
765
- return ctx;
766
- }
767
- function AnimatedSelect({ value, defaultValue, onValueChange, disabled = false, className, children }) {
768
- const reduce = useReducedMotion() ?? false;
769
- const baseId = useId();
770
- const rootRef = useRef(null);
771
- const [open, setOpen] = useState(false);
772
- const [internal, setInternal] = useState(defaultValue);
773
- const [labels, setLabels] = useState(/* @__PURE__ */ new Map());
774
- const [placement, setPlacement] = useState("bottom");
775
- const controlled = value !== void 0;
776
- const current = controlled ? value : internal;
777
- const select = useCallback((next) => {
778
- if (!controlled) setInternal(next);
779
- onValueChange?.(next);
780
- setOpen(false);
781
- }, [controlled, onValueChange]);
782
- const register = useCallback((v, label) => {
783
- setLabels((m2) => m2.get(v) === label ? m2 : new Map(m2).set(v, label));
784
- }, []);
785
- const unregister = useCallback((v) => {
786
- setLabels((m2) => {
787
- if (!m2.has(v)) return m2;
788
- const next = new Map(m2);
789
- next.delete(v);
790
- return next;
791
- });
792
- }, []);
793
- useEffect(() => {
794
- if (!open) return;
795
- const onKey = (e) => e.key === "Escape" && setOpen(false);
796
- const onPointer = (e) => {
797
- if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
798
- };
799
- window.addEventListener("keydown", onKey);
800
- window.addEventListener("pointerdown", onPointer);
801
- return () => {
802
- window.removeEventListener("keydown", onKey);
803
- window.removeEventListener("pointerdown", onPointer);
804
- };
805
- }, [open]);
806
- const ctx = useMemo(() => ({
807
- value: current,
808
- open,
809
- setOpen,
810
- select,
811
- register,
812
- unregister,
813
- labelFor: (v) => v === void 0 ? void 0 : labels.get(v),
814
- reduce,
815
- triggerId: `${baseId}-trigger`,
816
- listId: `${baseId}-list`,
817
- disabled,
818
- placement,
819
- setPlacement
820
- }), [
821
- current,
822
- open,
823
- select,
824
- register,
825
- unregister,
826
- labels,
827
- reduce,
828
- baseId,
829
- disabled,
830
- placement
831
- ]);
832
- return /* @__PURE__ */ jsx(AnimatedSelectContext.Provider, {
833
- value: ctx,
834
- children: /* @__PURE__ */ jsx("div", {
835
- ref: rootRef,
836
- className: cn("relative", className),
837
- children
838
- })
839
- });
840
- }
841
- function AnimatedSelectTrigger({ className, children }) {
842
- const ctx = useAnimatedSelectContext("AnimatedSelectTrigger");
843
- const isTop = ctx.placement === "top";
844
- const kf = ctx.open ? [
845
- 0,
846
- 0,
847
- 12
848
- ] : [
849
- 12,
850
- 0,
851
- 12
852
- ];
853
- const kfT = ctx.reduce ? { duration: 0 } : ctx.open ? {
854
- duration: 0.6,
855
- times: [
856
- 0,
857
- 0.4,
858
- 1
859
- ],
860
- ease: EASE_OUT
861
- } : {
862
- duration: 0.42,
863
- times: [
864
- 0,
865
- 0.5,
866
- 1
867
- ],
868
- ease: EASE_OUT
869
- };
870
- return /* @__PURE__ */ jsxs(m.button, {
871
- type: "button",
355
+ return /* @__PURE__ */ jsxs(m.button, {
356
+ type: "button",
872
357
  id: ctx.triggerId,
873
358
  disabled: ctx.disabled,
874
359
  "aria-haspopup": "listbox",
@@ -1032,6 +517,524 @@ function AnimatedSelectItem({ value, disabled = false, className, children }) {
1032
517
  })
1033
518
  });
1034
519
  }
520
+ var VARIANT_CLASS = {
521
+ primary: "bg-primary text-primary-foreground hover:bg-primary/90",
522
+ secondary: "border border-border bg-card text-foreground hover:border-border",
523
+ ghost: "text-muted-foreground hover:text-foreground hover:bg-primary/5",
524
+ outline: "border border-border bg-transparent text-foreground hover:bg-primary/5"
525
+ };
526
+ var SIZE_CLASS = {
527
+ sm: "h-8 px-3 text-xs gap-1.5 rounded-full",
528
+ md: "h-10 px-5 text-sm gap-2 rounded-full",
529
+ lg: "h-12 px-6 text-base gap-2 rounded-full",
530
+ icon: "h-8 w-8 rounded-lg"
531
+ };
532
+ var Button = forwardRef(function Button2({ variant = "primary", size = "md", pressScale = 0.93, ripple = false, className, children, onPointerDown, ...rest }, ref) {
533
+ const reduce = useReducedMotion();
534
+ const canHover = useHoverCapable();
535
+ const [ripples, setRipples] = useState([]);
536
+ const nextId = useRef(0);
537
+ const handlePointerDown = useCallback((event) => {
538
+ if (ripple && !reduce) {
539
+ const rect = event.currentTarget.getBoundingClientRect();
540
+ const size2 = Math.max(rect.width, rect.height) * 2;
541
+ const id = nextId.current++;
542
+ setRipples((prev) => [...prev, {
543
+ id,
544
+ x: event.clientX - rect.left,
545
+ y: event.clientY - rect.top,
546
+ size: size2
547
+ }]);
548
+ }
549
+ onPointerDown?.(event);
550
+ }, [
551
+ ripple,
552
+ reduce,
553
+ onPointerDown
554
+ ]);
555
+ return /* @__PURE__ */ jsxs(m.button, {
556
+ ref,
557
+ type: "button",
558
+ whileTap: reduce ? void 0 : { scale: pressScale },
559
+ whileHover: reduce || !canHover ? void 0 : { scale: 1.02 },
560
+ transition: SPRING_PRESS,
561
+ onPointerDown: handlePointerDown,
562
+ className: cn("inline-flex items-center justify-center font-medium select-none", "transition-colors", "disabled:pointer-events-none disabled:opacity-50", ripple && "relative overflow-hidden", VARIANT_CLASS[variant], SIZE_CLASS[size], className),
563
+ ...rest,
564
+ children: [/* @__PURE__ */ jsx("span", {
565
+ className: cn("pointer-events-none absolute inset-0 overflow-hidden rounded-[inherit]", !ripple && "hidden"),
566
+ children: /* @__PURE__ */ jsx(AnimatePresence, { children: ripple && !reduce ? ripples.map((r) => /* @__PURE__ */ jsx(m.span, {
567
+ className: "absolute rounded-full bg-current",
568
+ style: {
569
+ left: r.x,
570
+ top: r.y,
571
+ width: r.size,
572
+ height: r.size,
573
+ x: "-50%",
574
+ y: "-50%"
575
+ },
576
+ initial: {
577
+ scale: 0.05,
578
+ opacity: 0.3
579
+ },
580
+ animate: {
581
+ scale: 1,
582
+ opacity: 0
583
+ },
584
+ exit: { opacity: 0 },
585
+ transition: {
586
+ duration: 1.6,
587
+ ease: EASE_OUT
588
+ },
589
+ onAnimationComplete: () => setRipples((prev) => prev.filter((x) => x.id !== r.id))
590
+ }, r.id)) : null })
591
+ }), children]
592
+ });
593
+ });
594
+ forwardRef(function ButtonLink({ variant = "primary", size = "md", pressScale = 0.93, className, children, ...rest }, ref) {
595
+ const reduce = useReducedMotion();
596
+ const canHover = useHoverCapable();
597
+ return /* @__PURE__ */ jsx(m.a, {
598
+ ref,
599
+ whileTap: reduce ? void 0 : { scale: pressScale },
600
+ whileHover: reduce || !canHover ? void 0 : { scale: 1.02 },
601
+ transition: SPRING_PRESS,
602
+ className: cn("inline-flex items-center justify-center font-medium select-none", "transition-colors", VARIANT_CLASS[variant], SIZE_CLASS[size], className),
603
+ ...rest,
604
+ children
605
+ });
606
+ });
607
+ function Magnetic({ children, strength = 0.35, className }) {
608
+ const ref = useRef(null);
609
+ const reduce = useReducedMotion();
610
+ const canHover = useHoverCapable();
611
+ const enabled = !reduce && canHover;
612
+ const x = useMotionValue(0);
613
+ const y = useMotionValue(0);
614
+ const sx = useSpring(x, SPRING_MOUSE);
615
+ const sy = useSpring(y, SPRING_MOUSE);
616
+ const onMove = (e) => {
617
+ const el = ref.current;
618
+ if (!el || !enabled) return;
619
+ const rect = el.getBoundingClientRect();
620
+ x.set((e.clientX - rect.left - rect.width / 2) * strength);
621
+ y.set((e.clientY - rect.top - rect.height / 2) * strength);
622
+ };
623
+ const onLeave = () => {
624
+ x.set(0);
625
+ y.set(0);
626
+ };
627
+ return /* @__PURE__ */ jsx(m.div, {
628
+ ref,
629
+ onMouseMove: onMove,
630
+ onMouseLeave: onLeave,
631
+ style: {
632
+ x: sx,
633
+ y: sy
634
+ },
635
+ className: cn("inline-block", className),
636
+ children
637
+ });
638
+ }
639
+ forwardRef(function MagneticButton({ strength = 0.25, magneticClassName, children, ...rest }, ref) {
640
+ return /* @__PURE__ */ jsx(Magnetic, {
641
+ strength,
642
+ className: magneticClassName,
643
+ children: /* @__PURE__ */ jsx(Button, {
644
+ ref,
645
+ ...rest,
646
+ children
647
+ })
648
+ });
649
+ });
650
+ var CASCADE_STAGGER = 0.025;
651
+ var ROLL_BLUR = "blur(6px)";
652
+ var CASCADE_LETTER_VARIANTS = {
653
+ initial: {
654
+ opacity: 0,
655
+ y: "105%",
656
+ filter: ROLL_BLUR
657
+ },
658
+ animate: (delay = 0) => ({
659
+ opacity: 1,
660
+ y: "0%",
661
+ filter: "blur(0px)",
662
+ transition: {
663
+ ...SPRING_SWAP,
664
+ delay
665
+ }
666
+ }),
667
+ exit: (delay = 0) => ({
668
+ opacity: 0,
669
+ y: "-105%",
670
+ filter: ROLL_BLUR,
671
+ transition: {
672
+ duration: 0.16,
673
+ ease: EASE_OUT,
674
+ delay: delay * 0.5
675
+ }
676
+ })
677
+ };
678
+ var ICON_VARIANTS = {
679
+ initial: {
680
+ opacity: 0,
681
+ width: 0,
682
+ scale: 0.7,
683
+ filter: ROLL_BLUR
684
+ },
685
+ animate: {
686
+ opacity: 1,
687
+ width: "1.5rem",
688
+ scale: 1,
689
+ filter: "blur(0px)",
690
+ transition: SPRING_SWAP
691
+ },
692
+ exit: {
693
+ opacity: 0,
694
+ width: 0,
695
+ scale: 0.7,
696
+ filter: ROLL_BLUR,
697
+ transition: {
698
+ duration: 0.16,
699
+ ease: EASE_OUT
700
+ }
701
+ }
702
+ };
703
+ function IconSlot({ keyId, children }) {
704
+ const reduce = useReducedMotion();
705
+ return /* @__PURE__ */ jsx(m.span, {
706
+ variants: ICON_VARIANTS,
707
+ initial: reduce ? { opacity: 0 } : "initial",
708
+ animate: reduce ? { opacity: 1 } : "animate",
709
+ exit: reduce ? { opacity: 0 } : "exit",
710
+ transition: reduce ? { duration: 0.15 } : void 0,
711
+ className: "inline-grid shrink-0 place-items-center overflow-hidden",
712
+ children
713
+ }, keyId);
714
+ }
715
+ function TextSlot({ value, children }) {
716
+ const reduce = useReducedMotion();
717
+ const measureRef = useRef(null);
718
+ const [width, setWidth] = useState();
719
+ const label = typeof children === "string" ? children : null;
720
+ const cascade = label !== null && !reduce;
721
+ useLayoutEffect(() => {
722
+ const nextWidth = measureRef.current?.offsetWidth;
723
+ if (!nextWidth) return;
724
+ setWidth((current) => current === nextWidth ? current : nextWidth);
725
+ });
726
+ return /* @__PURE__ */ jsxs(m.span, {
727
+ initial: false,
728
+ layout: "size",
729
+ style: { width },
730
+ transition: reduce ? { duration: 0 } : SPRING_SWAP,
731
+ className: "relative inline-block overflow-hidden whitespace-nowrap align-bottom",
732
+ children: [
733
+ /* @__PURE__ */ jsx("span", {
734
+ ref: measureRef,
735
+ "aria-hidden": true,
736
+ className: "invisible inline-block whitespace-nowrap",
737
+ children: cascade ? label.split("").map((char, index) => /* @__PURE__ */ jsx("span", {
738
+ className: "inline-block whitespace-pre",
739
+ children: char
740
+ }, index)) : children
741
+ }),
742
+ cascade ? /* @__PURE__ */ jsx("span", {
743
+ className: "sr-only",
744
+ children: label
745
+ }) : null,
746
+ /* @__PURE__ */ jsx(AnimatePresence, {
747
+ initial: false,
748
+ children: cascade ? /* @__PURE__ */ jsx(m.span, {
749
+ "aria-hidden": true,
750
+ initial: "initial",
751
+ animate: "animate",
752
+ exit: "exit",
753
+ className: "absolute left-0 top-0 inline-block whitespace-pre",
754
+ children: label.split("").map((char, index) => /* @__PURE__ */ jsx(m.span, {
755
+ custom: index * CASCADE_STAGGER,
756
+ variants: CASCADE_LETTER_VARIANTS,
757
+ className: "inline-block whitespace-pre",
758
+ children: char
759
+ }, index))
760
+ }, `cascade-${value}`) : /* @__PURE__ */ jsx(m.span, {
761
+ initial: reduce ? { opacity: 0 } : {
762
+ opacity: 0,
763
+ y: 14,
764
+ filter: ROLL_BLUR
765
+ },
766
+ animate: reduce ? { opacity: 1 } : {
767
+ opacity: 1,
768
+ y: 0,
769
+ filter: "blur(0px)"
770
+ },
771
+ exit: reduce ? { opacity: 0 } : {
772
+ opacity: 0,
773
+ y: -14,
774
+ filter: ROLL_BLUR
775
+ },
776
+ transition: reduce ? { duration: 0.15 } : SPRING_SWAP,
777
+ className: "absolute left-0 top-0 inline-block",
778
+ children
779
+ }, `text-${value}`)
780
+ })
781
+ ]
782
+ });
783
+ }
784
+ forwardRef(function StatefulButton({ state = "idle", children, loadingText = "Loading", successText = "Done", errorText = "Try again", icon, disabled, ...rest }, ref) {
785
+ const isBusy = state === "loading";
786
+ const stateText = state === "loading" ? loadingText : state === "success" ? successText : state === "error" ? errorText : children;
787
+ const textKey = typeof stateText === "string" ? `${state}-${stateText}` : state;
788
+ return /* @__PURE__ */ jsx(Button, {
789
+ ref,
790
+ disabled: disabled || isBusy,
791
+ "aria-busy": isBusy,
792
+ whileHover: void 0,
793
+ ...rest,
794
+ children: /* @__PURE__ */ jsxs("span", {
795
+ "aria-live": "polite",
796
+ className: "relative inline-flex items-center justify-center overflow-hidden",
797
+ children: [
798
+ /* @__PURE__ */ jsxs(AnimatePresence, {
799
+ initial: false,
800
+ children: [
801
+ state === "loading" ? /* @__PURE__ */ jsx(IconSlot, {
802
+ keyId: "loading-icon",
803
+ children: /* @__PURE__ */ jsx(LoaderCircle, { className: "size-4 animate-spin" })
804
+ }) : null,
805
+ state === "success" ? /* @__PURE__ */ jsx(IconSlot, {
806
+ keyId: "success-icon",
807
+ children: /* @__PURE__ */ jsx(Check, { className: "size-4" })
808
+ }) : null,
809
+ state === "error" ? /* @__PURE__ */ jsx(IconSlot, {
810
+ keyId: "error-icon",
811
+ children: /* @__PURE__ */ jsx(X, { className: "size-4" })
812
+ }) : null
813
+ ]
814
+ }),
815
+ /* @__PURE__ */ jsx(TextSlot, {
816
+ value: textKey,
817
+ children: stateText
818
+ }),
819
+ /* @__PURE__ */ jsx(AnimatePresence, {
820
+ initial: false,
821
+ children: state === "idle" && icon ? /* @__PURE__ */ jsx(IconSlot, {
822
+ keyId: "idle-icon",
823
+ children: icon
824
+ }) : null
825
+ })
826
+ ]
827
+ })
828
+ });
829
+ });
830
+ function sameLayout(a, b) {
831
+ return a?.trigger.left === b.trigger.left && a.trigger.top === b.trigger.top && a.trigger.width === b.trigger.width && a.trigger.height === b.trigger.height && a.content.width === b.content.width && a.content.height === b.content.height;
832
+ }
833
+ function usePopoverPortalPosition(triggerRef, contentRef, active) {
834
+ const [layout, setLayout] = useState(null);
835
+ const update = useCallback(() => {
836
+ const trigger = triggerRef.current;
837
+ const content = contentRef.current;
838
+ if (!trigger || !content) return;
839
+ const rect = trigger.getBoundingClientRect();
840
+ const next = {
841
+ trigger: {
842
+ left: rect.left,
843
+ top: rect.top,
844
+ width: rect.width,
845
+ height: rect.height
846
+ },
847
+ content: {
848
+ width: content.offsetWidth,
849
+ height: content.offsetHeight
850
+ }
851
+ };
852
+ setLayout((current) => sameLayout(current, next) ? current : next);
853
+ }, [contentRef, triggerRef]);
854
+ useLayoutEffect(() => {
855
+ update();
856
+ if (!active) return;
857
+ const trigger = triggerRef.current;
858
+ const content = contentRef.current;
859
+ const observer = new ResizeObserver(update);
860
+ if (trigger) observer.observe(trigger);
861
+ if (content) observer.observe(content);
862
+ window.addEventListener("scroll", update, true);
863
+ window.addEventListener("resize", update);
864
+ return () => {
865
+ observer.disconnect();
866
+ window.removeEventListener("scroll", update, true);
867
+ window.removeEventListener("resize", update);
868
+ };
869
+ }, [
870
+ active,
871
+ contentRef,
872
+ triggerRef,
873
+ update
874
+ ]);
875
+ return layout;
876
+ }
877
+ function subscribe() {
878
+ return () => {
879
+ };
880
+ }
881
+ function getSnapshot() {
882
+ return true;
883
+ }
884
+ function getServerSnapshot() {
885
+ return false;
886
+ }
887
+ function useHydrated() {
888
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
889
+ }
890
+ var MorphContext = createContext(null);
891
+ function useMorphContext(component) {
892
+ const ctx = useContext(MorphContext);
893
+ if (!ctx) throw new Error(`${component} must be used within <MorphPopover>`);
894
+ return ctx;
895
+ }
896
+ function MorphPopover({ children, open: controlledOpen, defaultOpen = false, onOpenChange, className }) {
897
+ const baseId = useId();
898
+ const rootRef = useRef(null);
899
+ const triggerRef = useRef(null);
900
+ const contentRef = useRef(null);
901
+ const [internalOpen, setInternalOpen] = useState(defaultOpen);
902
+ const controlled = controlledOpen !== void 0;
903
+ const open = controlled ? controlledOpen : internalOpen;
904
+ const setOpen = useCallback((next) => {
905
+ if (!controlled) setInternalOpen(next);
906
+ onOpenChange?.(next);
907
+ }, [controlled, onOpenChange]);
908
+ const toggle = useCallback(() => setOpen(!open), [setOpen, open]);
909
+ const setOpenEvent = useEffectEvent(setOpen);
910
+ useEffect(() => {
911
+ if (!open) return;
912
+ const onKey = (e) => e.key === "Escape" && setOpenEvent(false);
913
+ const onPointer = (e) => {
914
+ const target = e.target;
915
+ if (rootRef.current && !rootRef.current.contains(target) && !contentRef.current?.contains(target)) setOpenEvent(false);
916
+ };
917
+ window.addEventListener("keydown", onKey);
918
+ window.addEventListener("pointerdown", onPointer);
919
+ return () => {
920
+ window.removeEventListener("keydown", onKey);
921
+ window.removeEventListener("pointerdown", onPointer);
922
+ };
923
+ }, [open]);
924
+ const ctx = useMemo(() => ({
925
+ open,
926
+ setOpen,
927
+ toggle,
928
+ triggerId: `${baseId}-trigger`,
929
+ contentId: `${baseId}-content`,
930
+ triggerRef,
931
+ contentRef
932
+ }), [
933
+ open,
934
+ setOpen,
935
+ toggle,
936
+ baseId
937
+ ]);
938
+ return /* @__PURE__ */ jsx(MorphContext.Provider, {
939
+ value: ctx,
940
+ children: /* @__PURE__ */ jsx("div", {
941
+ ref: rootRef,
942
+ className: cn("relative inline-flex", className),
943
+ children
944
+ })
945
+ });
946
+ }
947
+ function mergeRefs(...refs) {
948
+ return (node) => {
949
+ for (const ref of refs) if (typeof ref === "function") ref(node);
950
+ else if (ref && typeof ref === "object") ref.current = node;
951
+ };
952
+ }
953
+ function MorphPopoverTrigger({ children }) {
954
+ const ctx = useMorphContext("MorphPopoverTrigger");
955
+ if (!isValidElement(children)) return children;
956
+ const child = children;
957
+ const childOnClick = child.props.onClick;
958
+ const childRef = child.props.ref;
959
+ return cloneElement(child, {
960
+ id: ctx.triggerId,
961
+ ref: mergeRefs(childRef, (node) => {
962
+ ctx.triggerRef.current = node;
963
+ }),
964
+ onClick: (e) => {
965
+ childOnClick?.(e);
966
+ ctx.toggle();
967
+ },
968
+ "aria-haspopup": "dialog",
969
+ "aria-expanded": ctx.open,
970
+ "aria-controls": ctx.open ? ctx.contentId : void 0
971
+ });
972
+ }
973
+ var originFor = (side, align) => `${side === "bottom" ? "top" : "bottom"} ${align === "end" ? "right" : "left"}`;
974
+ function clipHidden(side, align, radius) {
975
+ return `inset(${side === "bottom" ? "0%" : "92%"} ${align === "end" ? "0%" : "92%"} ${side === "bottom" ? "92%" : "0%"} ${align === "end" ? "92%" : "0%"} round ${radius}px)`;
976
+ }
977
+ var clipShown = (radius) => `inset(0% 0% 0% 0% round ${radius}px)`;
978
+ var MORPH_CLIP_TRANSITION = {
979
+ duration: 0.32,
980
+ ease: EASE_OUT
981
+ };
982
+ function MorphPopoverContent({ children, side = "bottom", align = "end", sideOffset = 8, radius = 16, className }) {
983
+ const ctx = useMorphContext("MorphPopoverContent");
984
+ const reduce = useReducedMotion() ?? false;
985
+ const portalReady = useHydrated();
986
+ const layout = usePopoverPortalPosition(ctx.triggerRef, ctx.contentRef, portalReady && ctx.open);
987
+ const left = layout ? align === "end" ? layout.trigger.left + layout.trigger.width - layout.content.width : layout.trigger.left : 0;
988
+ const top = layout ? side === "bottom" ? layout.trigger.top + layout.trigger.height + sideOffset : layout.trigger.top - layout.content.height - sideOffset : 0;
989
+ const wrap = reduce ? void 0 : {
990
+ hidden: {
991
+ opacity: 0,
992
+ scale: 0.96,
993
+ transition: SPRING_PANEL
994
+ },
995
+ show: {
996
+ opacity: 1,
997
+ scale: 1,
998
+ transition: SPRING_PANEL
999
+ }
1000
+ };
1001
+ const clip = reduce ? void 0 : {
1002
+ hidden: {
1003
+ clipPath: clipHidden(side, align, radius),
1004
+ transition: MORPH_CLIP_TRANSITION
1005
+ },
1006
+ show: {
1007
+ clipPath: clipShown(radius),
1008
+ transition: MORPH_CLIP_TRANSITION
1009
+ }
1010
+ };
1011
+ if (!portalReady) return null;
1012
+ return createPortal(/* @__PURE__ */ jsx(AnimatePresence, { children: ctx.open ? /* @__PURE__ */ jsx(m.div, {
1013
+ "data-morph-popover-portal": "",
1014
+ variants: wrap,
1015
+ initial: reduce ? { opacity: 0 } : "hidden",
1016
+ animate: reduce ? { opacity: 1 } : "show",
1017
+ exit: reduce ? { opacity: 0 } : "hidden",
1018
+ transition: reduce ? { duration: 0.12 } : void 0,
1019
+ style: {
1020
+ left,
1021
+ top,
1022
+ visibility: layout ? "visible" : "hidden",
1023
+ transformOrigin: originFor(side, align)
1024
+ },
1025
+ className: "fixed z-[9999] [filter:drop-shadow(0_10px_18px_rgba(0,0,0,0.14))]",
1026
+ children: /* @__PURE__ */ jsx(m.div, {
1027
+ ref: ctx.contentRef,
1028
+ id: ctx.contentId,
1029
+ role: "dialog",
1030
+ "aria-labelledby": ctx.triggerId,
1031
+ variants: clip,
1032
+ style: { borderRadius: radius },
1033
+ className: cn("overflow-hidden", elevatedMenu, className),
1034
+ children
1035
+ })
1036
+ }) : null }), document.body);
1037
+ }
1035
1038
  function PromptInput({ value, defaultValue = "", onValueChange, models = [], model, defaultModel, onModelChange, actions = [], onAction, onSubmit, loading = false, submitWhileLoading = false, onStop, minRows = 2, maxRows = 8, leadingAction, className, disabled, placeholder = "Ask the agent to do something\u2026", "aria-label": ariaLabel = "Prompt", onKeyDown, ...textareaProps }) {
1036
1039
  const reduce = useReducedMotion() ?? false;
1037
1040
  const textareaRef = useRef(null);