@waveso/ui 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/accordion.js +2 -2
  2. package/dist/accordion.js.map +1 -1
  3. package/dist/action-bar.js +2 -2
  4. package/dist/action-bar.js.map +1 -1
  5. package/dist/alert-dialog.js +4 -4
  6. package/dist/alert-dialog.js.map +1 -1
  7. package/dist/alert.js +5 -5
  8. package/dist/alert.js.map +1 -1
  9. package/dist/animate.d.ts.map +1 -1
  10. package/dist/animate.js +1 -2
  11. package/dist/animate.js.map +1 -1
  12. package/dist/autocomplete.js +8 -8
  13. package/dist/autocomplete.js.map +1 -1
  14. package/dist/avatar.js +5 -5
  15. package/dist/avatar.js.map +1 -1
  16. package/dist/badge.d.ts +1 -1
  17. package/dist/badge.d.ts.map +1 -1
  18. package/dist/badge.js +5 -6
  19. package/dist/badge.js.map +1 -1
  20. package/dist/breadcrumb.js +3 -3
  21. package/dist/breadcrumb.js.map +1 -1
  22. package/dist/button-group.js +5 -5
  23. package/dist/button-group.js.map +1 -1
  24. package/dist/button.d.ts +1 -1
  25. package/dist/button.d.ts.map +1 -1
  26. package/dist/button.js +9 -10
  27. package/dist/button.js.map +1 -1
  28. package/dist/card.js +4 -4
  29. package/dist/card.js.map +1 -1
  30. package/dist/checkbox.js +1 -1
  31. package/dist/checkbox.js.map +1 -1
  32. package/dist/combobox.d.ts.map +1 -1
  33. package/dist/combobox.js +10 -10
  34. package/dist/combobox.js.map +1 -1
  35. package/dist/context-menu.js +9 -9
  36. package/dist/context-menu.js.map +1 -1
  37. package/dist/dialog.d.ts.map +1 -1
  38. package/dist/dialog.js +4 -4
  39. package/dist/dialog.js.map +1 -1
  40. package/dist/drawer.js +4 -4
  41. package/dist/drawer.js.map +1 -1
  42. package/dist/field.js +2 -2
  43. package/dist/field.js.map +1 -1
  44. package/dist/form.js +2 -2
  45. package/dist/form.js.map +1 -1
  46. package/dist/infinite-scroll.js +2 -2
  47. package/dist/infinite-scroll.js.map +1 -1
  48. package/dist/input-group.d.ts +1 -1
  49. package/dist/input-group.js +5 -5
  50. package/dist/input-group.js.map +1 -1
  51. package/dist/input-otp.js +3 -3
  52. package/dist/input-otp.js.map +1 -1
  53. package/dist/input.js +1 -1
  54. package/dist/input.js.map +1 -1
  55. package/dist/item.js +4 -4
  56. package/dist/item.js.map +1 -1
  57. package/dist/kbd.js +1 -1
  58. package/dist/kbd.js.map +1 -1
  59. package/dist/menu.js +9 -9
  60. package/dist/menu.js.map +1 -1
  61. package/dist/menubar.js +1 -1
  62. package/dist/menubar.js.map +1 -1
  63. package/dist/popover.js +2 -2
  64. package/dist/popover.js.map +1 -1
  65. package/dist/preview-card.js +1 -1
  66. package/dist/preview-card.js.map +1 -1
  67. package/dist/progress.js +2 -2
  68. package/dist/progress.js.map +1 -1
  69. package/dist/radio.js +2 -2
  70. package/dist/radio.js.map +1 -1
  71. package/dist/scroll-area.js +2 -2
  72. package/dist/scroll-area.js.map +1 -1
  73. package/dist/select.js +8 -8
  74. package/dist/select.js.map +1 -1
  75. package/dist/separator.js +1 -1
  76. package/dist/separator.js.map +1 -1
  77. package/dist/sidebar.js +19 -19
  78. package/dist/sidebar.js.map +1 -1
  79. package/dist/skeleton.js +1 -1
  80. package/dist/skeleton.js.map +1 -1
  81. package/dist/slider.js +2 -2
  82. package/dist/slider.js.map +1 -1
  83. package/dist/styles.css +405 -173
  84. package/dist/switch.js +2 -2
  85. package/dist/switch.js.map +1 -1
  86. package/dist/table.js +4 -4
  87. package/dist/table.js.map +1 -1
  88. package/dist/tabs.js +3 -3
  89. package/dist/tabs.js.map +1 -1
  90. package/dist/textarea.js +1 -1
  91. package/dist/textarea.js.map +1 -1
  92. package/dist/toast.d.ts +3 -3
  93. package/dist/toast.d.ts.map +1 -1
  94. package/dist/toast.js +37 -10
  95. package/dist/toast.js.map +1 -1
  96. package/dist/toggle-group.js +2 -2
  97. package/dist/toggle-group.js.map +1 -1
  98. package/dist/toggle.js +3 -3
  99. package/dist/toggle.js.map +1 -1
  100. package/dist/tooltip.js +1 -1
  101. package/dist/tooltip.js.map +1 -1
  102. package/package.json +2 -5
