@photon-ai/pho-ui 2.1.0 → 2.2.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 (113) hide show
  1. package/dist/chunks/IconAlertCircleFilled-VxKU8TYK.js.map +1 -1
  2. package/dist/chunks/IconArrowUpRight-DGgKzQwV.js.map +1 -1
  3. package/dist/chunks/IconCheck-D2WuculQ.js.map +1 -1
  4. package/dist/chunks/IconChevronLeft-CSWMKQ4C.js.map +1 -1
  5. package/dist/chunks/IconInfoCircle-L0zfhg7R.js.map +1 -1
  6. package/dist/chunks/IconX-pZ9vrtSr.js.map +1 -1
  7. package/dist/chunks/animated-height-C2eQstGy.js.map +1 -1
  8. package/dist/chunks/{avatar-CiAvJNNs.js → avatar-BkmGDIqf.js} +3 -3
  9. package/dist/chunks/{avatar-CiAvJNNs.js.map → avatar-BkmGDIqf.js.map} +1 -1
  10. package/dist/chunks/basic-page-CB36yrpL.js +643 -0
  11. package/dist/chunks/basic-page-CB36yrpL.js.map +1 -0
  12. package/dist/chunks/{button-X5wsWvRa.js → button-BmhyLgy5.js} +3 -3
  13. package/dist/chunks/{button-X5wsWvRa.js.map → button-BmhyLgy5.js.map} +1 -1
  14. package/dist/chunks/{card-9cGnv-VD.js → card-DSW3Uhag.js} +2 -2
  15. package/dist/chunks/{card-9cGnv-VD.js.map → card-DSW3Uhag.js.map} +1 -1
  16. package/dist/chunks/{close-button-xadxp0j8.js → close-button-GvqWbLl0.js} +2 -2
  17. package/dist/chunks/{close-button-xadxp0j8.js.map → close-button-GvqWbLl0.js.map} +1 -1
  18. package/dist/chunks/{cn-DTiB6ek_.js → cn-ChIgwEl3.js} +99 -96
  19. package/dist/chunks/{cn-DTiB6ek_.js.map → cn-ChIgwEl3.js.map} +1 -1
  20. package/dist/chunks/{combobox-rLdS6fl-.js → combobox-Dj5m_dDd.js} +2 -2
  21. package/dist/chunks/{combobox-rLdS6fl-.js.map → combobox-Dj5m_dDd.js.map} +1 -1
  22. package/dist/chunks/createReactComponent-BqCmnqfX.js.map +1 -1
  23. package/dist/chunks/{dialog-BC23YRUq.js → dialog-DtFO7oy0.js} +5 -5
  24. package/dist/chunks/{dialog-BC23YRUq.js.map → dialog-DtFO7oy0.js.map} +1 -1
  25. package/dist/chunks/{error-DR6G2LmG.js → error-Da7P5WZi.js} +11 -10
  26. package/dist/chunks/{error-DR6G2LmG.js.map → error-Da7P5WZi.js.map} +1 -1
  27. package/dist/chunks/{input-D3XQcC4J.js → input-QSAUO30c.js} +2 -2
  28. package/dist/chunks/{input-D3XQcC4J.js.map → input-QSAUO30c.js.map} +1 -1
  29. package/dist/chunks/{input-group-D6dlma8k.js → input-group-5AtpIhC_.js} +2 -2
  30. package/dist/chunks/{input-group-D6dlma8k.js.map → input-group-5AtpIhC_.js.map} +1 -1
  31. package/dist/chunks/{menu-BC-9IP29.js → menu-Cgj3lq9z.js} +3 -3
  32. package/dist/chunks/{menu-BC-9IP29.js.map → menu-Cgj3lq9z.js.map} +1 -1
  33. package/dist/chunks/{popover-EL1SE1kj.js → popover-BhBJO346.js} +2 -2
  34. package/dist/chunks/{popover-EL1SE1kj.js.map → popover-BhBJO346.js.map} +1 -1
  35. package/dist/chunks/{scroll-area-CNZVwe7v.js → scroll-area-Cw4JFqNG.js} +2 -2
  36. package/dist/chunks/{scroll-area-CNZVwe7v.js.map → scroll-area-Cw4JFqNG.js.map} +1 -1
  37. package/dist/chunks/{sidebar-DDJC1MeD.js → sidebar-BETMObNj.js} +25 -24
  38. package/dist/chunks/{sidebar-DDJC1MeD.js.map → sidebar-BETMObNj.js.map} +1 -1
  39. package/dist/chunks/{spinner-Cy8bkyJf.js → spinner-BzLUo4Xk.js} +2 -2
  40. package/dist/chunks/{spinner-Cy8bkyJf.js.map → spinner-BzLUo4Xk.js.map} +1 -1
  41. package/dist/chunks/{status-view-CcbctPqR.js → status-view-C8tabjDu.js} +2 -2
  42. package/dist/chunks/{status-view-CcbctPqR.js.map → status-view-C8tabjDu.js.map} +1 -1
  43. package/dist/components/accordion.js +1 -1
  44. package/dist/components/autocomplete.js +1 -1
  45. package/dist/components/avatar.js +1 -1
  46. package/dist/components/badge.js +1 -1
  47. package/dist/components/button.js +2 -2
  48. package/dist/components/card.js +1 -1
  49. package/dist/components/checkbox.js +1 -1
  50. package/dist/components/checkbox.js.map +1 -1
  51. package/dist/components/collapsible.js +1 -1
  52. package/dist/components/combobox.js +1 -1
  53. package/dist/components/command.js +2 -2
  54. package/dist/components/command.js.map +1 -1
  55. package/dist/components/context-menu.js +2 -2
  56. package/dist/components/context-menu.js.map +1 -1
  57. package/dist/components/dialog.js +1 -1
  58. package/dist/components/drawer.js +1 -1
  59. package/dist/components/error.js +1 -1
  60. package/dist/components/field.js +1 -1
  61. package/dist/components/fieldset.js +1 -1
  62. package/dist/components/form.js +1 -1
  63. package/dist/components/input-group.js +1 -1
  64. package/dist/components/input.js +1 -1
  65. package/dist/components/kbd.js +1 -1
  66. package/dist/components/kbd.js.map +1 -1
  67. package/dist/components/menu.js +1 -1
  68. package/dist/components/menubar.js +1 -1
  69. package/dist/components/meter.js +1 -1
  70. package/dist/components/navigation-menu.js +1 -1
  71. package/dist/components/notification.js +1 -1
  72. package/dist/components/notification.js.map +1 -1
  73. package/dist/components/number-field.js +1 -1
  74. package/dist/components/otp-field.js +1 -1
  75. package/dist/components/otp-field.js.map +1 -1
  76. package/dist/components/phone-input.js +2064 -2050
  77. package/dist/components/phone-input.js.map +1 -1
  78. package/dist/components/popover.js +1 -1
  79. package/dist/components/preview-card.js +1 -1
  80. package/dist/components/progress.js +1 -1
  81. package/dist/components/radio-group.js +1 -1
  82. package/dist/components/radio-group.js.map +1 -1
  83. package/dist/components/scroll-area.js +1 -1
  84. package/dist/components/select.js +1 -1
  85. package/dist/components/select.js.map +1 -1
  86. package/dist/components/separator.js +1 -1
  87. package/dist/components/skeleton.js +1 -1
  88. package/dist/components/slider.js +1 -1
  89. package/dist/components/spinner.js +1 -1
  90. package/dist/components/status-view.js +1 -1
  91. package/dist/components/switch.js +1 -1
  92. package/dist/components/switch.js.map +1 -1
  93. package/dist/components/tabs.js +1 -1
  94. package/dist/components/theme-toggle.js +1 -1
  95. package/dist/components/theme-toggle.js.map +1 -1
  96. package/dist/components/toast.js +1 -1
  97. package/dist/components/toggle-group.js +1 -1
  98. package/dist/components/toggle.js +1 -1
  99. package/dist/components/toolbar.js +1 -1
  100. package/dist/components/tooltip.js +1 -1
  101. package/dist/icons.js.map +1 -1
  102. package/dist/index.js +11 -11
  103. package/dist/primitives.js +1 -3
  104. package/dist/sections/basic-page.js +1 -1
  105. package/dist/sections/sidebar.js +1 -1
  106. package/dist/src/components/toast/toast.d.ts +1 -1
  107. package/dist/src/sections/basic-page/basic-page.d.ts +57 -21
  108. package/dist/src/sections/basic-page/index.d.ts +1 -1
  109. package/dist/utils.js +1 -1
  110. package/package.json +21 -20
  111. package/dist/chunks/basic-page-Dfln58iw.js +0 -482
  112. package/dist/chunks/basic-page-Dfln58iw.js.map +0 -1
  113. package/dist/primitives.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.js","names":[],"sources":["../../src/components/checkbox/check-glyph.tsx","../../src/components/checkbox/checkbox.tsx","../../src/components/checkbox/checkbox-group.tsx","../../src/components/checkbox/checkbox-card.tsx"],"sourcesContent":["import { motion } from \"motion/react\";\n\n// Tabler's IconCheck / IconMinus paths, redrawn as a single animatable\n// `motion.path` — same 24×24 outline geometry (stroke 2, round caps/joins),\n// so the glyph matches every other Tabler-sourced icon at rest.\nconst CHECK_PATH = \"M5 12l5 5l10 -10\";\nconst MINUS_PATH = \"M5 12l14 0\";\n\nconst DRAW_TRANSITION = { duration: 0.22, ease: \"easeOut\" } as const;\n\n/**\n * The checkbox glyph, stroked on rather than popped in solid — same\n * considered-motion spirit as Button's press/wake effects. Re-keyed per\n * state (check vs. dash) so every appearance draws fresh from empty instead\n * of resuming a stroke left mid-way by whatever the glyph showed before.\n */\nexport function DrawnCheckGlyph({\n indeterminate,\n className,\n}: {\n indeterminate?: boolean;\n className?: string;\n}) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <motion.path\n key={indeterminate ? \"minus\" : \"check\"}\n d={indeterminate ? MINUS_PATH : CHECK_PATH}\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n transition={DRAW_TRANSITION}\n />\n </svg>\n );\n}\n","import { type ComponentProps, type ReactNode } from \"react\";\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { motion } from \"motion/react\";\nimport { DrawnCheckGlyph } from \"./check-glyph\";\nimport { cn } from \"../../utils/cn\";\nimport { usePressPulse } from \"../../utils/use-press-pulse\";\n\nexport type CheckboxSize = \"sm\" | \"md\";\n\nconst BOX: Record<CheckboxSize, string> = { sm: \"size-4\", md: \"size-5\" };\nconst ICON: Record<CheckboxSize, string> = { sm: \"size-3\", md: \"size-3.5\" };\n\nexport interface CheckboxProps extends Omit<\n ComponentProps<typeof BaseCheckbox.Root>,\n \"className\"\n> {\n className?: string;\n /** Text rendered beside the box; the whole row toggles the checkbox. */\n label?: ReactNode;\n /** Size variant. @default \"md\" */\n size?: CheckboxSize;\n}\n\n/**\n * Checkbox built on Base UI `Checkbox`. Supports checked, unchecked, and\n * `indeterminate` states; pass `label` for a clickable text row, or omit it\n * and provide an `aria-label`. For a set of related options that submit\n * together, wrap them in `CheckboxGroup`.\n *\n * Animation is the Effect Button family scaled to a toggle, kept restrained:\n * a quick shallow press pulse on pointer-down (always plays out), the\n * fill/stroke easing between states, and the glyph popping in.\n */\nexport function Checkbox({\n className,\n label,\n size = \"md\",\n disabled,\n indeterminate,\n ...props\n}: CheckboxProps) {\n const { motionProps } = usePressPulse({\n scale: 0.94,\n disabled: Boolean(disabled),\n });\n // With a label, the whole row is the hit target — press-trigger from there\n // (pointerdown bubbles up from the label text too) so the box still\n // animates when the text, not the box itself, is what's clicked.\n const { onPointerDown, ...boxMotionProps } = motionProps;\n\n const box = (\n <BaseCheckbox.Root\n disabled={disabled}\n indeterminate={indeterminate}\n render={\n <motion.span\n {...boxMotionProps}\n onPointerDown={label ? undefined : onPointerDown}\n />\n }\n className={cn(\n // Flat field surface with the input-strength ring; the glyph only shows\n // on the brand-solid checked fill, so it must be on-brand (not white —\n // brand-solid is white in dark mode).\n \"group/cb outline-pho-brand bg-pho-primary ring-pho-primary text-pho-on-brand flex shrink-0 cursor-pointer items-center justify-center rounded-sm ring-1 ring-inset focus-visible:outline-2 focus-visible:outline-offset-2\",\n // Fill and stroke ease between states (stroke dissolves into the\n // fill on tick). Transform stays out — Motion owns the press pulse.\n \"transition-[background-color,box-shadow,color,outline-color] duration-150 ease-out\",\n // group-hover covers hovering the label text, not just the box itself.\n \"hover:bg-pho-primary-hover hover:ring-pho-ink group-hover:bg-pho-primary-hover group-hover:ring-pho-ink\",\n \"data-[checked]:bg-pho-brand-solid data-[checked]:ring-transparent\",\n \"data-[indeterminate]:bg-pho-brand-solid data-[indeterminate]:ring-transparent\",\n \"data-[checked]:hover:bg-pho-brand-solid-hover data-[checked]:group-hover:bg-pho-brand-solid-hover\",\n \"data-[indeterminate]:hover:bg-pho-brand-solid-hover data-[indeterminate]:group-hover:bg-pho-brand-solid-hover\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n BOX[size],\n className,\n )}\n {...props}\n >\n {/* The glyph draws itself on (see DrawnCheckGlyph) — no separate\n pop-in needed. A quick fade covers the exit, since an unmount\n can't play the stroke backwards. */}\n <BaseCheckbox.Indicator\n className={cn(\n \"flex items-center justify-center transition-opacity duration-100 ease-out\",\n \"data-[ending-style]:opacity-0\",\n )}\n >\n <DrawnCheckGlyph indeterminate={indeterminate} className={ICON[size]} />\n </BaseCheckbox.Indicator>\n </BaseCheckbox.Root>\n );\n\n if (!label) return box;\n return (\n <label\n className=\"group flex cursor-pointer items-center gap-2 select-none\"\n onPointerDown={onPointerDown}\n >\n {box}\n <span className=\"text-pho-secondary text-base\">{label}</span>\n </label>\n );\n}\n\nCheckbox.displayName = \"Checkbox\";\n","import { type ComponentProps } from \"react\";\nimport { CheckboxGroup as BaseCheckboxGroup } from \"@base-ui/react/checkbox-group\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface CheckboxGroupProps extends Omit<\n ComponentProps<typeof BaseCheckboxGroup>,\n \"className\"\n> {\n className?: string;\n}\n\n/**\n * Groups related `Checkbox`es and tracks their values as one. Built on Base UI\n * `CheckboxGroup` — supports a parent \"select all\" checkbox via `allValues`.\n * Control with `value` / `onValueChange` or leave uncontrolled with\n * `defaultValue`.\n */\nexport function CheckboxGroup({ className, ...props }: CheckboxGroupProps) {\n return (\n <BaseCheckboxGroup\n className={cn(\"flex flex-col gap-3\", className)}\n {...props}\n />\n );\n}\n\nCheckboxGroup.displayName = \"CheckboxGroup\";\n","import { type ComponentProps, type ReactNode } from \"react\";\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { motion } from \"motion/react\";\nimport { DrawnCheckGlyph } from \"./check-glyph\";\nimport { cn } from \"../../utils/cn\";\nimport { usePressPulse } from \"../../utils/use-press-pulse\";\nimport {\n CHOICE_CARD_BASE,\n CHOICE_CARD_WITH_ICON,\n CHOICE_CARD_PRESS_SCALE,\n CHOICE_CARD_PRESS_TRANSITION,\n} from \"../../utils/choice-card\";\n\nexport interface CheckboxCardProps extends Omit<\n ComponentProps<typeof BaseCheckbox.Root>,\n \"className\" | \"title\"\n> {\n className?: string;\n /** Tile heading. */\n title: ReactNode;\n /** Supporting copy shown below the title. */\n description?: ReactNode;\n /** Glyph stacked above the title. When set, it replaces the checkbox box. */\n icon?: ReactNode;\n}\n\nfunction CardCopy({\n title,\n description,\n}: {\n title: ReactNode;\n description?: ReactNode;\n}) {\n return (\n <span>\n <span className=\"text-pho-primary block\">{title}</span>\n {description ? (\n <span className=\"text-pho-description block\">{description}</span>\n ) : null}\n </span>\n );\n}\n\n/**\n * A `Checkbox` styled as a bordered, selectable tile — title, optional\n * description, and either a stacked icon or the checkbox box. The tile is a\n * `<label>` around the control so clicks (including on the icon/title) are a\n * trusted activation of the hidden input Base UI renders beside the root.\n */\nexport function CheckboxCard({\n className,\n title,\n description,\n icon,\n disabled,\n indeterminate,\n ...props\n}: CheckboxCardProps) {\n const { motionProps } = usePressPulse({\n scale: CHOICE_CARD_PRESS_SCALE,\n disabled: Boolean(disabled),\n transition: CHOICE_CARD_PRESS_TRANSITION,\n });\n const hasIcon = icon != null;\n\n return (\n <motion.label\n {...motionProps}\n className={cn(\n CHOICE_CARD_BASE,\n hasIcon && CHOICE_CARD_WITH_ICON,\n className,\n )}\n data-disabled={disabled ? \"\" : undefined}\n >\n <BaseCheckbox.Root\n disabled={disabled}\n indeterminate={indeterminate}\n className={\n hasIcon\n ? \"sr-only\"\n : cn(\n \"bg-pho-primary ring-pho-primary text-pho-on-brand mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-sm ring-1 ring-inset\",\n \"group-hover:bg-pho-primary-hover group-hover:ring-pho-ink transition-[background-color,box-shadow,color] duration-150 ease-out\",\n \"data-[checked]:bg-pho-brand-solid data-[checked]:group-hover:bg-pho-brand-solid-hover data-[checked]:ring-transparent\",\n \"data-[indeterminate]:bg-pho-brand-solid data-[indeterminate]:group-hover:bg-pho-brand-solid-hover data-[indeterminate]:ring-transparent\",\n )\n }\n {...props}\n >\n {hasIcon ? null : (\n <BaseCheckbox.Indicator\n className={cn(\n \"flex items-center justify-center transition-opacity duration-100 ease-out\",\n \"data-[ending-style]:opacity-0\",\n )}\n >\n <DrawnCheckGlyph\n indeterminate={indeterminate}\n className=\"size-2.5\"\n />\n </BaseCheckbox.Indicator>\n )}\n </BaseCheckbox.Root>\n {hasIcon ? (\n <span\n aria-hidden\n className=\"text-pho-secondary flex size-6 shrink-0 items-center justify-center [&>svg]:size-6\"\n >\n {icon}\n </span>\n ) : null}\n <CardCopy title={title} description={description} />\n </motion.label>\n );\n}\n\nCheckboxCard.displayName = \"CheckboxCard\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"checkbox.js","names":[],"sources":["../../src/components/checkbox/check-glyph.tsx","../../src/components/checkbox/checkbox.tsx","../../src/components/checkbox/checkbox-group.tsx","../../src/components/checkbox/checkbox-card.tsx"],"sourcesContent":["import { motion } from \"motion/react\";\n\n// Tabler's IconCheck / IconMinus paths, redrawn as a single animatable\n// `motion.path` — same 24×24 outline geometry (stroke 2, round caps/joins),\n// so the glyph matches every other Tabler-sourced icon at rest.\nconst CHECK_PATH = \"M5 12l5 5l10 -10\";\nconst MINUS_PATH = \"M5 12l14 0\";\n\nconst DRAW_TRANSITION = { duration: 0.22, ease: \"easeOut\" } as const;\n\n/**\n * The checkbox glyph, stroked on rather than popped in solid — same\n * considered-motion spirit as Button's press/wake effects. Re-keyed per\n * state (check vs. dash) so every appearance draws fresh from empty instead\n * of resuming a stroke left mid-way by whatever the glyph showed before.\n */\nexport function DrawnCheckGlyph({\n indeterminate,\n className,\n}: {\n indeterminate?: boolean;\n className?: string;\n}) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <motion.path\n key={indeterminate ? \"minus\" : \"check\"}\n d={indeterminate ? MINUS_PATH : CHECK_PATH}\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n transition={DRAW_TRANSITION}\n />\n </svg>\n );\n}\n","import { type ComponentProps, type ReactNode } from \"react\";\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { motion } from \"motion/react\";\nimport { DrawnCheckGlyph } from \"./check-glyph\";\nimport { cn } from \"../../utils/cn\";\nimport { usePressPulse } from \"../../utils/use-press-pulse\";\n\nexport type CheckboxSize = \"sm\" | \"md\";\n\nconst BOX: Record<CheckboxSize, string> = { sm: \"size-4\", md: \"size-5\" };\nconst ICON: Record<CheckboxSize, string> = { sm: \"size-3\", md: \"size-3.5\" };\n\nexport interface CheckboxProps extends Omit<\n ComponentProps<typeof BaseCheckbox.Root>,\n \"className\"\n> {\n className?: string;\n /** Text rendered beside the box; the whole row toggles the checkbox. */\n label?: ReactNode;\n /** Size variant. @default \"md\" */\n size?: CheckboxSize;\n}\n\n/**\n * Checkbox built on Base UI `Checkbox`. Supports checked, unchecked, and\n * `indeterminate` states; pass `label` for a clickable text row, or omit it\n * and provide an `aria-label`. For a set of related options that submit\n * together, wrap them in `CheckboxGroup`.\n *\n * Animation is the Effect Button family scaled to a toggle, kept restrained:\n * a quick shallow press pulse on pointer-down (always plays out), the\n * fill/stroke easing between states, and the glyph popping in.\n */\nexport function Checkbox({\n className,\n label,\n size = \"md\",\n disabled,\n indeterminate,\n ...props\n}: CheckboxProps) {\n const { motionProps } = usePressPulse({\n scale: 0.94,\n disabled: Boolean(disabled),\n });\n // With a label, the whole row is the hit target — press-trigger from there\n // (pointerdown bubbles up from the label text too) so the box still\n // animates when the text, not the box itself, is what's clicked.\n const { onPointerDown, ...boxMotionProps } = motionProps;\n\n const box = (\n <BaseCheckbox.Root\n disabled={disabled}\n indeterminate={indeterminate}\n render={\n <motion.span\n {...boxMotionProps}\n onPointerDown={label ? undefined : onPointerDown}\n />\n }\n className={cn(\n // Flat field surface with the input-strength ring; the glyph only shows\n // on the brand-solid checked fill, so it must be on-brand (not white —\n // brand-solid is white in dark mode).\n \"group/cb outline-pho-brand bg-pho-primary ring-pho-primary text-pho-on-brand flex shrink-0 cursor-pointer items-center justify-center rounded-sm ring-1 ring-inset focus-visible:outline-2 focus-visible:outline-offset-2\",\n // Fill and stroke ease between states (stroke dissolves into the\n // fill on tick). Transform stays out — Motion owns the press pulse.\n \"transition-[background-color,box-shadow,color,outline-color] duration-150 ease-out\",\n // group-hover covers hovering the label text, not just the box itself.\n \"hover:bg-pho-primary-hover hover:ring-pho-ink group-hover:bg-pho-primary-hover group-hover:ring-pho-ink\",\n \"data-[checked]:bg-pho-brand-solid data-[checked]:ring-transparent\",\n \"data-[indeterminate]:bg-pho-brand-solid data-[indeterminate]:ring-transparent\",\n \"data-[checked]:hover:bg-pho-brand-solid-hover data-[checked]:group-hover:bg-pho-brand-solid-hover\",\n \"data-[indeterminate]:hover:bg-pho-brand-solid-hover data-[indeterminate]:group-hover:bg-pho-brand-solid-hover\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n BOX[size],\n className,\n )}\n {...props}\n >\n {/* The glyph draws itself on (see DrawnCheckGlyph) — no separate\n pop-in needed. A quick fade covers the exit, since an unmount\n can't play the stroke backwards. */}\n <BaseCheckbox.Indicator\n className={cn(\n \"flex items-center justify-center transition-opacity duration-100 ease-out\",\n \"data-[ending-style]:opacity-0\",\n )}\n >\n <DrawnCheckGlyph indeterminate={indeterminate} className={ICON[size]} />\n </BaseCheckbox.Indicator>\n </BaseCheckbox.Root>\n );\n\n if (!label) return box;\n return (\n <label\n className=\"group flex cursor-pointer items-center gap-2 select-none\"\n onPointerDown={onPointerDown}\n >\n {box}\n <span className=\"text-pho-secondary text-base\">{label}</span>\n </label>\n );\n}\n\nCheckbox.displayName = \"Checkbox\";\n","import { type ComponentProps } from \"react\";\nimport { CheckboxGroup as BaseCheckboxGroup } from \"@base-ui/react/checkbox-group\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface CheckboxGroupProps extends Omit<\n ComponentProps<typeof BaseCheckboxGroup>,\n \"className\"\n> {\n className?: string;\n}\n\n/**\n * Groups related `Checkbox`es and tracks their values as one. Built on Base UI\n * `CheckboxGroup` — supports a parent \"select all\" checkbox via `allValues`.\n * Control with `value` / `onValueChange` or leave uncontrolled with\n * `defaultValue`.\n */\nexport function CheckboxGroup({ className, ...props }: CheckboxGroupProps) {\n return (\n <BaseCheckboxGroup\n className={cn(\"flex flex-col gap-3\", className)}\n {...props}\n />\n );\n}\n\nCheckboxGroup.displayName = \"CheckboxGroup\";\n","import { type ComponentProps, type ReactNode } from \"react\";\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { motion } from \"motion/react\";\nimport { DrawnCheckGlyph } from \"./check-glyph\";\nimport { cn } from \"../../utils/cn\";\nimport { usePressPulse } from \"../../utils/use-press-pulse\";\nimport {\n CHOICE_CARD_BASE,\n CHOICE_CARD_WITH_ICON,\n CHOICE_CARD_PRESS_SCALE,\n CHOICE_CARD_PRESS_TRANSITION,\n} from \"../../utils/choice-card\";\n\nexport interface CheckboxCardProps extends Omit<\n ComponentProps<typeof BaseCheckbox.Root>,\n \"className\" | \"title\"\n> {\n className?: string;\n /** Tile heading. */\n title: ReactNode;\n /** Supporting copy shown below the title. */\n description?: ReactNode;\n /** Glyph stacked above the title. When set, it replaces the checkbox box. */\n icon?: ReactNode;\n}\n\nfunction CardCopy({\n title,\n description,\n}: {\n title: ReactNode;\n description?: ReactNode;\n}) {\n return (\n <span>\n <span className=\"text-pho-primary block\">{title}</span>\n {description ? (\n <span className=\"text-pho-description block\">{description}</span>\n ) : null}\n </span>\n );\n}\n\n/**\n * A `Checkbox` styled as a bordered, selectable tile — title, optional\n * description, and either a stacked icon or the checkbox box. The tile is a\n * `<label>` around the control so clicks (including on the icon/title) are a\n * trusted activation of the hidden input Base UI renders beside the root.\n */\nexport function CheckboxCard({\n className,\n title,\n description,\n icon,\n disabled,\n indeterminate,\n ...props\n}: CheckboxCardProps) {\n const { motionProps } = usePressPulse({\n scale: CHOICE_CARD_PRESS_SCALE,\n disabled: Boolean(disabled),\n transition: CHOICE_CARD_PRESS_TRANSITION,\n });\n const hasIcon = icon != null;\n\n return (\n <motion.label\n {...motionProps}\n className={cn(\n CHOICE_CARD_BASE,\n hasIcon && CHOICE_CARD_WITH_ICON,\n className,\n )}\n data-disabled={disabled ? \"\" : undefined}\n >\n <BaseCheckbox.Root\n disabled={disabled}\n indeterminate={indeterminate}\n className={\n hasIcon\n ? \"sr-only\"\n : cn(\n \"bg-pho-primary ring-pho-primary text-pho-on-brand mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-sm ring-1 ring-inset\",\n \"group-hover:bg-pho-primary-hover group-hover:ring-pho-ink transition-[background-color,box-shadow,color] duration-150 ease-out\",\n \"data-[checked]:bg-pho-brand-solid data-[checked]:group-hover:bg-pho-brand-solid-hover data-[checked]:ring-transparent\",\n \"data-[indeterminate]:bg-pho-brand-solid data-[indeterminate]:group-hover:bg-pho-brand-solid-hover data-[indeterminate]:ring-transparent\",\n )\n }\n {...props}\n >\n {hasIcon ? null : (\n <BaseCheckbox.Indicator\n className={cn(\n \"flex items-center justify-center transition-opacity duration-100 ease-out\",\n \"data-[ending-style]:opacity-0\",\n )}\n >\n <DrawnCheckGlyph\n indeterminate={indeterminate}\n className=\"size-2.5\"\n />\n </BaseCheckbox.Indicator>\n )}\n </BaseCheckbox.Root>\n {hasIcon ? (\n <span\n aria-hidden\n className=\"text-pho-secondary flex size-6 shrink-0 items-center justify-center [&>svg]:size-6\"\n >\n {icon}\n </span>\n ) : null}\n <CardCopy title={title} description={description} />\n </motion.label>\n );\n}\n\nCheckboxCard.displayName = \"CheckboxCard\";\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as r } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as r } from "../chunks/cn-ChIgwEl3.js";