package/dist/accordion.js CHANGED
@@ -25,7 +25,7 @@ function AccordionTrigger({ className, children, ...props }) {
25
25
  className: "flex",
26
26
  children: /* @__PURE__ */ jsxs(Accordion$1.Trigger, {
27
27
  "data-slot": "accordion-trigger",
28
- className: cn("cursor-clickable focus-visible:ring-ring/50 focus-visible:border-ring focus-visible:after:border-ring **:data-[slot=accordion-trigger-icon]:text-muted-foreground group/accordion-trigger relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-medium motion-color outline-none hover:underline focus-visible:ring-3 aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4", className),
28
+ className: cn("cursor-clickable focus-visible:ring-focus/50 focus-visible:border-focus focus-visible:after:border-focus **:data-[slot=accordion-trigger-icon]:text-muted group/accordion-trigger relative flex flex-1 items-start justify-between rounded-md border border-transparent py-2.5 text-left text-sm font-medium motion-color outline-none hover:underline focus-visible:ring-3 aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4", className),
29
29
  ...props,
30
30
  children: [
31
31
  children,
@@ -48,7 +48,7 @@ function AccordionContent({ className, children, ...props }) {
48
48
  ...props,
49
49
  children: /* @__PURE__ */ jsx("div", {
50
50
  "data-slot": "accordion-content",
51
- className: cn("[&_a]:hover:text-foreground h-(--accordion-panel-height) pt-0 pb-2.5 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4", className),
51
+ className: cn("[&_a]:hover:text-contrast h-(--accordion-panel-height) pt-0 pb-2.5 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4", className),
52
52
  children
53
53
  })
54
54
  });
@@ -1 +1 @@
1
- {"version":3,"file":"accordion.js","names":["AccordionPrimitive"],"sources":["../src/accordion.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\n\nimport { Accordion as AccordionPrimitive } from \"@base-ui/react/accordion\"\n\nimport { cn } from \"./lib/utils\"\n\nimport { ChevronDownIcon, ChevronUpIcon } from \"./lib/internal-icons\"\n\ntype AccordionProps = React.ComponentProps<typeof AccordionPrimitive.Root>\ntype AccordionItemProps = React.ComponentProps<typeof AccordionPrimitive.Item>\ntype AccordionTriggerProps = React.ComponentProps<typeof AccordionPrimitive.Trigger>\ntype AccordionContentProps = React.ComponentProps<typeof AccordionPrimitive.Panel>\n\nfunction Accordion({ className, ...props }: AccordionProps) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n className={cn(\n \"overflow-hidden flex w-full flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AccordionItem({ className, ...props }: AccordionItemProps) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\n \"not-last:border-b\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: AccordionTriggerProps) {\n return (\n <AccordionPrimitive.Header data-slot=\"accordion-header\" className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n \"cursor-clickable focus-visible:ring-ring/50 focus-visible:border-ring focus-visible:after:border-ring **:data-[slot=accordion-trigger-icon]:text-muted-foreground group/accordion-trigger relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-medium motion-color outline-none hover:underline focus-visible:ring-3 aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronDownIcon data-slot=\"accordion-trigger-icon\" className=\"pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden\" />\n <ChevronUpIcon data-slot=\"accordion-trigger-icon\" className=\"pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: AccordionContentProps) {\n return (\n <AccordionPrimitive.Panel\n data-slot=\"accordion-panel\"\n className=\"data-open:animate-accordion-down data-closed:animate-accordion-up overflow-hidden text-sm\"\n {...props}\n >\n <div\n data-slot=\"accordion-content\"\n className={cn(\n \"[&_a]:hover:text-foreground h-(--accordion-panel-height) pt-0 pb-2.5 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4\",\n className\n )}\n >\n {children}\n </div>\n </AccordionPrimitive.Panel>\n )\n}\n\nexport {\n Accordion,\n AccordionItem,\n AccordionTrigger,\n AccordionContent,\n}\n"],"mappings":";;;;;;;AAeA,SAAS,UAAU,EAAE,WAAW,GAAG,SAAyB;AAC1D,QACE,oBAACA,YAAmB,MAApB;EACE,aAAU;EACV,WAAW,GACT,wCACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,cAAc,EAAE,WAAW,GAAG,SAA6B;AAClE,QACE,oBAACA,YAAmB,MAApB;EACE,aAAU;EACV,WAAW,GACT,qBACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACqB;AACxB,QACE,oBAACA,YAAmB,QAApB;EAA2B,aAAU;EAAmB,WAAU;YAChE,qBAACA,YAAmB,SAApB;GACE,aAAU;GACV,WAAW,GACT,6gBACA,UACD;GACD,GAAI;aANN;IAQG;IACD,oBAAC,iBAAD;KAAiB,aAAU;KAAyB,WAAU;KAA8E,CAAA;IAC5I,oBAAC,eAAD;KAAe,aAAU;KAAyB,WAAU;KAAqF,CAAA;IACtH;;EACH,CAAA;;AAIhC,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACqB;AACxB,QACE,oBAACA,YAAmB,OAApB;EACE,aAAU;EACV,WAAU;EACV,GAAI;YAEJ,oBAAC,OAAD;GACE,aAAU;GACV,WAAW,GACT,2LACA,UACD;GAEA;GACG,CAAA;EACmB,CAAA"}
1
+ {"version":3,"file":"accordion.js","names":["AccordionPrimitive"],"sources":["../src/accordion.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\n\nimport { Accordion as AccordionPrimitive } from \"@base-ui/react/accordion\"\n\nimport { cn } from \"./lib/utils\"\n\nimport { ChevronDownIcon, ChevronUpIcon } from \"./lib/internal-icons\"\n\ntype AccordionProps = React.ComponentProps<typeof AccordionPrimitive.Root>\ntype AccordionItemProps = React.ComponentProps<typeof AccordionPrimitive.Item>\ntype AccordionTriggerProps = React.ComponentProps<typeof AccordionPrimitive.Trigger>\ntype AccordionContentProps = React.ComponentProps<typeof AccordionPrimitive.Panel>\n\nfunction Accordion({ className, ...props }: AccordionProps) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n className={cn(\n \"overflow-hidden flex w-full flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AccordionItem({ className, ...props }: AccordionItemProps) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\n \"not-last:border-b\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: AccordionTriggerProps) {\n return (\n <AccordionPrimitive.Header data-slot=\"accordion-header\" className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n \"cursor-clickable focus-visible:ring-focus/50 focus-visible:border-focus focus-visible:after:border-focus **:data-[slot=accordion-trigger-icon]:text-muted group/accordion-trigger relative flex flex-1 items-start justify-between rounded-md border border-transparent py-2.5 text-left text-sm font-medium motion-color outline-none hover:underline focus-visible:ring-3 aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronDownIcon data-slot=\"accordion-trigger-icon\" className=\"pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden\" />\n <ChevronUpIcon data-slot=\"accordion-trigger-icon\" className=\"pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: AccordionContentProps) {\n return (\n <AccordionPrimitive.Panel\n data-slot=\"accordion-panel\"\n className=\"data-open:animate-accordion-down data-closed:animate-accordion-up overflow-hidden text-sm\"\n {...props}\n >\n <div\n data-slot=\"accordion-content\"\n className={cn(\n \"[&_a]:hover:text-contrast h-(--accordion-panel-height) pt-0 pb-2.5 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4\",\n className\n )}\n >\n {children}\n </div>\n </AccordionPrimitive.Panel>\n )\n}\n\nexport {\n Accordion,\n AccordionItem,\n AccordionTrigger,\n AccordionContent,\n}\n"],"mappings":";;;;;;;AAeA,SAAS,UAAU,EAAE,WAAW,GAAG,SAAyB;AAC1D,QACE,oBAACA,YAAmB,MAApB;EACE,aAAU;EACV,WAAW,GACT,wCACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,cAAc,EAAE,WAAW,GAAG,SAA6B;AAClE,QACE,oBAACA,YAAmB,MAApB;EACE,aAAU;EACV,WAAW,GACT,qBACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACqB;AACxB,QACE,oBAACA,YAAmB,QAApB;EAA2B,aAAU;EAAmB,WAAU;YAChE,qBAACA,YAAmB,SAApB;GACE,aAAU;GACV,WAAW,GACT,qgBACA,UACD;GACD,GAAI;aANN;IAQG;IACD,oBAAC,iBAAD;KAAiB,aAAU;KAAyB,WAAU;KAA8E,CAAA;IAC5I,oBAAC,eAAD;KAAe,aAAU;KAAyB,WAAU;KAAqF,CAAA;IACtH;;EACH,CAAA;;AAIhC,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACqB;AACxB,QACE,oBAACA,YAAmB,OAApB;EACE,aAAU;EACV,WAAU;EACV,GAAI;YAEJ,oBAAC,OAAD;GACE,aAAU;GACV,WAAW,GACT,yLACA,UACD;GAEA;GACG,CAAA;EACmB,CAAA"}
@@ -182,10 +182,10 @@ function ActionBarProvider({ children, message = "You have unsaved changes", plu
182
182
  className: "fixed bottom-6 left-1/2 z-50",
183
183
  children: /* @__PURE__ */ jsxs("div", {
184
184
  "data-slot": "action-bar-content",
185
- className: cn("flex items-center gap-6 rounded-xl border border-border/60 bg-card px-5 py-2.5 shadow-lg ring-1 ring-black/5 backdrop-blur-sm dark:ring-white/5", className),
185
+ className: cn("flex items-center gap-6 rounded-lg border border-line/60 bg-surface px-5 py-2.5 shadow-lg ring-1 ring-line backdrop-blur-sm", className),
186
186
  children: [/* @__PURE__ */ jsx("span", {
187
187
  "data-slot": "action-bar-message",
188
- className: "whitespace-nowrap text-sm font-medium text-foreground",
188
+ className: "whitespace-nowrap text-sm font-medium text-contrast",
189
189
  children: displayMessage
190
190
  }), /* @__PURE__ */ jsxs("div", {
191
191
  "data-slot": "action-bar-actions",
@@ -1 +1 @@
1
- {"version":3,"file":"action-bar.js","names":[],"sources":["../src/action-bar.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\"\n\nimport { cn } from \"./lib/utils\"\nimport { Button } from \"./button\"\nimport { Spinner } from \"./spinner\"\nimport { Kbd } from \"./kbd\"\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** State a form registers with the ActionBar. */\nexport interface ActionBarEntry {\n /** Whether this form has unsaved changes. */\n hasChanges: boolean\n /** Whether this form is currently saving. */\n saving: boolean\n /** Save this form's changes. */\n onSave: () => void | Promise<void>\n /** Discard this form's changes. */\n onReset: () => void\n}\n\ninterface ActionBarContextValue {\n register: (id: string, entry: ActionBarEntry) => void\n unregister: (id: string) => void\n /** Returns true if any registered form has unsaved changes. */\n hasDirty: () => boolean\n /** Trigger the jiggle effect on blocked navigation. */\n jiggle: () => void\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst JIGGLE_STEPS = 6\nconst JIGGLE_INTERVAL = 50\nconst JIGGLE_RANGE = 15\n\n/**\n * SSR-safe platform detection. Returns `false` on the server and on the\n * first client render so hydration matches, then resolves the real\n * platform after mount. Avoids the `⌘S`/`Ctrl+S` hydration mismatch\n * that a module-scope `navigator` read would cause.\n */\nfunction useIsMac(): boolean {\n const [isMac, setIsMac] = React.useState(false)\n React.useEffect(() => {\n setIsMac(/Mac|iPhone|iPad/.test(navigator.userAgent))\n }, [])\n return isMac\n}\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst ActionBarContext = React.createContext<ActionBarContextValue | null>(null)\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport interface ActionBarProviderProps {\n children: React.ReactNode\n /** Message when one form has changes. */\n message?: string\n /** Message template for multiple dirty forms. */\n pluralMessage?: (count: number) => string\n /**\n * Announced to assistive tech (and the only feedback reduced-motion\n * users get) when guarded navigation is blocked.\n */\n blockedMessage?: string\n /** Additional className for the bar's outer wrapper. */\n className?: string\n}\n\n/**\n * Global action bar for unsaved changes.\n *\n * Place once at the root layout. Forms register via `useActionBar()`.\n *\n * Features:\n * - Multi-form aggregation (Save All / Reset All)\n * - ⌘S / Ctrl+S keyboard shortcut\n * - Navigation guard with Discord-style page jiggle\n * - `beforeunload` guard for browser close/refresh\n *\n * @example\n * ```tsx\n * // Root layout — once\n * <ActionBarProvider>{children}</ActionBarProvider>\n *\n * // Any form component\n * useActionBar('profile', { hasChanges, saving, onSave, onReset });\n * ```\n */\nfunction ActionBarProvider({\n children,\n message = \"You have unsaved changes\",\n pluralMessage = (count) => `${count} unsaved changes`,\n blockedMessage = \"Save or reset your changes before leaving this page\",\n className,\n}: ActionBarProviderProps) {\n const entriesRef = React.useRef(new Map<string, ActionBarEntry>())\n const [, forceUpdate] = React.useState(0)\n const [jiggleTransform, setJiggleTransform] = React.useState<string | null>(\n null\n )\n const jiggleTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(\n null\n )\n const contentRef = React.useRef<HTMLDivElement>(null)\n const isMac = useIsMac()\n const prefersReducedMotion = useReducedMotion()\n const reducedMotionRef = React.useRef(prefersReducedMotion)\n reducedMotionRef.current = prefersReducedMotion\n // Assertive announcement for blocked navigation. This is the *only*\n // feedback channel that works for screen-reader and reduced-motion\n // users (the visual jiggle is suppressed for them), so it is driven\n // independently of the shake.\n const [blockedNotice, setBlockedNotice] = React.useState(\"\")\n\n // --- Registry ---\n\n const register = React.useCallback((id: string, entry: ActionBarEntry) => {\n const prev = entriesRef.current.get(id)\n entriesRef.current.set(id, entry)\n if (\n !prev ||\n prev.hasChanges !== entry.hasChanges ||\n prev.saving !== entry.saving\n ) {\n forceUpdate((n) => n + 1)\n }\n }, [])\n\n const unregister = React.useCallback((id: string) => {\n if (entriesRef.current.delete(id)) {\n forceUpdate((n) => n + 1)\n }\n }, [])\n\n const hasDirty = React.useCallback(() => {\n for (const entry of entriesRef.current.values()) {\n if (entry.hasChanges) return true\n }\n return false\n }, [])\n\n // --- Jiggle ---\n\n const jiggle = React.useCallback(() => {\n // Announce to assistive tech on every blocked attempt. Clearing\n // first guarantees a text change so an identical message\n // re-announces on repeat presses.\n setBlockedNotice(\"\")\n requestAnimationFrame(() => setBlockedNotice(blockedMessage))\n\n // Vestibular safety: the random-translate shake is purely a motion\n // cue, so skip it under prefers-reduced-motion. The assertive\n // announcement above is the accessible equivalent.\n if (reducedMotionRef.current) return\n if (jiggleTimerRef.current) return\n\n let step = 0\n\n function tick() {\n step++\n if (step >= JIGGLE_STEPS) {\n setJiggleTransform(null)\n jiggleTimerRef.current = null\n return\n }\n const x = (Math.random() - 0.5) * 2 * JIGGLE_RANGE\n const y = (Math.random() - 0.5) * 2 * JIGGLE_RANGE\n setJiggleTransform(\n `translate3d(${x.toFixed(5)}px, ${y.toFixed(5)}px, 0px)`\n )\n jiggleTimerRef.current = setTimeout(tick, JIGGLE_INTERVAL)\n }\n\n tick()\n }, [blockedMessage])\n\n // --- Aggregated state ---\n\n const dirty: ActionBarEntry[] = []\n let anySaving = false\n\n for (const entry of entriesRef.current.values()) {\n if (entry.hasChanges) dirty.push(entry)\n if (entry.saving) anySaving = true\n }\n\n const showBar = dirty.length > 0 || anySaving\n const dirtyCount = dirty.length\n const displayMessage =\n dirtyCount > 1 ? pluralMessage(dirtyCount) : message\n\n // --- Save / Reset ---\n\n const handleSaveAll = React.useCallback(async () => {\n const saves = [...entriesRef.current.values()]\n .filter((e) => e.hasChanges)\n .map((e) => e.onSave())\n await Promise.all(saves)\n }, [])\n\n const handleResetAll = React.useCallback(() => {\n for (const entry of entriesRef.current.values()) {\n if (entry.hasChanges) entry.onReset()\n }\n }, [])\n\n // --- ⌘S / Ctrl+S ---\n\n React.useEffect(() => {\n function handleKeyDown(e: KeyboardEvent) {\n if ((e.metaKey || e.ctrlKey) && e.key === \"s\") {\n e.preventDefault()\n if (hasDirty()) {\n handleSaveAll()\n }\n }\n }\n\n document.addEventListener(\"keydown\", handleKeyDown)\n return () => document.removeEventListener(\"keydown\", handleKeyDown)\n }, [hasDirty, handleSaveAll])\n\n // --- beforeunload ---\n\n React.useEffect(() => {\n function handleBeforeUnload(e: BeforeUnloadEvent) {\n if (hasDirty()) {\n e.preventDefault()\n }\n }\n\n window.addEventListener(\"beforeunload\", handleBeforeUnload)\n return () => window.removeEventListener(\"beforeunload\", handleBeforeUnload)\n }, [hasDirty])\n\n // --- Context ---\n\n const ctx = React.useMemo(\n () => ({ register, unregister, hasDirty, jiggle }),\n [register, unregister, hasDirty, jiggle]\n )\n\n return (\n <ActionBarContext.Provider value={ctx}>\n <div\n data-slot=\"action-bar-shell\"\n ref={contentRef}\n style={jiggleTransform ? { transform: jiggleTransform } : undefined}\n >\n {children}\n </div>\n\n {/*\n Persistent SR-only live regions. They are always mounted so the\n announcement fires reliably when their text changes — a region\n mounted already-populated is not announced consistently across\n screen reader / browser combinations.\n */}\n <span data-slot=\"action-bar-status\" aria-live=\"polite\" className=\"sr-only\">\n {showBar ? displayMessage : \"\"}\n </span>\n <span\n data-slot=\"action-bar-blocked-status\"\n aria-live=\"assertive\"\n className=\"sr-only\"\n >\n {blockedNotice}\n </span>\n\n <AnimatePresence>\n {showBar && (\n <motion.div\n data-slot=\"action-bar\"\n initial={\n prefersReducedMotion\n ? { opacity: 0, x: \"-50%\" }\n : { opacity: 0, y: 20, x: \"-50%\" }\n }\n animate={{ opacity: 1, y: 0, x: \"-50%\" }}\n exit={\n prefersReducedMotion\n ? { opacity: 0, x: \"-50%\" }\n : { opacity: 0, y: 20, x: \"-50%\" }\n }\n transition={{ duration: 0.2, ease: \"easeOut\" }}\n className=\"fixed bottom-6 left-1/2 z-50\"\n >\n <div\n data-slot=\"action-bar-content\"\n className={cn(\n \"flex items-center gap-6 rounded-xl border border-border/60 bg-card px-5 py-2.5 shadow-lg ring-1 ring-black/5 backdrop-blur-sm dark:ring-white/5\",\n className\n )}\n >\n <span\n data-slot=\"action-bar-message\"\n className=\"whitespace-nowrap text-sm font-medium text-foreground\"\n >\n {displayMessage}\n </span>\n\n <div\n data-slot=\"action-bar-actions\"\n className=\"flex items-center gap-1.5\"\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={anySaving}\n onClick={handleResetAll}\n className=\"h-9 px-3 text-sm hover:text-destructive\"\n >\n Reset\n </Button>\n\n <Button\n type=\"button\"\n variant=\"default\"\n disabled={anySaving}\n onClick={handleSaveAll}\n className=\"h-9 px-4 text-sm\"\n >\n {anySaving ? (\n <>\n <Spinner className=\"mr-1.5 h-3.5 w-3.5\" />\n Saving\n </>\n ) : (\n <>\n Save\n <Kbd className=\"ml-1.5\">\n {isMac ? \"⌘S\" : \"Ctrl+S\"}\n </Kbd>\n </>\n )}\n </Button>\n </div>\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n </ActionBarContext.Provider>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Hook — register form state\n// ---------------------------------------------------------------------------\n\n/**\n * Register a form's unsaved state with the global ActionBar.\n *\n * Unregisters automatically on unmount.\n *\n * @param id — Unique key (e.g., 'profile', 'notifications')\n * @param entry — Current form state\n */\nfunction useActionBar(id: string, entry: ActionBarEntry) {\n const ctx = React.useContext(ActionBarContext)\n if (!ctx)\n throw new Error(\"useActionBar must be used within <ActionBarProvider>\")\n\n const { register, unregister } = ctx\n\n // Intentionally no dependency array: `entry` (and its `onSave`/\n // `onReset` closures) is rebuilt by the caller every render, so we\n // must re-register each render to keep the latest closures. The\n // `register` impl diffs the entry and only forces an update when\n // `hasChanges`/`saving` actually changed, so this can't loop.\n React.useEffect(() => {\n register(id, entry)\n })\n\n React.useEffect(() => {\n return () => unregister(id)\n }, [id, unregister])\n}\n\n// ---------------------------------------------------------------------------\n// Navigation guard hook\n// ---------------------------------------------------------------------------\n\n/**\n * Returns a function that guards navigation.\n * If unsaved changes exist, triggers the jiggle and blocks navigation.\n * Otherwise navigates normally via the provided callback.\n *\n * @param navigate — Your navigation function (e.g., `router.push`)\n *\n * @example\n * ```tsx\n * const router = useRouter();\n * const guardedPush = useActionBarGuard(router.push);\n * <button onClick={() => guardedPush('/settings')}>Settings</button>\n * ```\n */\nfunction useActionBarGuard(navigate: (href: string) => void) {\n const ctx = React.useContext(ActionBarContext)\n\n return React.useCallback(\n (href: string) => {\n if (ctx?.hasDirty()) {\n ctx.jiggle()\n return false\n }\n navigate(href)\n return true\n },\n [ctx, navigate]\n )\n}\n\n// ---------------------------------------------------------------------------\n// Exports\n// ---------------------------------------------------------------------------\n\nexport {\n ActionBarProvider,\n useActionBar,\n useActionBarGuard,\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"action-bar.js","names":[],"sources":["../src/action-bar.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\"\n\nimport { cn } from \"./lib/utils\"\nimport { Button } from \"./button\"\nimport { Spinner } from \"./spinner\"\nimport { Kbd } from \"./kbd\"\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** State a form registers with the ActionBar. */\nexport interface ActionBarEntry {\n /** Whether this form has unsaved changes. */\n hasChanges: boolean\n /** Whether this form is currently saving. */\n saving: boolean\n /** Save this form's changes. */\n onSave: () => void | Promise<void>\n /** Discard this form's changes. */\n onReset: () => void\n}\n\ninterface ActionBarContextValue {\n register: (id: string, entry: ActionBarEntry) => void\n unregister: (id: string) => void\n /** Returns true if any registered form has unsaved changes. */\n hasDirty: () => boolean\n /** Trigger the jiggle effect on blocked navigation. */\n jiggle: () => void\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst JIGGLE_STEPS = 6\nconst JIGGLE_INTERVAL = 50\nconst JIGGLE_RANGE = 15\n\n/**\n * SSR-safe platform detection. Returns `false` on the server and on the\n * first client render so hydration matches, then resolves the real\n * platform after mount. Avoids the `⌘S`/`Ctrl+S` hydration mismatch\n * that a module-scope `navigator` read would cause.\n */\nfunction useIsMac(): boolean {\n const [isMac, setIsMac] = React.useState(false)\n React.useEffect(() => {\n setIsMac(/Mac|iPhone|iPad/.test(navigator.userAgent))\n }, [])\n return isMac\n}\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst ActionBarContext = React.createContext<ActionBarContextValue | null>(null)\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport interface ActionBarProviderProps {\n children: React.ReactNode\n /** Message when one form has changes. */\n message?: string\n /** Message template for multiple dirty forms. */\n pluralMessage?: (count: number) => string\n /**\n * Announced to assistive tech (and the only feedback reduced-motion\n * users get) when guarded navigation is blocked.\n */\n blockedMessage?: string\n /** Additional className for the bar's outer wrapper. */\n className?: string\n}\n\n/**\n * Global action bar for unsaved changes.\n *\n * Place once at the root layout. Forms register via `useActionBar()`.\n *\n * Features:\n * - Multi-form aggregation (Save All / Reset All)\n * - ⌘S / Ctrl+S keyboard shortcut\n * - Navigation guard with Discord-style page jiggle\n * - `beforeunload` guard for browser close/refresh\n *\n * @example\n * ```tsx\n * // Root layout — once\n * <ActionBarProvider>{children}</ActionBarProvider>\n *\n * // Any form component\n * useActionBar('profile', { hasChanges, saving, onSave, onReset });\n * ```\n */\nfunction ActionBarProvider({\n children,\n message = \"You have unsaved changes\",\n pluralMessage = (count) => `${count} unsaved changes`,\n blockedMessage = \"Save or reset your changes before leaving this page\",\n className,\n}: ActionBarProviderProps) {\n const entriesRef = React.useRef(new Map<string, ActionBarEntry>())\n const [, forceUpdate] = React.useState(0)\n const [jiggleTransform, setJiggleTransform] = React.useState<string | null>(\n null\n )\n const jiggleTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(\n null\n )\n const contentRef = React.useRef<HTMLDivElement>(null)\n const isMac = useIsMac()\n const prefersReducedMotion = useReducedMotion()\n const reducedMotionRef = React.useRef(prefersReducedMotion)\n reducedMotionRef.current = prefersReducedMotion\n // Assertive announcement for blocked navigation. This is the *only*\n // feedback channel that works for screen-reader and reduced-motion\n // users (the visual jiggle is suppressed for them), so it is driven\n // independently of the shake.\n const [blockedNotice, setBlockedNotice] = React.useState(\"\")\n\n // --- Registry ---\n\n const register = React.useCallback((id: string, entry: ActionBarEntry) => {\n const prev = entriesRef.current.get(id)\n entriesRef.current.set(id, entry)\n if (\n !prev ||\n prev.hasChanges !== entry.hasChanges ||\n prev.saving !== entry.saving\n ) {\n forceUpdate((n) => n + 1)\n }\n }, [])\n\n const unregister = React.useCallback((id: string) => {\n if (entriesRef.current.delete(id)) {\n forceUpdate((n) => n + 1)\n }\n }, [])\n\n const hasDirty = React.useCallback(() => {\n for (const entry of entriesRef.current.values()) {\n if (entry.hasChanges) return true\n }\n return false\n }, [])\n\n // --- Jiggle ---\n\n const jiggle = React.useCallback(() => {\n // Announce to assistive tech on every blocked attempt. Clearing\n // first guarantees a text change so an identical message\n // re-announces on repeat presses.\n setBlockedNotice(\"\")\n requestAnimationFrame(() => setBlockedNotice(blockedMessage))\n\n // Vestibular safety: the random-translate shake is purely a motion\n // cue, so skip it under prefers-reduced-motion. The assertive\n // announcement above is the accessible equivalent.\n if (reducedMotionRef.current) return\n if (jiggleTimerRef.current) return\n\n let step = 0\n\n function tick() {\n step++\n if (step >= JIGGLE_STEPS) {\n setJiggleTransform(null)\n jiggleTimerRef.current = null\n return\n }\n const x = (Math.random() - 0.5) * 2 * JIGGLE_RANGE\n const y = (Math.random() - 0.5) * 2 * JIGGLE_RANGE\n setJiggleTransform(\n `translate3d(${x.toFixed(5)}px, ${y.toFixed(5)}px, 0px)`\n )\n jiggleTimerRef.current = setTimeout(tick, JIGGLE_INTERVAL)\n }\n\n tick()\n }, [blockedMessage])\n\n // --- Aggregated state ---\n\n const dirty: ActionBarEntry[] = []\n let anySaving = false\n\n for (const entry of entriesRef.current.values()) {\n if (entry.hasChanges) dirty.push(entry)\n if (entry.saving) anySaving = true\n }\n\n const showBar = dirty.length > 0 || anySaving\n const dirtyCount = dirty.length\n const displayMessage =\n dirtyCount > 1 ? pluralMessage(dirtyCount) : message\n\n // --- Save / Reset ---\n\n const handleSaveAll = React.useCallback(async () => {\n const saves = [...entriesRef.current.values()]\n .filter((e) => e.hasChanges)\n .map((e) => e.onSave())\n await Promise.all(saves)\n }, [])\n\n const handleResetAll = React.useCallback(() => {\n for (const entry of entriesRef.current.values()) {\n if (entry.hasChanges) entry.onReset()\n }\n }, [])\n\n // --- ⌘S / Ctrl+S ---\n\n React.useEffect(() => {\n function handleKeyDown(e: KeyboardEvent) {\n if ((e.metaKey || e.ctrlKey) && e.key === \"s\") {\n e.preventDefault()\n if (hasDirty()) {\n handleSaveAll()\n }\n }\n }\n\n document.addEventListener(\"keydown\", handleKeyDown)\n return () => document.removeEventListener(\"keydown\", handleKeyDown)\n }, [hasDirty, handleSaveAll])\n\n // --- beforeunload ---\n\n React.useEffect(() => {\n function handleBeforeUnload(e: BeforeUnloadEvent) {\n if (hasDirty()) {\n e.preventDefault()\n }\n }\n\n window.addEventListener(\"beforeunload\", handleBeforeUnload)\n return () => window.removeEventListener(\"beforeunload\", handleBeforeUnload)\n }, [hasDirty])\n\n // --- Context ---\n\n const ctx = React.useMemo(\n () => ({ register, unregister, hasDirty, jiggle }),\n [register, unregister, hasDirty, jiggle]\n )\n\n return (\n <ActionBarContext.Provider value={ctx}>\n <div\n data-slot=\"action-bar-shell\"\n ref={contentRef}\n style={jiggleTransform ? { transform: jiggleTransform } : undefined}\n >\n {children}\n </div>\n\n {/*\n Persistent SR-only live regions. They are always mounted so the\n announcement fires reliably when their text changes — a region\n mounted already-populated is not announced consistently across\n screen reader / browser combinations.\n */}\n <span data-slot=\"action-bar-status\" aria-live=\"polite\" className=\"sr-only\">\n {showBar ? displayMessage : \"\"}\n </span>\n <span\n data-slot=\"action-bar-blocked-status\"\n aria-live=\"assertive\"\n className=\"sr-only\"\n >\n {blockedNotice}\n </span>\n\n <AnimatePresence>\n {showBar && (\n <motion.div\n data-slot=\"action-bar\"\n initial={\n prefersReducedMotion\n ? { opacity: 0, x: \"-50%\" }\n : { opacity: 0, y: 20, x: \"-50%\" }\n }\n animate={{ opacity: 1, y: 0, x: \"-50%\" }}\n exit={\n prefersReducedMotion\n ? { opacity: 0, x: \"-50%\" }\n : { opacity: 0, y: 20, x: \"-50%\" }\n }\n transition={{ duration: 0.2, ease: \"easeOut\" }}\n className=\"fixed bottom-6 left-1/2 z-50\"\n >\n <div\n data-slot=\"action-bar-content\"\n className={cn(\n \"flex items-center gap-6 rounded-lg border border-line/60 bg-surface px-5 py-2.5 shadow-lg ring-1 ring-line backdrop-blur-sm\",\n className\n )}\n >\n <span\n data-slot=\"action-bar-message\"\n className=\"whitespace-nowrap text-sm font-medium text-contrast\"\n >\n {displayMessage}\n </span>\n\n <div\n data-slot=\"action-bar-actions\"\n className=\"flex items-center gap-1.5\"\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={anySaving}\n onClick={handleResetAll}\n className=\"h-9 px-3 text-sm hover:text-destructive\"\n >\n Reset\n </Button>\n\n <Button\n type=\"button\"\n variant=\"default\"\n disabled={anySaving}\n onClick={handleSaveAll}\n className=\"h-9 px-4 text-sm\"\n >\n {anySaving ? (\n <>\n <Spinner className=\"mr-1.5 h-3.5 w-3.5\" />\n Saving\n </>\n ) : (\n <>\n Save\n <Kbd className=\"ml-1.5\">\n {isMac ? \"⌘S\" : \"Ctrl+S\"}\n </Kbd>\n </>\n )}\n </Button>\n </div>\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n </ActionBarContext.Provider>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Hook — register form state\n// ---------------------------------------------------------------------------\n\n/**\n * Register a form's unsaved state with the global ActionBar.\n *\n * Unregisters automatically on unmount.\n *\n * @param id — Unique key (e.g., 'profile', 'notifications')\n * @param entry — Current form state\n */\nfunction useActionBar(id: string, entry: ActionBarEntry) {\n const ctx = React.useContext(ActionBarContext)\n if (!ctx)\n throw new Error(\"useActionBar must be used within <ActionBarProvider>\")\n\n const { register, unregister } = ctx\n\n // Intentionally no dependency array: `entry` (and its `onSave`/\n // `onReset` closures) is rebuilt by the caller every render, so we\n // must re-register each render to keep the latest closures. The\n // `register` impl diffs the entry and only forces an update when\n // `hasChanges`/`saving` actually changed, so this can't loop.\n React.useEffect(() => {\n register(id, entry)\n })\n\n React.useEffect(() => {\n return () => unregister(id)\n }, [id, unregister])\n}\n\n// ---------------------------------------------------------------------------\n// Navigation guard hook\n// ---------------------------------------------------------------------------\n\n/**\n * Returns a function that guards navigation.\n * If unsaved changes exist, triggers the jiggle and blocks navigation.\n * Otherwise navigates normally via the provided callback.\n *\n * @param navigate — Your navigation function (e.g., `router.push`)\n *\n * @example\n * ```tsx\n * const router = useRouter();\n * const guardedPush = useActionBarGuard(router.push);\n * <button onClick={() => guardedPush('/settings')}>Settings</button>\n * ```\n */\nfunction useActionBarGuard(navigate: (href: string) => void) {\n const ctx = React.useContext(ActionBarContext)\n\n return React.useCallback(\n (href: string) => {\n if (ctx?.hasDirty()) {\n ctx.jiggle()\n return false\n }\n navigate(href)\n return true\n },\n [ctx, navigate]\n )\n}\n\n// ---------------------------------------------------------------------------\n// Exports\n// ---------------------------------------------------------------------------\n\nexport {\n ActionBarProvider,\n useActionBar,\n useActionBarGuard,\n}\n"],"mappings":"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"}
@@ -34,7 +34,7 @@ function AlertDialogContent({ className, size = "default", ...props }) {
34
34
  return /* @__PURE__ */ jsxs(AlertDialogPortal, { children: [/* @__PURE__ */ jsx(AlertDialogOverlay, {}), /* @__PURE__ */ jsx(AlertDialog$1.Popup, {
35
35
  "data-slot": "alert-dialog-content",
36
36
  "data-size": size,
37
- className: cn("motion-scale bg-background ring-foreground/10 group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl p-4 ring-1 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=lg]:max-w-lg data-[size=xl]:max-w-xl data-[size=default]:sm:max-w-sm data-[size=lg]:sm:max-w-lg data-[size=xl]:sm:max-w-xl", className),
37
+ className: cn("motion-scale-lg bg-foundation ring-contrast/10 group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-lg p-4 ring-1 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=lg]:max-w-lg data-[size=xl]:max-w-xl data-[size=default]:sm:max-w-sm data-[size=lg]:sm:max-w-lg data-[size=xl]:sm:max-w-xl", className),
38
38
  ...props
39
39
  })] });
40
40
  }
@@ -48,14 +48,14 @@ function AlertDialogHeader({ className, ...props }) {
48
48
  function AlertDialogFooter({ className, ...props }) {
49
49
  return /* @__PURE__ */ jsx("div", {
50
50
  "data-slot": "alert-dialog-footer",
51
- className: cn("bg-muted/50 -mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end", className),
51
+ className: cn("bg-secondary/50 -mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-lg border-t p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end", className),
52
52
  ...props
53
53
  });
54
54
  }
55
55
  function AlertDialogMedia({ className, ...props }) {
56
56
  return /* @__PURE__ */ jsx("div", {
57
57
  "data-slot": "alert-dialog-media",
58
- className: cn("bg-muted mb-2 inline-flex size-10 items-center justify-center rounded-md sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6", className),
58
+ className: cn("bg-secondary mb-2 inline-flex size-10 items-center justify-center rounded-md sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6", className),
59
59
  ...props
60
60
  });
61
61
  }
@@ -69,7 +69,7 @@ function AlertDialogTitle({ className, ...props }) {
69
69
  function AlertDialogDescription({ className, ...props }) {
70
70
  return /* @__PURE__ */ jsx(AlertDialog$1.Description, {
71
71
  "data-slot": "alert-dialog-description",
72
- className: cn("text-muted-foreground *:[a]:hover:text-foreground text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3", className),
72
+ className: cn("text-muted *:[a]:hover:text-contrast text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3", className),
73
73
  ...props
74
74
  });
75
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"alert-dialog.js","names":["AlertDialogPrimitive"],"sources":["../src/alert-dialog.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { AlertDialog as AlertDialogPrimitive } from \"@base-ui/react/alert-dialog\"\n\nimport { Button } from \"./button\"\nimport { cn } from \"./lib/utils\"\n\ntype AlertDialogProps = React.ComponentProps<typeof AlertDialogPrimitive.Root>\n\ntype AlertDialogTriggerProps = React.ComponentProps<typeof AlertDialogPrimitive.Trigger>\n\ntype AlertDialogPortalProps = React.ComponentProps<typeof AlertDialogPrimitive.Portal>\n\ntype AlertDialogOverlayProps = React.ComponentProps<typeof AlertDialogPrimitive.Backdrop>\n\ntype AlertDialogContentProps = React.ComponentProps<typeof AlertDialogPrimitive.Popup> & {\n size?: \"default\" | \"sm\" | \"lg\" | \"xl\"\n}\n\ntype AlertDialogHeaderProps = React.ComponentProps<\"div\">\n\ntype AlertDialogFooterProps = React.ComponentProps<\"div\">\n\ntype AlertDialogMediaProps = React.ComponentProps<\"div\">\n\ntype AlertDialogTitleProps = React.ComponentProps<typeof AlertDialogPrimitive.Title>\n\ntype AlertDialogDescriptionProps = React.ComponentProps<typeof AlertDialogPrimitive.Description>\n\ntype AlertDialogActionProps = React.ComponentProps<typeof Button>\n\ntype AlertDialogCancelProps = React.ComponentProps<typeof AlertDialogPrimitive.Close> &\n Pick<React.ComponentProps<typeof Button>, \"variant\" | \"size\">\n\nfunction AlertDialog({ ...props }: AlertDialogProps) {\n return <AlertDialogPrimitive.Root data-slot=\"alert-dialog\" {...props} />\n}\n\nfunction AlertDialogTrigger({ ...props }: AlertDialogTriggerProps) {\n return <AlertDialogPrimitive.Trigger data-slot=\"alert-dialog-trigger\" {...props} />\n}\n\nfunction AlertDialogPortal({ ...props }: AlertDialogPortalProps) {\n return <AlertDialogPrimitive.Portal data-slot=\"alert-dialog-portal\" {...props} />\n}\n\nfunction AlertDialogOverlay({ className, ...props }: AlertDialogOverlayProps) {\n return (\n <AlertDialogPrimitive.Backdrop\n data-slot=\"alert-dialog-overlay\"\n className={cn(\n \"motion-scrim fixed inset-0 isolate z-50 bg-black/10 supports-backdrop-filter:backdrop-blur-xs\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogContent({\n className,\n size = \"default\",\n ...props\n}: AlertDialogContentProps) {\n return (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Popup\n data-slot=\"alert-dialog-content\"\n data-size={size}\n className={cn(\n \"motion-scale bg-background ring-foreground/10 group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl p-4 ring-1 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=lg]:max-w-lg data-[size=xl]:max-w-xl data-[size=default]:sm:max-w-sm data-[size=lg]:sm:max-w-lg data-[size=xl]:sm:max-w-xl\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n )\n}\n\nfunction AlertDialogHeader({ className, ...props }: AlertDialogHeaderProps) {\n return (\n <div\n data-slot=\"alert-dialog-header\"\n className={cn(\n \"grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr] group-data-[size=lg]/alert-dialog-content:place-items-start group-data-[size=lg]/alert-dialog-content:text-left group-data-[size=xl]/alert-dialog-content:place-items-start group-data-[size=xl]/alert-dialog-content:text-left\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogFooter({ className, ...props }: AlertDialogFooterProps) {\n return (\n <div\n data-slot=\"alert-dialog-footer\"\n className={cn(\n \"bg-muted/50 -mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogMedia({ className, ...props }: AlertDialogMediaProps) {\n return (\n <div\n data-slot=\"alert-dialog-media\"\n className={cn(\n \"bg-muted mb-2 inline-flex size-10 items-center justify-center rounded-md sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogTitle({ className, ...props }: AlertDialogTitleProps) {\n return (\n <AlertDialogPrimitive.Title\n data-slot=\"alert-dialog-title\"\n className={cn(\n \"text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogDescription({\n className,\n ...props\n}: AlertDialogDescriptionProps) {\n return (\n <AlertDialogPrimitive.Description\n data-slot=\"alert-dialog-description\"\n className={cn(\n \"text-muted-foreground *:[a]:hover:text-foreground text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogAction({\n className,\n ...props\n}: AlertDialogActionProps) {\n return (\n <Button\n data-slot=\"alert-dialog-action\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogCancel({\n className,\n variant = \"outline\",\n size = \"default\",\n ...props\n}: AlertDialogCancelProps) {\n return (\n <AlertDialogPrimitive.Close\n data-slot=\"alert-dialog-cancel\"\n className={className}\n render={<Button variant={variant} size={size} />}\n {...props}\n />\n )\n}\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogMedia,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n}\n"],"mappings":";;;;;;;AAmCA,SAAS,YAAY,EAAE,GAAG,SAA2B;AACnD,QAAO,oBAACA,cAAqB,MAAtB;EAA2B,aAAU;EAAe,GAAI;EAAS,CAAA;;AAG1E,SAAS,mBAAmB,EAAE,GAAG,SAAkC;AACjE,QAAO,oBAACA,cAAqB,SAAtB;EAA8B,aAAU;EAAuB,GAAI;EAAS,CAAA;;AAGrF,SAAS,kBAAkB,EAAE,GAAG,SAAiC;AAC/D,QAAO,oBAACA,cAAqB,QAAtB;EAA6B,aAAU;EAAsB,GAAI;EAAS,CAAA;;AAGnF,SAAS,mBAAmB,EAAE,WAAW,GAAG,SAAkC;AAC5E,QACE,oBAACA,cAAqB,UAAtB;EACE,aAAU;EACV,WAAW,GACT,iGACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,mBAAmB,EAC1B,WACA,OAAO,WACP,GAAG,SACuB;AAC1B,QACE,qBAAC,mBAAD,EAAA,UAAA,CACE,oBAAC,oBAAD,EAAsB,CAAA,EACtB,oBAACA,cAAqB,OAAtB;EACE,aAAU;EACV,aAAW;EACX,WAAW,GACT,0XACA,UACD;EACD,GAAI;EACJ,CAAA,CACgB,EAAA,CAAA;;AAIxB,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAiC;AAC1E,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,snBACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAiC;AAC1E,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,iNACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAgC;AACxE,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,8KACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAgC;AACxE,QACE,oBAACA,cAAqB,OAAtB;EACE,aAAU;EACV,WAAW,GACT,qJACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,uBAAuB,EAC9B,WACA,GAAG,SAC2B;AAC9B,QACE,oBAACA,cAAqB,aAAtB;EACE,aAAU;EACV,WAAW,GACT,kIACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,kBAAkB,EACzB,WACA,GAAG,SACsB;AACzB,QACE,oBAAC,QAAD;EACE,aAAU;EACV,WAAW,GAAG,UAAU;EACxB,GAAI;EACJ,CAAA;;AAIN,SAAS,kBAAkB,EACzB,WACA,UAAU,WACV,OAAO,WACP,GAAG,SACsB;AACzB,QACE,oBAACA,cAAqB,OAAtB;EACE,aAAU;EACC;EACX,QAAQ,oBAAC,QAAD;GAAiB;GAAe;GAAQ,CAAA;EAChD,GAAI;EACJ,CAAA"}
1
+ {"version":3,"file":"alert-dialog.js","names":["AlertDialogPrimitive"],"sources":["../src/alert-dialog.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { AlertDialog as AlertDialogPrimitive } from \"@base-ui/react/alert-dialog\"\n\nimport { Button } from \"./button\"\nimport { cn } from \"./lib/utils\"\n\ntype AlertDialogProps = React.ComponentProps<typeof AlertDialogPrimitive.Root>\n\ntype AlertDialogTriggerProps = React.ComponentProps<typeof AlertDialogPrimitive.Trigger>\n\ntype AlertDialogPortalProps = React.ComponentProps<typeof AlertDialogPrimitive.Portal>\n\ntype AlertDialogOverlayProps = React.ComponentProps<typeof AlertDialogPrimitive.Backdrop>\n\ntype AlertDialogContentProps = React.ComponentProps<typeof AlertDialogPrimitive.Popup> & {\n size?: \"default\" | \"sm\" | \"lg\" | \"xl\"\n}\n\ntype AlertDialogHeaderProps = React.ComponentProps<\"div\">\n\ntype AlertDialogFooterProps = React.ComponentProps<\"div\">\n\ntype AlertDialogMediaProps = React.ComponentProps<\"div\">\n\ntype AlertDialogTitleProps = React.ComponentProps<typeof AlertDialogPrimitive.Title>\n\ntype AlertDialogDescriptionProps = React.ComponentProps<typeof AlertDialogPrimitive.Description>\n\ntype AlertDialogActionProps = React.ComponentProps<typeof Button>\n\ntype AlertDialogCancelProps = React.ComponentProps<typeof AlertDialogPrimitive.Close> &\n Pick<React.ComponentProps<typeof Button>, \"variant\" | \"size\">\n\nfunction AlertDialog({ ...props }: AlertDialogProps) {\n return <AlertDialogPrimitive.Root data-slot=\"alert-dialog\" {...props} />\n}\n\nfunction AlertDialogTrigger({ ...props }: AlertDialogTriggerProps) {\n return <AlertDialogPrimitive.Trigger data-slot=\"alert-dialog-trigger\" {...props} />\n}\n\nfunction AlertDialogPortal({ ...props }: AlertDialogPortalProps) {\n return <AlertDialogPrimitive.Portal data-slot=\"alert-dialog-portal\" {...props} />\n}\n\nfunction AlertDialogOverlay({ className, ...props }: AlertDialogOverlayProps) {\n return (\n <AlertDialogPrimitive.Backdrop\n data-slot=\"alert-dialog-overlay\"\n className={cn(\n \"motion-scrim fixed inset-0 isolate z-50 bg-black/10 supports-backdrop-filter:backdrop-blur-xs\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogContent({\n className,\n size = \"default\",\n ...props\n}: AlertDialogContentProps) {\n return (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Popup\n data-slot=\"alert-dialog-content\"\n data-size={size}\n className={cn(\n \"motion-scale-lg bg-foundation ring-contrast/10 group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-lg p-4 ring-1 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=lg]:max-w-lg data-[size=xl]:max-w-xl data-[size=default]:sm:max-w-sm data-[size=lg]:sm:max-w-lg data-[size=xl]:sm:max-w-xl\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n )\n}\n\nfunction AlertDialogHeader({ className, ...props }: AlertDialogHeaderProps) {\n return (\n <div\n data-slot=\"alert-dialog-header\"\n className={cn(\n \"grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr] group-data-[size=lg]/alert-dialog-content:place-items-start group-data-[size=lg]/alert-dialog-content:text-left group-data-[size=xl]/alert-dialog-content:place-items-start group-data-[size=xl]/alert-dialog-content:text-left\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogFooter({ className, ...props }: AlertDialogFooterProps) {\n return (\n <div\n data-slot=\"alert-dialog-footer\"\n className={cn(\n \"bg-secondary/50 -mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-lg border-t p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogMedia({ className, ...props }: AlertDialogMediaProps) {\n return (\n <div\n data-slot=\"alert-dialog-media\"\n className={cn(\n \"bg-secondary mb-2 inline-flex size-10 items-center justify-center rounded-md sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogTitle({ className, ...props }: AlertDialogTitleProps) {\n return (\n <AlertDialogPrimitive.Title\n data-slot=\"alert-dialog-title\"\n className={cn(\n \"text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogDescription({\n className,\n ...props\n}: AlertDialogDescriptionProps) {\n return (\n <AlertDialogPrimitive.Description\n data-slot=\"alert-dialog-description\"\n className={cn(\n \"text-muted *:[a]:hover:text-contrast text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogAction({\n className,\n ...props\n}: AlertDialogActionProps) {\n return (\n <Button\n data-slot=\"alert-dialog-action\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogCancel({\n className,\n variant = \"outline\",\n size = \"default\",\n ...props\n}: AlertDialogCancelProps) {\n return (\n <AlertDialogPrimitive.Close\n data-slot=\"alert-dialog-cancel\"\n className={className}\n render={<Button variant={variant} size={size} />}\n {...props}\n />\n )\n}\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogMedia,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n}\n"],"mappings":";;;;;;;AAmCA,SAAS,YAAY,EAAE,GAAG,SAA2B;AACnD,QAAO,oBAACA,cAAqB,MAAtB;EAA2B,aAAU;EAAe,GAAI;EAAS,CAAA;;AAG1E,SAAS,mBAAmB,EAAE,GAAG,SAAkC;AACjE,QAAO,oBAACA,cAAqB,SAAtB;EAA8B,aAAU;EAAuB,GAAI;EAAS,CAAA;;AAGrF,SAAS,kBAAkB,EAAE,GAAG,SAAiC;AAC/D,QAAO,oBAACA,cAAqB,QAAtB;EAA6B,aAAU;EAAsB,GAAI;EAAS,CAAA;;AAGnF,SAAS,mBAAmB,EAAE,WAAW,GAAG,SAAkC;AAC5E,QACE,oBAACA,cAAqB,UAAtB;EACE,aAAU;EACV,WAAW,GACT,iGACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,mBAAmB,EAC1B,WACA,OAAO,WACP,GAAG,SACuB;AAC1B,QACE,qBAAC,mBAAD,EAAA,UAAA,CACE,oBAAC,oBAAD,EAAsB,CAAA,EACtB,oBAACA,cAAqB,OAAtB;EACE,aAAU;EACV,aAAW;EACX,WAAW,GACT,2XACA,UACD;EACD,GAAI;EACJ,CAAA,CACgB,EAAA,CAAA;;AAIxB,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAiC;AAC1E,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,snBACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAiC;AAC1E,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,qNACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAgC;AACxE,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,kLACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAgC;AACxE,QACE,oBAACA,cAAqB,OAAtB;EACE,aAAU;EACV,WAAW,GACT,qJACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,uBAAuB,EAC9B,WACA,GAAG,SAC2B;AAC9B,QACE,oBAACA,cAAqB,aAAtB;EACE,aAAU;EACV,WAAW,GACT,qHACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,kBAAkB,EACzB,WACA,GAAG,SACsB;AACzB,QACE,oBAAC,QAAD;EACE,aAAU;EACV,WAAW,GAAG,UAAU;EACxB,GAAI;EACJ,CAAA;;AAIN,SAAS,kBAAkB,EACzB,WACA,UAAU,WACV,OAAO,WACP,GAAG,SACsB;AACzB,QACE,oBAACA,cAAqB,OAAtB;EACE,aAAU;EACC;EACX,QAAQ,oBAAC,QAAD;GAAiB;GAAe;GAAQ,CAAA;EAChD,GAAI;EACJ,CAAA"}
package/dist/alert.js CHANGED
@@ -3,10 +3,10 @@ import "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  import { cva } from "class-variance-authority";
5
5
  //#region src/alert.tsx
6
- const alertVariants = cva("grid gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-data-[icon]:grid-cols-[auto_1fr] has-data-[icon]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 w-full relative group/alert", {
6
+ const alertVariants = cva("grid gap-0.5 rounded-md border border-edge px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-data-[icon]:grid-cols-[auto_1fr] has-data-[icon]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 w-full relative group/alert", {
7
7
  variants: { variant: {
8
- default: "bg-card text-card-foreground",
9
- destructive: "text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current"
8
+ default: "bg-surface text-contrast",
9
+ destructive: "text-destructive bg-surface *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current"
10
10
  } },
11
11
  defaultVariants: { variant: "default" }
12
12
  });
@@ -21,14 +21,14 @@ function Alert({ className, variant, ...props }) {
21
21
  function AlertTitle({ className, ...props }) {
22
22
  return /* @__PURE__ */ jsx("div", {
23
23
  "data-slot": "alert-title",
24
- className: cn("[&_a]:hover:text-foreground font-medium group-has-data-[icon]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3", className),
24
+ className: cn("[&_a]:hover:text-contrast font-medium group-has-data-[icon]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3", className),
25
25
  ...props
26
26
  });
27
27
  }
28
28
  function AlertDescription({ className, ...props }) {
29
29
  return /* @__PURE__ */ jsx("div", {
30
30
  "data-slot": "alert-description",
31
- className: cn("text-muted-foreground [&_a]:hover:text-foreground text-sm text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4", className),
31
+ className: cn("text-muted [&_a]:hover:text-contrast text-sm text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4", className),
32
32
  ...props
33
33
  });
34
34
  }
package/dist/alert.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"alert.js","names":[],"sources":["../src/alert.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"./lib/utils\"\n\nconst alertVariants = cva(\n \"grid gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-data-[icon]:grid-cols-[auto_1fr] has-data-[icon]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 w-full relative group/alert\",\n {\n variants: {\n variant: {\n default: \"bg-card text-card-foreground\",\n destructive:\n \"text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\ntype AlertProps = React.ComponentProps<\"div\"> & VariantProps<typeof alertVariants>\ntype AlertTitleProps = React.ComponentProps<\"div\">\ntype AlertDescriptionProps = React.ComponentProps<\"div\">\ntype AlertActionProps = React.ComponentProps<\"div\">\n\nfunction Alert({\n className,\n variant,\n ...props\n}: AlertProps) {\n return (\n <div\n data-slot=\"alert\"\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nfunction AlertTitle({ className, ...props }: AlertTitleProps) {\n return (\n <div\n data-slot=\"alert-title\"\n className={cn(\n \"[&_a]:hover:text-foreground font-medium group-has-data-[icon]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDescription({\n className,\n ...props\n}: AlertDescriptionProps) {\n return (\n <div\n data-slot=\"alert-description\"\n className={cn(\n \"text-muted-foreground [&_a]:hover:text-foreground text-sm text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertAction({ className, ...props }: AlertActionProps) {\n return (\n <div\n data-slot=\"alert-action\"\n className={cn(\"absolute top-2 right-2\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Alert,\n AlertTitle,\n AlertDescription,\n AlertAction\n}\n"],"mappings":";;;;;AAKA,MAAM,gBAAgB,IACpB,uUACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,aACE;EACH,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;AAOD,SAAS,MAAM,EACb,WACA,SACA,GAAG,SACU;AACb,QACE,oBAAC,OAAD;EACE,aAAU;EACV,MAAK;EACL,WAAW,GAAG,cAAc,EAAE,SAAS,CAAC,EAAE,UAAU;EACpD,GAAI;EACJ,CAAA;;AAIN,SAAS,WAAW,EAAE,WAAW,GAAG,SAA0B;AAC5D,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,4HACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EACxB,WACA,GAAG,SACqB;AACxB,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,8JACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,YAAY,EAAE,WAAW,GAAG,SAA2B;AAC9D,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,0BAA0B,UAAU;EAClD,GAAI;EACJ,CAAA"}
1
+ {"version":3,"file":"alert.js","names":[],"sources":["../src/alert.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"./lib/utils\"\n\nconst alertVariants = cva(\n \"grid gap-0.5 rounded-md border border-edge px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-data-[icon]:grid-cols-[auto_1fr] has-data-[icon]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 w-full relative group/alert\",\n {\n variants: {\n variant: {\n default: \"bg-surface text-contrast\",\n destructive:\n \"text-destructive bg-surface *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\ntype AlertProps = React.ComponentProps<\"div\"> & VariantProps<typeof alertVariants>\ntype AlertTitleProps = React.ComponentProps<\"div\">\ntype AlertDescriptionProps = React.ComponentProps<\"div\">\ntype AlertActionProps = React.ComponentProps<\"div\">\n\nfunction Alert({\n className,\n variant,\n ...props\n}: AlertProps) {\n return (\n <div\n data-slot=\"alert\"\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nfunction AlertTitle({ className, ...props }: AlertTitleProps) {\n return (\n <div\n data-slot=\"alert-title\"\n className={cn(\n \"[&_a]:hover:text-contrast font-medium group-has-data-[icon]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDescription({\n className,\n ...props\n}: AlertDescriptionProps) {\n return (\n <div\n data-slot=\"alert-description\"\n className={cn(\n \"text-muted [&_a]:hover:text-contrast text-sm text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertAction({ className, ...props }: AlertActionProps) {\n return (\n <div\n data-slot=\"alert-action\"\n className={cn(\"absolute top-2 right-2\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Alert,\n AlertTitle,\n AlertDescription,\n AlertAction\n}\n"],"mappings":";;;;;AAKA,MAAM,gBAAgB,IACpB,mVACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,aACE;EACH,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;AAOD,SAAS,MAAM,EACb,WACA,SACA,GAAG,SACU;AACb,QACE,oBAAC,OAAD;EACE,aAAU;EACV,MAAK;EACL,WAAW,GAAG,cAAc,EAAE,SAAS,CAAC,EAAE,UAAU;EACpD,GAAI;EACJ,CAAA;;AAIN,SAAS,WAAW,EAAE,WAAW,GAAG,SAA0B;AAC5D,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,0HACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EACxB,WACA,GAAG,SACqB;AACxB,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,iJACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,YAAY,EAAE,WAAW,GAAG,SAA2B;AAC9D,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,0BAA0B,UAAU;EAClD,GAAI;EACJ,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"animate.d.ts","names":[],"sources":["../src/animate.tsx"],"mappings":";;;;;;KAkBK,SAAA;AAAA,UAEK,kBAAA;EACR,QAAA,EAAU,YAAA;;EAEV,KAAA;EALY;EAOZ,IAAA,GAAO,SAAA;EAPK;EASZ,QAAA;EAPQ;EASR,KAAA;;EAEA,IAAA;EANO;EAQP,MAAA;EAQuB;EANvB,IAAA;EAdA;EAgBA,MAAA;EAdA;EAgBA,IAAA;EAdO;EAgBP,UAAA,GAAa,UAAA;AAAA;AAAA,UAGL,cAAA;EACR,QAAA,EAAU,YAAA;EAVV;EAYA,KAAA;EARA;EAUA,IAAA,GAAO,SAAA;EARM;EAUb,QAAA;EAVuB;EAYvB,KAAA;EATsB;EAWtB,IAAA;EAVU;EAYV,MAAA;EAMa;EAJb,IAAA;EAIuB;EAFvB,MAAA;EAhBU;EAkBV,UAAA,GAAa,UAAA;AAAA;AAAA,UAGL,YAAA;EACR,QAAA,EAAU,YAAA;EAdV;EAgBA,QAAA;EAZA;EAcA,SAAA;AAAA;AAAA,UAGQ,UAAA;EACR,QAAA,EAAU,YAAA;EAZa;EAcvB,GAAA;EAXQ;EAaR,GAAA;;EAEA,QAAA;EAdA;EAgBA,OAAA;EAdA;EAgBA,MAAA;AAAA;AAAA,UAGQ,UAAA;EACR,QAAA,EAAU,YAAA;EAfQ;EAiBlB,QAAA;EAhBsB;EAkBtB,QAAA;EAlBU;EAoBV,MAAA;EAhBA;EAkBA,MAAA;AAAA;;;;AAZM;;;;;;;;;;;;AAYA;iBAgIC,aAAA,CAAA;EACP,QAAA;EACA,KAAA;EACA,IAAA;EACA,QAAA;EACA,KAAA;EACA,IAAA;EACA,MAAA;EACA,IAAA;EACA,MAAA;EACA,IAAA;EACA;AAAA,GACC,kBAAA,GAAkB,YAAA,mBAAA,OAAA,CAAA,qBAAA;;;;;;;;;;;;;;iBAoDZ,SAAA,CAAA;EACP,QAAA;EACA,KAAA;EACA,IAAA;EACA,QAAA;EACA,KAAA;EACA,IAAA;EACA,MAAA;EACA,IAAA;EACA,MAAA;EACA;AAAA,GACC,cAAA,GAAc,YAAA,mBAAA,OAAA,CAAA,qBAAA;;;;;;;;;;;;;iBA8CR,OAAA,CAAA;EACP,QAAA;EACA,QAAA;EACA;AAAA,GACC,YAAA,GAAY,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;;;;;;;iBA0BN,KAAA,CAAA;EACP,QAAA;EACA,GAAA;EACA,GAAA;EACA,QAAA;EACA,OAAA;EACA;AAAA,GACC,UAAA,GAAU,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;AAlJQ;;;;;;iBAsMZ,KAAA,CAAA;EACP,QAAA;EACA,QAAA;EACA,QAAA;EACA,MAAA;EACA;AAAA,GACC,UAAA,GAAU,oBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"animate.d.ts","names":[],"sources":["../src/animate.tsx"],"mappings":";;;;;;KAkBK,SAAA;AAAA,UAEK,kBAAA;EACR,QAAA,EAAU,YAAA;;EAEV,KAAA;EALY;EAOZ,IAAA,GAAO,SAAA;EAPK;EASZ,QAAA;EAPQ;EASR,KAAA;;EAEA,IAAA;EANO;EAQP,MAAA;EAQuB;EANvB,IAAA;EAdA;EAgBA,MAAA;EAdA;EAgBA,IAAA;EAdO;EAgBP,UAAA,GAAa,UAAA;AAAA;AAAA,UAGL,cAAA;EACR,QAAA,EAAU,YAAA;EAVV;EAYA,KAAA;EARA;EAUA,IAAA,GAAO,SAAA;EARM;EAUb,QAAA;EAVuB;EAYvB,KAAA;EATsB;EAWtB,IAAA;EAVU;EAYV,MAAA;EAMa;EAJb,IAAA;EAIuB;EAFvB,MAAA;EAhBU;EAkBV,UAAA,GAAa,UAAA;AAAA;AAAA,UAGL,YAAA;EACR,QAAA,EAAU,YAAA;EAdV;EAgBA,QAAA;EAZA;EAcA,SAAA;AAAA;AAAA,UAGQ,UAAA;EACR,QAAA,EAAU,YAAA;EAZa;EAcvB,GAAA;EAXQ;EAaR,GAAA;;EAEA,QAAA;EAdA;EAgBA,OAAA;EAdA;EAgBA,MAAA;AAAA;AAAA,UAGQ,UAAA;EACR,QAAA,EAAU,YAAA;EAfQ;EAiBlB,QAAA;EAhBsB;EAkBtB,QAAA;EAlBU;EAoBV,MAAA;EAhBA;EAkBA,MAAA;AAAA;;;;AAZM;;;;;;;;;;;;AAYA;iBA+HC,aAAA,CAAA;EACP,QAAA;EACA,KAAA;EACA,IAAA;EACA,QAAA;EACA,KAAA;EACA,IAAA;EACA,MAAA;EACA,IAAA;EACA,MAAA;EACA,IAAA;EACA;AAAA,GACC,kBAAA,GAAkB,YAAA,mBAAA,OAAA,CAAA,qBAAA;;;;;;;;;;;;;;iBAoDZ,SAAA,CAAA;EACP,QAAA;EACA,KAAA;EACA,IAAA;EACA,QAAA;EACA,KAAA;EACA,IAAA;EACA,MAAA;EACA,IAAA;EACA,MAAA;EACA;AAAA,GACC,cAAA,GAAc,YAAA,mBAAA,OAAA,CAAA,qBAAA;;;;;;;;;;;;;iBA8CR,OAAA,CAAA;EACP,QAAA;EACA,QAAA;EACA;AAAA,GACC,YAAA,GAAY,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;;;;;;;iBA0BN,KAAA,CAAA;EACP,QAAA;EACA,GAAA;EACA,GAAA;EACA,QAAA;EACA,OAAA;EACA;AAAA,GACC,UAAA,GAAU,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;AAlJQ;;;;;;iBAsMZ,KAAA,CAAA;EACP,QAAA;EACA,QAAA;EACA,QAAA;EACA,MAAA;EACA;AAAA,GACC,UAAA,GAAU,oBAAA,CAAA,GAAA,CAAA,OAAA"}
package/dist/animate.js CHANGED
@@ -34,8 +34,7 @@ const FLIP_MAP = {
34
34
  };
35
35
  /** Overshoot ("spring") easing for the opt-in `spring` prop on
36
36
  * `AnimateIn` / `AnimateOnView`. This is `animate.tsx`'s own page-entrance
37
- * bounce — the CSS recipe system intentionally has no spring (one circ-out
38
- * curve), so this is a standalone constant, not a shared token. */
37
+ * bounce — the CSS recipe system intentionally has no spring, so this is a standalone constant, not a shared token. */
39
38
  const SPRING_EASE = "cubic-bezier(0.34, 1.45, 0.64, 1)";
40
39
  function buildStyles(opts) {
41
40
  const { from, distance, doScale, blur, rotate, flip } = opts;
@@ -1 +1 @@
1
- {"version":3,"file":"animate.js","names":[],"sources":["../src/animate.tsx"],"sourcesContent":["\"use client\"\n\nimport {\n Children,\n type CSSProperties,\n type ReactElement,\n type Ref,\n cloneElement,\n isValidElement,\n useEffect,\n useId,\n useRef,\n useState,\n} from \"react\"\nimport { useInView, type Transition } from \"motion/react\"\n\n// ── Types ────────────────────────────────────────────────────────────\n\ntype Direction = \"up\" | \"down\" | \"left\" | \"right\"\n\ninterface AnimateOnViewProps {\n children: ReactElement\n /** Delay in seconds before animation starts. Default: 0 */\n delay?: number\n /** Direction to animate from. Default: 'down' */\n from?: Direction\n /** Distance in px. Default: 16 (scroll reveals need more travel than `AnimateIn`) */\n distance?: number\n /** Also scale in (0.85 → 1). Default: false */\n scale?: boolean\n /** Blur in from a given amount in px. Default: false */\n blur?: boolean | number\n /** Rotate in from a given angle in degrees. Default: 0 */\n rotate?: number\n /** 3D flip entrance along the axis matching `from`. Default: false */\n flip?: boolean\n /** Spring easing with overshoot. Default: false */\n spring?: boolean\n /** Trigger once or every time it enters view. Default: true */\n once?: boolean\n /** Custom transition override */\n transition?: Transition\n}\n\ninterface AnimateInProps {\n children: ReactElement\n /** Delay in seconds before animation starts. Default: 0 */\n delay?: number\n /** Direction to animate from. Default: 'down' */\n from?: Direction\n /** Distance in px. Default: 4 */\n distance?: number\n /** Also scale in (0.85 → 1). Default: false */\n scale?: boolean\n /** Blur in from a given amount in px. Default: false */\n blur?: boolean | number\n /** Rotate in from a given angle in degrees. Default: 0 */\n rotate?: number\n /** 3D flip entrance along the axis matching `from`. Default: false */\n flip?: boolean\n /** Spring easing with overshoot. Default: false */\n spring?: boolean\n /** Custom transition override */\n transition?: Transition\n}\n\ninterface StaggerProps {\n children: ReactElement[]\n /** Delay increment between each child in seconds. Default: 0.08 */\n interval?: number\n /** Base delay before the first child animates in seconds. Default: 0 */\n baseDelay?: number\n}\n\ninterface PulseProps {\n children: ReactElement\n /** Min scale factor. Default: 0.97 */\n min?: number\n /** Max scale factor. Default: 1.03 */\n max?: number\n /** Animation duration in seconds. Default: 2 */\n duration?: number\n /** Also pulse opacity between these bounds [min, max]. Off by default. */\n opacity?: [number, number]\n /** Pause animation. Default: false */\n paused?: boolean\n}\n\ninterface FloatProps {\n children: ReactElement\n /** Vertical float distance in px. Default: 6 */\n distance?: number\n /** Animation duration in seconds. Default: 3 */\n duration?: number\n /** Also rotate slightly while floating (degrees). Default: 0 */\n rotate?: number\n /** Pause animation. Default: false */\n paused?: boolean\n}\n\n// ── Internals ────────────────────────────────────────────────────────\n\n/**\n * Direction map: `from` means where the element COMES FROM.\n * `from=\"left\"` = starts to the left, slides right into place.\n */\nconst DIRECTION_MAP = {\n up: { prop: \"translateY\", value: -1 },\n down: { prop: \"translateY\", value: 1 },\n left: { prop: \"translateX\", value: -1 },\n right: { prop: \"translateX\", value: 1 },\n} as const\n\n/** Flip axis: vertical directions flip around X, horizontal around Y */\nconst FLIP_MAP = {\n up: \"rotateX(90deg)\",\n down: \"rotateX(-90deg)\",\n left: \"rotateY(-90deg)\",\n right: \"rotateY(90deg)\",\n} as const\n\n/** Overshoot (\"spring\") easing for the opt-in `spring` prop on\n * `AnimateIn` / `AnimateOnView`. This is `animate.tsx`'s own page-entrance\n * bounce — the CSS recipe system intentionally has no spring (one circ-out\n * curve), so this is a standalone constant, not a shared token. */\nconst SPRING_EASE = \"cubic-bezier(0.34, 1.45, 0.64, 1)\"\n\ninterface BuildStylesOptions {\n from: Direction\n distance: number\n doScale: boolean\n blur: boolean | number\n rotate: number\n flip: boolean\n}\n\nfunction buildStyles(opts: BuildStylesOptions) {\n const { from, distance, doScale, blur, rotate, flip } = opts\n const dir = DIRECTION_MAP[from]\n\n const hiddenParts: string[] = []\n if (flip) hiddenParts.push(\"perspective(800px)\")\n hiddenParts.push(`${dir.prop}(${dir.value * distance}px)`)\n if (doScale) hiddenParts.push(\"scale(0.85)\")\n if (rotate) hiddenParts.push(`rotate(${rotate}deg)`)\n if (flip) hiddenParts.push(FLIP_MAP[from])\n\n const visibleParts: string[] = []\n if (flip) visibleParts.push(\"perspective(800px)\")\n visibleParts.push(\"translateX(0) translateY(0)\")\n if (doScale) visibleParts.push(\"scale(1)\")\n if (rotate) visibleParts.push(\"rotate(0deg)\")\n if (flip) visibleParts.push(from === \"up\" || from === \"down\" ? \"rotateX(0deg)\" : \"rotateY(0deg)\")\n\n const blurPx = blur === true ? 8 : typeof blur === \"number\" ? blur : 0\n\n const hidden: CSSProperties = {\n opacity: \"0\",\n transform: hiddenParts.join(\" \"),\n }\n\n const visible: CSSProperties = {\n opacity: \"1\",\n transform: visibleParts.join(\" \"),\n }\n\n if (blurPx > 0) {\n hidden.filter = `blur(${blurPx}px)`\n visible.filter = \"blur(0px)\"\n }\n\n return { hidden, visible, hasFilter: blurPx > 0 }\n}\n\nfunction mergeRefs<T>(...refs: (Ref<T> | undefined)[]) {\n return (el: T | null) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") ref(el)\n else if (ref && typeof ref === \"object\") {\n ;(ref as { current: T | null }).current = el\n }\n })\n }\n}\n\nfunction getTransitionParams(transition?: Transition, useSpring?: boolean, fallbackDuration = 0.15) {\n const duration =\n (transition as Record<string, number>)?.duration ?? fallbackDuration\n const ease =\n useSpring ? SPRING_EASE : ((transition as Record<string, string>)?.ease ?? \"ease-out\")\n return { duration, ease }\n}\n\nfunction buildTransitionStr(\n duration: number,\n ease: string,\n delay: number,\n hasFilter: boolean,\n) {\n const parts = [\n `opacity ${duration}s ${ease} ${delay}s`,\n `transform ${duration}s ${ease} ${delay}s`,\n ]\n if (hasFilter) parts.push(`filter ${duration}s ${ease} ${delay}s`)\n return parts.join(\", \")\n}\n\n// ── AnimateOnView ────────────────────────────────────────────────────\n\n/**\n * Animates a child element when it scrolls into view.\n *\n * Defaults are tuned for scroll reveals — larger travel and a slower duration\n * than `AnimateIn` — so the motion reads as the content enters the viewport.\n *\n * Zero DOM overhead — applies styles directly to the child via cloneElement.\n * Renders children unchanged on server to avoid hydration mismatch.\n *\n * @example\n * ```tsx\n * <AnimateOnView from=\"up\" blur scale>\n * <Card>Hello</Card>\n * </AnimateOnView>\n * ```\n */\nfunction AnimateOnView({\n children,\n delay = 0,\n from = \"down\",\n distance = 16,\n scale = false,\n blur = false,\n rotate = 0,\n flip = false,\n spring = false,\n once = true,\n transition,\n}: AnimateOnViewProps) {\n const ref = useRef<HTMLElement>(null)\n const [hydrated, setHydrated] = useState(false)\n const isInView = useInView(ref, { once, margin: \"-50px\" })\n\n useEffect(() => {\n setHydrated(true)\n }, [])\n\n if (!isValidElement(children)) return children\n\n const childProps = children.props as Record<string, unknown>\n const existingStyle = (childProps.style ?? {}) as CSSProperties\n const existingRef = (childProps as { ref?: Ref<HTMLElement> }).ref\n\n if (!hydrated) {\n return cloneElement(children, {\n ref: mergeRefs(ref, existingRef),\n } as Record<string, unknown>)\n }\n\n const styles = buildStyles({ from, distance, doScale: scale, blur, rotate, flip })\n const { duration, ease } = getTransitionParams(transition, spring, 0.4)\n const currentStyle = isInView ? styles.visible : styles.hidden\n const transitionStr = buildTransitionStr(duration, ease, delay, styles.hasFilter)\n\n return cloneElement(children, {\n ref: mergeRefs(ref, existingRef),\n style: {\n ...existingStyle,\n ...currentStyle,\n ...(isInView ? { transition: transitionStr } : {}),\n willChange: \"opacity, transform\",\n },\n } as Record<string, unknown>)\n}\n\n// ── AnimateIn ────────────────────────────────────────────────────────\n\n/**\n * Animates a child element immediately on mount.\n *\n * Zero DOM overhead — applies styles directly to the child via cloneElement.\n * Uses a two-phase approach: hidden → visible with requestAnimationFrame.\n *\n * @example\n * ```tsx\n * <AnimateIn from=\"up\" blur spring>\n * <h1>Welcome</h1>\n * </AnimateIn>\n * ```\n */\nfunction AnimateIn({\n children,\n delay = 0,\n from = \"down\",\n distance = 4,\n scale = false,\n blur = false,\n rotate = 0,\n flip = false,\n spring = false,\n transition,\n}: AnimateInProps) {\n const ref = useRef<HTMLElement>(null)\n const [visible, setVisible] = useState(false)\n\n useEffect(() => {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => setVisible(true))\n })\n }, [])\n\n if (!isValidElement(children)) return children\n\n const childProps = children.props as Record<string, unknown>\n const existingStyle = (childProps.style ?? {}) as CSSProperties\n const existingRef = (childProps as { ref?: Ref<HTMLElement> }).ref\n\n const styles = buildStyles({ from, distance, doScale: scale, blur, rotate, flip })\n const { duration, ease } = getTransitionParams(transition, spring)\n const currentStyle = visible ? styles.visible : styles.hidden\n const transitionStr = buildTransitionStr(duration, ease, delay, styles.hasFilter)\n\n return cloneElement(children, {\n ref: mergeRefs(ref, existingRef),\n style: {\n ...existingStyle,\n ...currentStyle,\n ...(visible ? { transition: transitionStr } : {}),\n willChange: \"opacity, transform\",\n },\n } as Record<string, unknown>)\n}\n\n// ── Stagger ──────────────────────────────────────────────────────────\n\n/**\n * Auto-staggers delay on child AnimateIn/AnimateOnView elements.\n * Eliminates manual `delay={i * 0.08}` math.\n *\n * @example\n * ```tsx\n * <Stagger interval={0.1}>\n * <AnimateIn from=\"up\"><Card>One</Card></AnimateIn>\n * <AnimateIn from=\"up\"><Card>Two</Card></AnimateIn>\n * </Stagger>\n * ```\n */\nfunction Stagger({\n children,\n interval = 0.08,\n baseDelay = 0,\n}: StaggerProps) {\n return (\n <>\n {Children.map(children, (child, index) => {\n if (!isValidElement(child)) return child\n return cloneElement(child as ReactElement<{ delay?: number }>, {\n delay: baseDelay + index * interval,\n })\n })}\n </>\n )\n}\n\n// ── Pulse ────────────────────────────────────────────────────────────\n\n/**\n * Continuous, subtle scale pulse. Great for live indicators and CTAs.\n * Zero DOM overhead — injects a scoped keyframe via `<style>`.\n *\n * @example\n * ```tsx\n * <Pulse>\n * <span className=\"size-3 rounded-full bg-green-500\" />\n * </Pulse>\n * ```\n */\nfunction Pulse({\n children,\n min = 0.97,\n max = 1.03,\n duration = 2,\n opacity,\n paused = false,\n}: PulseProps) {\n const id = useId().replace(/:/g, \"\")\n const [hydrated, setHydrated] = useState(false)\n\n useEffect(() => {\n setHydrated(true)\n }, [])\n\n if (!isValidElement(children)) return children\n if (!hydrated) return children\n\n const name = `pulse-${id}`\n const opacityFrom = opacity?.[0] ?? 1\n const opacityTo = opacity?.[1] ?? 1\n\n const keyframes = `@keyframes ${name} {\n 0%, 100% { transform: scale(${min}); opacity: ${opacityFrom}; }\n 50% { transform: scale(${max}); opacity: ${opacityTo}; }\n}`\n\n const childProps = children.props as Record<string, unknown>\n const existingStyle = (childProps.style ?? {}) as CSSProperties\n const existingRef = (childProps as { ref?: Ref<HTMLElement> }).ref\n\n return (\n <>\n <style>{keyframes}</style>\n {cloneElement(children, {\n ref: existingRef ? mergeRefs(existingRef) : undefined,\n style: {\n ...existingStyle,\n animation: `${name} ${duration}s ease-in-out infinite`,\n animationPlayState: paused ? \"paused\" : \"running\",\n },\n } as Record<string, unknown>)}\n </>\n )\n}\n\n// ── Float ────────────────────────────────────────────────────────────\n\n/**\n * Gentle continuous up/down float. Perfect for decorative elements.\n * Zero DOM overhead — injects a scoped keyframe via `<style>`.\n *\n * @example\n * ```tsx\n * <Float distance={10} duration={4}>\n * <Card>Floating</Card>\n * </Float>\n * ```\n */\nfunction Float({\n children,\n distance = 6,\n duration = 3,\n rotate = 0,\n paused = false,\n}: FloatProps) {\n const id = useId().replace(/:/g, \"\")\n const [hydrated, setHydrated] = useState(false)\n\n useEffect(() => {\n setHydrated(true)\n }, [])\n\n if (!isValidElement(children)) return children\n if (!hydrated) return children\n\n const name = `float-${id}`\n const rotA = rotate ? ` rotate(${-rotate}deg)` : \"\"\n const rotB = rotate ? ` rotate(${rotate}deg)` : \"\"\n\n const keyframes = `@keyframes ${name} {\n 0%, 100% { transform: translateY(0px)${rotA}; }\n 50% { transform: translateY(${-distance}px)${rotB}; }\n}`\n\n const childProps = children.props as Record<string, unknown>\n const existingStyle = (childProps.style ?? {}) as CSSProperties\n const existingRef = (childProps as { ref?: Ref<HTMLElement> }).ref\n\n return (\n <>\n <style>{keyframes}</style>\n {cloneElement(children, {\n ...(existingRef ? { ref: existingRef } : {}),\n style: {\n ...existingStyle,\n animation: `${name} ${duration}s ease-in-out infinite`,\n animationPlayState: paused ? \"paused\" : \"running\",\n },\n } as Record<string, unknown>)}\n </>\n )\n}\n\n// ── Exports ──────────────────────────────────────────────────────────\n\nexport { AnimateOnView, AnimateIn, Stagger, Pulse, Float }\nexport type {\n AnimateOnViewProps,\n AnimateInProps,\n StaggerProps,\n PulseProps,\n FloatProps,\n Direction,\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"animate.js","names":[],"sources":["../src/animate.tsx"],"sourcesContent":["\"use client\"\n\nimport {\n Children,\n type CSSProperties,\n type ReactElement,\n type Ref,\n cloneElement,\n isValidElement,\n useEffect,\n useId,\n useRef,\n useState,\n} from \"react\"\nimport { useInView, type Transition } from \"motion/react\"\n\n// ── Types ────────────────────────────────────────────────────────────\n\ntype Direction = \"up\" | \"down\" | \"left\" | \"right\"\n\ninterface AnimateOnViewProps {\n children: ReactElement\n /** Delay in seconds before animation starts. Default: 0 */\n delay?: number\n /** Direction to animate from. Default: 'down' */\n from?: Direction\n /** Distance in px. Default: 16 (scroll reveals need more travel than `AnimateIn`) */\n distance?: number\n /** Also scale in (0.85 → 1). Default: false */\n scale?: boolean\n /** Blur in from a given amount in px. Default: false */\n blur?: boolean | number\n /** Rotate in from a given angle in degrees. Default: 0 */\n rotate?: number\n /** 3D flip entrance along the axis matching `from`. Default: false */\n flip?: boolean\n /** Spring easing with overshoot. Default: false */\n spring?: boolean\n /** Trigger once or every time it enters view. Default: true */\n once?: boolean\n /** Custom transition override */\n transition?: Transition\n}\n\ninterface AnimateInProps {\n children: ReactElement\n /** Delay in seconds before animation starts. Default: 0 */\n delay?: number\n /** Direction to animate from. Default: 'down' */\n from?: Direction\n /** Distance in px. Default: 4 */\n distance?: number\n /** Also scale in (0.85 → 1). Default: false */\n scale?: boolean\n /** Blur in from a given amount in px. Default: false */\n blur?: boolean | number\n /** Rotate in from a given angle in degrees. Default: 0 */\n rotate?: number\n /** 3D flip entrance along the axis matching `from`. Default: false */\n flip?: boolean\n /** Spring easing with overshoot. Default: false */\n spring?: boolean\n /** Custom transition override */\n transition?: Transition\n}\n\ninterface StaggerProps {\n children: ReactElement[]\n /** Delay increment between each child in seconds. Default: 0.08 */\n interval?: number\n /** Base delay before the first child animates in seconds. Default: 0 */\n baseDelay?: number\n}\n\ninterface PulseProps {\n children: ReactElement\n /** Min scale factor. Default: 0.97 */\n min?: number\n /** Max scale factor. Default: 1.03 */\n max?: number\n /** Animation duration in seconds. Default: 2 */\n duration?: number\n /** Also pulse opacity between these bounds [min, max]. Off by default. */\n opacity?: [number, number]\n /** Pause animation. Default: false */\n paused?: boolean\n}\n\ninterface FloatProps {\n children: ReactElement\n /** Vertical float distance in px. Default: 6 */\n distance?: number\n /** Animation duration in seconds. Default: 3 */\n duration?: number\n /** Also rotate slightly while floating (degrees). Default: 0 */\n rotate?: number\n /** Pause animation. Default: false */\n paused?: boolean\n}\n\n// ── Internals ────────────────────────────────────────────────────────\n\n/**\n * Direction map: `from` means where the element COMES FROM.\n * `from=\"left\"` = starts to the left, slides right into place.\n */\nconst DIRECTION_MAP = {\n up: { prop: \"translateY\", value: -1 },\n down: { prop: \"translateY\", value: 1 },\n left: { prop: \"translateX\", value: -1 },\n right: { prop: \"translateX\", value: 1 },\n} as const\n\n/** Flip axis: vertical directions flip around X, horizontal around Y */\nconst FLIP_MAP = {\n up: \"rotateX(90deg)\",\n down: \"rotateX(-90deg)\",\n left: \"rotateY(-90deg)\",\n right: \"rotateY(90deg)\",\n} as const\n\n/** Overshoot (\"spring\") easing for the opt-in `spring` prop on\n * `AnimateIn` / `AnimateOnView`. This is `animate.tsx`'s own page-entrance\n * bounce — the CSS recipe system intentionally has no spring, so this is a standalone constant, not a shared token. */\nconst SPRING_EASE = \"cubic-bezier(0.34, 1.45, 0.64, 1)\"\n\ninterface BuildStylesOptions {\n from: Direction\n distance: number\n doScale: boolean\n blur: boolean | number\n rotate: number\n flip: boolean\n}\n\nfunction buildStyles(opts: BuildStylesOptions) {\n const { from, distance, doScale, blur, rotate, flip } = opts\n const dir = DIRECTION_MAP[from]\n\n const hiddenParts: string[] = []\n if (flip) hiddenParts.push(\"perspective(800px)\")\n hiddenParts.push(`${dir.prop}(${dir.value * distance}px)`)\n if (doScale) hiddenParts.push(\"scale(0.85)\")\n if (rotate) hiddenParts.push(`rotate(${rotate}deg)`)\n if (flip) hiddenParts.push(FLIP_MAP[from])\n\n const visibleParts: string[] = []\n if (flip) visibleParts.push(\"perspective(800px)\")\n visibleParts.push(\"translateX(0) translateY(0)\")\n if (doScale) visibleParts.push(\"scale(1)\")\n if (rotate) visibleParts.push(\"rotate(0deg)\")\n if (flip) visibleParts.push(from === \"up\" || from === \"down\" ? \"rotateX(0deg)\" : \"rotateY(0deg)\")\n\n const blurPx = blur === true ? 8 : typeof blur === \"number\" ? blur : 0\n\n const hidden: CSSProperties = {\n opacity: \"0\",\n transform: hiddenParts.join(\" \"),\n }\n\n const visible: CSSProperties = {\n opacity: \"1\",\n transform: visibleParts.join(\" \"),\n }\n\n if (blurPx > 0) {\n hidden.filter = `blur(${blurPx}px)`\n visible.filter = \"blur(0px)\"\n }\n\n return { hidden, visible, hasFilter: blurPx > 0 }\n}\n\nfunction mergeRefs<T>(...refs: (Ref<T> | undefined)[]) {\n return (el: T | null) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") ref(el)\n else if (ref && typeof ref === \"object\") {\n ;(ref as { current: T | null }).current = el\n }\n })\n }\n}\n\nfunction getTransitionParams(transition?: Transition, useSpring?: boolean, fallbackDuration = 0.15) {\n const duration =\n (transition as Record<string, number>)?.duration ?? fallbackDuration\n const ease =\n useSpring ? SPRING_EASE : ((transition as Record<string, string>)?.ease ?? \"ease-out\")\n return { duration, ease }\n}\n\nfunction buildTransitionStr(\n duration: number,\n ease: string,\n delay: number,\n hasFilter: boolean,\n) {\n const parts = [\n `opacity ${duration}s ${ease} ${delay}s`,\n `transform ${duration}s ${ease} ${delay}s`,\n ]\n if (hasFilter) parts.push(`filter ${duration}s ${ease} ${delay}s`)\n return parts.join(\", \")\n}\n\n// ── AnimateOnView ────────────────────────────────────────────────────\n\n/**\n * Animates a child element when it scrolls into view.\n *\n * Defaults are tuned for scroll reveals — larger travel and a slower duration\n * than `AnimateIn` — so the motion reads as the content enters the viewport.\n *\n * Zero DOM overhead — applies styles directly to the child via cloneElement.\n * Renders children unchanged on server to avoid hydration mismatch.\n *\n * @example\n * ```tsx\n * <AnimateOnView from=\"up\" blur scale>\n * <Card>Hello</Card>\n * </AnimateOnView>\n * ```\n */\nfunction AnimateOnView({\n children,\n delay = 0,\n from = \"down\",\n distance = 16,\n scale = false,\n blur = false,\n rotate = 0,\n flip = false,\n spring = false,\n once = true,\n transition,\n}: AnimateOnViewProps) {\n const ref = useRef<HTMLElement>(null)\n const [hydrated, setHydrated] = useState(false)\n const isInView = useInView(ref, { once, margin: \"-50px\" })\n\n useEffect(() => {\n setHydrated(true)\n }, [])\n\n if (!isValidElement(children)) return children\n\n const childProps = children.props as Record<string, unknown>\n const existingStyle = (childProps.style ?? {}) as CSSProperties\n const existingRef = (childProps as { ref?: Ref<HTMLElement> }).ref\n\n if (!hydrated) {\n return cloneElement(children, {\n ref: mergeRefs(ref, existingRef),\n } as Record<string, unknown>)\n }\n\n const styles = buildStyles({ from, distance, doScale: scale, blur, rotate, flip })\n const { duration, ease } = getTransitionParams(transition, spring, 0.4)\n const currentStyle = isInView ? styles.visible : styles.hidden\n const transitionStr = buildTransitionStr(duration, ease, delay, styles.hasFilter)\n\n return cloneElement(children, {\n ref: mergeRefs(ref, existingRef),\n style: {\n ...existingStyle,\n ...currentStyle,\n ...(isInView ? { transition: transitionStr } : {}),\n willChange: \"opacity, transform\",\n },\n } as Record<string, unknown>)\n}\n\n// ── AnimateIn ────────────────────────────────────────────────────────\n\n/**\n * Animates a child element immediately on mount.\n *\n * Zero DOM overhead — applies styles directly to the child via cloneElement.\n * Uses a two-phase approach: hidden → visible with requestAnimationFrame.\n *\n * @example\n * ```tsx\n * <AnimateIn from=\"up\" blur spring>\n * <h1>Welcome</h1>\n * </AnimateIn>\n * ```\n */\nfunction AnimateIn({\n children,\n delay = 0,\n from = \"down\",\n distance = 4,\n scale = false,\n blur = false,\n rotate = 0,\n flip = false,\n spring = false,\n transition,\n}: AnimateInProps) {\n const ref = useRef<HTMLElement>(null)\n const [visible, setVisible] = useState(false)\n\n useEffect(() => {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => setVisible(true))\n })\n }, [])\n\n if (!isValidElement(children)) return children\n\n const childProps = children.props as Record<string, unknown>\n const existingStyle = (childProps.style ?? {}) as CSSProperties\n const existingRef = (childProps as { ref?: Ref<HTMLElement> }).ref\n\n const styles = buildStyles({ from, distance, doScale: scale, blur, rotate, flip })\n const { duration, ease } = getTransitionParams(transition, spring)\n const currentStyle = visible ? styles.visible : styles.hidden\n const transitionStr = buildTransitionStr(duration, ease, delay, styles.hasFilter)\n\n return cloneElement(children, {\n ref: mergeRefs(ref, existingRef),\n style: {\n ...existingStyle,\n ...currentStyle,\n ...(visible ? { transition: transitionStr } : {}),\n willChange: \"opacity, transform\",\n },\n } as Record<string, unknown>)\n}\n\n// ── Stagger ──────────────────────────────────────────────────────────\n\n/**\n * Auto-staggers delay on child AnimateIn/AnimateOnView elements.\n * Eliminates manual `delay={i * 0.08}` math.\n *\n * @example\n * ```tsx\n * <Stagger interval={0.1}>\n * <AnimateIn from=\"up\"><Card>One</Card></AnimateIn>\n * <AnimateIn from=\"up\"><Card>Two</Card></AnimateIn>\n * </Stagger>\n * ```\n */\nfunction Stagger({\n children,\n interval = 0.08,\n baseDelay = 0,\n}: StaggerProps) {\n return (\n <>\n {Children.map(children, (child, index) => {\n if (!isValidElement(child)) return child\n return cloneElement(child as ReactElement<{ delay?: number }>, {\n delay: baseDelay + index * interval,\n })\n })}\n </>\n )\n}\n\n// ── Pulse ────────────────────────────────────────────────────────────\n\n/**\n * Continuous, subtle scale pulse. Great for live indicators and CTAs.\n * Zero DOM overhead — injects a scoped keyframe via `<style>`.\n *\n * @example\n * ```tsx\n * <Pulse>\n * <span className=\"size-3 rounded-full bg-green-500\" />\n * </Pulse>\n * ```\n */\nfunction Pulse({\n children,\n min = 0.97,\n max = 1.03,\n duration = 2,\n opacity,\n paused = false,\n}: PulseProps) {\n const id = useId().replace(/:/g, \"\")\n const [hydrated, setHydrated] = useState(false)\n\n useEffect(() => {\n setHydrated(true)\n }, [])\n\n if (!isValidElement(children)) return children\n if (!hydrated) return children\n\n const name = `pulse-${id}`\n const opacityFrom = opacity?.[0] ?? 1\n const opacityTo = opacity?.[1] ?? 1\n\n const keyframes = `@keyframes ${name} {\n 0%, 100% { transform: scale(${min}); opacity: ${opacityFrom}; }\n 50% { transform: scale(${max}); opacity: ${opacityTo}; }\n}`\n\n const childProps = children.props as Record<string, unknown>\n const existingStyle = (childProps.style ?? {}) as CSSProperties\n const existingRef = (childProps as { ref?: Ref<HTMLElement> }).ref\n\n return (\n <>\n <style>{keyframes}</style>\n {cloneElement(children, {\n ref: existingRef ? mergeRefs(existingRef) : undefined,\n style: {\n ...existingStyle,\n animation: `${name} ${duration}s ease-in-out infinite`,\n animationPlayState: paused ? \"paused\" : \"running\",\n },\n } as Record<string, unknown>)}\n </>\n )\n}\n\n// ── Float ────────────────────────────────────────────────────────────\n\n/**\n * Gentle continuous up/down float. Perfect for decorative elements.\n * Zero DOM overhead — injects a scoped keyframe via `<style>`.\n *\n * @example\n * ```tsx\n * <Float distance={10} duration={4}>\n * <Card>Floating</Card>\n * </Float>\n * ```\n */\nfunction Float({\n children,\n distance = 6,\n duration = 3,\n rotate = 0,\n paused = false,\n}: FloatProps) {\n const id = useId().replace(/:/g, \"\")\n const [hydrated, setHydrated] = useState(false)\n\n useEffect(() => {\n setHydrated(true)\n }, [])\n\n if (!isValidElement(children)) return children\n if (!hydrated) return children\n\n const name = `float-${id}`\n const rotA = rotate ? ` rotate(${-rotate}deg)` : \"\"\n const rotB = rotate ? ` rotate(${rotate}deg)` : \"\"\n\n const keyframes = `@keyframes ${name} {\n 0%, 100% { transform: translateY(0px)${rotA}; }\n 50% { transform: translateY(${-distance}px)${rotB}; }\n}`\n\n const childProps = children.props as Record<string, unknown>\n const existingStyle = (childProps.style ?? {}) as CSSProperties\n const existingRef = (childProps as { ref?: Ref<HTMLElement> }).ref\n\n return (\n <>\n <style>{keyframes}</style>\n {cloneElement(children, {\n ...(existingRef ? { ref: existingRef } : {}),\n style: {\n ...existingStyle,\n animation: `${name} ${duration}s ease-in-out infinite`,\n animationPlayState: paused ? \"paused\" : \"running\",\n },\n } as Record<string, unknown>)}\n </>\n )\n}\n\n// ── Exports ──────────────────────────────────────────────────────────\n\nexport { AnimateOnView, AnimateIn, Stagger, Pulse, Float }\nexport type {\n AnimateOnViewProps,\n AnimateInProps,\n StaggerProps,\n PulseProps,\n FloatProps,\n Direction,\n}\n"],"mappings":"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"}
@@ -13,7 +13,7 @@ function Autocomplete({ ...props }) {
13
13
  function AutocompleteInput({ className, ...props }) {
14
14
  return /* @__PURE__ */ jsx(Autocomplete$1.Input, {
15
15
  "data-slot": "autocomplete-input",
16
- className: cn("dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 placeholder:text-muted-foreground h-8 w-full min-w-0 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors outline-none focus-visible:ring-3 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm", className),
16
+ className: cn("dark:bg-edge/30 border-edge focus-visible:border-focus focus-visible:ring-focus/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-edge/50 dark:disabled:bg-edge/80 placeholder:text-soft h-8 w-full min-w-0 rounded-md border bg-transparent px-2.5 py-1 text-base transition-colors outline-none focus-visible:ring-3 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm", className),
17
17
  ...props
18
18
  });
19
19
  }
@@ -68,28 +68,28 @@ function AutocompletePositioner({ className, ...props }) {
68
68
  function AutocompletePopup({ className, ...props }) {
69
69
  return /* @__PURE__ */ jsx(Autocomplete$1.Popup, {
70
70
  "data-slot": "autocomplete-popup",
71
- className: cn("motion-slide bg-popover text-popover-foreground ring-foreground/10 group/autocomplete-content relative max-h-(--available-height) min-w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg shadow-md ring-1", className),
71
+ className: cn("motion-pop-md bg-elevated text-contrast ring-contrast/10 group/autocomplete-content relative max-h-(--available-height) min-w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-md shadow-md ring-1", className),
72
72
  ...props
73
73
  });
74
74
  }
75
75
  function AutocompleteArrow({ className, ...props }) {
76
76
  return /* @__PURE__ */ jsx(Autocomplete$1.Arrow, {
77
77
  "data-slot": "autocomplete-arrow",
78
- className: cn("fill-popover", className),
78
+ className: cn("fill-elevated", className),
79
79
  ...props
80
80
  });
81
81
  }
82
82
  function AutocompleteStatus({ className, ...props }) {
83
83
  return /* @__PURE__ */ jsx(Autocomplete$1.Status, {
84
84
  "data-slot": "autocomplete-status",
85
- className: cn("text-muted-foreground flex w-full justify-center py-2 text-center text-sm", className),
85
+ className: cn("text-muted flex w-full justify-center py-2 text-center text-sm", className),
86
86
  ...props
87
87
  });
88
88
  }
89
89
  function AutocompleteEmpty({ className, ...props }) {
90
90
  return /* @__PURE__ */ jsx(Autocomplete$1.Empty, {
91
91
  "data-slot": "autocomplete-empty",
92
- className: cn("text-muted-foreground hidden w-full justify-center py-2 text-center text-sm group-data-empty/autocomplete-content:flex", className),
92
+ className: cn("text-muted hidden w-full justify-center py-2 text-center text-sm group-data-empty/autocomplete-content:flex", className),
93
93
  ...props
94
94
  });
95
95
  }
@@ -110,14 +110,14 @@ function AutocompleteRow({ className, ...props }) {
110
110
  function AutocompleteItem({ className, ...props }) {
111
111
  return /* @__PURE__ */ jsx(Autocomplete$1.Item, {
112
112
  "data-slot": "autocomplete-item",
113
- className: cn("data-highlighted:bg-accent data-highlighted:text-accent-foreground relative flex w-full cursor-clickable items-center gap-2 rounded-md py-1 pl-1.5 pr-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
113
+ className: cn("data-highlighted:bg-primary data-highlighted:text-white relative flex w-full cursor-clickable items-center gap-2 rounded-sm py-1 pl-1.5 pr-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
114
114
  ...props
115
115
  });
116
116
  }
117
117
  function AutocompleteSeparator({ className, ...props }) {
118
118
  return /* @__PURE__ */ jsx(Autocomplete$1.Separator, {
119
119
  "data-slot": "autocomplete-separator",
120
- className: cn("bg-border -mx-1 my-1 h-px", className),
120
+ className: cn("bg-line -mx-1 my-1 h-px", className),
121
121
  ...props
122
122
  });
123
123
  }
@@ -131,7 +131,7 @@ function AutocompleteGroup({ className, ...props }) {
131
131
  function AutocompleteGroupLabel({ className, ...props }) {
132
132
  return /* @__PURE__ */ jsx(Autocomplete$1.GroupLabel, {
133
133
  "data-slot": "autocomplete-group-label",
134
- className: cn("text-muted-foreground px-2 py-1.5 text-xs", className),
134
+ className: cn("text-muted px-2 py-1.5 text-xs", className),
135
135
  ...props
136
136
  });
137
137
  }
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete.js","names":["AutocompletePrimitive"],"sources":["../src/autocomplete.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\n\nimport { Autocomplete as AutocompletePrimitive } from \"@base-ui/react/autocomplete\"\n\nimport { cn } from \"./lib/utils\"\n\ntype AutocompleteProps = React.ComponentProps<typeof AutocompletePrimitive.Root>\ntype AutocompleteInputProps = React.ComponentProps<typeof AutocompletePrimitive.Input>\ntype AutocompleteTriggerProps = React.ComponentProps<typeof AutocompletePrimitive.Trigger>\ntype AutocompleteIconProps = React.ComponentProps<typeof AutocompletePrimitive.Icon>\ntype AutocompleteClearProps = React.ComponentProps<typeof AutocompletePrimitive.Clear>\ntype AutocompleteValueProps = React.ComponentProps<typeof AutocompletePrimitive.Value>\n\ntype AutocompletePortalProps = React.ComponentProps<typeof AutocompletePrimitive.Portal>\ntype AutocompleteBackdropProps = React.ComponentProps<typeof AutocompletePrimitive.Backdrop>\ntype AutocompletePositionerProps = React.ComponentProps<typeof AutocompletePrimitive.Positioner>\ntype AutocompletePopupProps = React.ComponentProps<typeof AutocompletePrimitive.Popup>\ntype AutocompleteArrowProps = React.ComponentProps<typeof AutocompletePrimitive.Arrow>\ntype AutocompleteStatusProps = React.ComponentProps<typeof AutocompletePrimitive.Status>\ntype AutocompleteEmptyProps = React.ComponentProps<typeof AutocompletePrimitive.Empty>\n\ntype AutocompleteListProps = React.ComponentProps<typeof AutocompletePrimitive.List>\ntype AutocompleteRowProps = React.ComponentProps<typeof AutocompletePrimitive.Row>\ntype AutocompleteItemProps = React.ComponentProps<typeof AutocompletePrimitive.Item>\ntype AutocompleteSeparatorProps = React.ComponentProps<typeof AutocompletePrimitive.Separator>\ntype AutocompleteGroupProps = React.ComponentProps<typeof AutocompletePrimitive.Group>\ntype AutocompleteGroupLabelProps = React.ComponentProps<typeof AutocompletePrimitive.GroupLabel>\ntype AutocompleteCollectionProps = React.ComponentProps<typeof AutocompletePrimitive.Collection>\n\ntype AutocompleteContentProps = AutocompletePopupProps &\n Pick<\n AutocompletePositionerProps,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >\n\nfunction Autocomplete({ ...props }: AutocompleteProps) {\n return <AutocompletePrimitive.Root data-slot=\"autocomplete\" {...props} />\n}\n\nfunction AutocompleteInput({ className, ...props }: AutocompleteInputProps) {\n return (\n <AutocompletePrimitive.Input\n data-slot=\"autocomplete-input\"\n className={cn(\n \"dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 placeholder:text-muted-foreground h-8 w-full min-w-0 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors outline-none focus-visible:ring-3 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AutocompleteTrigger({ className, ...props }: AutocompleteTriggerProps) {\n return (\n <AutocompletePrimitive.Trigger\n data-slot=\"autocomplete-trigger\"\n className={cn(\"shrink-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteIcon({ className, ...props }: AutocompleteIconProps) {\n return (\n <AutocompletePrimitive.Icon\n data-slot=\"autocomplete-icon\"\n className={cn(\"shrink-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteClear({ className, ...props }: AutocompleteClearProps) {\n return (\n <AutocompletePrimitive.Clear\n data-slot=\"autocomplete-clear\"\n className={cn(\"shrink-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteValue({ ...props }: AutocompleteValueProps) {\n return (\n <AutocompletePrimitive.Value data-slot=\"autocomplete-value\" {...props} />\n )\n}\n\nfunction AutocompletePortal({ className, ...props }: AutocompletePortalProps) {\n return (\n <AutocompletePrimitive.Portal\n data-slot=\"autocomplete-portal\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteBackdrop({ className, ...props }: AutocompleteBackdropProps) {\n return (\n <AutocompletePrimitive.Backdrop\n data-slot=\"autocomplete-backdrop\"\n className={cn(\"fixed inset-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompletePositioner({ className, ...props }: AutocompletePositionerProps) {\n return (\n <AutocompletePrimitive.Positioner\n data-slot=\"autocomplete-positioner\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction AutocompletePopup({ className, ...props }: AutocompletePopupProps) {\n return (\n <AutocompletePrimitive.Popup\n data-slot=\"autocomplete-popup\"\n className={cn(\n \"motion-slide bg-popover text-popover-foreground ring-foreground/10 group/autocomplete-content relative max-h-(--available-height) min-w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg shadow-md ring-1\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AutocompleteArrow({ className, ...props }: AutocompleteArrowProps) {\n return (\n <AutocompletePrimitive.Arrow\n data-slot=\"autocomplete-arrow\"\n className={cn(\"fill-popover\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteStatus({ className, ...props }: AutocompleteStatusProps) {\n return (\n <AutocompletePrimitive.Status\n data-slot=\"autocomplete-status\"\n className={cn(\"text-muted-foreground flex w-full justify-center py-2 text-center text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteEmpty({ className, ...props }: AutocompleteEmptyProps) {\n return (\n <AutocompletePrimitive.Empty\n data-slot=\"autocomplete-empty\"\n className={cn(\"text-muted-foreground hidden w-full justify-center py-2 text-center text-sm group-data-empty/autocomplete-content:flex\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteList({ className, ...props }: AutocompleteListProps) {\n return (\n <AutocompletePrimitive.List\n data-slot=\"autocomplete-list\"\n className={cn(\"scroll-py-1 overflow-y-auto overscroll-contain p-1 data-empty:p-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteRow({ className, ...props }: AutocompleteRowProps) {\n return (\n <AutocompletePrimitive.Row\n data-slot=\"autocomplete-row\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteItem({ className, ...props }: AutocompleteItemProps) {\n return (\n <AutocompletePrimitive.Item\n data-slot=\"autocomplete-item\"\n className={cn(\n \"data-highlighted:bg-accent data-highlighted:text-accent-foreground relative flex w-full cursor-clickable items-center gap-2 rounded-md py-1 pl-1.5 pr-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AutocompleteSeparator({ className, ...props }: AutocompleteSeparatorProps) {\n return (\n <AutocompletePrimitive.Separator\n data-slot=\"autocomplete-separator\"\n className={cn(\"bg-border -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteGroup({ className, ...props }: AutocompleteGroupProps) {\n return (\n <AutocompletePrimitive.Group\n data-slot=\"autocomplete-group\"\n className={cn(\"pt-1\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteGroupLabel({ className, ...props }: AutocompleteGroupLabelProps) {\n return (\n <AutocompletePrimitive.GroupLabel\n data-slot=\"autocomplete-group-label\"\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteCollection({ ...props }: AutocompleteCollectionProps) {\n return (\n <AutocompletePrimitive.Collection\n data-slot=\"autocomplete-collection\"\n {...props}\n />\n )\n}\n\nfunction AutocompleteContent({\n className,\n align = \"start\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 6,\n ...props\n}: AutocompleteContentProps) {\n return (\n <AutocompletePortal>\n <AutocompletePositioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <AutocompletePopup className={className} {...props} />\n </AutocompletePositioner>\n </AutocompletePortal>\n )\n}\n\nexport {\n Autocomplete,\n AutocompleteArrow,\n AutocompleteBackdrop,\n AutocompleteClear,\n AutocompleteCollection,\n AutocompleteContent,\n AutocompleteEmpty,\n AutocompleteGroup,\n AutocompleteGroupLabel,\n AutocompleteIcon,\n AutocompleteInput,\n AutocompleteItem,\n AutocompleteList,\n AutocompletePopup,\n AutocompletePortal,\n AutocompletePositioner,\n AutocompleteRow,\n AutocompleteSeparator,\n AutocompleteStatus,\n AutocompleteTrigger,\n AutocompleteValue,\n}"],"mappings":"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"}
1
+ {"version":3,"file":"autocomplete.js","names":["AutocompletePrimitive"],"sources":["../src/autocomplete.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\n\nimport { Autocomplete as AutocompletePrimitive } from \"@base-ui/react/autocomplete\"\n\nimport { cn } from \"./lib/utils\"\n\ntype AutocompleteProps = React.ComponentProps<typeof AutocompletePrimitive.Root>\ntype AutocompleteInputProps = React.ComponentProps<typeof AutocompletePrimitive.Input>\ntype AutocompleteTriggerProps = React.ComponentProps<typeof AutocompletePrimitive.Trigger>\ntype AutocompleteIconProps = React.ComponentProps<typeof AutocompletePrimitive.Icon>\ntype AutocompleteClearProps = React.ComponentProps<typeof AutocompletePrimitive.Clear>\ntype AutocompleteValueProps = React.ComponentProps<typeof AutocompletePrimitive.Value>\n\ntype AutocompletePortalProps = React.ComponentProps<typeof AutocompletePrimitive.Portal>\ntype AutocompleteBackdropProps = React.ComponentProps<typeof AutocompletePrimitive.Backdrop>\ntype AutocompletePositionerProps = React.ComponentProps<typeof AutocompletePrimitive.Positioner>\ntype AutocompletePopupProps = React.ComponentProps<typeof AutocompletePrimitive.Popup>\ntype AutocompleteArrowProps = React.ComponentProps<typeof AutocompletePrimitive.Arrow>\ntype AutocompleteStatusProps = React.ComponentProps<typeof AutocompletePrimitive.Status>\ntype AutocompleteEmptyProps = React.ComponentProps<typeof AutocompletePrimitive.Empty>\n\ntype AutocompleteListProps = React.ComponentProps<typeof AutocompletePrimitive.List>\ntype AutocompleteRowProps = React.ComponentProps<typeof AutocompletePrimitive.Row>\ntype AutocompleteItemProps = React.ComponentProps<typeof AutocompletePrimitive.Item>\ntype AutocompleteSeparatorProps = React.ComponentProps<typeof AutocompletePrimitive.Separator>\ntype AutocompleteGroupProps = React.ComponentProps<typeof AutocompletePrimitive.Group>\ntype AutocompleteGroupLabelProps = React.ComponentProps<typeof AutocompletePrimitive.GroupLabel>\ntype AutocompleteCollectionProps = React.ComponentProps<typeof AutocompletePrimitive.Collection>\n\ntype AutocompleteContentProps = AutocompletePopupProps &\n Pick<\n AutocompletePositionerProps,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >\n\nfunction Autocomplete({ ...props }: AutocompleteProps) {\n return <AutocompletePrimitive.Root data-slot=\"autocomplete\" {...props} />\n}\n\nfunction AutocompleteInput({ className, ...props }: AutocompleteInputProps) {\n return (\n <AutocompletePrimitive.Input\n data-slot=\"autocomplete-input\"\n className={cn(\n \"dark:bg-edge/30 border-edge focus-visible:border-focus focus-visible:ring-focus/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-edge/50 dark:disabled:bg-edge/80 placeholder:text-soft h-8 w-full min-w-0 rounded-md border bg-transparent px-2.5 py-1 text-base transition-colors outline-none focus-visible:ring-3 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AutocompleteTrigger({ className, ...props }: AutocompleteTriggerProps) {\n return (\n <AutocompletePrimitive.Trigger\n data-slot=\"autocomplete-trigger\"\n className={cn(\"shrink-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteIcon({ className, ...props }: AutocompleteIconProps) {\n return (\n <AutocompletePrimitive.Icon\n data-slot=\"autocomplete-icon\"\n className={cn(\"shrink-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteClear({ className, ...props }: AutocompleteClearProps) {\n return (\n <AutocompletePrimitive.Clear\n data-slot=\"autocomplete-clear\"\n className={cn(\"shrink-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteValue({ ...props }: AutocompleteValueProps) {\n return (\n <AutocompletePrimitive.Value data-slot=\"autocomplete-value\" {...props} />\n )\n}\n\nfunction AutocompletePortal({ className, ...props }: AutocompletePortalProps) {\n return (\n <AutocompletePrimitive.Portal\n data-slot=\"autocomplete-portal\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteBackdrop({ className, ...props }: AutocompleteBackdropProps) {\n return (\n <AutocompletePrimitive.Backdrop\n data-slot=\"autocomplete-backdrop\"\n className={cn(\"fixed inset-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompletePositioner({ className, ...props }: AutocompletePositionerProps) {\n return (\n <AutocompletePrimitive.Positioner\n data-slot=\"autocomplete-positioner\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction AutocompletePopup({ className, ...props }: AutocompletePopupProps) {\n return (\n <AutocompletePrimitive.Popup\n data-slot=\"autocomplete-popup\"\n className={cn(\n \"motion-pop-md bg-elevated text-contrast ring-contrast/10 group/autocomplete-content relative max-h-(--available-height) min-w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-md shadow-md ring-1\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AutocompleteArrow({ className, ...props }: AutocompleteArrowProps) {\n return (\n <AutocompletePrimitive.Arrow\n data-slot=\"autocomplete-arrow\"\n className={cn(\"fill-elevated\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteStatus({ className, ...props }: AutocompleteStatusProps) {\n return (\n <AutocompletePrimitive.Status\n data-slot=\"autocomplete-status\"\n className={cn(\"text-muted flex w-full justify-center py-2 text-center text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteEmpty({ className, ...props }: AutocompleteEmptyProps) {\n return (\n <AutocompletePrimitive.Empty\n data-slot=\"autocomplete-empty\"\n className={cn(\"text-muted hidden w-full justify-center py-2 text-center text-sm group-data-empty/autocomplete-content:flex\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteList({ className, ...props }: AutocompleteListProps) {\n return (\n <AutocompletePrimitive.List\n data-slot=\"autocomplete-list\"\n className={cn(\"scroll-py-1 overflow-y-auto overscroll-contain p-1 data-empty:p-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteRow({ className, ...props }: AutocompleteRowProps) {\n return (\n <AutocompletePrimitive.Row\n data-slot=\"autocomplete-row\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteItem({ className, ...props }: AutocompleteItemProps) {\n return (\n <AutocompletePrimitive.Item\n data-slot=\"autocomplete-item\"\n className={cn(\n \"data-highlighted:bg-primary data-highlighted:text-white relative flex w-full cursor-clickable items-center gap-2 rounded-sm py-1 pl-1.5 pr-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction AutocompleteSeparator({ className, ...props }: AutocompleteSeparatorProps) {\n return (\n <AutocompletePrimitive.Separator\n data-slot=\"autocomplete-separator\"\n className={cn(\"bg-line -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteGroup({ className, ...props }: AutocompleteGroupProps) {\n return (\n <AutocompletePrimitive.Group\n data-slot=\"autocomplete-group\"\n className={cn(\"pt-1\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteGroupLabel({ className, ...props }: AutocompleteGroupLabelProps) {\n return (\n <AutocompletePrimitive.GroupLabel\n data-slot=\"autocomplete-group-label\"\n className={cn(\"text-muted px-2 py-1.5 text-xs\", className)}\n {...props}\n />\n )\n}\n\nfunction AutocompleteCollection({ ...props }: AutocompleteCollectionProps) {\n return (\n <AutocompletePrimitive.Collection\n data-slot=\"autocomplete-collection\"\n {...props}\n />\n )\n}\n\nfunction AutocompleteContent({\n className,\n align = \"start\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 6,\n ...props\n}: AutocompleteContentProps) {\n return (\n <AutocompletePortal>\n <AutocompletePositioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <AutocompletePopup className={className} {...props} />\n </AutocompletePositioner>\n </AutocompletePortal>\n )\n}\n\nexport {\n Autocomplete,\n AutocompleteArrow,\n AutocompleteBackdrop,\n AutocompleteClear,\n AutocompleteCollection,\n AutocompleteContent,\n AutocompleteEmpty,\n AutocompleteGroup,\n AutocompleteGroupLabel,\n AutocompleteIcon,\n AutocompleteInput,\n AutocompleteItem,\n AutocompleteList,\n AutocompletePopup,\n AutocompletePortal,\n AutocompletePositioner,\n AutocompleteRow,\n AutocompleteSeparator,\n AutocompleteStatus,\n AutocompleteTrigger,\n AutocompleteValue,\n}"],"mappings":";;;;;;AAqCA,SAAS,aAAa,EAAE,GAAG,SAA4B;AACrD,QAAO,oBAACA,eAAsB,MAAvB;EAA4B,aAAU;EAAe,GAAI;EAAS,CAAA;;AAG3E,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAiC;AAC1E,QACE,oBAACA,eAAsB,OAAvB;EACE,aAAU;EACV,WAAW,GACT,khBACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,oBAAoB,EAAE,WAAW,GAAG,SAAmC;AAC9E,QACE,oBAACA,eAAsB,SAAvB;EACE,aAAU;EACV,WAAW,GAAG,YAAY,UAAU;EACpC,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAgC;AACxE,QACE,oBAACA,eAAsB,MAAvB;EACE,aAAU;EACV,WAAW,GAAG,YAAY,UAAU;EACpC,GAAI;EACJ,CAAA;;AAIN,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAiC;AAC1E,QACE,oBAACA,eAAsB,OAAvB;EACE,aAAU;EACV,WAAW,GAAG,YAAY,UAAU;EACpC,GAAI;EACJ,CAAA;;AAIN,SAAS,kBAAkB,EAAE,GAAG,SAAiC;AAC/D,QACE,oBAACA,eAAsB,OAAvB;EAA6B,aAAU;EAAqB,GAAI;EAAS,CAAA;;AAI7E,SAAS,mBAAmB,EAAE,WAAW,GAAG,SAAkC;AAC5E,QACE,oBAACA,eAAsB,QAAvB;EACE,aAAU;EACV,WAAW,GAAG,UAAU;EACxB,GAAI;EACJ,CAAA;;AAIN,SAAS,qBAAqB,EAAE,WAAW,GAAG,SAAoC;AAChF,QACE,oBAACA,eAAsB,UAAvB;EACE,aAAU;EACV,WAAW,GAAG,iBAAiB,UAAU;EACzC,GAAI;EACJ,CAAA;;AAIN,SAAS,uBAAuB,EAAE,WAAW,GAAG,SAAsC;AACpF,QACE,oBAACA,eAAsB,YAAvB;EACE,aAAU;EACV,WAAW,GAAG,UAAU;EACxB,GAAI;EACJ,CAAA;;AAIN,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAiC;AAC1E,QACE,oBAACA,eAAsB,OAAvB;EACE,aAAU;EACV,WAAW,GACT,4OACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAiC;AAC1E,QACE,oBAACA,eAAsB,OAAvB;EACE,aAAU;EACV,WAAW,GAAG,iBAAiB,UAAU;EACzC,GAAI;EACJ,CAAA;;AAIN,SAAS,mBAAmB,EAAE,WAAW,GAAG,SAAkC;AAC5E,QACE,oBAACA,eAAsB,QAAvB;EACE,aAAU;EACV,WAAW,GAAG,kEAAkE,UAAU;EAC1F,GAAI;EACJ,CAAA;;AAIN,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAiC;AAC1E,QACE,oBAACA,eAAsB,OAAvB;EACE,aAAU;EACV,WAAW,GAAG,+GAA+G,UAAU;EACvI,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAgC;AACxE,QACE,oBAACA,eAAsB,MAAvB;EACE,aAAU;EACV,WAAW,GAAG,qEAAqE,UAAU;EAC7F,GAAI;EACJ,CAAA;;AAIN,SAAS,gBAAgB,EAAE,WAAW,GAAG,SAA+B;AACtE,QACE,oBAACA,eAAsB,KAAvB;EACE,aAAU;EACV,WAAW,GAAG,UAAU;EACxB,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAgC;AACxE,QACE,oBAACA,eAAsB,MAAvB;EACE,aAAU;EACV,WAAW,GACT,kUACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,sBAAsB,EAAE,WAAW,GAAG,SAAqC;AAClF,QACE,oBAACA,eAAsB,WAAvB;EACE,aAAU;EACV,WAAW,GAAG,2BAA2B,UAAU;EACnD,GAAI;EACJ,CAAA;;AAIN,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAiC;AAC1E,QACE,oBAACA,eAAsB,OAAvB;EACE,aAAU;EACV,WAAW,GAAG,QAAQ,UAAU;EAChC,GAAI;EACJ,CAAA;;AAIN,SAAS,uBAAuB,EAAE,WAAW,GAAG,SAAsC;AACpF,QACE,oBAACA,eAAsB,YAAvB;EACE,aAAU;EACV,WAAW,GAAG,kCAAkC,UAAU;EAC1D,GAAI;EACJ,CAAA;;AAIN,SAAS,uBAAuB,EAAE,GAAG,SAAsC;AACzE,QACE,oBAACA,eAAsB,YAAvB;EACE,aAAU;EACV,GAAI;EACJ,CAAA;;AAIN,SAAS,oBAAoB,EAC3B,WACA,QAAQ,SACR,cAAc,GACd,OAAO,UACP,aAAa,GACb,GAAG,SACwB;AAC3B,QACE,oBAAC,oBAAD,EAAA,UACE,oBAAC,wBAAD;EACS;EACM;EACP;EACM;EACZ,WAAU;YAEV,oBAAC,mBAAD;GAA8B;GAAW,GAAI;GAAS,CAAA;EAC/B,CAAA,EACN,CAAA"}
package/dist/avatar.js CHANGED
@@ -8,7 +8,7 @@ function Avatar({ className, size = "default", ...props }) {
8
8
  return /* @__PURE__ */ jsx(Avatar$1.Root, {
9
9
  "data-slot": "avatar",
10
10
  "data-size": size,
11
- className: cn("after:border-border group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten", className),
11
+ className: cn("after:border-line group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten", className),
12
12
  ...props
13
13
  });
14
14
  }
@@ -22,28 +22,28 @@ function AvatarImage({ className, ...props }) {
22
22
  function AvatarFallback({ className, ...props }) {
23
23
  return /* @__PURE__ */ jsx(Avatar$1.Fallback, {
24
24
  "data-slot": "avatar-fallback",
25
- className: cn("bg-muted text-muted-foreground flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs", className),
25
+ className: cn("bg-secondary text-muted flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs", className),
26
26
  ...props
27
27
  });
28
28
  }
29
29
  function AvatarBadge({ className, ...props }) {
30
30
  return /* @__PURE__ */ jsx("span", {
31
31
  "data-slot": "avatar-badge",
32
- className: cn("bg-primary text-primary-foreground ring-background absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-blend-color ring-2 select-none", "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden", "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2", "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2", className),
32
+ className: cn("bg-primary text-white ring-foundation absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-blend-color ring-2 select-none", "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden", "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2", "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2", className),
33
33
  ...props
34
34
  });
35
35
  }
36
36
  function AvatarGroup({ className, ...props }) {
37
37
  return /* @__PURE__ */ jsx("div", {
38
38
  "data-slot": "avatar-group",
39
- className: cn("*:data-[slot=avatar]:ring-background group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2", className),
39
+ className: cn("*:data-[slot=avatar]:ring-foundation group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2", className),
40
40
  ...props
41
41
  });
42
42
  }
43
43
  function AvatarGroupCount({ className, ...props }) {
44
44
  return /* @__PURE__ */ jsx("div", {
45
45
  "data-slot": "avatar-group-count",
46
- className: cn("bg-muted text-muted-foreground ring-background relative flex size-8 shrink-0 items-center justify-center rounded-full text-sm ring-2 group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3", className),
46
+ className: cn("bg-secondary text-muted ring-foundation relative flex size-8 shrink-0 items-center justify-center rounded-full text-sm ring-2 group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3", className),
47
47
  ...props
48
48
  });
49
49
  }