3
3
  import "react";
4
4
  import { jsx as i } from "react/jsx-runtime";
5
5
  import { Collapsible as o } from "@base-ui/react/collapsible";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t } from "../chunks/combobox-rLdS6fl-.js";
2
+ import { t } from "../chunks/combobox-Dj5m_dDd.js";
3
3
  export {
4
4
  t as Combobox
5
5
  };
@@ -1,9 +1,9 @@
1
1
  "use client";
2
- import { t as l } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as l } from "../chunks/cn-ChIgwEl3.js";
3
3
  import { t as V } from "../chunks/IconArrowUpRight-DGgKzQwV.js";
4
4
  import { t as $ } from "../chunks/IconChevronLeft-CSWMKQ4C.js";
5
5
  import { t as q } from "../chunks/animated-height-C2eQstGy.js";
6
- import { t as N } from "../chunks/dialog-BC23YRUq.js";
6
+ import { t as N } from "../chunks/dialog-DtFO7oy0.js";
7
7
  import { useEffect as D, useId as A, useLayoutEffect as W, useRef as I } from "react";
8
8
  import { Fragment as P, jsx as n, jsxs as y } from "react/jsx-runtime";
9
9
  import { LayoutGroup as B, animate as j, motion as G, useMotionValue as E, useReducedMotion as O } from "motion/react";
@@ -1 +1 @@
1
- {"version":3,"file":"command.js","names":[],"sources":["../../src/components/command/command.tsx"],"sourcesContent":["import {\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n type ComponentProps,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { IconArrowUpRight, IconChevronLeft } from \"@tabler/icons-react\";\nimport { Command as CommandPrimitive, useCommandState } from \"cmdk\";\nimport {\n animate,\n LayoutGroup,\n motion,\n useMotionValue,\n useReducedMotion,\n} from \"motion/react\";\nimport { AnimatedHeight } from \"../../utils/animated-height\";\nimport { cn } from \"../../utils/cn\";\nimport { Dialog as PhoDialog } from \"../dialog\";\n\n/**\n * Spring for row moves (FLIP / shared-layout) — same feel as\n * `AnimatedHeight`: quick and critically damped, so rows glide to their new\n * slot without overshooting into neighbours.\n */\nconst ROW_MOVE_SPRING = {\n type: \"spring\",\n stiffness: 640,\n damping: 50,\n} as const;\n\nfunction Root({\n className,\n children,\n ...props\n}: ComponentProps<typeof CommandPrimitive>) {\n // Namespace row layoutIds per palette instance — the docs page mounts the\n // inline demo and the dialog demo at once, with identical item values.\n const layoutNamespace = useId();\n return (\n <CommandPrimitive\n className={cn(\n \"bg-pho-primary text-pho-primary flex w-full flex-col overflow-hidden outline-none\",\n className,\n )}\n {...props}\n >\n <LayoutGroup id={layoutNamespace}>{children}</LayoutGroup>\n </CommandPrimitive>\n );\n}\n\n/**\n * The input row — a bottom hairline separates it from the list. Position\n * leading icons absolutely and pad the input (`pl-9`), mirroring\n * `Autocomplete.InputGroup`.\n */\nfunction InputGroup({ className, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\n \"border-pho-secondary relative flex items-center border-b\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** SSR-safe layout effect (same pattern cmdk uses internally). */\nconst useIsomorphicLayoutEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (typeof ref === \"function\") ref(value);\n else if (ref) ref.current = value;\n}\n\nfunction Input({\n className,\n value,\n ref: consumerRef,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Input>) {\n const inputRef = useRef<HTMLInputElement>(null);\n const search = useCommandState((state) => state.search);\n\n // cmdk stays uncontrolled here on purpose. Its controlled path syncs the\n // `value` prop into the search store through a passive effect — one painted\n // frame late — so on that stale frame the old row is still \"selected\" while\n // the list has already reflowed, and the selection pill visibly rides it\n // before snapping to the re-selected first row. Uncontrolled keystrokes\n // update search + first-row selection synchronously (pre-paint), killing\n // that frame in both directions (typing and clearing).\n //\n // The consumer-facing API is still controlled: external `value` changes\n // (programmatic reset, initial query) are replayed through the native input\n // path below so store, display, and selection take the same sync route.\n useIsomorphicLayoutEffect(() => {\n const input = inputRef.current;\n if (value == null || input == null || value === search) return;\n const setNativeValue = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n \"value\",\n )?.set;\n setNativeValue?.call(input, value);\n input.dispatchEvent(new Event(\"input\", { bubbles: true }));\n }, [value, search]);\n\n return (\n <CommandPrimitive.Input\n className={cn(\n // Borderless inside the palette surface — the InputGroup hairline\n // carries the edge. display-xs (18px) keeps iOS from zooming in.\n \"text-pho-primary placeholder:text-pho-placeholder text-display-xs w-full bg-transparent px-3 py-3 outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n ref={(node) => {\n inputRef.current = node;\n assignRef(consumerRef, node);\n }}\n />\n );\n}\n\n/**\n * The selection highlight, decoupled from the rows. Rendered once per list as\n * an absolutely-positioned layer sitting on the selected row's *final* layout\n * position (`offsetTop` ignores in-flight FLIP transforms).\n *\n * The invariant (learned the hard way): the highlight must sit exactly on the\n * selected row at every moment. So when the list reflows (search change) the\n * pill *snaps* to the re-anchored row — which itself skips its travel\n * animation (see `Item`) — and the highlight simply *is* on the new content.\n * Only selection moves within a stable list (arrow keys / hover) glide.\n */\nfunction SelectionPill() {\n const pillRef = useRef<HTMLDivElement>(null);\n const selectedValue = useCommandState((state) => state.value);\n const search = useCommandState((state) => state.search);\n const top = useMotionValue(0);\n const height = useMotionValue(0);\n const opacity = useMotionValue(0);\n const visibleRef = useRef(false);\n const measuredSearchRef = useRef<string | null>(null);\n\n useIsomorphicLayoutEffect(() => {\n const pill = pillRef.current;\n const list = pill?.closest<HTMLElement>(\"[cmdk-list]\");\n if (!pill || !list) return;\n\n const measure = () => {\n const row = list.querySelector<HTMLElement>(\n '[cmdk-item][aria-selected=\"true\"]',\n );\n if (!row) {\n // Hide only when the list truly has no rows (empty state). A missing\n // selected row while rows exist is the mid-cascade moment before\n // cmdk re-anchors to the first row — hold position until the\n // follow-up pass instead of blinking out and snapping back in.\n if (!list.querySelector(\"[cmdk-item]\")) {\n visibleRef.current = false;\n opacity.set(0);\n }\n return;\n }\n const reflowed = measuredSearchRef.current !== search;\n if (reflowed) {\n // After a search change cmdk always re-anchors selection to the first\n // enabled row. A selected row anywhere else is the *old* value still\n // mid-cascade (its twin can exist in the new tree, e.g. a search\n // result reverting to its idle group row) — measuring it would send\n // the pill on a long flight. Hold; the corrective pass lands here.\n const firstEnabledRow = list.querySelector<HTMLElement>(\n '[cmdk-item]:not([aria-disabled=\"true\"])',\n );\n if (row !== firstEnabledRow) return;\n }\n // Layout-space position relative to the list (offsetTop is unaffected\n // by the rows' FLIP transforms, so this is the settled target).\n let nextTop = 0;\n let node: HTMLElement | null = row;\n while (node && node !== list) {\n nextTop += node.offsetTop;\n node =\n node.offsetParent instanceof HTMLElement ? node.offsetParent : null;\n }\n pill.style.left = `${row.offsetLeft}px`;\n pill.style.width = `${row.offsetWidth}px`;\n // Snap on (re)appearance and on list reflows (search changed): the\n // re-anchored row appears in place, and the highlight must be on it in\n // the same frame. Glide only for selection moves in a stable list.\n measuredSearchRef.current = search;\n if (!visibleRef.current || reflowed) {\n visibleRef.current = true;\n top.jump(nextTop);\n height.jump(row.offsetHeight);\n opacity.set(1);\n return;\n }\n animate(top, nextTop, ROW_MOVE_SPRING);\n animate(height, row.offsetHeight, ROW_MOVE_SPRING);\n };\n\n measure();\n\n // Re-measure when content reflows without a selection change (rows\n // entering / leaving above the selected row shift its slot). The list\n // box itself is height-capped — observe its content children so inner\n // reflows still fire once the outer size stops changing.\n const listEl = pill.parentElement;\n if (!listEl) return;\n const observer = new ResizeObserver(measure);\n observer.observe(listEl);\n for (const child of listEl.children) {\n if (child !== pill) observer.observe(child);\n }\n const mutations = new MutationObserver(() => {\n for (const child of listEl.children) {\n if (child !== pill) observer.observe(child);\n }\n measure();\n });\n mutations.observe(listEl, { childList: true });\n return () => {\n observer.disconnect();\n mutations.disconnect();\n };\n }, [selectedValue, search, top, height, opacity]);\n\n return (\n <motion.div\n ref={pillRef}\n aria-hidden\n data-command-selection=\"\"\n className=\"bg-pho-ghost-hover pointer-events-none absolute -z-10 rounded-[calc(var(--radius-base)-4px)]\"\n style={{ top, height, opacity }}\n />\n );\n}\n\nfunction List({\n className,\n children,\n ...props\n}: ComponentProps<typeof CommandPrimitive.List>) {\n const reduceMotion = useReducedMotion();\n return (\n // Same spring as the onboarding / invite Card shell — list height glides\n // when idle ↔ search (or filter) changes instead of jumping.\n <AnimatedHeight>\n <CommandPrimitive.List\n className={cn(\n // relative anchors the pill's offset math; isolate keeps its\n // negative z-index below the rows but above the panel background.\n \"relative isolate max-h-[min(24rem,60vh)] overflow-y-auto overscroll-contain p-1\",\n className,\n )}\n {...props}\n >\n {reduceMotion ? null : <SelectionPill />}\n {children}\n </CommandPrimitive.List>\n </AnimatedHeight>\n );\n}\n\nfunction Empty({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n className={cn(\n \"text-pho-description px-2.5 py-6 text-center text-base\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Group({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n className={cn(\n // cmdk renders the `heading` prop in a [cmdk-group-heading] wrapper —\n // typography mirrors `Autocomplete.GroupLabel`.\n \"[&_[cmdk-group-heading]]:text-pho-secondary [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Row layout mode:\n * - `item` / `subitem` / `subsubitem` — idle hierarchy (icon column + indent)\n * - `result` — flat search hit (breadcrumb + trailing scope)\n */\nexport type CommandItemLevel = \"item\" | \"subitem\" | \"subsubitem\" | \"result\";\n\ntype ItemPrimitiveProps = ComponentProps<typeof CommandPrimitive.Item>;\n\nexport interface CommandItemProps extends Omit<\n ItemPrimitiveProps,\n \"children\" | \"title\"\n> {\n /**\n * Row depth / mode in the palette:\n * - `item` — page / top destination (icon + title)\n * - `subitem` — section under an item (label aligns with the item title)\n * - `subsubitem` — row under a section (one step deeper)\n * - `result` — flat search hit (`title` + `path` crumbs + `scope`)\n */\n level?: CommandItemLevel;\n /**\n * Leading glyph. On idle `item` rows (and reserved for sub-levels). On\n * `result` rows, pass the resolved icon (self → parent → grandparent).\n */\n icon?: ReactNode;\n /**\n * When `level=\"result\"`, force the icon column so labels align across the\n * list even if this row's `icon` is empty. Set true when any sibling result\n * has an icon; omit when the whole result set is icon-less.\n */\n iconSlot?: boolean;\n /** Primary label. Prefer this over free-form children for the shared layout. */\n title?: ReactNode;\n /**\n * Ancestors after `title` for `level=\"result\"` — parent → page\n * (e.g. `[\"Agent profile\", \"Settings\"]` → `Name < Agent profile < Settings`).\n */\n path?: ReactNode[];\n /**\n * Trailing scope for `level=\"result\"` — `Project` vs `Personal`, not a nav group.\n */\n scope?: ReactNode;\n /** Shows a trailing external-link glyph (opens outside the app). */\n external?: boolean;\n /**\n * Free-form content. When `title` is set, rendered after the label stack.\n * When `title` is omitted, becomes the row body (legacy / simple items).\n */\n children?: ReactNode;\n}\n\n/** Leading icon column — `size-4`, secondary ink. */\nfunction ItemIcon({ className, ...props }: ComponentProps<\"span\">) {\n return (\n <span\n className={cn(\n \"text-pho-secondary flex size-4 shrink-0 items-center justify-center [&>svg]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Primary label — medium + primary ink on `item` rows. */\nfunction ItemTitle({\n className,\n level = \"item\",\n ...props\n}: ComponentProps<\"span\"> & { level?: CommandItemLevel }) {\n return (\n <span\n className={cn(\n \"text-md block truncate\",\n level === \"item\" && \"text-pho-primary\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * One selectable row. Idle palettes use `level` + `icon` / `title`\n * (item → subitem → subsubitem). Searching uses `level=\"result\"` with `path`\n * crumbs and a trailing `scope` (Project / Personal). No description line —\n * match via `keywords` / aliases instead.\n */\nfunction ExternalGlyph() {\n return (\n <IconArrowUpRight\n aria-hidden\n className=\"text-pho-description size-4 shrink-0\"\n />\n );\n}\n\nfunction Item({\n className,\n level = \"item\",\n icon,\n iconSlot,\n title,\n path,\n scope,\n external,\n children,\n value,\n ...props\n}: CommandItemProps) {\n const reduceMotion = useReducedMotion();\n // cmdk registers `value.trim()` and exposes the selected one as\n // `state.value` — mirrors cmdk's own `data-selected` computation.\n const trimmedValue = typeof value === \"string\" ? value.trim() : \"\";\n const selectedValue = useCommandState((state) => state.value);\n const isSelected = trimmedValue !== \"\" && selectedValue === trimmedValue;\n const structured = title != null;\n const isResult = level === \"result\";\n // Reserve the icon column when the row has an icon, or when the list asks\n // for alignment (`iconSlot`) even if this row's glyph is empty.\n const showResultIcon = isResult && (icon != null || iconSlot);\n\n const row = (\n <CommandPrimitive.Item\n data-level={level}\n value={value}\n className={cn(\n \"text-pho-secondary flex cursor-pointer items-center gap-2 rounded-[calc(var(--radius-base)-4px)] py-2 pr-2.5 text-base outline-none select-none\",\n // subsubitem steps in; item/subitem share the base gutter.\n level === \"subsubitem\" ? \"pl-6\" : \"pl-2\",\n // Secondary at rest; selection lifts to primary ink (Menu idiom). The\n // ghost wash comes from the list's SelectionPill overlay; fall back\n // to a static background when motion is off (no pill rendered).\n \"data-[selected=true]:text-pho-primary\",\n reduceMotion && \"data-[selected=true]:bg-pho-ghost-hover\",\n \"data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50\",\n className,\n )}\n {...props}\n >\n {structured && isResult ? (\n <>\n {showResultIcon ? (\n <ItemIcon aria-hidden={icon == null ? true : undefined}>\n {icon ?? null}\n </ItemIcon>\n ) : null}\n {/* Same text-md line box as idle ItemTitle so row height matches (36px). */}\n <span className=\"text-md flex min-w-0 flex-1 items-center gap-1 overflow-hidden\">\n <span className=\"text-pho-primary truncate\">{title}</span>\n {(path ?? []).map((segment, index) => (\n <span\n key={index}\n className=\"text-pho-description flex shrink-0 items-center gap-0.5\"\n >\n <IconChevronLeft aria-hidden className=\"size-4 shrink-0\" />\n {segment}\n </span>\n ))}\n </span>\n {scope != null && scope !== \"\" ? (\n <span className=\"text-pho-description shrink-0 text-xs\">\n {scope}\n </span>\n ) : null}\n {external ? <ExternalGlyph /> : null}\n {children}\n </>\n ) : structured ? (\n <>\n {/* Icon column always reserved so subitem labels share the item title edge. */}\n <ItemIcon aria-hidden={icon == null ? true : undefined}>\n {icon ?? null}\n </ItemIcon>\n <span className=\"min-w-0 flex-1\">\n <ItemTitle level={level}>{title}</ItemTitle>\n </span>\n {external ? <ExternalGlyph /> : null}\n {children}\n </>\n ) : (\n children\n )}\n </CommandPrimitive.Item>\n );\n\n if (reduceMotion) return row;\n\n return (\n // FLIP wrapper: rows that stay mounted glide when neighbours enter or\n // leave, and a row remounting elsewhere with the same `value` (idle group\n // ↔ flat search result) inherits the old bounds via its layoutId and\n // slides to the new slot — the iOS list-diff feel. Rows without a match\n // simply appear / disappear so the whole list never swarms.\n //\n // The selected row is the exception: it skips the travel and appears at\n // its final slot immediately, so the selection highlight (which also\n // snaps on reflow — see SelectionPill) is never sitting on empty space\n // waiting for its row to fly in.\n <motion.div\n layout=\"position\"\n layoutId={typeof value === \"string\" ? value : undefined}\n initial={false}\n transition={isSelected ? { duration: 0 } : ROW_MOVE_SPRING}\n >\n {row}\n </motion.div>\n );\n}\n\nfunction Separator({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n className={cn(\n \"-mx-1 my-1 h-px bg-[var(--border-color-pho-secondary)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Loading({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Loading>) {\n return (\n <CommandPrimitive.Loading\n className={cn(\"text-pho-description px-2.5 py-1.5 text-base\", className)}\n {...props}\n />\n );\n}\n\ntype DialogRootProps = ComponentProps<typeof PhoDialog.Root>;\n\ninterface CommandDialogProps extends ComponentProps<typeof CommandPrimitive> {\n /** Controlled dialog state — pass straight through to `Dialog.Root`. */\n open?: DialogRootProps[\"open\"];\n onOpenChange?: DialogRootProps[\"onOpenChange\"];\n /** Accessible name for the palette (dialog and command menu). */\n label?: string;\n /** Extra classes for the dialog panel (not the command root). */\n className?: string;\n}\n\n/**\n * A command palette in a modal — Pho's `Dialog` overlay (Base UI) around a\n * `Command.Root`, raised above center. We deliberately skip cmdk's own\n * `Command.Dialog` (Radix) so overlays stay on one primitive stack.\n *\n * List height springs via `AnimatedHeight` (same feel as the Card shell on\n * onboarding / invite) — the input row stays put while results resize.\n */\nfunction Dialog({\n open,\n onOpenChange,\n label,\n className,\n children,\n ...props\n}: CommandDialogProps) {\n return (\n <PhoDialog.Root open={open} onOpenChange={onOpenChange}>\n <PhoDialog.Portal>\n <PhoDialog.Backdrop />\n <PhoDialog.Popup\n aria-label={label}\n // Palette sits above center so the list grows downward from a\n // stable top edge instead of jumping around it.\n className={cn(\n \"top-[max(4rem,18vh)] max-w-xl translate-y-0 overflow-hidden p-0\",\n className,\n )}\n >\n <Root label={label} {...props}>\n {children}\n </Root>\n </PhoDialog.Popup>\n </PhoDialog.Portal>\n </PhoDialog.Root>\n );\n}\n\n/**\n * Command menu built on `cmdk` — a filterable list of actions driven from a\n * single input, keyboard-first. Compose inline (`Command.Root`) or as a\n * ⌘K-style modal palette (`Command.Dialog`, which owns the overlay). By\n * default cmdk filters and ranks items for you; pass `shouldFilter={false}`\n * to render your own result set (e.g. hierarchy-preserving navigation).\n *\n * Rows share one layout via `Command.Item` `level` — idle\n * `item` → `subitem` → `subsubitem`, or flat `result` while searching.\n */\nexport const Command = {\n Root,\n InputGroup,\n Input,\n List,\n Empty,\n Group,\n Item,\n ItemIcon,\n ItemTitle,\n Separator,\n Loading,\n Dialog,\n};\n\n/** Re-export of cmdk's state selector hook (search, value, filtered counts). */\nexport { useCommandState };\n"],"mappings":"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"}
1
+ {"version":3,"file":"command.js","names":[],"sources":["../../src/components/command/command.tsx"],"sourcesContent":["import {\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n type ComponentProps,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { IconArrowUpRight, IconChevronLeft } from \"@tabler/icons-react\";\nimport { Command as CommandPrimitive, useCommandState } from \"cmdk\";\nimport {\n animate,\n LayoutGroup,\n motion,\n useMotionValue,\n useReducedMotion,\n} from \"motion/react\";\nimport { AnimatedHeight } from \"../../utils/animated-height\";\nimport { cn } from \"../../utils/cn\";\nimport { Dialog as PhoDialog } from \"../dialog\";\n\n/**\n * Spring for row moves (FLIP / shared-layout) — same feel as\n * `AnimatedHeight`: quick and critically damped, so rows glide to their new\n * slot without overshooting into neighbours.\n */\nconst ROW_MOVE_SPRING = {\n type: \"spring\",\n stiffness: 640,\n damping: 50,\n} as const;\n\nfunction Root({\n className,\n children,\n ...props\n}: ComponentProps<typeof CommandPrimitive>) {\n // Namespace row layoutIds per palette instance — the docs page mounts the\n // inline demo and the dialog demo at once, with identical item values.\n const layoutNamespace = useId();\n return (\n <CommandPrimitive\n className={cn(\n \"bg-pho-primary text-pho-primary flex w-full flex-col overflow-hidden outline-none\",\n className,\n )}\n {...props}\n >\n <LayoutGroup id={layoutNamespace}>{children}</LayoutGroup>\n </CommandPrimitive>\n );\n}\n\n/**\n * The input row — a bottom hairline separates it from the list. Position\n * leading icons absolutely and pad the input (`pl-9`), mirroring\n * `Autocomplete.InputGroup`.\n */\nfunction InputGroup({ className, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\n \"border-pho-secondary relative flex items-center border-b\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** SSR-safe layout effect (same pattern cmdk uses internally). */\nconst useIsomorphicLayoutEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (typeof ref === \"function\") ref(value);\n else if (ref) ref.current = value;\n}\n\nfunction Input({\n className,\n value,\n ref: consumerRef,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Input>) {\n const inputRef = useRef<HTMLInputElement>(null);\n const search = useCommandState((state) => state.search);\n\n // cmdk stays uncontrolled here on purpose. Its controlled path syncs the\n // `value` prop into the search store through a passive effect — one painted\n // frame late — so on that stale frame the old row is still \"selected\" while\n // the list has already reflowed, and the selection pill visibly rides it\n // before snapping to the re-selected first row. Uncontrolled keystrokes\n // update search + first-row selection synchronously (pre-paint), killing\n // that frame in both directions (typing and clearing).\n //\n // The consumer-facing API is still controlled: external `value` changes\n // (programmatic reset, initial query) are replayed through the native input\n // path below so store, display, and selection take the same sync route.\n useIsomorphicLayoutEffect(() => {\n const input = inputRef.current;\n if (value == null || input == null || value === search) return;\n const setNativeValue = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n \"value\",\n )?.set;\n setNativeValue?.call(input, value);\n input.dispatchEvent(new Event(\"input\", { bubbles: true }));\n }, [value, search]);\n\n return (\n <CommandPrimitive.Input\n className={cn(\n // Borderless inside the palette surface — the InputGroup hairline\n // carries the edge. display-xs (18px) keeps iOS from zooming in.\n \"text-pho-primary placeholder:text-pho-placeholder text-display-xs w-full bg-transparent px-3 py-3 outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n ref={(node) => {\n inputRef.current = node;\n assignRef(consumerRef, node);\n }}\n />\n );\n}\n\n/**\n * The selection highlight, decoupled from the rows. Rendered once per list as\n * an absolutely-positioned layer sitting on the selected row's *final* layout\n * position (`offsetTop` ignores in-flight FLIP transforms).\n *\n * The invariant (learned the hard way): the highlight must sit exactly on the\n * selected row at every moment. So when the list reflows (search change) the\n * pill *snaps* to the re-anchored row — which itself skips its travel\n * animation (see `Item`) — and the highlight simply *is* on the new content.\n * Only selection moves within a stable list (arrow keys / hover) glide.\n */\nfunction SelectionPill() {\n const pillRef = useRef<HTMLDivElement>(null);\n const selectedValue = useCommandState((state) => state.value);\n const search = useCommandState((state) => state.search);\n const top = useMotionValue(0);\n const height = useMotionValue(0);\n const opacity = useMotionValue(0);\n const visibleRef = useRef(false);\n const measuredSearchRef = useRef<string | null>(null);\n\n useIsomorphicLayoutEffect(() => {\n const pill = pillRef.current;\n const list = pill?.closest<HTMLElement>(\"[cmdk-list]\");\n if (!pill || !list) return;\n\n const measure = () => {\n const row = list.querySelector<HTMLElement>(\n '[cmdk-item][aria-selected=\"true\"]',\n );\n if (!row) {\n // Hide only when the list truly has no rows (empty state). A missing\n // selected row while rows exist is the mid-cascade moment before\n // cmdk re-anchors to the first row — hold position until the\n // follow-up pass instead of blinking out and snapping back in.\n if (!list.querySelector(\"[cmdk-item]\")) {\n visibleRef.current = false;\n opacity.set(0);\n }\n return;\n }\n const reflowed = measuredSearchRef.current !== search;\n if (reflowed) {\n // After a search change cmdk always re-anchors selection to the first\n // enabled row. A selected row anywhere else is the *old* value still\n // mid-cascade (its twin can exist in the new tree, e.g. a search\n // result reverting to its idle group row) — measuring it would send\n // the pill on a long flight. Hold; the corrective pass lands here.\n const firstEnabledRow = list.querySelector<HTMLElement>(\n '[cmdk-item]:not([aria-disabled=\"true\"])',\n );\n if (row !== firstEnabledRow) return;\n }\n // Layout-space position relative to the list (offsetTop is unaffected\n // by the rows' FLIP transforms, so this is the settled target).\n let nextTop = 0;\n let node: HTMLElement | null = row;\n while (node && node !== list) {\n nextTop += node.offsetTop;\n node =\n node.offsetParent instanceof HTMLElement ? node.offsetParent : null;\n }\n pill.style.left = `${row.offsetLeft}px`;\n pill.style.width = `${row.offsetWidth}px`;\n // Snap on (re)appearance and on list reflows (search changed): the\n // re-anchored row appears in place, and the highlight must be on it in\n // the same frame. Glide only for selection moves in a stable list.\n measuredSearchRef.current = search;\n if (!visibleRef.current || reflowed) {\n visibleRef.current = true;\n top.jump(nextTop);\n height.jump(row.offsetHeight);\n opacity.set(1);\n return;\n }\n animate(top, nextTop, ROW_MOVE_SPRING);\n animate(height, row.offsetHeight, ROW_MOVE_SPRING);\n };\n\n measure();\n\n // Re-measure when content reflows without a selection change (rows\n // entering / leaving above the selected row shift its slot). The list\n // box itself is height-capped — observe its content children so inner\n // reflows still fire once the outer size stops changing.\n const listEl = pill.parentElement;\n if (!listEl) return;\n const observer = new ResizeObserver(measure);\n observer.observe(listEl);\n for (const child of listEl.children) {\n if (child !== pill) observer.observe(child);\n }\n const mutations = new MutationObserver(() => {\n for (const child of listEl.children) {\n if (child !== pill) observer.observe(child);\n }\n measure();\n });\n mutations.observe(listEl, { childList: true });\n return () => {\n observer.disconnect();\n mutations.disconnect();\n };\n }, [selectedValue, search, top, height, opacity]);\n\n return (\n <motion.div\n ref={pillRef}\n aria-hidden\n data-command-selection=\"\"\n className=\"bg-pho-ghost-hover pointer-events-none absolute -z-10 rounded-[calc(var(--radius-base)-4px)]\"\n style={{ top, height, opacity }}\n />\n );\n}\n\nfunction List({\n className,\n children,\n ...props\n}: ComponentProps<typeof CommandPrimitive.List>) {\n const reduceMotion = useReducedMotion();\n return (\n // Same spring as the onboarding / invite Card shell — list height glides\n // when idle ↔ search (or filter) changes instead of jumping.\n <AnimatedHeight>\n <CommandPrimitive.List\n className={cn(\n // relative anchors the pill's offset math; isolate keeps its\n // negative z-index below the rows but above the panel background.\n \"relative isolate max-h-[min(24rem,60vh)] overflow-y-auto overscroll-contain p-1\",\n className,\n )}\n {...props}\n >\n {reduceMotion ? null : <SelectionPill />}\n {children}\n </CommandPrimitive.List>\n </AnimatedHeight>\n );\n}\n\nfunction Empty({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n className={cn(\n \"text-pho-description px-2.5 py-6 text-center text-base\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Group({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n className={cn(\n // cmdk renders the `heading` prop in a [cmdk-group-heading] wrapper —\n // typography mirrors `Autocomplete.GroupLabel`.\n \"[&_[cmdk-group-heading]]:text-pho-secondary [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Row layout mode:\n * - `item` / `subitem` / `subsubitem` — idle hierarchy (icon column + indent)\n * - `result` — flat search hit (breadcrumb + trailing scope)\n */\nexport type CommandItemLevel = \"item\" | \"subitem\" | \"subsubitem\" | \"result\";\n\ntype ItemPrimitiveProps = ComponentProps<typeof CommandPrimitive.Item>;\n\nexport interface CommandItemProps extends Omit<\n ItemPrimitiveProps,\n \"children\" | \"title\"\n> {\n /**\n * Row depth / mode in the palette:\n * - `item` — page / top destination (icon + title)\n * - `subitem` — section under an item (label aligns with the item title)\n * - `subsubitem` — row under a section (one step deeper)\n * - `result` — flat search hit (`title` + `path` crumbs + `scope`)\n */\n level?: CommandItemLevel;\n /**\n * Leading glyph. On idle `item` rows (and reserved for sub-levels). On\n * `result` rows, pass the resolved icon (self → parent → grandparent).\n */\n icon?: ReactNode;\n /**\n * When `level=\"result\"`, force the icon column so labels align across the\n * list even if this row's `icon` is empty. Set true when any sibling result\n * has an icon; omit when the whole result set is icon-less.\n */\n iconSlot?: boolean;\n /** Primary label. Prefer this over free-form children for the shared layout. */\n title?: ReactNode;\n /**\n * Ancestors after `title` for `level=\"result\"` — parent → page\n * (e.g. `[\"Agent profile\", \"Settings\"]` → `Name < Agent profile < Settings`).\n */\n path?: ReactNode[];\n /**\n * Trailing scope for `level=\"result\"` — `Project` vs `Personal`, not a nav group.\n */\n scope?: ReactNode;\n /** Shows a trailing external-link glyph (opens outside the app). */\n external?: boolean;\n /**\n * Free-form content. When `title` is set, rendered after the label stack.\n * When `title` is omitted, becomes the row body (legacy / simple items).\n */\n children?: ReactNode;\n}\n\n/** Leading icon column — `size-4`, secondary ink. */\nfunction ItemIcon({ className, ...props }: ComponentProps<\"span\">) {\n return (\n <span\n className={cn(\n \"text-pho-secondary flex size-4 shrink-0 items-center justify-center [&>svg]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Primary label — medium + primary ink on `item` rows. */\nfunction ItemTitle({\n className,\n level = \"item\",\n ...props\n}: ComponentProps<\"span\"> & { level?: CommandItemLevel }) {\n return (\n <span\n className={cn(\n \"text-md block truncate\",\n level === \"item\" && \"text-pho-primary\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * One selectable row. Idle palettes use `level` + `icon` / `title`\n * (item → subitem → subsubitem). Searching uses `level=\"result\"` with `path`\n * crumbs and a trailing `scope` (Project / Personal). No description line —\n * match via `keywords` / aliases instead.\n */\nfunction ExternalGlyph() {\n return (\n <IconArrowUpRight\n aria-hidden\n className=\"text-pho-description size-4 shrink-0\"\n />\n );\n}\n\nfunction Item({\n className,\n level = \"item\",\n icon,\n iconSlot,\n title,\n path,\n scope,\n external,\n children,\n value,\n ...props\n}: CommandItemProps) {\n const reduceMotion = useReducedMotion();\n // cmdk registers `value.trim()` and exposes the selected one as\n // `state.value` — mirrors cmdk's own `data-selected` computation.\n const trimmedValue = typeof value === \"string\" ? value.trim() : \"\";\n const selectedValue = useCommandState((state) => state.value);\n const isSelected = trimmedValue !== \"\" && selectedValue === trimmedValue;\n const structured = title != null;\n const isResult = level === \"result\";\n // Reserve the icon column when the row has an icon, or when the list asks\n // for alignment (`iconSlot`) even if this row's glyph is empty.\n const showResultIcon = isResult && (icon != null || iconSlot);\n\n const row = (\n <CommandPrimitive.Item\n data-level={level}\n value={value}\n className={cn(\n \"text-pho-secondary flex cursor-pointer items-center gap-2 rounded-[calc(var(--radius-base)-4px)] py-2 pr-2.5 text-base outline-none select-none\",\n // subsubitem steps in; item/subitem share the base gutter.\n level === \"subsubitem\" ? \"pl-6\" : \"pl-2\",\n // Secondary at rest; selection lifts to primary ink (Menu idiom). The\n // ghost wash comes from the list's SelectionPill overlay; fall back\n // to a static background when motion is off (no pill rendered).\n \"data-[selected=true]:text-pho-primary\",\n reduceMotion && \"data-[selected=true]:bg-pho-ghost-hover\",\n \"data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50\",\n className,\n )}\n {...props}\n >\n {structured && isResult ? (\n <>\n {showResultIcon ? (\n <ItemIcon aria-hidden={icon == null ? true : undefined}>\n {icon ?? null}\n </ItemIcon>\n ) : null}\n {/* Same text-md line box as idle ItemTitle so row height matches (36px). */}\n <span className=\"text-md flex min-w-0 flex-1 items-center gap-1 overflow-hidden\">\n <span className=\"text-pho-primary truncate\">{title}</span>\n {(path ?? []).map((segment, index) => (\n <span\n key={index}\n className=\"text-pho-description flex shrink-0 items-center gap-0.5\"\n >\n <IconChevronLeft aria-hidden className=\"size-4 shrink-0\" />\n {segment}\n </span>\n ))}\n </span>\n {scope != null && scope !== \"\" ? (\n <span className=\"text-pho-description shrink-0 text-xs\">\n {scope}\n </span>\n ) : null}\n {external ? <ExternalGlyph /> : null}\n {children}\n </>\n ) : structured ? (\n <>\n {/* Icon column always reserved so subitem labels share the item title edge. */}\n <ItemIcon aria-hidden={icon == null ? true : undefined}>\n {icon ?? null}\n </ItemIcon>\n <span className=\"min-w-0 flex-1\">\n <ItemTitle level={level}>{title}</ItemTitle>\n </span>\n {external ? <ExternalGlyph /> : null}\n {children}\n </>\n ) : (\n children\n )}\n </CommandPrimitive.Item>\n );\n\n if (reduceMotion) return row;\n\n return (\n // FLIP wrapper: rows that stay mounted glide when neighbours enter or\n // leave, and a row remounting elsewhere with the same `value` (idle group\n // ↔ flat search result) inherits the old bounds via its layoutId and\n // slides to the new slot — the iOS list-diff feel. Rows without a match\n // simply appear / disappear so the whole list never swarms.\n //\n // The selected row is the exception: it skips the travel and appears at\n // its final slot immediately, so the selection highlight (which also\n // snaps on reflow — see SelectionPill) is never sitting on empty space\n // waiting for its row to fly in.\n <motion.div\n layout=\"position\"\n layoutId={typeof value === \"string\" ? value : undefined}\n initial={false}\n transition={isSelected ? { duration: 0 } : ROW_MOVE_SPRING}\n >\n {row}\n </motion.div>\n );\n}\n\nfunction Separator({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n className={cn(\n \"-mx-1 my-1 h-px bg-[var(--border-color-pho-secondary)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Loading({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Loading>) {\n return (\n <CommandPrimitive.Loading\n className={cn(\"text-pho-description px-2.5 py-1.5 text-base\", className)}\n {...props}\n />\n );\n}\n\ntype DialogRootProps = ComponentProps<typeof PhoDialog.Root>;\n\ninterface CommandDialogProps extends ComponentProps<typeof CommandPrimitive> {\n /** Controlled dialog state — pass straight through to `Dialog.Root`. */\n open?: DialogRootProps[\"open\"];\n onOpenChange?: DialogRootProps[\"onOpenChange\"];\n /** Accessible name for the palette (dialog and command menu). */\n label?: string;\n /** Extra classes for the dialog panel (not the command root). */\n className?: string;\n}\n\n/**\n * A command palette in a modal — Pho's `Dialog` overlay (Base UI) around a\n * `Command.Root`, raised above center. We deliberately skip cmdk's own\n * `Command.Dialog` (Radix) so overlays stay on one primitive stack.\n *\n * List height springs via `AnimatedHeight` (same feel as the Card shell on\n * onboarding / invite) — the input row stays put while results resize.\n */\nfunction Dialog({\n open,\n onOpenChange,\n label,\n className,\n children,\n ...props\n}: CommandDialogProps) {\n return (\n <PhoDialog.Root open={open} onOpenChange={onOpenChange}>\n <PhoDialog.Portal>\n <PhoDialog.Backdrop />\n <PhoDialog.Popup\n aria-label={label}\n // Palette sits above center so the list grows downward from a\n // stable top edge instead of jumping around it.\n className={cn(\n \"top-[max(4rem,18vh)] max-w-xl translate-y-0 overflow-hidden p-0\",\n className,\n )}\n >\n <Root label={label} {...props}>\n {children}\n </Root>\n </PhoDialog.Popup>\n </PhoDialog.Portal>\n </PhoDialog.Root>\n );\n}\n\n/**\n * Command menu built on `cmdk` — a filterable list of actions driven from a\n * single input, keyboard-first. Compose inline (`Command.Root`) or as a\n * ⌘K-style modal palette (`Command.Dialog`, which owns the overlay). By\n * default cmdk filters and ranks items for you; pass `shouldFilter={false}`\n * to render your own result set (e.g. hierarchy-preserving navigation).\n *\n * Rows share one layout via `Command.Item` `level` — idle\n * `item` → `subitem` → `subsubitem`, or flat `result` while searching.\n */\nexport const Command = {\n Root,\n InputGroup,\n Input,\n List,\n Empty,\n Group,\n Item,\n ItemIcon,\n ItemTitle,\n Separator,\n Loading,\n Dialog,\n};\n\n/** Re-export of cmdk's state selector hook (search, value, filtered counts). */\nexport { useCommandState };\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { t as a } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as a } from "../chunks/cn-ChIgwEl3.js";
3
3
  import { t as v } from "../chunks/resolve-variant-CcD8iG5l.js";
4
- import { a as b, c as x, n as M, o as h, r as N, t as s } from "../chunks/menu-BC-9IP29.js";
4
+ import { a as b, c as x, n as M, o as h, r as N, t as s } from "../chunks/menu-Cgj3lq9z.js";
5
5
  import "react";
6
6
  import { Fragment as P, jsx as t, jsxs as i } from "react/jsx-runtime";
7
7
  import { Separator as S } from "@base-ui/react/separator";
@@ -1 +1 @@
1
- {"version":3,"file":"context-menu.js","names":[],"sources":["../../src/components/context-menu/context-menu.tsx"],"sourcesContent":["import {\n type ComponentProps,\n type ElementType,\n type MouseEvent as ReactMouseEvent,\n} from \"react\";\nimport { ContextMenu as BaseContextMenu } from \"@base-ui/react/context-menu\";\nimport { Separator as BaseSeparator } from \"@base-ui/react/separator\";\nimport { cn } from \"../../utils/cn\";\nimport { resolveVariant } from \"../../utils/resolve-variant\";\nimport {\n MENU_POPUP,\n MENU_ITEM,\n MENU_ITEM_COLORS,\n type MenuItemColor,\n} from \"../menu/menu\";\nimport {\n MenuItemSpinner,\n useAsyncMenuItem,\n withMenuPendingRoot,\n type AsyncMenuItemClick,\n} from \"../menu/menu-pending\";\n\n/** Override Base UI's `string | (state) => string` className with plain string. */\ntype StyledProps<T extends ElementType> = Omit<\n ComponentProps<T>,\n \"className\" | \"color\"\n> & {\n className?: string;\n};\n\ntype ContextMenuItemProps = Omit<\n StyledProps<typeof BaseContextMenu.Item>,\n \"onClick\"\n> & {\n /** Semantic ink. @default \"default\" */\n color?: MenuItemColor;\n /**\n * Action handler. Return a promise to keep the menu open while it runs —\n * same behavior as `Menu.Item`.\n */\n onClick?: AsyncMenuItemClick;\n /** Declarative loading state. @default false */\n loading?: boolean;\n};\n\nconst Root = withMenuPendingRoot(BaseContextMenu.Root);\nconst Trigger = BaseContextMenu.Trigger;\nconst Portal = BaseContextMenu.Portal;\nconst Group = BaseContextMenu.Group;\nconst RadioGroup = BaseContextMenu.RadioGroup;\n// Don't wrap SubmenuRoot — nested pending context would shadow the parent\n// Root and fail to lock dismissal for async items inside a submenu.\nconst SubmenuRoot = BaseContextMenu.SubmenuRoot;\n\nfunction Positioner({\n className,\n ...props\n}: StyledProps<typeof BaseContextMenu.Positioner>) {\n return (\n <BaseContextMenu.Positioner className={cn(\"z-50\", className)} {...props} />\n );\n}\n\nfunction Popup({\n className,\n ...props\n}: StyledProps<typeof BaseContextMenu.Popup>) {\n return (\n <BaseContextMenu.Popup className={cn(MENU_POPUP, className)} {...props} />\n );\n}\n\nfunction Item({\n className,\n color = \"default\",\n onClick,\n closeOnClick = true,\n loading = false,\n disabled = false,\n children,\n ...props\n}: ContextMenuItemProps) {\n const { inert, blocked, handleClick } = useAsyncMenuItem({\n onClick,\n closeOnClick,\n loading,\n disabled,\n });\n\n return (\n <BaseContextMenu.Item\n className={cn(\n MENU_ITEM,\n resolveVariant(MENU_ITEM_COLORS, color),\n className,\n )}\n closeOnClick={closeOnClick}\n disabled={blocked}\n data-loading={inert || undefined}\n aria-busy={inert || undefined}\n onClick={handleClick as (event: ReactMouseEvent<HTMLElement>) => void}\n {...props}\n >\n {inert ? (\n <>\n <MenuItemSpinner />\n <output className=\"sr-only\" aria-live=\"polite\" />\n </>\n ) : null}\n {children}\n </BaseContextMenu.Item>\n );\n}\n\nfunction GroupLabel({\n className,\n ...props\n}: StyledProps<typeof BaseContextMenu.GroupLabel>) {\n return (\n <BaseContextMenu.GroupLabel\n className={cn(\n \"text-pho-secondary px-2.5 py-1.5 text-xs font-medium\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Separator({ className, ...props }: StyledProps<typeof BaseSeparator>) {\n return (\n <BaseSeparator\n className={cn(\n \"-mx-1.5 my-1.5 h-px bg-[var(--border-color-pho-secondary)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SubmenuTrigger({\n className,\n ...props\n}: StyledProps<typeof BaseContextMenu.SubmenuTrigger>) {\n return (\n <BaseContextMenu.SubmenuTrigger\n className={cn(\n MENU_ITEM,\n \"data-[popup-open]:bg-pho-ghost-hover\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Right-click (context) menu built on Base UI `ContextMenu`. `ContextMenu.Trigger`\n * wraps the area that opens the menu on right-click / long-press; the popup\n * shares its look with `Menu`. `ContextMenu.Item` has the same native promise\n * support as `Menu.Item`. Always mirror these actions somewhere visible —\n * a context menu must not be the only way to reach them.\n */\nexport const ContextMenu = {\n Root,\n Trigger,\n Portal,\n Positioner,\n Popup,\n Item,\n Group,\n GroupLabel,\n Separator,\n SubmenuRoot,\n SubmenuTrigger,\n RadioGroup,\n};\n"],"mappings":";;;;;;;;AA6CA,IAAM,IAAO,EAAoB,EAAgB,IAAI,GAC/C,IAAU,EAAgB,SAC1B,IAAS,EAAgB,QACzB,IAAQ,EAAgB,OACxB,IAAa,EAAgB,YAG7B,IAAc,EAAgB;AAEpC,SAAS,EAAW,EAClB,WAAA,GACA,GAAG,EAAA,GAC8C;AACjD,SACE,gBAAA,EAAC,EAAgB,YAAjB;AAAA,IAA4B,WAAW,EAAG,QAAQ,CAAS;AAAA,IAAG,GAAI;AAAA,EAAQ,CAAA;AAE9E;AAEA,SAAS,EAAM,EACb,WAAA,GACA,GAAG,EAAA,GACyC;AAC5C,SACE,gBAAA,EAAC,EAAgB,OAAjB;AAAA,IAAuB,WAAW,EAAG,GAAY,CAAS;AAAA,IAAG,GAAI;AAAA,EAAQ,CAAA;AAE7E;AAEA,SAAS,EAAK,EACZ,WAAA,GACA,OAAA,IAAQ,WACR,SAAA,GACA,cAAA,IAAe,IACf,SAAA,IAAU,IACV,UAAA,IAAW,IACX,UAAA,GACA,GAAG,EAAA,GACoB;AACvB,QAAM,EAAE,OAAA,GAAO,SAAA,GAAS,aAAA,EAAA,IAAgB,EAAiB;AAAA,IACvD,SAAA;AAAA,IACA,cAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,EACF,CAAC;AAED,SACE,gBAAA,EAAC,EAAgB,MAAjB;AAAA,IACE,WAAW,EACT,GACA,EAAe,GAAkB,CAAK,GACtC,CACF;AAAA,IACc,cAAA;AAAA,IACd,UAAU;AAAA,IACV,gBAAc,KAAS;AAAA,IACvB,aAAW,KAAS;AAAA,IACpB,SAAS;AAAA,IACT,GAAI;AAAA,cAXN,CAaG,IACC,gBAAA,EAAA,GAAA,EAAA,UAAA,CACE,gBAAA,EAAC,GAAD,CAAkB,CAAA,GAClB,gBAAA,EAAC,UAAD;AAAA,MAAQ,WAAU;AAAA,MAAU,aAAU;AAAA,IAAU,CAAA,CAChD,EAAA,CAAA,IACA,MACH,CACmB;AAAA;AAE1B;AAEA,SAAS,EAAW,EAClB,WAAA,GACA,GAAG,EAAA,GAC8C;AACjD,SACE,gBAAA,EAAC,EAAgB,YAAjB;AAAA,IACE,WAAW,EACT,wDACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAEA,SAAS,EAAU,EAAE,WAAA,GAAW,GAAG,EAAA,GAA4C;AAC7E,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,WAAW,EACT,8DACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAEA,SAAS,EAAe,EACtB,WAAA,GACA,GAAG,EAAA,GACkD;AACrD,SACE,gBAAA,EAAC,EAAgB,gBAAjB;AAAA,IACE,WAAW,EACT,GACA,wCACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AASA,IAAa,IAAc;AAAA,EACzB,MAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AACF"}
1
+ {"version":3,"file":"context-menu.js","names":[],"sources":["../../src/components/context-menu/context-menu.tsx"],"sourcesContent":["import {\n type ComponentProps,\n type ElementType,\n type MouseEvent as ReactMouseEvent,\n} from \"react\";\nimport { ContextMenu as BaseContextMenu } from \"@base-ui/react/context-menu\";\nimport { Separator as BaseSeparator } from \"@base-ui/react/separator\";\nimport { cn } from \"../../utils/cn\";\nimport { resolveVariant } from \"../../utils/resolve-variant\";\nimport {\n MENU_POPUP,\n MENU_ITEM,\n MENU_ITEM_COLORS,\n type MenuItemColor,\n} from \"../menu/menu\";\nimport {\n MenuItemSpinner,\n useAsyncMenuItem,\n withMenuPendingRoot,\n type AsyncMenuItemClick,\n} from \"../menu/menu-pending\";\n\n/** Override Base UI's `string | (state) => string` className with plain string. */\ntype StyledProps<T extends ElementType> = Omit<\n ComponentProps<T>,\n \"className\" | \"color\"\n> & {\n className?: string;\n};\n\ntype ContextMenuItemProps = Omit<\n StyledProps<typeof BaseContextMenu.Item>,\n \"onClick\"\n> & {\n /** Semantic ink. @default \"default\" */\n color?: MenuItemColor;\n /**\n * Action handler. Return a promise to keep the menu open while it runs —\n * same behavior as `Menu.Item`.\n */\n onClick?: AsyncMenuItemClick;\n /** Declarative loading state. @default false */\n loading?: boolean;\n};\n\nconst Root = withMenuPendingRoot(BaseContextMenu.Root);\nconst Trigger = BaseContextMenu.Trigger;\nconst Portal = BaseContextMenu.Portal;\nconst Group = BaseContextMenu.Group;\nconst RadioGroup = BaseContextMenu.RadioGroup;\n// Don't wrap SubmenuRoot — nested pending context would shadow the parent\n// Root and fail to lock dismissal for async items inside a submenu.\nconst SubmenuRoot = BaseContextMenu.SubmenuRoot;\n\nfunction Positioner({\n className,\n ...props\n}: StyledProps<typeof BaseContextMenu.Positioner>) {\n return (\n <BaseContextMenu.Positioner className={cn(\"z-50\", className)} {...props} />\n );\n}\n\nfunction Popup({\n className,\n ...props\n}: StyledProps<typeof BaseContextMenu.Popup>) {\n return (\n <BaseContextMenu.Popup className={cn(MENU_POPUP, className)} {...props} />\n );\n}\n\nfunction Item({\n className,\n color = \"default\",\n onClick,\n closeOnClick = true,\n loading = false,\n disabled = false,\n children,\n ...props\n}: ContextMenuItemProps) {\n const { inert, blocked, handleClick } = useAsyncMenuItem({\n onClick,\n closeOnClick,\n loading,\n disabled,\n });\n\n return (\n <BaseContextMenu.Item\n className={cn(\n MENU_ITEM,\n resolveVariant(MENU_ITEM_COLORS, color),\n className,\n )}\n closeOnClick={closeOnClick}\n disabled={blocked}\n data-loading={inert || undefined}\n aria-busy={inert || undefined}\n onClick={handleClick as (event: ReactMouseEvent<HTMLElement>) => void}\n {...props}\n >\n {inert ? (\n <>\n <MenuItemSpinner />\n <output className=\"sr-only\" aria-live=\"polite\" />\n </>\n ) : null}\n {children}\n </BaseContextMenu.Item>\n );\n}\n\nfunction GroupLabel({\n className,\n ...props\n}: StyledProps<typeof BaseContextMenu.GroupLabel>) {\n return (\n <BaseContextMenu.GroupLabel\n className={cn(\n \"text-pho-secondary px-2.5 py-1.5 text-xs font-medium\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Separator({ className, ...props }: StyledProps<typeof BaseSeparator>) {\n return (\n <BaseSeparator\n className={cn(\n \"-mx-1.5 my-1.5 h-px bg-[var(--border-color-pho-secondary)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SubmenuTrigger({\n className,\n ...props\n}: StyledProps<typeof BaseContextMenu.SubmenuTrigger>) {\n return (\n <BaseContextMenu.SubmenuTrigger\n className={cn(\n MENU_ITEM,\n \"data-[popup-open]:bg-pho-ghost-hover\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Right-click (context) menu built on Base UI `ContextMenu`. `ContextMenu.Trigger`\n * wraps the area that opens the menu on right-click / long-press; the popup\n * shares its look with `Menu`. `ContextMenu.Item` has the same native promise\n * support as `Menu.Item`. Always mirror these actions somewhere visible —\n * a context menu must not be the only way to reach them.\n */\nexport const ContextMenu = {\n Root,\n Trigger,\n Portal,\n Positioner,\n Popup,\n Item,\n Group,\n GroupLabel,\n Separator,\n SubmenuRoot,\n SubmenuTrigger,\n RadioGroup,\n};\n"],"mappings":";;;;;;;;AA6CA,IAAM,IAAO,EAAoB,EAAgB,IAAI,GAC/C,IAAU,EAAgB,SAC1B,IAAS,EAAgB,QACzB,IAAQ,EAAgB,OACxB,IAAa,EAAgB,YAG7B,IAAc,EAAgB;AAEpC,SAAS,EAAW,EAClB,WAAA,GACA,GAAG,EAAA,GAC8C;AACjD,SACE,gBAAA,EAAC,EAAgB,YAAjB;AAAA,IAA4B,WAAW,EAAG,QAAQ,CAAS;AAAA,IAAG,GAAI;AAAA,EAAQ,CAAA;AAE9E;AAEA,SAAS,EAAM,EACb,WAAA,GACA,GAAG,EAAA,GACyC;AAC5C,SACE,gBAAA,EAAC,EAAgB,OAAjB;AAAA,IAAuB,WAAW,EAAG,GAAY,CAAS;AAAA,IAAG,GAAI;AAAA,EAAQ,CAAA;AAE7E;AAEA,SAAS,EAAK,EACZ,WAAA,GACA,OAAA,IAAQ,WACR,SAAA,GACA,cAAA,IAAe,IACf,SAAA,IAAU,IACV,UAAA,IAAW,IACX,UAAA,GACA,GAAG,EAAA,GACoB;AACvB,QAAM,EAAE,OAAA,GAAO,SAAA,GAAS,aAAA,EAAA,IAAgB,EAAiB;AAAA,IACvD,SAAA;AAAA,IACA,cAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,EACF,CAAC;AAED,SACE,gBAAA,EAAC,EAAgB,MAAjB;AAAA,IACE,WAAW,EACT,GACA,EAAe,GAAkB,CAAK,GACtC,CACF;AAAA,IACc,cAAA;AAAA,IACd,UAAU;AAAA,IACV,gBAAc,KAAS;AAAA,IACvB,aAAW,KAAS;AAAA,IACpB,SAAS;AAAA,IACT,GAAI;AAAA,IAXN,UAAA,CAaG,IACC,gBAAA,EAAA,GAAA,EAAA,UAAA,CACE,gBAAA,EAAC,GAAD,CAAkB,CAAA,GAClB,gBAAA,EAAC,UAAD;AAAA,MAAQ,WAAU;AAAA,MAAU,aAAU;AAAA,IAAU,CAAA,CAChD,EAAA,CAAA,IACA,MACH,CACmB;AAAA;AAE1B;AAEA,SAAS,EAAW,EAClB,WAAA,GACA,GAAG,EAAA,GAC8C;AACjD,SACE,gBAAA,EAAC,EAAgB,YAAjB;AAAA,IACE,WAAW,EACT,wDACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAEA,SAAS,EAAU,EAAE,WAAA,GAAW,GAAG,EAAA,GAA4C;AAC7E,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,WAAW,EACT,8DACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAEA,SAAS,EAAe,EACtB,WAAA,GACA,GAAG,EAAA,GACkD;AACrD,SACE,gBAAA,EAAC,EAAgB,gBAAjB;AAAA,IACE,WAAW,EACT,GACA,wCACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AASA,IAAa,IAAc;AAAA,EACzB,MAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AACF"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { n as i, t as o } from "../chunks/dialog-BC23YRUq.js";
2
+ import { n as i, t as o } from "../chunks/dialog-DtFO7oy0.js";
3
3
  export {
4
4
  o as Dialog,
5
5
  i as useDialogPending
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as e } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as e } from "../chunks/cn-ChIgwEl3.js";
3
3
  import "react";
4
4
  import { jsx as o } from "react/jsx-runtime";
5
5
  import { Drawer as a } from "@base-ui/react/drawer";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { a, c as s, i as t, l as e, n as o, o as i, r as E, s as p, t as l } from "../chunks/error-DR6G2LmG.js";
2
+ import { a, c as s, i as t, l as e, n as o, o as i, r as E, s as p, t as l } from "../chunks/error-Da7P5WZi.js";
3
3
  export {
4
4
  l as Error,
5
5
  o as ErrorView,
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as o } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as o } from "../chunks/cn-ChIgwEl3.js";
3
3
  import "react";
4
4
  import { jsx as t } from "react/jsx-runtime";
5
5
  import { Field as i } from "@base-ui/react/field";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as o } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as o } from "../chunks/cn-ChIgwEl3.js";
3
3
  import "react";
4
4
  import { jsx as r } from "react/jsx-runtime";
5
5
  import { Fieldset as i } from "@base-ui/react/fieldset";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as m } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as m } from "../chunks/cn-ChIgwEl3.js";
3
3
  import "react";
4
4
  import { jsx as t } from "react/jsx-runtime";
5
5
  import { Form as e } from "@base-ui/react/form";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as o } from "../chunks/input-group-D6dlma8k.js";
2
+ import { t as o } from "../chunks/input-group-5AtpIhC_.js";
3
3
  export {
4
4
  o as InputGroup
5
5
  };
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as e } from "../chunks/input-D3XQcC4J.js";
2
+ import { t as e } from "../chunks/input-QSAUO30c.js";
3
3
  export {
4
4
  e as Input
5
5
  };
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as i } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as i } from "../chunks/cn-ChIgwEl3.js";
3
3
  import "react";
4
4
  import { jsx as o } from "react/jsx-runtime";
5
5
  var s = "inline-flex h-4 min-w-4 items-center justify-center rounded-[3px] px-1 font-mono text-xs font-medium text-pho-secondary ring-1 ring-pho-secondary ring-inset select-none";
@@ -1 +1 @@
1
- {"version":3,"file":"kbd.js","names":[],"sources":["../../src/components/kbd/kbd.tsx"],"sourcesContent":["import { type ComponentProps } from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** A single keycap surface — a mono-label pill with the site hairline (ring-pho-secondary) in secondary ink. */\nconst KBD_CLASS =\n \"inline-flex h-4 min-w-4 items-center justify-center rounded-[3px] px-1 font-mono text-xs font-medium text-pho-secondary ring-1 ring-pho-secondary ring-inset select-none\";\n\ninterface KbdBaseProps {\n /** Convenience string for the key(s) to show, e.g. \"⌘K\". Ignored when `children` are provided. */\n keys?: string;\n}\n\nexport interface KbdProps\n extends KbdBaseProps, Omit<ComponentProps<\"kbd\">, keyof KbdBaseProps> {}\n\n/**\n * Kbd — a keyboard keycap for documenting a shortcut (`⌘K`, `Esc`, `↵`). Supply\n * the key via `children` or the `keys` string; for a chord, place several in a\n * row (`Press ⌘ K`). It's purely presentational and carries no interaction — to\n * actually trigger a shortcut, wire a key handler on the target control.\n */\nexport function Kbd({ keys, className, children, ...props }: KbdProps) {\n return (\n <kbd className={cn(KBD_CLASS, className)} {...props}>\n {children ?? keys}\n </kbd>\n );\n}\n\nKbd.displayName = \"Kbd\";\n"],"mappings":";;;;AAIA,IAAM,IACJ;AAgBF,SAAgB,EAAI,EAAE,MAAA,GAAM,WAAA,GAAW,UAAA,GAAU,GAAG,EAAA,GAAmB;AACrE,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAW,EAAG,GAAW,CAAS;AAAA,IAAG,GAAI;AAAA,cAC3C,KAAY;AAAA,EACV,CAAA;AAET;AAEA,EAAI,cAAc"}
1
+ {"version":3,"file":"kbd.js","names":[],"sources":["../../src/components/kbd/kbd.tsx"],"sourcesContent":["import { type ComponentProps } from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** A single keycap surface — a mono-label pill with the site hairline (ring-pho-secondary) in secondary ink. */\nconst KBD_CLASS =\n \"inline-flex h-4 min-w-4 items-center justify-center rounded-[3px] px-1 font-mono text-xs font-medium text-pho-secondary ring-1 ring-pho-secondary ring-inset select-none\";\n\ninterface KbdBaseProps {\n /** Convenience string for the key(s) to show, e.g. \"⌘K\". Ignored when `children` are provided. */\n keys?: string;\n}\n\nexport interface KbdProps\n extends KbdBaseProps, Omit<ComponentProps<\"kbd\">, keyof KbdBaseProps> {}\n\n/**\n * Kbd — a keyboard keycap for documenting a shortcut (`⌘K`, `Esc`, `↵`). Supply\n * the key via `children` or the `keys` string; for a chord, place several in a\n * row (`Press ⌘ K`). It's purely presentational and carries no interaction — to\n * actually trigger a shortcut, wire a key handler on the target control.\n */\nexport function Kbd({ keys, className, children, ...props }: KbdProps) {\n return (\n <kbd className={cn(KBD_CLASS, className)} {...props}>\n {children ?? keys}\n </kbd>\n );\n}\n\nKbd.displayName = \"Kbd\";\n"],"mappings":";;;;AAIA,IAAM,IACJ;AAgBF,SAAgB,EAAI,EAAE,MAAA,GAAM,WAAA,GAAW,UAAA,GAAU,GAAG,EAAA,GAAmB;AACrE,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAW,EAAG,GAAW,CAAS;AAAA,IAAG,GAAI;AAAA,IAC3C,UAAA,KAAY;AAAA,EACV,CAAA;AAET;AAEA,EAAI,cAAc"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { i as e, n as M, r as n, s as a, t as E } from "../chunks/menu-BC-9IP29.js";
2
+ import { i as e, n as M, r as n, s as a, t as E } from "../chunks/menu-Cgj3lq9z.js";
3
3
  export {
4
4
  E as MENU_ITEM,
5
5
  M as MENU_ITEM_COLORS,
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as o } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as o } from "../chunks/cn-ChIgwEl3.js";
3
3
  import "react";
4
4
  import { jsx as a } from "react/jsx-runtime";
5
5
  import { Menubar as n } from "@base-ui/react/menubar";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as r } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as r } from "../chunks/cn-ChIgwEl3.js";
3
3
  import "react";
4
4
  import { jsx as o } from "react/jsx-runtime";
5
5
  import { Meter as a } from "@base-ui/react/meter";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as n } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as n } from "../chunks/cn-ChIgwEl3.js";
3
3
  import "react";
4
4
  import { jsx as i } from "react/jsx-runtime";
5
5
  import { NavigationMenu as e } from "@base-ui/react/navigation-menu";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t } from "../chunks/cn-ChIgwEl3.js";
3
3
  import { t as y } from "../chunks/resolve-variant-CcD8iG5l.js";
4
4
  import { t as d } from "../chunks/createReactComponent-BqCmnqfX.js";
5
5
  import { t as n } from "../chunks/IconInfoCircle-L0zfhg7R.js";
@@ -1 +1 @@
1
- {"version":3,"file":"notification.js","names":["__iconNode"],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.44.0_react@19.2.7/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.44.0_react@19.2.7/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleCheck.mjs","../../src/components/notification/notification.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.44.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M12 8v4\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M12 16h.01\", \"key\": \"svg-2\" }]];\nconst IconAlertCircle = createReactComponent(\"outline\", \"alert-circle\", \"AlertCircle\", __iconNode);\n\nexport { __iconNode, IconAlertCircle as default };\n//# sourceMappingURL=IconAlertCircle.mjs.map\n","/**\n * @license @tabler/icons-react v3.44.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M9 12l2 2l4 -4\", \"key\": \"svg-1\" }]];\nconst IconCircleCheck = createReactComponent(\"outline\", \"circle-check\", \"CircleCheck\", __iconNode);\n\nexport { __iconNode, IconCircleCheck as default };\n//# sourceMappingURL=IconCircleCheck.mjs.map\n","import { type HTMLAttributes, type ReactNode, type Ref } from \"react\";\nimport {\n IconCircleCheck,\n IconInfoCircle,\n IconAlertCircle,\n IconX,\n type Icon,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../../utils/cn\";\nimport { resolveVariant, type VariantMap } from \"../../utils/resolve-variant\";\n\n/**\n * Design notes (Geist-aligned):\n * - ONE closed, semantic axis: `color`. It selects a status glyph *and* its\n * tint together — you never pick an icon and a color separately. This is the\n * `IconNotification` flavor from the app; the unused avatar/image variants of\n * the source family are intentionally dropped.\n * - The action row is a single reduced pair: a brand `confirmLabel` link beside\n * a gray dismiss link. It appears only when there's something to confirm.\n * - `onClose` is the only thing that renders the top-right close button — no\n * separate boolean flag to keep in sync.\n */\n\n/** Status color → icon tint. A bare status-tinted glyph, no badge surface. */\nexport const NOTIFICATION_COLORS = {\n brand: {\n classes: \"text-pho-brand\",\n description: \"Informational / product update (default)\",\n },\n gray: {\n classes: \"text-pho-secondary\",\n description: \"Neutral, low-stakes note\",\n },\n success: {\n classes: \"text-pho-success\",\n description: \"An action completed\",\n },\n warning: {\n classes: \"text-pho-warning\",\n description: \"Needs attention, not yet failed\",\n },\n error: {\n classes: \"text-pho-error\",\n description: \"Something went wrong\",\n },\n} satisfies VariantMap;\n\nexport type NotificationColor = keyof typeof NOTIFICATION_COLORS;\n\n/** Status color → glyph. Mirrors the source's `iconMap` semantics. */\nconst ICON_MAP = {\n brand: IconInfoCircle,\n gray: IconInfoCircle,\n success: IconCircleCheck,\n warning: IconAlertCircle,\n error: IconAlertCircle,\n} satisfies Record<NotificationColor, Icon>;\n\nexport interface NotificationProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"title\" | \"color\"\n> {\n /** Status color — selects the glyph and its tint. @default \"brand\" */\n color?: NotificationColor;\n /** Bold heading line. */\n title: ReactNode;\n /** Supporting line under the title. */\n description?: ReactNode;\n /** Confirm action label — renders a brand link paired with a dismiss link. */\n confirmLabel?: string;\n /** Called when the confirm link is clicked. */\n onConfirm?: () => void;\n /** Dismiss link label, shown beside the confirm link. @default \"Dismiss\" */\n dismissLabel?: string;\n /** Called on dismiss. Its presence also renders the top-right close button. */\n onClose?: () => void;\n /** Override the status glyph while keeping the color's tint. */\n icon?: Icon;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n}\n\nconst LINK_CLASS =\n \"cursor-pointer text-base font-medium outline-pho-brand transition duration-100 ease-linear focus-visible:outline-2 focus-visible:outline-offset-2\";\n\n/**\n * Notification — the standalone status card ported from the app's\n * `IconNotification`: a status glyph, a title/description, an optional\n * confirm+dismiss link pair, and an optional close button. It is a *card*, not a\n * lifecycle: it owns its surface but nothing about timing or stacking.\n *\n * For a transient, auto-stacking toast, drop it inside pho-ui's Base UI\n * {@link Toast} — render it as the child of a `Toast.Root` whose own surface you\n * neutralize (`className=\"bg-transparent p-0 shadow-none ring-0\"`) so the\n * manager owns motion and swipe while this card owns the look. For a choice the\n * user must make, use `Dialog` instead.\n */\nexport function Notification({\n color = \"brand\",\n title,\n description,\n confirmLabel,\n onConfirm,\n dismissLabel = \"Dismiss\",\n onClose,\n icon,\n className,\n ref,\n ...props\n}: NotificationProps) {\n const Glyph = icon ?? ICON_MAP[color];\n const showActions = Boolean(confirmLabel);\n\n return (\n <div\n ref={ref}\n {...props}\n className={cn(\n // Floating layer: keeps its shadow elevation, hairline card edge.\n \"ring-pho-secondary bg-pho-primary shadow-pho-lg rounded-base relative flex w-full max-w-sm gap-4 p-4 ring-1 ring-inset\",\n className,\n )}\n >\n <Glyph\n aria-hidden=\"true\"\n className={cn(\n \"mt-0.5 size-5 shrink-0\",\n resolveVariant(NOTIFICATION_COLORS, color),\n )}\n />\n\n <div className=\"flex flex-1 flex-col gap-3 pr-6\">\n <div className=\"flex flex-col gap-1\">\n <p className=\"text-pho-primary text-base font-medium\">{title}</p>\n {description != null && description !== false && (\n <p className=\"text-pho-description text-base\">{description}</p>\n )}\n </div>\n\n {showActions && (\n <div className=\"flex gap-4\">\n <button\n type=\"button\"\n onClick={onConfirm}\n className={cn(\n LINK_CLASS,\n // brand text is monochrome now — underline carries the hover.\n \"text-pho-brand hover:underline\",\n )}\n >\n {confirmLabel}\n </button>\n <button\n type=\"button\"\n onClick={onClose}\n className={cn(\n LINK_CLASS,\n \"text-pho-secondary hover:text-pho-secondary-hover\",\n )}\n >\n {dismissLabel}\n </button>\n </div>\n )}\n </div>\n\n {onClose && (\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Dismiss\"\n className=\"text-pho-secondary hover:text-pho-secondary-hover hover:bg-pho-ghost-hover outline-pho-brand absolute top-2.5 right-2.5 flex size-6 cursor-pointer items-center justify-center rounded-sm transition focus-visible:outline-2 [&>svg]:size-4\"\n >\n <IconX aria-hidden=\"true\" />\n </button>\n )}\n </div>\n );\n}\n\nNotification.displayName = \"Notification\";\n"],"x_google_ignoreList":[0,1],"mappings":";;;;;;;;AASA,IAAMA,IAAa;AAAA,EAAC,CAAC,QAAQ;AAAA,IAAE,GAAK;AAAA,IAAwC,KAAO;AAAA,EAAQ,CAAC;AAAA,EAAG,CAAC,QAAQ;AAAA,IAAE,GAAK;AAAA,IAAW,KAAO;AAAA,EAAQ,CAAC;AAAA,EAAG,CAAC,QAAQ;AAAA,IAAE,GAAK;AAAA,IAAc,KAAO;AAAA,EAAQ,CAAC;AAAC,GACtL,IAAkB,EAAqB,WAAW,gBAAgB,eAAeA,CAAU,GCD3F,IAAa,CAAC,CAAC,QAAQ;AAAA,EAAE,GAAK;AAAA,EAAwC,KAAO;AAAQ,CAAC,GAAG,CAAC,QAAQ;AAAA,EAAE,GAAK;AAAA,EAAkB,KAAO;AAAQ,CAAC,CAAC,GAC5I,IAAkB,EAAqB,WAAW,gBAAgB,eAAe,CAAU,GCcpF,IAAsB;AAAA,EACjC,OAAO;AAAA,IACL,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA,SAAS;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA,SAAS;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA,OAAO;AAAA,IACL,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AACF,GAKM,IAAW;AAAA,EACf,OAAO;AAAA,EACP,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAO;AACT,GA0BM,IACJ;AAcF,SAAgB,EAAa,EAC3B,OAAA,IAAQ,SACR,OAAA,GACA,aAAA,GACA,cAAA,GACA,WAAA,GACA,cAAA,IAAe,WACf,SAAA,GACA,MAAA,GACA,WAAA,GACA,KAAA,GACA,GAAG,EAAA,GACiB;AACpB,QAAM,IAAQ,KAAQ,EAAS,CAAA,GACzB,IAAc,EAAQ;AAE5B,SACE,gBAAA,EAAC,OAAD;AAAA,IACO,KAAA;AAAA,IACL,GAAI;AAAA,IACJ,WAAW,EAET,0HACA,CACF;AAAA,cAPF;AAAA,MASE,gBAAA,EAAC,GAAD;AAAA,QACE,eAAY;AAAA,QACZ,WAAW,EACT,0BACA,EAAe,GAAqB,CAAK,CAC3C;AAAA,MACD,CAAA;AAAA,MAED,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,kBAAf,CACE,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,oBAAf,CACE,gBAAA,EAAC,KAAD;AAAA,YAAG,WAAU;AAAA,sBAA0C;AAAA,UAAS,CAAA,GAC/D,KAAe,QAAQ,MAAgB,MACtC,gBAAA,EAAC,KAAD;AAAA,YAAG,WAAU;AAAA,sBAAkC;AAAA,UAAe,CAAA,CAE7D;AAAA,YAEJ,KACC,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,oBAAf,CACE,gBAAA,EAAC,UAAD;AAAA,YACE,MAAK;AAAA,YACL,SAAS;AAAA,YACT,WAAW,EACT,GAEA,gCACF;AAAA,sBAEC;AAAA,UACK,CAAA,GACR,gBAAA,EAAC,UAAD;AAAA,YACE,MAAK;AAAA,YACL,SAAS;AAAA,YACT,WAAW,EACT,GACA,mDACF;AAAA,sBAEC;AAAA,UACK,CAAA,CACL;AAAA,UAEJ;AAAA;MAEJ,KACC,gBAAA,EAAC,UAAD;AAAA,QACE,MAAK;AAAA,QACL,SAAS;AAAA,QACT,cAAW;AAAA,QACX,WAAU;AAAA,kBAEV,gBAAA,EAAC,GAAD,EAAO,eAAY,OAAQ,CAAA;AAAA,MACrB,CAAA;AAAA,IAEP;AAAA;AAET;AAEA,EAAa,cAAc"}
1
+ {"version":3,"file":"notification.js","names":["__iconNode"],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleCheck.mjs","../../src/components/notification/notification.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M12 8v4\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M12 16h.01\", \"key\": \"svg-2\" }]];\nconst IconAlertCircle = createReactComponent(\"outline\", \"alert-circle\", \"AlertCircle\", __iconNode);\n\nexport { __iconNode, IconAlertCircle as default };\n//# sourceMappingURL=IconAlertCircle.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M9 12l2 2l4 -4\", \"key\": \"svg-1\" }]];\nconst IconCircleCheck = createReactComponent(\"outline\", \"circle-check\", \"CircleCheck\", __iconNode);\n\nexport { __iconNode, IconCircleCheck as default };\n//# sourceMappingURL=IconCircleCheck.mjs.map\n","import { type HTMLAttributes, type ReactNode, type Ref } from \"react\";\nimport {\n IconCircleCheck,\n IconInfoCircle,\n IconAlertCircle,\n IconX,\n type Icon,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../../utils/cn\";\nimport { resolveVariant, type VariantMap } from \"../../utils/resolve-variant\";\n\n/**\n * Design notes (Geist-aligned):\n * - ONE closed, semantic axis: `color`. It selects a status glyph *and* its\n * tint together — you never pick an icon and a color separately. This is the\n * `IconNotification` flavor from the app; the unused avatar/image variants of\n * the source family are intentionally dropped.\n * - The action row is a single reduced pair: a brand `confirmLabel` link beside\n * a gray dismiss link. It appears only when there's something to confirm.\n * - `onClose` is the only thing that renders the top-right close button — no\n * separate boolean flag to keep in sync.\n */\n\n/** Status color → icon tint. A bare status-tinted glyph, no badge surface. */\nexport const NOTIFICATION_COLORS = {\n brand: {\n classes: \"text-pho-brand\",\n description: \"Informational / product update (default)\",\n },\n gray: {\n classes: \"text-pho-secondary\",\n description: \"Neutral, low-stakes note\",\n },\n success: {\n classes: \"text-pho-success\",\n description: \"An action completed\",\n },\n warning: {\n classes: \"text-pho-warning\",\n description: \"Needs attention, not yet failed\",\n },\n error: {\n classes: \"text-pho-error\",\n description: \"Something went wrong\",\n },\n} satisfies VariantMap;\n\nexport type NotificationColor = keyof typeof NOTIFICATION_COLORS;\n\n/** Status color → glyph. Mirrors the source's `iconMap` semantics. */\nconst ICON_MAP = {\n brand: IconInfoCircle,\n gray: IconInfoCircle,\n success: IconCircleCheck,\n warning: IconAlertCircle,\n error: IconAlertCircle,\n} satisfies Record<NotificationColor, Icon>;\n\nexport interface NotificationProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"title\" | \"color\"\n> {\n /** Status color — selects the glyph and its tint. @default \"brand\" */\n color?: NotificationColor;\n /** Bold heading line. */\n title: ReactNode;\n /** Supporting line under the title. */\n description?: ReactNode;\n /** Confirm action label — renders a brand link paired with a dismiss link. */\n confirmLabel?: string;\n /** Called when the confirm link is clicked. */\n onConfirm?: () => void;\n /** Dismiss link label, shown beside the confirm link. @default \"Dismiss\" */\n dismissLabel?: string;\n /** Called on dismiss. Its presence also renders the top-right close button. */\n onClose?: () => void;\n /** Override the status glyph while keeping the color's tint. */\n icon?: Icon;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n}\n\nconst LINK_CLASS =\n \"cursor-pointer text-base font-medium outline-pho-brand transition duration-100 ease-linear focus-visible:outline-2 focus-visible:outline-offset-2\";\n\n/**\n * Notification — the standalone status card ported from the app's\n * `IconNotification`: a status glyph, a title/description, an optional\n * confirm+dismiss link pair, and an optional close button. It is a *card*, not a\n * lifecycle: it owns its surface but nothing about timing or stacking.\n *\n * For a transient, auto-stacking toast, drop it inside pho-ui's Base UI\n * {@link Toast} — render it as the child of a `Toast.Root` whose own surface you\n * neutralize (`className=\"bg-transparent p-0 shadow-none ring-0\"`) so the\n * manager owns motion and swipe while this card owns the look. For a choice the\n * user must make, use `Dialog` instead.\n */\nexport function Notification({\n color = \"brand\",\n title,\n description,\n confirmLabel,\n onConfirm,\n dismissLabel = \"Dismiss\",\n onClose,\n icon,\n className,\n ref,\n ...props\n}: NotificationProps) {\n const Glyph = icon ?? ICON_MAP[color];\n const showActions = Boolean(confirmLabel);\n\n return (\n <div\n ref={ref}\n {...props}\n className={cn(\n // Floating layer: keeps its shadow elevation, hairline card edge.\n \"ring-pho-secondary bg-pho-primary shadow-pho-lg rounded-base relative flex w-full max-w-sm gap-4 p-4 ring-1 ring-inset\",\n className,\n )}\n >\n <Glyph\n aria-hidden=\"true\"\n className={cn(\n \"mt-0.5 size-5 shrink-0\",\n resolveVariant(NOTIFICATION_COLORS, color),\n )}\n />\n\n <div className=\"flex flex-1 flex-col gap-3 pr-6\">\n <div className=\"flex flex-col gap-1\">\n <p className=\"text-pho-primary text-base font-medium\">{title}</p>\n {description != null && description !== false && (\n <p className=\"text-pho-description text-base\">{description}</p>\n )}\n </div>\n\n {showActions && (\n <div className=\"flex gap-4\">\n <button\n type=\"button\"\n onClick={onConfirm}\n className={cn(\n LINK_CLASS,\n // brand text is monochrome now — underline carries the hover.\n \"text-pho-brand hover:underline\",\n )}\n >\n {confirmLabel}\n </button>\n <button\n type=\"button\"\n onClick={onClose}\n className={cn(\n LINK_CLASS,\n \"text-pho-secondary hover:text-pho-secondary-hover\",\n )}\n >\n {dismissLabel}\n </button>\n </div>\n )}\n </div>\n\n {onClose && (\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Dismiss\"\n className=\"text-pho-secondary hover:text-pho-secondary-hover hover:bg-pho-ghost-hover outline-pho-brand absolute top-2.5 right-2.5 flex size-6 cursor-pointer items-center justify-center rounded-sm transition focus-visible:outline-2 [&>svg]:size-4\"\n >\n <IconX aria-hidden=\"true\" />\n </button>\n )}\n </div>\n );\n}\n\nNotification.displayName = \"Notification\";\n"],"x_google_ignoreList":[0,1],"mappings":";;;;;;;;AASA,IAAMA,IAAa;AAAA,EAAC,CAAC,QAAQ;AAAA,IAAE,GAAK;AAAA,IAAwC,KAAO;AAAA,EAAQ,CAAC;AAAA,EAAG,CAAC,QAAQ;AAAA,IAAE,GAAK;AAAA,IAAW,KAAO;AAAA,EAAQ,CAAC;AAAA,EAAG,CAAC,QAAQ;AAAA,IAAE,GAAK;AAAA,IAAc,KAAO;AAAA,EAAQ,CAAC;AAAC,GACtL,IAAkB,EAAqB,WAAW,gBAAgB,eAAeA,CAAU,GCD3F,IAAa,CAAC,CAAC,QAAQ;AAAA,EAAE,GAAK;AAAA,EAAwC,KAAO;AAAQ,CAAC,GAAG,CAAC,QAAQ;AAAA,EAAE,GAAK;AAAA,EAAkB,KAAO;AAAQ,CAAC,CAAC,GAC5I,IAAkB,EAAqB,WAAW,gBAAgB,eAAe,CAAU,GCcpF,IAAsB;AAAA,EACjC,OAAO;AAAA,IACL,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA,SAAS;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA,SAAS;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA,OAAO;AAAA,IACL,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AACF,GAKM,IAAW;AAAA,EACf,OAAO;AAAA,EACP,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAO;AACT,GA0BM,IACJ;AAcF,SAAgB,EAAa,EAC3B,OAAA,IAAQ,SACR,OAAA,GACA,aAAA,GACA,cAAA,GACA,WAAA,GACA,cAAA,IAAe,WACf,SAAA,GACA,MAAA,GACA,WAAA,GACA,KAAA,GACA,GAAG,EAAA,GACiB;AACpB,QAAM,IAAQ,KAAQ,EAAS,CAAA,GACzB,IAAc,EAAQ;AAE5B,SACE,gBAAA,EAAC,OAAD;AAAA,IACO,KAAA;AAAA,IACL,GAAI;AAAA,IACJ,WAAW,EAET,0HACA,CACF;AAAA,IAPF,UAAA;AAAA,MASE,gBAAA,EAAC,GAAD;AAAA,QACE,eAAY;AAAA,QACZ,WAAW,EACT,0BACA,EAAe,GAAqB,CAAK,CAC3C;AAAA,MACD,CAAA;AAAA,MAED,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,QAAf,UAAA,CACE,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UAAf,UAAA,CACE,gBAAA,EAAC,KAAD;AAAA,YAAG,WAAU;AAAA,YAA0C,UAAA;AAAA,UAAS,CAAA,GAC/D,KAAe,QAAQ,MAAgB,MACtC,gBAAA,EAAC,KAAD;AAAA,YAAG,WAAU;AAAA,YAAkC,UAAA;AAAA,UAAe,CAAA,CAE7D;AAAA,QAEJ,CAAA,GAAA,KACC,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UAAf,UAAA,CACE,gBAAA,EAAC,UAAD;AAAA,YACE,MAAK;AAAA,YACL,SAAS;AAAA,YACT,WAAW,EACT,GAEA,gCACF;AAAA,YAEC,UAAA;AAAA,UACK,CAAA,GACR,gBAAA,EAAC,UAAD;AAAA,YACE,MAAK;AAAA,YACL,SAAS;AAAA,YACT,WAAW,EACT,GACA,mDACF;AAAA,YAEC,UAAA;AAAA,UACK,CAAA,CACL;AAAA,QAEJ,CAAA,CAAA;AAAA;MAEJ,KACC,gBAAA,EAAC,UAAD;AAAA,QACE,MAAK;AAAA,QACL,SAAS;AAAA,QACT,cAAW;AAAA,QACX,WAAU;AAAA,QAEV,UAAA,gBAAA,EAAC,GAAD,EAAO,eAAY,OAAQ,CAAA;AAAA,MACrB,CAAA;AAAA,IAEP;AAAA;AAET;AAEA,EAAa,cAAc"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as n } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as n } from "../chunks/cn-ChIgwEl3.js";
3
3
  import "react";
4
4
  import { jsx as o } from "react/jsx-runtime";
5
5
  import { NumberField as t } from "@base-ui/react/number-field";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as e } from "../chunks/cn-DTiB6ek_.js";
2
+ import { t as e } from "../chunks/cn-ChIgwEl3.js";
3
3
  import "react";
4
4
  import { jsx as r } from "react/jsx-runtime";
5
5
  import { OTPField as t } from "@base-ui/react/otp-field";
@@ -1 +1 @@
1
- {"version":3,"file":"otp-field.js","names":[],"sources":["../../src/components/otp-field/otp-field.tsx"],"sourcesContent":["import { type ComponentProps } from \"react\";\nimport { OTPField as BaseOTPField } from \"@base-ui/react/otp-field\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface OtpFieldProps extends Omit<\n ComponentProps<typeof BaseOTPField.Root>,\n \"className\"\n> {\n /** Class applied to the cell row. */\n className?: string;\n /** Number of single-character cells. */\n length: number;\n}\n\n/**\n * One-time-code input built on Base UI `OTPField` — a row of single-character\n * cells with paste, arrow-key, and auto-advance handling. Control with `value`\n * / `onValueChange`, or read the completed code via `onValueChange`.\n */\nexport function OtpField({ className, length, ...props }: OtpFieldProps) {\n return (\n <BaseOTPField.Root\n length={length}\n className={cn(\"flex items-center gap-2\", className)}\n {...props}\n >\n {Array.from({ length }, (_, i) => (\n <BaseOTPField.Input\n key={i}\n className={cn(\n // Flat field surface — shadows are reserved for floating layers;\n // the 15% ring-pho-primary hairline carries the input edge.\n \"bg-pho-primary ring-pho-primary text-pho-primary rounded-base size-11 text-center text-lg font-medium ring-1 transition-shadow duration-100 ease-linear outline-none ring-inset\",\n \"focus-visible:ring-pho-brand focus-visible:ring-2\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n )}\n />\n ))}\n </BaseOTPField.Root>\n );\n}\n\nOtpField.displayName = \"OtpField\";\n"],"mappings":";;;;;AAmBA,SAAgB,EAAS,EAAE,WAAA,GAAW,QAAA,GAAQ,GAAG,EAAA,GAAwB;AACvE,SACE,gBAAA,EAAC,EAAa,MAAd;AAAA,IACU,QAAA;AAAA,IACR,WAAW,EAAG,2BAA2B,CAAS;AAAA,IAClD,GAAI;AAAA,cAEH,MAAM,KAAK,EAAE,QAAA,EAAO,GAAA,CAAI,GAAG,MAC1B,gBAAA,EAAC,EAAa,OAAd,EAEE,WAAW,EAGT,mLACA,qDACA,+DACF,EACD,GARM,CAQN,CACF;AAAA,EACgB,CAAA;AAEvB;AAEA,EAAS,cAAc"}
1
+ {"version":3,"file":"otp-field.js","names":[],"sources":["../../src/components/otp-field/otp-field.tsx"],"sourcesContent":["import { type ComponentProps } from \"react\";\nimport { OTPField as BaseOTPField } from \"@base-ui/react/otp-field\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface OtpFieldProps extends Omit<\n ComponentProps<typeof BaseOTPField.Root>,\n \"className\"\n> {\n /** Class applied to the cell row. */\n className?: string;\n /** Number of single-character cells. */\n length: number;\n}\n\n/**\n * One-time-code input built on Base UI `OTPField` — a row of single-character\n * cells with paste, arrow-key, and auto-advance handling. Control with `value`\n * / `onValueChange`, or read the completed code via `onValueChange`.\n */\nexport function OtpField({ className, length, ...props }: OtpFieldProps) {\n return (\n <BaseOTPField.Root\n length={length}\n className={cn(\"flex items-center gap-2\", className)}\n {...props}\n >\n {Array.from({ length }, (_, i) => (\n <BaseOTPField.Input\n key={i}\n className={cn(\n // Flat field surface — shadows are reserved for floating layers;\n // the 15% ring-pho-primary hairline carries the input edge.\n \"bg-pho-primary ring-pho-primary text-pho-primary rounded-base size-11 text-center text-lg font-medium ring-1 transition-shadow duration-100 ease-linear outline-none ring-inset\",\n \"focus-visible:ring-pho-brand focus-visible:ring-2\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n )}\n />\n ))}\n </BaseOTPField.Root>\n );\n}\n\nOtpField.displayName = \"OtpField\";\n"],"mappings":";;;;;AAmBA,SAAgB,EAAS,EAAE,WAAA,GAAW,QAAA,GAAQ,GAAG,EAAA,GAAwB;AACvE,SACE,gBAAA,EAAC,EAAa,MAAd;AAAA,IACU,QAAA;AAAA,IACR,WAAW,EAAG,2BAA2B,CAAS;AAAA,IAClD,GAAI;AAAA,IAEH,UAAA,MAAM,KAAK,EAAE,QAAA,EAAO,GAAA,CAAI,GAAG,MAC1B,gBAAA,EAAC,EAAa,OAAd,EAEE,WAAW,EAGT,mLACA,qDACA,+DACF,EACD,GARM,CAQN,CACF;AAAA,EACgB,CAAA;AAEvB;AAEA,EAAS,cAAc"}