@keboola/design 11.6.0 → 11.9.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 (162) hide show
  1. package/AGENTS.md +16 -1
  2. package/CHANGELOG.md +92 -0
  3. package/COMPONENT-API.md +47 -46
  4. package/README.md +1 -1
  5. package/dist/{AIKit-BExvt9pt.js → AIKit-ELIsegJz.js} +551 -104
  6. package/dist/AIKit-ELIsegJz.js.map +1 -0
  7. package/dist/{Alert-Ba5b2YPq.js → Alert-BsIM_oFK.js} +2 -2
  8. package/dist/{Alert-Ba5b2YPq.js.map → Alert-BsIM_oFK.js.map} +1 -1
  9. package/dist/{Badge-D0pXdekt.js → Badge-o5jURtpB.js} +2 -2
  10. package/dist/{Badge-D0pXdekt.js.map → Badge-o5jURtpB.js.map} +1 -1
  11. package/dist/{BrandEditor-CSANsxUz.js → BrandEditor-BsTBM3s6.js} +5 -5
  12. package/dist/{BrandEditor-CSANsxUz.js.map → BrandEditor-BsTBM3s6.js.map} +1 -1
  13. package/dist/{Breadcrumb-g_xn_-Nf.js → Breadcrumb-xqEUxfwn.js} +2 -2
  14. package/dist/{Breadcrumb-g_xn_-Nf.js.map → Breadcrumb-xqEUxfwn.js.map} +1 -1
  15. package/dist/{Checkbox-CUIn2jap.js → Checkbox-Dq5fPNrO.js} +2 -2
  16. package/dist/{Checkbox-CUIn2jap.js.map → Checkbox-Dq5fPNrO.js.map} +1 -1
  17. package/dist/{Clipboard-BTW6C-b_.js → Clipboard-BZitKiSA.js} +2 -2
  18. package/dist/{Clipboard-BTW6C-b_.js.map → Clipboard-BZitKiSA.js.map} +1 -1
  19. package/dist/{ClipboardButton-CwZJdRaz.js → ClipboardButton-KHQnPEh_.js} +2 -2
  20. package/dist/{ClipboardButton-CwZJdRaz.js.map → ClipboardButton-KHQnPEh_.js.map} +1 -1
  21. package/dist/{CodeEditor-C9zy7PxK.js → CodeEditor-BJKJXA0c.js} +4 -4
  22. package/dist/{CodeEditor-C9zy7PxK.js.map → CodeEditor-BJKJXA0c.js.map} +1 -1
  23. package/dist/{ColorInput-BZV-u_94.js → ColorInput-Bj3dfPFA.js} +3 -3
  24. package/dist/{ColorInput-BZV-u_94.js.map → ColorInput-Bj3dfPFA.js.map} +1 -1
  25. package/dist/{ColorModeSwitch-CsWLiTBX.js → ColorModeSwitch-CWt-DZGC.js} +2 -2
  26. package/dist/{ColorModeSwitch-CsWLiTBX.js.map → ColorModeSwitch-CWt-DZGC.js.map} +1 -1
  27. package/dist/{Combobox-BfIfaVMA.js → Combobox-D8PrEqTG.js} +4 -4
  28. package/dist/{Combobox-BfIfaVMA.js.map → Combobox-D8PrEqTG.js.map} +1 -1
  29. package/dist/{Command-Bfa1kpbt.js → Command-BDU3C1gg.js} +2 -2
  30. package/dist/{Command-Bfa1kpbt.js.map → Command-BDU3C1gg.js.map} +1 -1
  31. package/dist/{CopyField-DpT0Ngz1.js → CopyField-BHRQUyuF.js} +2 -2
  32. package/dist/{CopyField-DpT0Ngz1.js.map → CopyField-BHRQUyuF.js.map} +1 -1
  33. package/dist/{DateInput-DiEd5uCL.js → DateInput-B6N8g0ra.js} +3 -3
  34. package/dist/{DateInput-DiEd5uCL.js.map → DateInput-B6N8g0ra.js.map} +1 -1
  35. package/dist/{DateRangeInput-DPfVYchl.js → DateRangeInput-7M9Z4cVO.js} +3 -3
  36. package/dist/{DateRangeInput-DPfVYchl.js.map → DateRangeInput-7M9Z4cVO.js.map} +1 -1
  37. package/dist/{DropdownMenu-CASr-jgl.js → DropdownMenu-CgVwhDvl.js} +9 -4
  38. package/dist/DropdownMenu-CgVwhDvl.js.map +1 -0
  39. package/dist/{FieldItem-B7XMmZSz.js → FieldItem-DZGIdiXE.js} +3 -3
  40. package/dist/{FieldItem-B7XMmZSz.js.map → FieldItem-DZGIdiXE.js.map} +1 -1
  41. package/dist/{FileUpload-ABThVZyg.js → FileUpload-DYQCTGjU.js} +3 -3
  42. package/dist/{FileUpload-ABThVZyg.js.map → FileUpload-DYQCTGjU.js.map} +1 -1
  43. package/dist/{Form-CsttTHn4.js → Form-CcK7dRrC.js} +5 -5
  44. package/dist/{Form-CsttTHn4.js.map → Form-CcK7dRrC.js.map} +1 -1
  45. package/dist/{FormGroup-DHvTFdno.js → FormGroup-DR_gZ25-.js} +3 -3
  46. package/dist/{FormGroup-DHvTFdno.js.map → FormGroup-DR_gZ25-.js.map} +1 -1
  47. package/dist/{InputGroup-DcZRlVnN.js → InputGroup-Do8K2hvD.js} +2 -1
  48. package/dist/InputGroup-Do8K2hvD.js.map +1 -0
  49. package/dist/{Kbd-Cvvt91Q8.js → Kbd-LCFMumoq.js} +2 -2
  50. package/dist/{Kbd-Cvvt91Q8.js.map → Kbd-LCFMumoq.js.map} +1 -1
  51. package/dist/{MermaidDiagram-DSI7xMu2.js → MermaidDiagram-ZG0iiDV_.js} +2 -2
  52. package/dist/{MermaidDiagram-DSI7xMu2.js.map → MermaidDiagram-ZG0iiDV_.js.map} +1 -1
  53. package/dist/{Modal-Coj-H02o.js → Modal-I3VWk2oo.js} +2 -2
  54. package/dist/{Modal-Coj-H02o.js.map → Modal-I3VWk2oo.js.map} +1 -1
  55. package/dist/{ModalTitle-C76ke2eo.js → ModalTitle-CeLM_mX9.js} +2 -2
  56. package/dist/ModalTitle-CeLM_mX9.js.map +1 -0
  57. package/dist/{MultiActionButtonGroup-DokHbPgM.js → MultiActionButtonGroup-CYZ8IgSf.js} +2 -2
  58. package/dist/{MultiActionButtonGroup-DokHbPgM.js.map → MultiActionButtonGroup-CYZ8IgSf.js.map} +1 -1
  59. package/dist/{PageToolbar-DExqEYGl.js → PageToolbar-BKVJiDAL.js} +2 -2
  60. package/dist/{PageToolbar-DExqEYGl.js.map → PageToolbar-BKVJiDAL.js.map} +1 -1
  61. package/dist/{RadioGroup-DXPbSj8P.js → RadioGroup-Byc2mym4.js} +2 -2
  62. package/dist/{RadioGroup-DXPbSj8P.js.map → RadioGroup-Byc2mym4.js.map} +1 -1
  63. package/dist/{Search-5uQAiNIP.js → Search-Dhig_hPD.js} +2 -2
  64. package/dist/{Search-5uQAiNIP.js.map → Search-Dhig_hPD.js.map} +1 -1
  65. package/dist/{SearchInput-D4UgAXJK.js → SearchInput-92r2bkA7.js} +3 -3
  66. package/dist/{SearchInput-D4UgAXJK.js.map → SearchInput-92r2bkA7.js.map} +1 -1
  67. package/dist/{SectionNav-OkKCjSA-.js → SectionNav-CNLJsiVG.js} +4 -4
  68. package/dist/{SectionNav-OkKCjSA-.js.map → SectionNav-CNLJsiVG.js.map} +1 -1
  69. package/dist/{Sheet-Chf0kX1E.js → Sheet-OparjIi-.js} +2 -2
  70. package/dist/{Sheet-Chf0kX1E.js.map → Sheet-OparjIi-.js.map} +1 -1
  71. package/dist/{Sidebar-D3cY1kha.js → Sidebar-CLEbBtNY.js} +190 -25
  72. package/dist/Sidebar-CLEbBtNY.js.map +1 -0
  73. package/dist/{Slider-CRf-bB4y.js → Slider-DLclvRws.js} +2 -2
  74. package/dist/{Slider-CRf-bB4y.js.map → Slider-DLclvRws.js.map} +1 -1
  75. package/dist/{TextInput-DH5SkbsE.js → TextInput-CFTf4Cz1.js} +5 -4
  76. package/dist/TextInput-CFTf4Cz1.js.map +1 -0
  77. package/dist/{ThemeProvider-2RMdVGxO.js → ThemeProvider-DAmNn9Sd.js} +2 -2
  78. package/dist/{ThemeProvider-2RMdVGxO.js.map → ThemeProvider-DAmNn9Sd.js.map} +1 -1
  79. package/dist/{Timeline-BG5Xogxh.js → Timeline-C8-wnRRr.js} +2 -2
  80. package/dist/{Timeline-BG5Xogxh.js.map → Timeline-C8-wnRRr.js.map} +1 -1
  81. package/dist/{ZoomableSvg-pooPb1Cu.js → ZoomableSvg-BZlk3PFJ.js} +3 -3
  82. package/dist/{ZoomableSvg-pooPb1Cu.js.map → ZoomableSvg-BZlk3PFJ.js.map} +1 -1
  83. package/dist/editors.js +2 -2
  84. package/dist/flint.js +1 -1
  85. package/dist/index.d.ts +900 -561
  86. package/dist/index.js +39 -37
  87. package/dist/internal/blocks/AIKit.js +2 -2
  88. package/dist/internal/blocks/BrandEditor.js +1 -1
  89. package/dist/internal/blocks/ChipEditor.js +137 -0
  90. package/dist/internal/blocks/ChipEditor.js.map +1 -0
  91. package/dist/internal/blocks/ClipboardButton.js +1 -1
  92. package/dist/internal/blocks/ColorInput.js +1 -1
  93. package/dist/internal/blocks/ColorModeSwitch.js +1 -1
  94. package/dist/internal/blocks/Command.js +1 -1
  95. package/dist/internal/blocks/CopyField.js +1 -1
  96. package/dist/internal/blocks/DateInput.js +1 -1
  97. package/dist/internal/blocks/DateRangeInput.js +1 -1
  98. package/dist/internal/blocks/ExportMenu.js +2 -2
  99. package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +1 -1
  100. package/dist/internal/blocks/Form.js +1 -1
  101. package/dist/internal/blocks/FormGroup.js +1 -1
  102. package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
  103. package/dist/internal/blocks/MultiCombobox.js +18 -28
  104. package/dist/internal/blocks/MultiCombobox.js.map +1 -1
  105. package/dist/internal/blocks/NumberInput.js +1 -1
  106. package/dist/internal/blocks/PageToolbar.js +1 -1
  107. package/dist/internal/blocks/PasswordInput.js +2 -2
  108. package/dist/internal/blocks/SearchInput.js +1 -1
  109. package/dist/internal/blocks/SearchInputWithNavigation.js +2 -2
  110. package/dist/internal/blocks/SectionNav.js +1 -1
  111. package/dist/internal/blocks/SplitButton.js +1 -1
  112. package/dist/internal/blocks/TextInput.js +1 -1
  113. package/dist/internal/blocks/Textarea.js +1 -1
  114. package/dist/internal/blocks/TimeInput.js +2 -2
  115. package/dist/internal/components/Alert.js +1 -1
  116. package/dist/internal/components/Avatar.js +1 -1
  117. package/dist/internal/components/Badge.js +1 -1
  118. package/dist/internal/components/Breadcrumb.js +1 -1
  119. package/dist/internal/components/Checkbox.js +1 -1
  120. package/dist/internal/components/Clipboard.js +1 -1
  121. package/dist/internal/components/CollapsiblePanel.js +1 -1
  122. package/dist/internal/components/Combobox.js +1 -1
  123. package/dist/internal/components/DropdownMenu.js +1 -1
  124. package/dist/internal/components/FileUpload.js +1 -1
  125. package/dist/internal/components/InputGroup.js +1 -1
  126. package/dist/internal/components/Kbd.js +1 -1
  127. package/dist/internal/components/Modal.js +1 -1
  128. package/dist/internal/components/RadioGroup.js +1 -1
  129. package/dist/internal/components/Search.js +1 -1
  130. package/dist/internal/components/Sheet.js +1 -1
  131. package/dist/internal/components/Sidebar.js +1 -1
  132. package/dist/internal/components/Slider.js +1 -1
  133. package/dist/internal/components/StatusDot.js +67 -0
  134. package/dist/internal/components/StatusDot.js.map +1 -0
  135. package/dist/internal/components/ThemeProvider.js +1 -1
  136. package/dist/internal/components/Timeline.js +1 -1
  137. package/dist/internal/components/Tooltip.js +2 -2
  138. package/dist/internal/components/Truncated.js +1 -1
  139. package/dist/internal/components/ZoomableSvg.js +1 -1
  140. package/dist/internal/hooks/useScrollbarPosition.js +1 -1
  141. package/dist/internal/utils/mergeRefs.js +27 -9
  142. package/dist/internal/utils/mergeRefs.js.map +1 -1
  143. package/dist/internal/utils.js +2 -2
  144. package/dist/markdown-editor.js +5 -5
  145. package/dist/mermaid.js +1 -1
  146. package/dist/rjsf.js +9 -9
  147. package/dist/styles.css +1 -1
  148. package/dist/testing.js +1 -1
  149. package/dist/useElement-BK3AAiIf.js +24 -0
  150. package/dist/useElement-BK3AAiIf.js.map +1 -0
  151. package/dist/{utils-DSvrhU8E.js → utils-BW4AE8VP.js} +33 -7
  152. package/dist/utils-BW4AE8VP.js.map +1 -0
  153. package/package.json +14 -13
  154. package/dist/AIKit-BExvt9pt.js.map +0 -1
  155. package/dist/DropdownMenu-CASr-jgl.js.map +0 -1
  156. package/dist/InputGroup-DcZRlVnN.js.map +0 -1
  157. package/dist/ModalTitle-C76ke2eo.js.map +0 -1
  158. package/dist/Sidebar-D3cY1kha.js.map +0 -1
  159. package/dist/TextInput-DH5SkbsE.js.map +0 -1
  160. package/dist/useElement-DkF6esWL.js +0 -15
  161. package/dist/useElement-DkF6esWL.js.map +0 -1
  162. package/dist/utils-DSvrhU8E.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Modal-Coj-H02o.js","names":[],"sources":["../src/components/Modal/ModalBody.tsx","../src/components/Modal/ModalContent.tsx","../src/components/Modal/ModalFooter.tsx","../src/components/Modal/ModalActions.tsx","../src/components/Modal/ModalHeader.tsx","../src/components/Modal/ModalIcon.tsx","../src/components/Modal/ModalImage.tsx","../src/components/Modal/Modal.tsx"],"sourcesContent":["import type { ComponentProps } from 'react';\n\nimport { cn } from '../../utils';\n\n/** Props for `Modal.Body`. Accepts all `<div>` attributes; `as=\"form\"` is reserved for future use. */\ntype Props = ComponentProps<'div'> & {\n as?: 'form';\n};\n\n/**\n * Scrollable body slot for `Modal`. Place form fields, content blocks, or detail panels here.\n * Takes available height inside `Modal.Content` and scrolls when content overflows.\n */\nexport const ModalBody = ({ className, ...props }: Props) => (\n <div\n data-slot=\"modal-body\"\n className={cn(\n // scrollable body - takes available space and scrolls when content overflows\n 'tw:flex-1',\n 'tw:overflow-y-auto',\n\n // argo: soft top/bottom edge fade in place of header/footer separators (pure-CSS utility)\n 'tw:group-data-[argo=true]/modal:scroll-fade-y',\n\n // Own horizontal padding, matching Header/Footer so content edges align (ModalContent adds none)\n 'tw:group-data-[argo=false]/modal:px-7',\n 'tw:group-data-[argo=true]/modal:px-4',\n 'tw:py-1',\n\n // normalize nested Lucide icon sizing, matching Popover/HoverCard/Alert content surfaces\n \"tw:[&_svg.lucide:not([class*='tw:size-'])]:size-4\",\n 'tw:[&_svg]:shrink-0',\n className,\n )}\n {...props}\n />\n);\n","import type { ComponentProps } from 'react';\nimport { Content, Portal } from '@radix-ui/react-dialog';\n\nimport { cn } from '../../utils';\nimport { useArgoDesign } from '../ThemeProvider/context';\n\nimport { ModalOverlay } from './ModalOverlay';\n\ntype Props = ComponentProps<typeof Content> & {\n size?: 'small' | 'medium' | 'large';\n};\n\nexport const ModalContent = ({\n size = 'medium',\n className,\n children,\n onEscapeKeyDown,\n ...props\n}: Props) => {\n const renderArgo = useArgoDesign();\n\n const handleEscapeKeyDown: typeof onEscapeKeyDown = (event) => {\n // Stop propagation to prevent parent modals (like FullScreenModal) from closing\n event.stopPropagation();\n onEscapeKeyDown?.(event);\n };\n\n return (\n <Portal>\n <ModalOverlay>\n <Content\n // props first so callers can't override the computed data-argo / data-size\n {...props}\n data-argo={renderArgo}\n data-size={size}\n className={cn(\n 'tailwindcss-preflight',\n 'tw:group/modal',\n\n // positioning - horizontally centered; vertical anchor depends on the design language\n 'tw:fixed',\n 'tw:left-1/2',\n 'tw:-translate-x-1/2',\n 'tw:z-[1051]',\n\n // legacy: anchored near the top; argo: centered in the viewport (like AlertModal)\n 'tw:data-[argo=false]:top-20',\n 'tw:data-[argo=true]:top-1/2',\n 'tw:data-[argo=true]:-translate-y-1/2',\n\n // sizing - responsive max dimensions\n 'tw:w-full',\n 'tw:max-w-2xl',\n 'tw:max-h-[calc(100vh-2*theme(spacing.20))]',\n\n // layout\n 'tw:flex',\n 'tw:flex-col',\n 'tw:gap-4',\n 'tw:data-[argo=false]:rounded-lg',\n 'tw:data-[argo=true]:rounded-3xl',\n 'tw:bg-card',\n 'tw:text-card-foreground',\n\n // Vertical (edge) padding lives here so it survives an omitted Header or Footer.\n // Horizontal padding is owned by Header / Body / Footer, so the Body runs full-bleed and\n // its scrollbar sits at the modal edge (see ModalBody).\n 'tw:data-[argo=false]:py-8',\n 'tw:data-[argo=true]:py-4',\n\n // animation — shared\n 'tw:duration-200',\n 'tw:data-[state=open]:animate-in',\n 'tw:data-[state=open]:fade-in-0',\n 'tw:data-[state=closed]:animate-out',\n 'tw:data-[state=closed]:fade-out-0',\n\n // NOTE: no `slide-*-left-1/2` (both) or argo `slide-*-top-1/2`. Those re-pinned the\n // -50%/-50% centring during the animation under v3, where centring and the animation\n // shared the `transform` property (the animation overrode it). Under v4 the centring\n // uses the `translate` PROPERTY while tw-animate-css animates `transform` — they compose\n // instead of overriding, so a -50% enter-translate stacks on the -50% centring (= -100%)\n // and the modal flies in from the top-left. Centring now persists on its own, so we\n // animate transform-only (zoom + fade) and the modal stays put.\n\n // legacy: slide-down + zoom (top-anchored via `top-20`, so no `translate-y` to double)\n 'tw:data-[argo=false]:data-[state=open]:zoom-in-80',\n 'tw:data-[argo=false]:data-[state=open]:slide-in-from-top-[48%]',\n 'tw:data-[argo=false]:data-[state=closed]:zoom-out-80',\n 'tw:data-[argo=false]:data-[state=closed]:slide-out-to-top-[48%]',\n\n // argo: pop from the centre — zoom only\n 'tw:data-[argo=true]:data-[state=open]:zoom-in-95',\n 'tw:data-[argo=true]:data-[state=closed]:zoom-out-95',\n\n {\n 'tw:max-w-[480px]': size === 'small',\n 'tw:max-w-4xl': size === 'large',\n },\n\n className,\n )}\n onEscapeKeyDown={handleEscapeKeyDown}\n >\n {children}\n </Content>\n </ModalOverlay>\n </Portal>\n );\n};\n","import type { ComponentPropsWithRef } from 'react';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentPropsWithRef<'div'>;\n\n/**\n * The modal's action row.\n *\n * - Right-aligns its children in a row, 8px apart, at their natural height.\n * - Imposes no width on its children: one that should fill the row carries `tw:w-full` itself\n * (`Button block`, `ButtonGroup variant=\"block\"`). Passing `tw:w-full` to the footer does\n * nothing — it already stretches to the modal's width as a `ModalContent` flex item.\n * - Owns the horizontal padding; `ModalContent` owns the vertical edge padding.\n * - Overriding the arrangement means passing the conflicting class: `cn` runs tailwind-merge, which\n * displaces only within a group. `tw:justify-between` replaces `justify-end`; `tw:flex-col`\n * leaves `items-center` and the gap in place, so a stacked footer wants `tw:items-stretch` too.\n */\nexport const ModalFooter = ({ className, ...props }: Props) => (\n <div\n {...props}\n className={cn(\n 'tw:flex',\n 'tw:items-center',\n 'tw:justify-end',\n 'tw:gap-2',\n\n // Own horizontal padding (ModalContent owns the vertical edge padding)\n 'tw:group-data-[argo=false]/modal:px-7',\n 'tw:group-data-[argo=true]/modal:px-4',\n className,\n )}\n />\n);\n","import type { ComponentProps } from 'react';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentProps<'div'>;\n\n/**\n * Container for the header's top-right controls — any `actions` passed to `Modal.Header` plus the\n * close icon. Sits in the header grid's last column, top-aligned. Mirrors `Alert`'s action slot.\n */\nexport const ModalActions = ({ className, ...props }: Props) => (\n <div\n className={cn(\n 'tw:col-start-3',\n 'tw:row-start-1',\n 'tw:self-start',\n 'tw:flex',\n 'tw:items-center',\n 'tw:gap-1',\n // argo: gutter separating the actions/close from the title (carried here so the grid needs no\n // column gap — see ModalHeader)\n 'tw:group-data-[argo=true]/modal:ml-3',\n className,\n )}\n {...props}\n />\n);\n","import type { ComponentProps, ReactNode } from 'react';\nimport { Close } from '@radix-ui/react-dialog';\n\nimport { X } from '../../icons';\nimport { cn } from '../../utils';\nimport { Button } from '../Button';\nimport { Separator } from '../Separator';\n\nimport { ModalActions } from './ModalActions';\nimport { ModalDescription } from './ModalDescription';\nimport { ModalTitle } from './ModalTitle';\n\ntype Props = {\n /** Status icon slot — `<Modal.Icon />` or `<Modal.Image />`. */\n icon?: ReactNode;\n /** Visible subtitle below the title (also fills `aria-describedby`). */\n description?: ReactNode;\n /** Screen-reader-only description; fills `aria-describedby` without rendering visibly. */\n 'aria-description'?: string;\n /** Controls rendered top-right, before the close icon. */\n actions?: ReactNode;\n /** Hide the top-right close icon. */\n hideCloseIcon?: boolean;\n} & ComponentProps<'div'>;\n\n/** Modal header: `[icon] | title (children) | actions + close` on row 1, `description` on row 2. */\nexport const ModalHeader = ({\n className,\n icon,\n description,\n 'aria-description': ariaDescription,\n actions,\n hideCloseIcon = false,\n children,\n ...props\n}: Props) => (\n <div\n {...props}\n data-slot=\"modal-header\"\n className={cn(\n 'tw:grid',\n 'tw:grid-cols-[auto_1fr_auto]',\n 'tw:items-center',\n 'tw:group-data-[argo=false]/modal:px-7',\n 'tw:group-data-[argo=true]/modal:px-4',\n className,\n )}\n >\n {icon}\n\n {children && <ModalTitle className=\"tw:col-start-2 tw:row-start-1\">{children}</ModalTitle>}\n {(actions || !hideCloseIcon) && (\n <ModalActions>\n {actions}\n {!hideCloseIcon && (\n <Close asChild>\n <Button variant=\"invisible\" size=\"icon-sm\">\n <X />\n <span className=\"tw:sr-only\">Close</span>\n </Button>\n </Close>\n )}\n </ModalActions>\n )}\n {(description || ariaDescription) && (\n <ModalDescription\n className={cn(\n 'tw:col-start-1',\n 'tw:col-end-4',\n 'tw:row-start-2',\n description ? 'tw:mt-1' : 'tw:sr-only',\n )}\n >\n {description ?? ariaDescription}\n </ModalDescription>\n )}\n\n {/* Legacy-only separator; shown when a Body follows, hidden when that body hosts Tabs. */}\n <div\n className={cn(\n 'tw:col-start-1',\n 'tw:col-end-4',\n 'tw:mt-5',\n 'tw:hidden',\n 'tw:group-data-[argo=false]/modal:[[data-slot=modal-header]:has(~[data-slot=modal-body])_&]:block',\n 'tw:group-data-[argo=false]/modal:[[data-slot=modal-header]:has(~[data-slot=modal-body]_[data-slot=tabs-root])_&]:!hidden',\n )}\n >\n <Separator orientation=\"horizontal\" />\n </div>\n </div>\n);\n","import type { ReactNode } from 'react';\n\nimport { cn } from '../../utils';\n\ntype NamedColor = 'orange' | 'blue' | 'red' | 'green' | 'gray' | 'violet';\n\ntype Props = {\n color: NamedColor | (string & {});\n icon: ReactNode;\n};\n\nconst NAMED_COLORS = new Set<string>(['orange', 'blue', 'red', 'green', 'gray', 'violet']);\n\n/**\n * Status-coloured icon for `Modal`. Authored inside `Modal.Header`. For a remote image badge (a\n * component or backend logo fetched by URL) use `Modal.Image` instead.\n *\n * - **Legacy anatomy:** a solid-filled circular badge docked to the top-left of `Modal.Content`\n * (absolutely positioned, so it renders identically wherever it is authored).\n * - **Argo anatomy** (`data-argo` on `Modal.Content`): a small soft-tinted inline badge in the\n * header grid, next to the title.\n *\n * Both variants are rendered and toggled purely via CSS (`group-data-[argo=true]/modal:`) — no\n * context. Use the categorical `color` (`red` destructive, `orange` warning, `green` success,\n * `blue` info, `gray` neutral, `violet` agent) to encode meaning; the palette stays fixed across\n * brand themes.\n */\nexport const ModalIcon = ({ color, icon }: Props) => {\n const customColor = color && !NAMED_COLORS.has(color) ? color : undefined;\n\n return (\n <span\n data-slot=\"modal-icon\"\n className={cn(\n 'tw:flex',\n 'tw:shrink-0',\n 'tw:items-center',\n 'tw:justify-center',\n 'tw:[&_svg]:aspect-square',\n\n // legacy: solid-filled circular badge floating at the modal's top-left\n 'tw:group-data-[argo=false]/modal:absolute',\n 'tw:group-data-[argo=false]/modal:top-0',\n 'tw:group-data-[argo=false]/modal:left-8',\n 'tw:group-data-[argo=false]/modal:-translate-y-1/2',\n 'tw:group-data-[argo=false]/modal:size-12',\n 'tw:group-data-[argo=false]/modal:rounded-full',\n 'tw:group-data-[argo=false]/modal:[&_svg:not([class*=\"tw:size-\"])]:size-6',\n\n // argo: soft-tinted inline badge in the header grid's first column\n 'tw:group-data-[argo=true]/modal:col-start-1',\n 'tw:group-data-[argo=true]/modal:row-start-1',\n 'tw:group-data-[argo=true]/modal:self-start',\n 'tw:group-data-[argo=true]/modal:mr-3',\n 'tw:group-data-[argo=true]/modal:size-8',\n 'tw:group-data-[argo=true]/modal:rounded',\n 'tw:group-data-[argo=true]/modal:overflow-hidden',\n 'tw:group-data-[argo=true]/modal:[&_svg:not([class*=\"tw:size-\"])]:size-5',\n\n // legacy palette: solid fill + white glyph (violet is the exception — tinted)\n {\n 'tw:group-data-[argo=false]/modal:bg-warning-500': color === 'orange',\n 'tw:group-data-[argo=false]/modal:bg-blue-500': color === 'blue',\n 'tw:group-data-[argo=false]/modal:bg-green-500': color === 'green',\n 'tw:group-data-[argo=false]/modal:bg-error-500': color === 'red',\n 'tw:group-data-[argo=false]/modal:bg-neutral-150': color === 'gray',\n 'tw:group-data-[argo=false]/modal:bg-purple-100': color === 'violet',\n 'tw:group-data-[argo=false]/modal:text-white': color !== 'violet',\n 'tw:group-data-[argo=false]/modal:text-purple-500': color === 'violet',\n },\n\n // argo palette: soft tint + matching glyph colour\n {\n 'tw:group-data-[argo=true]/modal:bg-warning-100 tw:group-data-[argo=true]/modal:text-warning-500':\n color === 'orange',\n 'tw:group-data-[argo=true]/modal:bg-blue-100 tw:group-data-[argo=true]/modal:text-blue-600':\n color === 'blue',\n 'tw:group-data-[argo=true]/modal:bg-green-100 tw:group-data-[argo=true]/modal:text-green-900':\n color === 'green',\n 'tw:group-data-[argo=true]/modal:bg-error-100 tw:group-data-[argo=true]/modal:text-error-500':\n color === 'red',\n 'tw:group-data-[argo=true]/modal:bg-neutral-100 tw:group-data-[argo=true]/modal:text-neutral-500':\n color === 'gray',\n 'tw:group-data-[argo=true]/modal:bg-purple-100 tw:group-data-[argo=true]/modal:text-purple-500':\n color === 'violet',\n },\n\n // custom (non-named) colour: caller-provided fill + white glyph\n { 'tw:text-white': !!customColor },\n )}\n style={customColor ? { backgroundColor: customColor } : undefined}\n >\n {icon}\n </span>\n );\n};\n","import { useEffect, useState } from 'react';\n\nimport { cn } from '../../utils';\n\ntype Props = {\n src: string;\n /** Accessible alt text. Defaults to `\"\"` (decorative) — provide it when the image carries meaning. */\n alt?: string;\n};\n\nexport const ModalImage = ({ src, alt = '' }: Props) => {\n const [hasImageError, setHasImageError] = useState(false);\n\n // Reset the error state when the source changes, so a reused badge (new logo, or a retry after a\n // transient failure) isn't permanently hidden by an earlier onError.\n useEffect(() => setHasImageError(false), [src]);\n\n if (hasImageError) return null;\n\n return (\n <span\n data-slot=\"modal-image\"\n className={cn(\n 'tw:shrink-0',\n 'tw:overflow-hidden',\n\n // legacy: circular badge floating at the top-left of the modal\n 'tw:group-data-[argo=false]/modal:absolute',\n 'tw:group-data-[argo=false]/modal:top-0',\n 'tw:group-data-[argo=false]/modal:left-8',\n 'tw:group-data-[argo=false]/modal:-translate-y-1/2',\n 'tw:group-data-[argo=false]/modal:size-12',\n 'tw:group-data-[argo=false]/modal:rounded-full',\n\n // argo: inline badge in the header grid's first column\n 'tw:group-data-[argo=true]/modal:flex',\n 'tw:group-data-[argo=true]/modal:col-start-1',\n 'tw:group-data-[argo=true]/modal:row-start-1',\n 'tw:group-data-[argo=true]/modal:self-start',\n 'tw:group-data-[argo=true]/modal:mr-3',\n 'tw:group-data-[argo=true]/modal:items-center',\n 'tw:group-data-[argo=true]/modal:justify-center',\n 'tw:group-data-[argo=true]/modal:rounded',\n 'tw:group-data-[argo=true]/modal:size-8',\n )}\n >\n <img\n src={src}\n alt={alt}\n className=\"tw:size-full tw:object-contain\"\n onError={() => setHasImageError(true)}\n />\n </span>\n );\n};\n","import type { ComponentProps } from 'react';\nimport { Close, Root, Trigger } from '@radix-ui/react-dialog';\n\nimport { ModalBody } from './ModalBody';\nimport { ModalContent } from './ModalContent';\nimport { ModalFooter } from './ModalFooter';\nimport { ModalHeader } from './ModalHeader';\nimport { ModalIcon } from './ModalIcon';\nimport { ModalImage } from './ModalImage';\nimport { ModalOverlay } from './ModalOverlay';\n\ntype Props = ComponentProps<typeof Root>;\n\n/**\n * Blocking dialog for confirmations, forms, and detail views. Built on Radix Dialog.\n *\n * **When to use:** the user must act before continuing (confirm a destructive action, fill a short form,\n * view a focused detail panel). Use the compound parts `Modal.Trigger`, `Modal.Content`, `Modal.Header`,\n * `Modal.Body`, `Modal.Footer`, and optionally `Modal.Icon` for a status-coloured header glyph.\n * **When NOT to use:** for slide-in side editing use `Sheet`; for an inline destructive confirmation anchored\n * to its trigger use `Popconfirm`; for hover previews use `HoverCard`.\n * **Composition:** wrap `Modal.Content` around `Modal.Header` + `Modal.Body` + `Modal.Footer`. Put `useAppForm`\n * `FormBody` inside `Modal.Body` and the submit / cancel buttons inside `Modal.Footer`.\n *\n * @see RECIPES.md#modal-form — for the canonical form-in-modal composition\n * @see RECIPES.md#confirm-dialog — for destructive-confirm dialogs\n */\nexport const Modal = (props: Props) => <Root {...props} />;\n\nModal.Close = Close;\nModal.Trigger = Trigger;\n\nModal.Content = ModalContent;\nModal.Body = ModalBody;\nModal.Icon = ModalIcon;\nModal.Image = ModalImage;\nModal.Footer = ModalFooter;\nModal.Header = ModalHeader;\nModal.Overlay = ModalOverlay;\n"],"mappings":"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"}
1
+ {"version":3,"file":"Modal-I3VWk2oo.js","names":[],"sources":["../src/components/Modal/ModalBody.tsx","../src/components/Modal/ModalContent.tsx","../src/components/Modal/ModalFooter.tsx","../src/components/Modal/ModalActions.tsx","../src/components/Modal/ModalHeader.tsx","../src/components/Modal/ModalIcon.tsx","../src/components/Modal/ModalImage.tsx","../src/components/Modal/Modal.tsx"],"sourcesContent":["import type { ComponentProps } from 'react';\n\nimport { cn } from '../../utils';\n\n/** Props for `Modal.Body`. Accepts all `<div>` attributes; `as=\"form\"` is reserved for future use. */\ntype Props = ComponentProps<'div'> & {\n as?: 'form';\n};\n\n/**\n * Scrollable body slot for `Modal`. Place form fields, content blocks, or detail panels here.\n * Takes available height inside `Modal.Content` and scrolls when content overflows.\n */\nexport const ModalBody = ({ className, ...props }: Props) => (\n <div\n data-slot=\"modal-body\"\n className={cn(\n // scrollable body - takes available space and scrolls when content overflows\n 'tw:flex-1',\n 'tw:overflow-y-auto',\n\n // argo: soft top/bottom edge fade in place of header/footer separators (pure-CSS utility)\n 'tw:group-data-[argo=true]/modal:scroll-fade-y',\n\n // Own horizontal padding, matching Header/Footer so content edges align (ModalContent adds none)\n 'tw:group-data-[argo=false]/modal:px-7',\n 'tw:group-data-[argo=true]/modal:px-4',\n 'tw:py-1',\n\n // normalize nested Lucide icon sizing, matching Popover/HoverCard/Alert content surfaces\n \"tw:[&_svg.lucide:not([class*='tw:size-'])]:size-4\",\n 'tw:[&_svg]:shrink-0',\n className,\n )}\n {...props}\n />\n);\n","import type { ComponentProps } from 'react';\nimport { Content, Portal } from '@radix-ui/react-dialog';\n\nimport { cn } from '../../utils';\nimport { useArgoDesign } from '../ThemeProvider/context';\n\nimport { ModalOverlay } from './ModalOverlay';\n\ntype Props = ComponentProps<typeof Content> & {\n size?: 'small' | 'medium' | 'large';\n};\n\nexport const ModalContent = ({\n size = 'medium',\n className,\n children,\n onEscapeKeyDown,\n ...props\n}: Props) => {\n const renderArgo = useArgoDesign();\n\n const handleEscapeKeyDown: typeof onEscapeKeyDown = (event) => {\n // Stop propagation to prevent parent modals (like FullScreenModal) from closing\n event.stopPropagation();\n onEscapeKeyDown?.(event);\n };\n\n return (\n <Portal>\n <ModalOverlay>\n <Content\n // props first so callers can't override the computed data-argo / data-size\n {...props}\n data-argo={renderArgo}\n data-size={size}\n className={cn(\n 'tailwindcss-preflight',\n 'tw:group/modal',\n\n // positioning - horizontally centered; vertical anchor depends on the design language\n 'tw:fixed',\n 'tw:left-1/2',\n 'tw:-translate-x-1/2',\n 'tw:z-[1051]',\n\n // legacy: anchored near the top; argo: centered in the viewport (like AlertModal)\n 'tw:data-[argo=false]:top-20',\n 'tw:data-[argo=true]:top-1/2',\n 'tw:data-[argo=true]:-translate-y-1/2',\n\n // sizing - responsive max dimensions\n 'tw:w-full',\n 'tw:max-w-2xl',\n 'tw:max-h-[calc(100vh-2*theme(spacing.20))]',\n\n // layout\n 'tw:flex',\n 'tw:flex-col',\n 'tw:gap-4',\n 'tw:data-[argo=false]:rounded-lg',\n 'tw:data-[argo=true]:rounded-3xl',\n 'tw:bg-card',\n 'tw:text-card-foreground',\n\n // Vertical (edge) padding lives here so it survives an omitted Header or Footer.\n // Horizontal padding is owned by Header / Body / Footer, so the Body runs full-bleed and\n // its scrollbar sits at the modal edge (see ModalBody).\n 'tw:data-[argo=false]:py-8',\n 'tw:data-[argo=true]:py-4',\n\n // animation — shared\n 'tw:duration-200',\n 'tw:data-[state=open]:animate-in',\n 'tw:data-[state=open]:fade-in-0',\n 'tw:data-[state=closed]:animate-out',\n 'tw:data-[state=closed]:fade-out-0',\n\n // NOTE: no `slide-*-left-1/2` (both) or argo `slide-*-top-1/2`. Those re-pinned the\n // -50%/-50% centring during the animation under v3, where centring and the animation\n // shared the `transform` property (the animation overrode it). Under v4 the centring\n // uses the `translate` PROPERTY while tw-animate-css animates `transform` — they compose\n // instead of overriding, so a -50% enter-translate stacks on the -50% centring (= -100%)\n // and the modal flies in from the top-left. Centring now persists on its own, so we\n // animate transform-only (zoom + fade) and the modal stays put.\n\n // legacy: slide-down + zoom (top-anchored via `top-20`, so no `translate-y` to double)\n 'tw:data-[argo=false]:data-[state=open]:zoom-in-80',\n 'tw:data-[argo=false]:data-[state=open]:slide-in-from-top-[48%]',\n 'tw:data-[argo=false]:data-[state=closed]:zoom-out-80',\n 'tw:data-[argo=false]:data-[state=closed]:slide-out-to-top-[48%]',\n\n // argo: pop from the centre — zoom only\n 'tw:data-[argo=true]:data-[state=open]:zoom-in-95',\n 'tw:data-[argo=true]:data-[state=closed]:zoom-out-95',\n\n {\n 'tw:max-w-[480px]': size === 'small',\n 'tw:max-w-4xl': size === 'large',\n },\n\n className,\n )}\n onEscapeKeyDown={handleEscapeKeyDown}\n >\n {children}\n </Content>\n </ModalOverlay>\n </Portal>\n );\n};\n","import type { ComponentPropsWithRef } from 'react';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentPropsWithRef<'div'>;\n\n/**\n * The modal's action row.\n *\n * - Right-aligns its children in a row, 8px apart, at their natural height.\n * - Imposes no width on its children: one that should fill the row carries `tw:w-full` itself\n * (`Button block`, `ButtonGroup variant=\"block\"`). Passing `tw:w-full` to the footer does\n * nothing — it already stretches to the modal's width as a `ModalContent` flex item.\n * - Owns the horizontal padding; `ModalContent` owns the vertical edge padding.\n * - Overriding the arrangement means passing the conflicting class: `cn` runs tailwind-merge, which\n * displaces only within a group. `tw:justify-between` replaces `justify-end`; `tw:flex-col`\n * leaves `items-center` and the gap in place, so a stacked footer wants `tw:items-stretch` too.\n */\nexport const ModalFooter = ({ className, ...props }: Props) => (\n <div\n {...props}\n className={cn(\n 'tw:flex',\n 'tw:items-center',\n 'tw:justify-end',\n 'tw:gap-2',\n\n // Own horizontal padding (ModalContent owns the vertical edge padding)\n 'tw:group-data-[argo=false]/modal:px-7',\n 'tw:group-data-[argo=true]/modal:px-4',\n className,\n )}\n />\n);\n","import type { ComponentProps } from 'react';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentProps<'div'>;\n\n/**\n * Container for the header's top-right controls — any `actions` passed to `Modal.Header` plus the\n * close icon. Sits in the header grid's last column, top-aligned. Mirrors `Alert`'s action slot.\n */\nexport const ModalActions = ({ className, ...props }: Props) => (\n <div\n className={cn(\n 'tw:col-start-3',\n 'tw:row-start-1',\n 'tw:self-start',\n 'tw:flex',\n 'tw:items-center',\n 'tw:gap-1',\n // argo: gutter separating the actions/close from the title (carried here so the grid needs no\n // column gap — see ModalHeader)\n 'tw:group-data-[argo=true]/modal:ml-3',\n className,\n )}\n {...props}\n />\n);\n","import type { ComponentProps, ReactNode } from 'react';\nimport { Close } from '@radix-ui/react-dialog';\n\nimport { X } from '../../icons';\nimport { cn } from '../../utils';\nimport { Button } from '../Button';\nimport { Separator } from '../Separator';\n\nimport { ModalActions } from './ModalActions';\nimport { ModalDescription } from './ModalDescription';\nimport { ModalTitle } from './ModalTitle';\n\ntype Props = {\n /** Status icon slot — `<Modal.Icon />` or `<Modal.Image />`. */\n icon?: ReactNode;\n /** Visible subtitle below the title (also fills `aria-describedby`). */\n description?: ReactNode;\n /** Screen-reader-only description; fills `aria-describedby` without rendering visibly. */\n 'aria-description'?: string;\n /** Controls rendered top-right, before the close icon. */\n actions?: ReactNode;\n /** Hide the top-right close icon. */\n hideCloseIcon?: boolean;\n} & ComponentProps<'div'>;\n\n/** Modal header: `[icon] | title (children) | actions + close` on row 1, `description` on row 2. */\nexport const ModalHeader = ({\n className,\n icon,\n description,\n 'aria-description': ariaDescription,\n actions,\n hideCloseIcon = false,\n children,\n ...props\n}: Props) => (\n <div\n {...props}\n data-slot=\"modal-header\"\n className={cn(\n 'tw:grid',\n 'tw:grid-cols-[auto_1fr_auto]',\n 'tw:items-center',\n 'tw:group-data-[argo=false]/modal:px-7',\n 'tw:group-data-[argo=true]/modal:px-4',\n className,\n )}\n >\n {icon}\n\n {children && <ModalTitle className=\"tw:col-start-2 tw:row-start-1\">{children}</ModalTitle>}\n {(actions || !hideCloseIcon) && (\n <ModalActions>\n {actions}\n {!hideCloseIcon && (\n <Close asChild>\n <Button variant=\"invisible\" size=\"icon-sm\">\n <X />\n <span className=\"tw:sr-only\">Close</span>\n </Button>\n </Close>\n )}\n </ModalActions>\n )}\n {(description || ariaDescription) && (\n <ModalDescription\n className={cn(\n 'tw:col-start-1',\n 'tw:col-end-4',\n 'tw:row-start-2',\n description ? 'tw:mt-1' : 'tw:sr-only',\n )}\n >\n {description ?? ariaDescription}\n </ModalDescription>\n )}\n\n {/* Legacy-only separator; shown when a Body follows, hidden when that body hosts Tabs. */}\n <div\n className={cn(\n 'tw:col-start-1',\n 'tw:col-end-4',\n 'tw:mt-5',\n 'tw:hidden',\n 'tw:group-data-[argo=false]/modal:[[data-slot=modal-header]:has(~[data-slot=modal-body])_&]:block',\n 'tw:group-data-[argo=false]/modal:[[data-slot=modal-header]:has(~[data-slot=modal-body]_[data-slot=tabs-root])_&]:!hidden',\n )}\n >\n <Separator orientation=\"horizontal\" />\n </div>\n </div>\n);\n","import type { ReactNode } from 'react';\n\nimport { cn } from '../../utils';\n\ntype NamedColor = 'orange' | 'blue' | 'red' | 'green' | 'gray' | 'violet';\n\ntype Props = {\n color: NamedColor | (string & {});\n icon: ReactNode;\n};\n\nconst NAMED_COLORS = new Set<string>(['orange', 'blue', 'red', 'green', 'gray', 'violet']);\n\n/**\n * Status-coloured icon for `Modal`. Authored inside `Modal.Header`. For a remote image badge (a\n * component or backend logo fetched by URL) use `Modal.Image` instead.\n *\n * - **Legacy anatomy:** a solid-filled circular badge docked to the top-left of `Modal.Content`\n * (absolutely positioned, so it renders identically wherever it is authored).\n * - **Argo anatomy** (`data-argo` on `Modal.Content`): a small soft-tinted inline badge in the\n * header grid, next to the title.\n *\n * Both variants are rendered and toggled purely via CSS (`group-data-[argo=true]/modal:`) — no\n * context. Use the categorical `color` (`red` destructive, `orange` warning, `green` success,\n * `blue` info, `gray` neutral, `violet` agent) to encode meaning; the palette stays fixed across\n * brand themes.\n */\nexport const ModalIcon = ({ color, icon }: Props) => {\n const customColor = color && !NAMED_COLORS.has(color) ? color : undefined;\n\n return (\n <span\n data-slot=\"modal-icon\"\n className={cn(\n 'tw:flex',\n 'tw:shrink-0',\n 'tw:items-center',\n 'tw:justify-center',\n 'tw:[&_svg]:aspect-square',\n\n // legacy: solid-filled circular badge floating at the modal's top-left\n 'tw:group-data-[argo=false]/modal:absolute',\n 'tw:group-data-[argo=false]/modal:top-0',\n 'tw:group-data-[argo=false]/modal:left-8',\n 'tw:group-data-[argo=false]/modal:-translate-y-1/2',\n 'tw:group-data-[argo=false]/modal:size-12',\n 'tw:group-data-[argo=false]/modal:rounded-full',\n 'tw:group-data-[argo=false]/modal:[&_svg:not([class*=\"tw:size-\"])]:size-6',\n\n // argo: soft-tinted inline badge in the header grid's first column\n 'tw:group-data-[argo=true]/modal:col-start-1',\n 'tw:group-data-[argo=true]/modal:row-start-1',\n 'tw:group-data-[argo=true]/modal:self-start',\n 'tw:group-data-[argo=true]/modal:mr-3',\n 'tw:group-data-[argo=true]/modal:size-8',\n 'tw:group-data-[argo=true]/modal:rounded',\n 'tw:group-data-[argo=true]/modal:overflow-hidden',\n 'tw:group-data-[argo=true]/modal:[&_svg:not([class*=\"tw:size-\"])]:size-5',\n\n // legacy palette: solid fill + white glyph (violet is the exception — tinted)\n {\n 'tw:group-data-[argo=false]/modal:bg-warning-500': color === 'orange',\n 'tw:group-data-[argo=false]/modal:bg-blue-500': color === 'blue',\n 'tw:group-data-[argo=false]/modal:bg-green-500': color === 'green',\n 'tw:group-data-[argo=false]/modal:bg-error-500': color === 'red',\n 'tw:group-data-[argo=false]/modal:bg-neutral-150': color === 'gray',\n 'tw:group-data-[argo=false]/modal:bg-purple-100': color === 'violet',\n 'tw:group-data-[argo=false]/modal:text-white': color !== 'violet',\n 'tw:group-data-[argo=false]/modal:text-purple-500': color === 'violet',\n },\n\n // argo palette: soft tint + matching glyph colour\n {\n 'tw:group-data-[argo=true]/modal:bg-warning-100 tw:group-data-[argo=true]/modal:text-warning-500':\n color === 'orange',\n 'tw:group-data-[argo=true]/modal:bg-blue-100 tw:group-data-[argo=true]/modal:text-blue-600':\n color === 'blue',\n 'tw:group-data-[argo=true]/modal:bg-green-100 tw:group-data-[argo=true]/modal:text-green-900':\n color === 'green',\n 'tw:group-data-[argo=true]/modal:bg-error-100 tw:group-data-[argo=true]/modal:text-error-500':\n color === 'red',\n 'tw:group-data-[argo=true]/modal:bg-neutral-100 tw:group-data-[argo=true]/modal:text-neutral-500':\n color === 'gray',\n 'tw:group-data-[argo=true]/modal:bg-purple-100 tw:group-data-[argo=true]/modal:text-purple-500':\n color === 'violet',\n },\n\n // custom (non-named) colour: caller-provided fill + white glyph\n { 'tw:text-white': !!customColor },\n )}\n style={customColor ? { backgroundColor: customColor } : undefined}\n >\n {icon}\n </span>\n );\n};\n","import { useEffect, useState } from 'react';\n\nimport { cn } from '../../utils';\n\ntype Props = {\n src: string;\n /** Accessible alt text. Defaults to `\"\"` (decorative) — provide it when the image carries meaning. */\n alt?: string;\n};\n\nexport const ModalImage = ({ src, alt = '' }: Props) => {\n const [hasImageError, setHasImageError] = useState(false);\n\n // Reset the error state when the source changes, so a reused badge (new logo, or a retry after a\n // transient failure) isn't permanently hidden by an earlier onError.\n useEffect(() => setHasImageError(false), [src]);\n\n if (hasImageError) return null;\n\n return (\n <span\n data-slot=\"modal-image\"\n className={cn(\n 'tw:shrink-0',\n 'tw:overflow-hidden',\n\n // legacy: circular badge floating at the top-left of the modal\n 'tw:group-data-[argo=false]/modal:absolute',\n 'tw:group-data-[argo=false]/modal:top-0',\n 'tw:group-data-[argo=false]/modal:left-8',\n 'tw:group-data-[argo=false]/modal:-translate-y-1/2',\n 'tw:group-data-[argo=false]/modal:size-12',\n 'tw:group-data-[argo=false]/modal:rounded-full',\n\n // argo: inline badge in the header grid's first column\n 'tw:group-data-[argo=true]/modal:flex',\n 'tw:group-data-[argo=true]/modal:col-start-1',\n 'tw:group-data-[argo=true]/modal:row-start-1',\n 'tw:group-data-[argo=true]/modal:self-start',\n 'tw:group-data-[argo=true]/modal:mr-3',\n 'tw:group-data-[argo=true]/modal:items-center',\n 'tw:group-data-[argo=true]/modal:justify-center',\n 'tw:group-data-[argo=true]/modal:rounded',\n 'tw:group-data-[argo=true]/modal:size-8',\n )}\n >\n <img\n src={src}\n alt={alt}\n className=\"tw:size-full tw:object-contain\"\n onError={() => setHasImageError(true)}\n />\n </span>\n );\n};\n","import type { ComponentProps } from 'react';\nimport { Close, Root, Trigger } from '@radix-ui/react-dialog';\n\nimport { ModalBody } from './ModalBody';\nimport { ModalContent } from './ModalContent';\nimport { ModalFooter } from './ModalFooter';\nimport { ModalHeader } from './ModalHeader';\nimport { ModalIcon } from './ModalIcon';\nimport { ModalImage } from './ModalImage';\nimport { ModalOverlay } from './ModalOverlay';\n\ntype Props = ComponentProps<typeof Root>;\n\n/**\n * Blocking dialog for confirmations, forms, and detail views. Built on Radix Dialog.\n *\n * **When to use:** the user must act before continuing (confirm a destructive action, fill a short form,\n * view a focused detail panel). Use the compound parts `Modal.Trigger`, `Modal.Content`, `Modal.Header`,\n * `Modal.Body`, `Modal.Footer`, and optionally `Modal.Icon` for a status-coloured header glyph.\n * **When NOT to use:** for slide-in side editing use `Sheet`; for an inline destructive confirmation anchored\n * to its trigger use `Popconfirm`; for hover previews use `HoverCard`.\n * **Composition:** wrap `Modal.Content` around `Modal.Header` + `Modal.Body` + `Modal.Footer`. Put `useAppForm`\n * `FormBody` inside `Modal.Body` and the submit / cancel buttons inside `Modal.Footer`.\n *\n * @see RECIPES.md#modal-form — for the canonical form-in-modal composition\n * @see RECIPES.md#confirm-dialog — for destructive-confirm dialogs\n */\nexport const Modal = (props: Props) => <Root {...props} />;\n\nModal.Close = Close;\nModal.Trigger = Trigger;\n\nModal.Content = ModalContent;\nModal.Body = ModalBody;\nModal.Icon = ModalIcon;\nModal.Image = ModalImage;\nModal.Footer = ModalFooter;\nModal.Header = ModalHeader;\nModal.Overlay = ModalOverlay;\n"],"mappings":"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"}
@@ -12,7 +12,7 @@ const ModalOverlay = ({ ref, className, disableTransition = false, ...props }) =
12
12
  //#endregion
13
13
  //#region src/components/Modal/ModalDescription.tsx
14
14
  const ModalDescription = ({ className, ...props }) => /* @__PURE__ */ jsx(DialogPrimitive.Description, {
15
- className: cn("tw:text-sm", "tw:font-sans", "tw:tracking-normal", "tw:font-normal", "tw:text-neutral-400", className),
15
+ className: cn("tw:break-anywhere", "tw:text-sm", "tw:font-sans", "tw:tracking-normal", "tw:font-normal", "tw:text-neutral-400", className),
16
16
  ...props
17
17
  });
18
18
  //#endregion
@@ -25,4 +25,4 @@ const ModalTitle = ({ children, className, ...props }) => /* @__PURE__ */ jsx(Ti
25
25
  //#endregion
26
26
  export { ModalDescription, ModalOverlay, ModalTitle };
27
27
 
28
- //# sourceMappingURL=ModalTitle-C76ke2eo.js.map
28
+ //# sourceMappingURL=ModalTitle-CeLM_mX9.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModalTitle-CeLM_mX9.js","names":[],"sources":["../src/components/Modal/ModalOverlay.tsx","../src/components/Modal/ModalDescription.tsx","../src/components/Modal/ModalTitle.tsx"],"sourcesContent":["import type { ComponentProps } from 'react';\nimport { Overlay } from '@radix-ui/react-dialog';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentProps<typeof Overlay> & {\n disableTransition?: boolean;\n};\n\nexport const ModalOverlay = ({ ref, className, disableTransition = false, ...props }: Props) => (\n <Overlay\n {...props}\n ref={ref}\n className={cn(\n // positioning\n 'tw:fixed',\n 'tw:inset-0',\n 'tw:z-[1051]',\n\n // background\n 'tw:bg-black/50',\n\n // opening animation\n 'tw:data-[state=open]:duration-500',\n 'tw:data-[state=open]:fade-in-0',\n\n // closing animation\n 'tw:data-[state=closed]:duration-500',\n 'tw:data-[state=closed]:fade-out-0',\n {\n 'tw:data-[state=open]:animate-in tw:data-[state=closed]:animate-out': !disableTransition,\n },\n className,\n )}\n onClick={(event) => event.stopPropagation()}\n />\n);\n","import type { ComponentProps } from 'react';\nimport * as DialogPrimitive from '@radix-ui/react-dialog';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentProps<typeof DialogPrimitive.Description>;\n\nexport const ModalDescription = ({ className, ...props }: Props) => (\n <DialogPrimitive.Description\n className={cn(\n // `break-anywhere` because the slot routinely carries an identifier — a Storage table id, a\n // fully-qualified name — which offers no break opportunity and paints outside the frame\n // without one. `ModalTitle` carries it for the same reason.\n 'tw:break-anywhere',\n 'tw:text-sm',\n 'tw:font-sans',\n 'tw:tracking-normal',\n 'tw:font-normal',\n 'tw:text-neutral-400',\n className,\n )}\n {...props}\n />\n);\n","import type { ComponentProps } from 'react';\nimport { Title } from '@radix-ui/react-dialog';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentProps<typeof Title>;\n\nexport const ModalTitle = ({ children, className, ...props }: Props) => (\n <Title\n {...props}\n className={cn('tw:flex-1', 'tw:break-anywhere', 'tw:text-base', 'tw:font-semibold', className)}\n >\n {children}\n </Title>\n);\n"],"mappings":";;;;;AASA,MAAa,gBAAgB,EAAE,KAAK,WAAW,oBAAoB,OAAO,GAAG,YAC3E,oBAAC,SAAD;CACE,GAAI;CACC;CACL,WAAW,GAET,YACA,cACA,eAGA,kBAGA,qCACA,kCAGA,uCACA,qCACA,EACE,sEAAsE,CAAC,kBACzE,GACA,SACF;CACA,UAAU,UAAU,MAAM,gBAAgB;AAC3C,CAAA;;;AC5BH,MAAa,oBAAoB,EAAE,WAAW,GAAG,YAC/C,oBAAC,gBAAgB,aAAjB;CACE,WAAW,GAIT,qBACA,cACA,gBACA,sBACA,kBACA,uBACA,SACF;CACA,GAAI;AACL,CAAA;;;ACfH,MAAa,cAAc,EAAE,UAAU,WAAW,GAAG,YACnD,oBAAC,OAAD;CACE,GAAI;CACJ,WAAW,GAAG,aAAa,qBAAqB,gBAAgB,oBAAoB,SAAS;CAE5F;AACI,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { cn } from "./classNames-BzrkDnOD.js";
2
- import { Tooltip } from "./utils-DSvrhU8E.js";
2
+ import { Tooltip } from "./utils-BW4AE8VP.js";
3
3
  import { Button } from "./Button-DsRrU5F1.js";
4
4
  import { ButtonGroup } from "./internal/components/ButtonGroup.js";
5
5
  import { jsx } from "react/jsx-runtime";
@@ -30,4 +30,4 @@ MultiActionButtonGroup.Button = MultiActionButton;
30
30
  //#endregion
31
31
  export { MultiActionButtonGroup };
32
32
 
33
- //# sourceMappingURL=MultiActionButtonGroup-DokHbPgM.js.map
33
+ //# sourceMappingURL=MultiActionButtonGroup-CYZ8IgSf.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MultiActionButtonGroup-DokHbPgM.js","names":[],"sources":["../src/blocks/MultiActionButtonGroup/MultiActionButton.tsx","../src/blocks/MultiActionButtonGroup/MultiActionButtonGroup.tsx"],"sourcesContent":["import type { ComponentProps, ReactNode } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { Tooltip } from '../../components/Tooltip';\n\ntype Props = {\n disabled?: boolean;\n icon: ReactNode;\n isLoading?: boolean;\n label: string;\n onClick: ComponentProps<typeof Button>['onClick'];\n tooltipContent: ReactNode;\n tooltipVariant?: ComponentProps<typeof Tooltip>['variant'];\n 'data-testid'?: string;\n};\n\nexport const MultiActionButton = ({\n disabled,\n icon,\n isLoading,\n label,\n onClick,\n tooltipContent,\n tooltipVariant,\n 'data-testid': dataTestId,\n}: Props) => (\n <Tooltip placement=\"top\" tooltip={tooltipContent} triggerAsChild variant={tooltipVariant}>\n <Button\n disabled={disabled}\n isLoading={isLoading}\n aria-label={label}\n onClick={onClick}\n variant=\"invisible\"\n size=\"icon\"\n data-testid={dataTestId}\n >\n {!isLoading && icon}\n </Button>\n </Tooltip>\n);\n","import type { PropsWithChildren } from 'react';\n\nimport { ButtonGroup } from '../../components/ButtonGroup';\nimport { cn } from '../../utils';\n\nimport { MultiActionButton } from './MultiActionButton';\n\ntype Props = {\n className?: string;\n} & PropsWithChildren;\n\nexport const MultiActionButtonGroup = ({ children, className }: Props) => (\n <ButtonGroup className={cn('tw:text-nowrap', className)}>{children}</ButtonGroup>\n);\n\nMultiActionButtonGroup.Button = MultiActionButton;\n"],"mappings":";;;;;;AAgBA,MAAa,qBAAqB,EAChC,UACA,MACA,WACA,OACA,SACA,gBACA,gBACA,eAAe,iBAEf,oBAAC,SAAD;CAAS,WAAU;CAAM,SAAS;CAAgB,gBAAA;CAAe,SAAS;CACxE,UAAA,oBAAC,QAAD;EACY;EACC;EACX,cAAY;EACH;EACT,SAAQ;EACR,MAAK;EACL,eAAa;EAEZ,UAAA,CAAC,aAAa;CACT,CAAA;AACD,CAAA;;;AC3BX,MAAa,0BAA0B,EAAE,UAAU,gBACjD,oBAAC,aAAD;CAAa,WAAW,GAAG,kBAAkB,SAAS;CAAI;AAAsB,CAAA;AAGlF,uBAAuB,SAAS"}
1
+ {"version":3,"file":"MultiActionButtonGroup-CYZ8IgSf.js","names":[],"sources":["../src/blocks/MultiActionButtonGroup/MultiActionButton.tsx","../src/blocks/MultiActionButtonGroup/MultiActionButtonGroup.tsx"],"sourcesContent":["import type { ComponentProps, ReactNode } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { Tooltip } from '../../components/Tooltip';\n\ntype Props = {\n disabled?: boolean;\n icon: ReactNode;\n isLoading?: boolean;\n label: string;\n onClick: ComponentProps<typeof Button>['onClick'];\n tooltipContent: ReactNode;\n tooltipVariant?: ComponentProps<typeof Tooltip>['variant'];\n 'data-testid'?: string;\n};\n\nexport const MultiActionButton = ({\n disabled,\n icon,\n isLoading,\n label,\n onClick,\n tooltipContent,\n tooltipVariant,\n 'data-testid': dataTestId,\n}: Props) => (\n <Tooltip placement=\"top\" tooltip={tooltipContent} triggerAsChild variant={tooltipVariant}>\n <Button\n disabled={disabled}\n isLoading={isLoading}\n aria-label={label}\n onClick={onClick}\n variant=\"invisible\"\n size=\"icon\"\n data-testid={dataTestId}\n >\n {!isLoading && icon}\n </Button>\n </Tooltip>\n);\n","import type { PropsWithChildren } from 'react';\n\nimport { ButtonGroup } from '../../components/ButtonGroup';\nimport { cn } from '../../utils';\n\nimport { MultiActionButton } from './MultiActionButton';\n\ntype Props = {\n className?: string;\n} & PropsWithChildren;\n\nexport const MultiActionButtonGroup = ({ children, className }: Props) => (\n <ButtonGroup className={cn('tw:text-nowrap', className)}>{children}</ButtonGroup>\n);\n\nMultiActionButtonGroup.Button = MultiActionButton;\n"],"mappings":";;;;;;AAgBA,MAAa,qBAAqB,EAChC,UACA,MACA,WACA,OACA,SACA,gBACA,gBACA,eAAe,iBAEf,oBAAC,SAAD;CAAS,WAAU;CAAM,SAAS;CAAgB,gBAAA;CAAe,SAAS;CACxE,UAAA,oBAAC,QAAD;EACY;EACC;EACX,cAAY;EACH;EACT,SAAQ;EACR,MAAK;EACL,eAAa;EAEZ,UAAA,CAAC,aAAa;CACT,CAAA;AACD,CAAA;;;AC3BX,MAAa,0BAA0B,EAAE,UAAU,gBACjD,oBAAC,aAAD;CAAa,WAAW,GAAG,kBAAkB,SAAS;CAAI;AAAsB,CAAA;AAGlF,uBAAuB,SAAS"}
@@ -2,7 +2,7 @@ import { cn } from "./classNames-BzrkDnOD.js";
2
2
  import { ChevronDown, Plus, X } from "./icons-Cek151jC.js";
3
3
  import { Button } from "./Button-DsRrU5F1.js";
4
4
  import { Popover } from "./Popover-BEbQrC_P.js";
5
- import { Badge } from "./Badge-D0pXdekt.js";
5
+ import { Badge } from "./Badge-o5jURtpB.js";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  //#region src/blocks/PageToolbar/PageToolbarToken.tsx
8
8
  /**
@@ -150,4 +150,4 @@ const PageToolbar = Object.assign(Root, {
150
150
  //#endregion
151
151
  export { PageToolbar };
152
152
 
153
- //# sourceMappingURL=PageToolbar-DExqEYGl.js.map
153
+ //# sourceMappingURL=PageToolbar-BKVJiDAL.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageToolbar-DExqEYGl.js","names":[],"sources":["../src/blocks/PageToolbar/PageToolbarToken.tsx","../src/blocks/PageToolbar/PageToolbar.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nimport { Badge } from '../../components/Badge';\nimport { Button } from '../../components/Button';\nimport { Popover } from '../../components/Popover';\nimport { ChevronDown, X } from '../../icons';\n\ntype PageToolbarTokenProps = Omit<\n ComponentPropsWithoutRef<typeof Badge>,\n 'variant' | 'color' | 'suffix' | 'children' | 'asChild' | 'popover'\n> & {\n children: ReactNode;\n /** Popover content rendered when the chevron-down trigger is clicked — typically a value editor. */\n popover: ReactNode;\n onRemove: () => void;\n removeAriaLabel: string;\n};\n\n/**\n * Editable filter token (Query Builder variant) — `Badge` pill with a `chevron-down`\n * popover trigger for editing values and an `×` dismiss button. The popover content\n * is supplied by the caller via the `popover` slot (typically a `Combobox` or option list).\n */\nexport const PageToolbarToken = ({\n children,\n popover,\n onRemove,\n removeAriaLabel,\n ...props\n}: PageToolbarTokenProps) => (\n <Popover>\n <Badge\n {...props}\n asChild\n variant=\"pill\"\n color=\"blue-inverse\"\n suffix={\n <Button\n type=\"button\"\n variant=\"inline\"\n size=\"icon-2xs\"\n aria-label={removeAriaLabel}\n onClick={onRemove}\n >\n <X className=\"tw:size-3\" />\n </Button>\n }\n >\n <Popover.Trigger\n type=\"button\"\n className=\"tw:inline-flex tw:cursor-pointer tw:items-center tw:gap-1 tw:bg-inherit tw:text-inherit tailwindcss-preflight\"\n >\n {children}\n <ChevronDown className=\"tw:size-3\" />\n </Popover.Trigger>\n </Badge>\n <Popover.Content align=\"start\">{popover}</Popover.Content>\n </Popover>\n);\n","import type { ComponentProps, ComponentPropsWithoutRef, ReactNode } from 'react';\n\nimport { Badge } from '../../components/Badge';\nimport { Button } from '../../components/Button';\nimport { Plus, X } from '../../icons';\nimport { cn } from '../../utils';\n\nimport { PageToolbarToken } from './PageToolbarToken';\n\ntype DivProps = ComponentProps<'div'>;\n\nconst Root = ({ ref, className, children, ...props }: DivProps) => (\n <div\n ref={ref}\n className={cn('tw:flex tw:flex-wrap tw:items-center tw:gap-3 tw:w-full', className)}\n {...props}\n >\n {children}\n </div>\n);\n\nconst Search = ({ ref, className, children, ...props }: DivProps) => (\n <div\n ref={ref}\n className={cn(\n 'tw:mr-auto tw:flex tw:items-center tw:gap-2 tw:w-full tw:sm:w-auto tw:sm:min-w-64 tw:sm:max-w-md',\n // The slot sizes itself between `min-w-64` and `max-w-md`, so the search field has to fill it —\n // without this the input stays content-width (≈224px inside a 448px slot) and truncates its own\n // placeholder, and every caller ends up hand-picking a width class to compensate.\n //\n // - First child only. The documented composition is the search field followed by filter pills;\n // stretching every child would size the pills to match the input.\n // - `min-w-0` so a long value shrinks the input rather than overflowing the toolbar.\n 'tw:*:first:min-w-0 tw:*:first:flex-1',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n);\n\nconst Right = ({ ref, className, children, ...props }: DivProps) => (\n <div\n ref={ref}\n className={cn('tw:flex tw:flex-wrap tw:items-center tw:gap-2', className)}\n {...props}\n >\n {children}\n </div>\n);\n\nconst ControlGroup = ({ ref, className, children, ...props }: DivProps) => (\n <div ref={ref} className={cn('tw:flex tw:items-center tw:gap-2', className)} {...props}>\n {children}\n </div>\n);\n\nconst ActiveFilters = ({ ref, className, children, ...props }: DivProps) => (\n <div\n ref={ref}\n className={cn('tw:flex tw:flex-wrap tw:items-center tw:gap-2 tw:basis-full', className)}\n {...props}\n >\n {children}\n </div>\n);\n\ntype ChipProps = Omit<\n ComponentPropsWithoutRef<typeof Badge>,\n 'variant' | 'color' | 'suffix' | 'children'\n> & {\n children: ReactNode;\n onRemove: () => void;\n removeAriaLabel: string;\n};\n\nconst Chip = ({ children, onRemove, removeAriaLabel, ...props }: ChipProps) => (\n <Badge\n {...props}\n variant=\"pill\"\n color=\"blue-inverse\"\n suffix={\n <Button\n type=\"button\"\n variant=\"inline\"\n size=\"icon-2xs\"\n aria-label={removeAriaLabel}\n onClick={onRemove}\n >\n <X className=\"tw:size-3\" />\n </Button>\n }\n >\n {children}\n </Badge>\n);\n\ntype ActionProps = ComponentPropsWithoutRef<typeof Button>;\n\nconst AddFilter = ({ className, children, ...props }: ActionProps) => (\n <Button variant=\"invisible\" size=\"small\" className={cn('tw:gap-1.5', className)} {...props}>\n <Plus className=\"tw:size-4\" />\n {children ?? 'Add filter'}\n </Button>\n);\n\nconst Clear = ({ className, children, ...props }: ActionProps) => (\n <Button variant=\"invisible\" size=\"small\" className={cn('tw:ml-auto', className)} {...props}>\n {children ?? 'Clear all'}\n </Button>\n);\n\n/**\n * Two-row toolbar for index pages — search on the left, filter / sort / utility / view\n * controls on the right, an optional Active Filters row below for filter chips or tokens.\n *\n * **When to use:** every index page that supports search or filtering. Hosts inside\n * `PageLayout` as the search / filter row, between `PageLayout.Header` and `PageLayout.Content`.\n * **When NOT to use:** detail pages, form pages, or anywhere there is no search / filter\n * surface. For routing-based tab rows reach for `PageLayout.Tabs`.\n *\n * **Recommended composition (enforced at the call site):**\n *\n * - `Search` sits on the left; the right cluster auto-aligns via flex.\n * - Right cluster order: `Filters` → `Sort` → `Actions` → `View`. View controls are always\n * the final control group — do not render any control after `View`.\n * - `ActiveFilters` is the second row. Render it only when one or more filters are active.\n * - `Clear` self-aligns to the far right of `ActiveFilters`.\n *\n * The block is variant-agnostic: render filter chips (Standard variant, non-editable) or\n * tokens (Query Builder variant, editable) into `ActiveFilters` as plain children — do not\n * mix the two in one toolbar.\n *\n * @see https://github.com/evviku/design-system-docs/blob/main/docs/patterns/toolbar/toolbar.md\n */\nexport const PageToolbar = Object.assign(Root, {\n /** Left slot — typically a `SearchInput`. */\n Search,\n /** Right cluster — host the four control groups below in the recommended order. */\n Right,\n /** Filter controls (`Combobox`, `Select`, `DatePicker`). */\n Filters: ControlGroup,\n /** Sort control. */\n Sort: ControlGroup,\n /** Utility actions (Export, Refresh, …). */\n Actions: ControlGroup,\n /** View toggle (List / Grid). Always render last in the right cluster. */\n View: ControlGroup,\n /**\n * Active filters row. Render only when one or more filters are active. Pass filter chips\n * (Standard variant) or tokens (Query Builder variant) as children, optionally followed\n * by `AddFilter` / `Clear`.\n */\n ActiveFilters,\n /** Non-editable filter chip (Standard variant) — `Badge` pill with a dismiss button. */\n Chip,\n /**\n * Editable filter token (Query Builder variant) — `Badge` pill with a `chevron-down`\n * popover trigger for editing values and an `×` dismiss button. The popover content\n * is supplied by the caller via the `popover` slot (typically a `Combobox` or option list).\n */\n Token: PageToolbarToken,\n /** \"+ Add filter\" action — typically rendered after the chips/tokens in `ActiveFilters`. */\n AddFilter,\n /** \"Clear all\" action — self-aligns to the far right of `ActiveFilters`. */\n Clear,\n});\n"],"mappings":";;;;;;;;;;;;AAuBA,MAAa,oBAAoB,EAC/B,UACA,SACA,UACA,iBACA,GAAG,YAEH,qBAAC,SAAD,EAAA,UAAA,CACE,oBAAC,OAAD;CACE,GAAI;CACJ,SAAA;CACA,SAAQ;CACR,OAAM;CACN,QACE,oBAAC,QAAD;EACE,MAAK;EACL,SAAQ;EACR,MAAK;EACL,cAAY;EACZ,SAAS;EAET,UAAA,oBAAC,GAAD,EAAG,WAAU,YAAa,CAAA;CACpB,CAAA;CAGV,UAAA,qBAAC,QAAQ,SAAT;EACE,MAAK;EACL,WAAU;EAFZ,UAAA,CAIG,UACD,oBAAC,aAAD,EAAa,WAAU,YAAa,CAAA,CACrB;;AACZ,CAAA,GACP,oBAAC,QAAQ,SAAT;CAAiB,OAAM;CAAS,UAAA;AAAyB,CAAA,CAClD,EAAA,CAAA;;;AC9CX,MAAM,QAAQ,EAAE,KAAK,WAAW,UAAU,GAAG,YAC3C,oBAAC,OAAD;CACO;CACL,WAAW,GAAG,2DAA2D,SAAS;CAClF,GAAI;CAEH;AACE,CAAA;AAGP,MAAM,UAAU,EAAE,KAAK,WAAW,UAAU,GAAG,YAC7C,oBAAC,OAAD;CACO;CACL,WAAW,GACT,oGAQA,wCACA,SACF;CACA,GAAI;CAEH;AACE,CAAA;AAGP,MAAM,SAAS,EAAE,KAAK,WAAW,UAAU,GAAG,YAC5C,oBAAC,OAAD;CACO;CACL,WAAW,GAAG,iDAAiD,SAAS;CACxE,GAAI;CAEH;AACE,CAAA;AAGP,MAAM,gBAAgB,EAAE,KAAK,WAAW,UAAU,GAAG,YACnD,oBAAC,OAAD;CAAU;CAAK,WAAW,GAAG,oCAAoC,SAAS;CAAG,GAAI;CAC9E;AACE,CAAA;AAGP,MAAM,iBAAiB,EAAE,KAAK,WAAW,UAAU,GAAG,YACpD,oBAAC,OAAD;CACO;CACL,WAAW,GAAG,+DAA+D,SAAS;CACtF,GAAI;CAEH;AACE,CAAA;AAYP,MAAM,QAAQ,EAAE,UAAU,UAAU,iBAAiB,GAAG,YACtD,oBAAC,OAAD;CACE,GAAI;CACJ,SAAQ;CACR,OAAM;CACN,QACE,oBAAC,QAAD;EACE,MAAK;EACL,SAAQ;EACR,MAAK;EACL,cAAY;EACZ,SAAS;EAET,UAAA,oBAAC,GAAD,EAAG,WAAU,YAAa,CAAA;CACpB,CAAA;CAGT;AACI,CAAA;AAKT,MAAM,aAAa,EAAE,WAAW,UAAU,GAAG,YAC3C,qBAAC,QAAD;CAAQ,SAAQ;CAAY,MAAK;CAAQ,WAAW,GAAG,cAAc,SAAS;CAAG,GAAI;CAArF,UAAA,CACE,oBAAC,MAAD,EAAM,WAAU,YAAa,CAAA,GAC5B,YAAY,YACP;;AAGV,MAAM,SAAS,EAAE,WAAW,UAAU,GAAG,YACvC,oBAAC,QAAD;CAAQ,SAAQ;CAAY,MAAK;CAAQ,WAAW,GAAG,cAAc,SAAS;CAAG,GAAI;CAClF,UAAA,YAAY;AACP,CAAA;;;;;;;;;;;;;;;;;;;;;;;;AA0BV,MAAa,cAAc,OAAO,OAAO,MAAM;;CAE7C;;CAEA;;CAEA,SAAS;;CAET,MAAM;;CAEN,SAAS;;CAET,MAAM;;;;;;CAMN;;CAEA;;;;;;CAMA,OAAO;;CAEP;;CAEA;AACF,CAAC"}
1
+ {"version":3,"file":"PageToolbar-BKVJiDAL.js","names":[],"sources":["../src/blocks/PageToolbar/PageToolbarToken.tsx","../src/blocks/PageToolbar/PageToolbar.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nimport { Badge } from '../../components/Badge';\nimport { Button } from '../../components/Button';\nimport { Popover } from '../../components/Popover';\nimport { ChevronDown, X } from '../../icons';\n\ntype PageToolbarTokenProps = Omit<\n ComponentPropsWithoutRef<typeof Badge>,\n 'variant' | 'color' | 'suffix' | 'children' | 'asChild' | 'popover'\n> & {\n children: ReactNode;\n /** Popover content rendered when the chevron-down trigger is clicked — typically a value editor. */\n popover: ReactNode;\n onRemove: () => void;\n removeAriaLabel: string;\n};\n\n/**\n * Editable filter token (Query Builder variant) — `Badge` pill with a `chevron-down`\n * popover trigger for editing values and an `×` dismiss button. The popover content\n * is supplied by the caller via the `popover` slot (typically a `Combobox` or option list).\n */\nexport const PageToolbarToken = ({\n children,\n popover,\n onRemove,\n removeAriaLabel,\n ...props\n}: PageToolbarTokenProps) => (\n <Popover>\n <Badge\n {...props}\n asChild\n variant=\"pill\"\n color=\"blue-inverse\"\n suffix={\n <Button\n type=\"button\"\n variant=\"inline\"\n size=\"icon-2xs\"\n aria-label={removeAriaLabel}\n onClick={onRemove}\n >\n <X className=\"tw:size-3\" />\n </Button>\n }\n >\n <Popover.Trigger\n type=\"button\"\n className=\"tw:inline-flex tw:cursor-pointer tw:items-center tw:gap-1 tw:bg-inherit tw:text-inherit tailwindcss-preflight\"\n >\n {children}\n <ChevronDown className=\"tw:size-3\" />\n </Popover.Trigger>\n </Badge>\n <Popover.Content align=\"start\">{popover}</Popover.Content>\n </Popover>\n);\n","import type { ComponentProps, ComponentPropsWithoutRef, ReactNode } from 'react';\n\nimport { Badge } from '../../components/Badge';\nimport { Button } from '../../components/Button';\nimport { Plus, X } from '../../icons';\nimport { cn } from '../../utils';\n\nimport { PageToolbarToken } from './PageToolbarToken';\n\ntype DivProps = ComponentProps<'div'>;\n\nconst Root = ({ ref, className, children, ...props }: DivProps) => (\n <div\n ref={ref}\n className={cn('tw:flex tw:flex-wrap tw:items-center tw:gap-3 tw:w-full', className)}\n {...props}\n >\n {children}\n </div>\n);\n\nconst Search = ({ ref, className, children, ...props }: DivProps) => (\n <div\n ref={ref}\n className={cn(\n 'tw:mr-auto tw:flex tw:items-center tw:gap-2 tw:w-full tw:sm:w-auto tw:sm:min-w-64 tw:sm:max-w-md',\n // The slot sizes itself between `min-w-64` and `max-w-md`, so the search field has to fill it —\n // without this the input stays content-width (≈224px inside a 448px slot) and truncates its own\n // placeholder, and every caller ends up hand-picking a width class to compensate.\n //\n // - First child only. The documented composition is the search field followed by filter pills;\n // stretching every child would size the pills to match the input.\n // - `min-w-0` so a long value shrinks the input rather than overflowing the toolbar.\n 'tw:*:first:min-w-0 tw:*:first:flex-1',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n);\n\nconst Right = ({ ref, className, children, ...props }: DivProps) => (\n <div\n ref={ref}\n className={cn('tw:flex tw:flex-wrap tw:items-center tw:gap-2', className)}\n {...props}\n >\n {children}\n </div>\n);\n\nconst ControlGroup = ({ ref, className, children, ...props }: DivProps) => (\n <div ref={ref} className={cn('tw:flex tw:items-center tw:gap-2', className)} {...props}>\n {children}\n </div>\n);\n\nconst ActiveFilters = ({ ref, className, children, ...props }: DivProps) => (\n <div\n ref={ref}\n className={cn('tw:flex tw:flex-wrap tw:items-center tw:gap-2 tw:basis-full', className)}\n {...props}\n >\n {children}\n </div>\n);\n\ntype ChipProps = Omit<\n ComponentPropsWithoutRef<typeof Badge>,\n 'variant' | 'color' | 'suffix' | 'children'\n> & {\n children: ReactNode;\n onRemove: () => void;\n removeAriaLabel: string;\n};\n\nconst Chip = ({ children, onRemove, removeAriaLabel, ...props }: ChipProps) => (\n <Badge\n {...props}\n variant=\"pill\"\n color=\"blue-inverse\"\n suffix={\n <Button\n type=\"button\"\n variant=\"inline\"\n size=\"icon-2xs\"\n aria-label={removeAriaLabel}\n onClick={onRemove}\n >\n <X className=\"tw:size-3\" />\n </Button>\n }\n >\n {children}\n </Badge>\n);\n\ntype ActionProps = ComponentPropsWithoutRef<typeof Button>;\n\nconst AddFilter = ({ className, children, ...props }: ActionProps) => (\n <Button variant=\"invisible\" size=\"small\" className={cn('tw:gap-1.5', className)} {...props}>\n <Plus className=\"tw:size-4\" />\n {children ?? 'Add filter'}\n </Button>\n);\n\nconst Clear = ({ className, children, ...props }: ActionProps) => (\n <Button variant=\"invisible\" size=\"small\" className={cn('tw:ml-auto', className)} {...props}>\n {children ?? 'Clear all'}\n </Button>\n);\n\n/**\n * Two-row toolbar for index pages — search on the left, filter / sort / utility / view\n * controls on the right, an optional Active Filters row below for filter chips or tokens.\n *\n * **When to use:** every index page that supports search or filtering. Hosts inside\n * `PageLayout` as the search / filter row, between `PageLayout.Header` and `PageLayout.Content`.\n * **When NOT to use:** detail pages, form pages, or anywhere there is no search / filter\n * surface. For routing-based tab rows reach for `PageLayout.Tabs`.\n *\n * **Recommended composition (enforced at the call site):**\n *\n * - `Search` sits on the left; the right cluster auto-aligns via flex.\n * - Right cluster order: `Filters` → `Sort` → `Actions` → `View`. View controls are always\n * the final control group — do not render any control after `View`.\n * - `ActiveFilters` is the second row. Render it only when one or more filters are active.\n * - `Clear` self-aligns to the far right of `ActiveFilters`.\n *\n * The block is variant-agnostic: render filter chips (Standard variant, non-editable) or\n * tokens (Query Builder variant, editable) into `ActiveFilters` as plain children — do not\n * mix the two in one toolbar.\n *\n * @see https://github.com/evviku/design-system-docs/blob/main/docs/patterns/toolbar/toolbar.md\n */\nexport const PageToolbar = Object.assign(Root, {\n /** Left slot — typically a `SearchInput`. */\n Search,\n /** Right cluster — host the four control groups below in the recommended order. */\n Right,\n /** Filter controls (`Combobox`, `Select`, `DatePicker`). */\n Filters: ControlGroup,\n /** Sort control. */\n Sort: ControlGroup,\n /** Utility actions (Export, Refresh, …). */\n Actions: ControlGroup,\n /** View toggle (List / Grid). Always render last in the right cluster. */\n View: ControlGroup,\n /**\n * Active filters row. Render only when one or more filters are active. Pass filter chips\n * (Standard variant) or tokens (Query Builder variant) as children, optionally followed\n * by `AddFilter` / `Clear`.\n */\n ActiveFilters,\n /** Non-editable filter chip (Standard variant) — `Badge` pill with a dismiss button. */\n Chip,\n /**\n * Editable filter token (Query Builder variant) — `Badge` pill with a `chevron-down`\n * popover trigger for editing values and an `×` dismiss button. The popover content\n * is supplied by the caller via the `popover` slot (typically a `Combobox` or option list).\n */\n Token: PageToolbarToken,\n /** \"+ Add filter\" action — typically rendered after the chips/tokens in `ActiveFilters`. */\n AddFilter,\n /** \"Clear all\" action — self-aligns to the far right of `ActiveFilters`. */\n Clear,\n});\n"],"mappings":";;;;;;;;;;;;AAuBA,MAAa,oBAAoB,EAC/B,UACA,SACA,UACA,iBACA,GAAG,YAEH,qBAAC,SAAD,EAAA,UAAA,CACE,oBAAC,OAAD;CACE,GAAI;CACJ,SAAA;CACA,SAAQ;CACR,OAAM;CACN,QACE,oBAAC,QAAD;EACE,MAAK;EACL,SAAQ;EACR,MAAK;EACL,cAAY;EACZ,SAAS;EAET,UAAA,oBAAC,GAAD,EAAG,WAAU,YAAa,CAAA;CACpB,CAAA;CAGV,UAAA,qBAAC,QAAQ,SAAT;EACE,MAAK;EACL,WAAU;EAFZ,UAAA,CAIG,UACD,oBAAC,aAAD,EAAa,WAAU,YAAa,CAAA,CACrB;;AACZ,CAAA,GACP,oBAAC,QAAQ,SAAT;CAAiB,OAAM;CAAS,UAAA;AAAyB,CAAA,CAClD,EAAA,CAAA;;;AC9CX,MAAM,QAAQ,EAAE,KAAK,WAAW,UAAU,GAAG,YAC3C,oBAAC,OAAD;CACO;CACL,WAAW,GAAG,2DAA2D,SAAS;CAClF,GAAI;CAEH;AACE,CAAA;AAGP,MAAM,UAAU,EAAE,KAAK,WAAW,UAAU,GAAG,YAC7C,oBAAC,OAAD;CACO;CACL,WAAW,GACT,oGAQA,wCACA,SACF;CACA,GAAI;CAEH;AACE,CAAA;AAGP,MAAM,SAAS,EAAE,KAAK,WAAW,UAAU,GAAG,YAC5C,oBAAC,OAAD;CACO;CACL,WAAW,GAAG,iDAAiD,SAAS;CACxE,GAAI;CAEH;AACE,CAAA;AAGP,MAAM,gBAAgB,EAAE,KAAK,WAAW,UAAU,GAAG,YACnD,oBAAC,OAAD;CAAU;CAAK,WAAW,GAAG,oCAAoC,SAAS;CAAG,GAAI;CAC9E;AACE,CAAA;AAGP,MAAM,iBAAiB,EAAE,KAAK,WAAW,UAAU,GAAG,YACpD,oBAAC,OAAD;CACO;CACL,WAAW,GAAG,+DAA+D,SAAS;CACtF,GAAI;CAEH;AACE,CAAA;AAYP,MAAM,QAAQ,EAAE,UAAU,UAAU,iBAAiB,GAAG,YACtD,oBAAC,OAAD;CACE,GAAI;CACJ,SAAQ;CACR,OAAM;CACN,QACE,oBAAC,QAAD;EACE,MAAK;EACL,SAAQ;EACR,MAAK;EACL,cAAY;EACZ,SAAS;EAET,UAAA,oBAAC,GAAD,EAAG,WAAU,YAAa,CAAA;CACpB,CAAA;CAGT;AACI,CAAA;AAKT,MAAM,aAAa,EAAE,WAAW,UAAU,GAAG,YAC3C,qBAAC,QAAD;CAAQ,SAAQ;CAAY,MAAK;CAAQ,WAAW,GAAG,cAAc,SAAS;CAAG,GAAI;CAArF,UAAA,CACE,oBAAC,MAAD,EAAM,WAAU,YAAa,CAAA,GAC5B,YAAY,YACP;;AAGV,MAAM,SAAS,EAAE,WAAW,UAAU,GAAG,YACvC,oBAAC,QAAD;CAAQ,SAAQ;CAAY,MAAK;CAAQ,WAAW,GAAG,cAAc,SAAS;CAAG,GAAI;CAClF,UAAA,YAAY;AACP,CAAA;;;;;;;;;;;;;;;;;;;;;;;;AA0BV,MAAa,cAAc,OAAO,OAAO,MAAM;;CAE7C;;CAEA;;CAEA,SAAS;;CAET,MAAM;;CAEN,SAAS;;CAET,MAAM;;;;;;CAMN;;CAEA;;;;;;CAMA,OAAO;;CAEP;;CAEA;AACF,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { cn } from "./classNames-BzrkDnOD.js";
2
- import { Tooltip } from "./utils-DSvrhU8E.js";
2
+ import { Tooltip } from "./utils-BW4AE8VP.js";
3
3
  import { useArgoDesign } from "./context-D7X470dy.js";
4
4
  import { Circle } from "./icons-Cek151jC.js";
5
5
  import { Separator } from "./internal/components/Separator.js";
@@ -230,4 +230,4 @@ RadioGroup.Separator = RadioGroupSeparator;
230
230
  //#endregion
231
231
  export { RadioGroup };
232
232
 
233
- //# sourceMappingURL=RadioGroup-DXPbSj8P.js.map
233
+ //# sourceMappingURL=RadioGroup-Byc2mym4.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RadioGroup-DXPbSj8P.js","names":[],"sources":["../src/components/RadioGroup/context.ts","../src/components/RadioGroup/styles.ts","../src/components/RadioGroup/Radio.tsx","../src/components/RadioGroup/RadioGroupItemButton.tsx","../src/components/RadioGroup/RadioGroupItem.tsx","../src/components/RadioGroup/RadioGroupSeparator.tsx","../src/components/RadioGroup/RadioGroup.tsx"],"sourcesContent":["import { createContext, use } from 'react';\n\nexport type Variant = 'radio' | 'button' | 'radio-block';\nexport type Orientation = 'vertical' | 'horizontal';\n\nconst RadioGroupContext = createContext<{\n variant: Variant;\n orientation: Orientation;\n}>({\n variant: 'radio',\n orientation: 'horizontal',\n});\n\nexport const RadioGroupProvider = RadioGroupContext;\n\nexport const useRadioGroupContext = () => use(RadioGroupContext);\n","import { cva } from 'class-variance-authority';\n\nexport const radioVariants = cva(\n [\n // reset\n 'tw:bg-transparent',\n 'tw:p-0',\n 'tw:peer',\n 'tw:cursor-pointer',\n 'tw:whitespace-nowrap',\n 'tw:shrink-0',\n\n // position\n 'tw:flex',\n 'tw:items-center',\n 'tw:justify-center',\n\n 'tw:disabled:cursor-not-allowed',\n\n 'tw:size-4',\n\n // border\n 'tw:rounded-full',\n 'tw:border',\n 'tw:border-solid',\n ],\n {\n defaultVariants: {\n variant: 'default',\n },\n variants: {\n variant: {\n default: [\n 'tw:disabled:opacity-40',\n\n 'tw:data-[state=checked]:border-primary',\n 'tw:data-[state=unchecked]:border-neutral-200',\n 'tw:data-[state=unchecked]:hover:border-primary',\n 'tw:data-[state=unchecked]:disabled:hover:border-neutral-200',\n\n 'tw:focus-visible:ring-2',\n 'tw:focus-visible:ring-ring/30',\n ],\n argo: [\n 'tw:disabled:opacity-50',\n\n 'tw:border-input',\n 'tw:transition-colors',\n\n 'tw:data-[state=checked]:bg-primary',\n 'tw:data-[state=checked]:border-primary',\n\n 'tw:data-[state=unchecked]:not-disabled:hover:bg-accent',\n 'tw:data-[state=checked]:not-disabled:hover:bg-primary',\n\n 'tw:focus-visible:outline-hidden',\n 'tw:focus-visible:border-primary',\n 'tw:focus-visible:ring-2',\n 'tw:focus-visible:ring-ring/50',\n ],\n },\n },\n },\n);\n\nexport const radioIndicatorVariants = cva(['tw:size-2.5', 'tw:fill-current'], {\n defaultVariants: {\n variant: 'default',\n },\n variants: {\n variant: {\n default: ['tw:text-primary'],\n argo: ['tw:text-primary-foreground'],\n },\n },\n});\n\nexport const radioItemButtonVariants = cva(\n [\n // reset\n 'tw:bg-transparent',\n 'tw:p-0',\n 'tw:peer',\n 'tw:cursor-pointer',\n 'tw:whitespace-nowrap',\n\n // position\n 'tw:flex',\n 'tw:items-center',\n 'tw:justify-center',\n\n 'tw:disabled:cursor-not-allowed',\n\n // layouts\n 'tw:w-full',\n 'tw:px-2',\n 'tw:py-1.5',\n\n // fonts\n 'tw:uppercase',\n 'tw:font-semibold',\n 'tw:font-sans',\n 'tw:text-[11px]',\n 'tw:whitespace-nowrap',\n 'tw:tracking-widest',\n 'tw:leading-[18px]',\n\n // border\n 'tw:border',\n 'tw:border-solid',\n 'tw:rounded',\n ],\n {\n defaultVariants: {\n variant: 'default',\n },\n variants: {\n variant: {\n default: [\n 'tw:disabled:opacity-40',\n 'tw:text-secondary-600',\n 'tw:border-secondary-500',\n\n 'tw:data-[state=unchecked]:hover:bg-secondary-500',\n 'tw:data-[state=unchecked]:hover:text-white',\n\n 'tw:data-[state=unchecked]:disabled:hover:bg-white',\n 'tw:data-[state=unchecked]:disabled:hover:text-secondary-500',\n 'tw:data-[state=checked]:disabled:cursor-not-allowed',\n\n 'tw:data-[state=unchecked]:bg-white',\n 'tw:data-[state=checked]:bg-secondary-500',\n 'tw:data-[state=checked]:text-white',\n 'tw:data-[state=checked]:cursor-default',\n\n 'tw:focus-visible:outline',\n 'tw:focus-visible:outline-ring',\n 'tw:focus-visible:ring-4',\n 'tw:focus-visible:ring-ring/30',\n ],\n argo: [\n 'tw:disabled:opacity-50',\n 'tw:text-foreground',\n 'tw:border-input',\n 'tw:transition-colors',\n\n // muted filled control surface — gray, distinct from white containers; not the app-background token\n 'tw:data-[state=unchecked]:bg-muted',\n 'tw:data-[state=unchecked]:not-disabled:hover:bg-accent',\n 'tw:data-[state=unchecked]:not-disabled:hover:text-accent-foreground',\n\n 'tw:data-[state=checked]:bg-primary',\n 'tw:data-[state=checked]:border-primary',\n 'tw:data-[state=checked]:text-primary-foreground',\n 'tw:data-[state=checked]:not-disabled:cursor-default',\n\n 'tw:focus-visible:outline-hidden',\n 'tw:focus-visible:border-primary',\n 'tw:focus-visible:ring-2',\n 'tw:focus-visible:ring-ring/50',\n ],\n },\n },\n },\n);\n\nexport type RadioStyleVariant = 'default' | 'argo';\n","import type { ComponentProps } from 'react';\nimport { Indicator, Item } from '@radix-ui/react-radio-group';\n\nimport { Circle } from '../../icons';\nimport { cn } from '../../utils';\n\nimport type { RadioStyleVariant } from './styles';\nimport { radioIndicatorVariants, radioVariants } from './styles';\n\ntype Props = ComponentProps<typeof Item> & { styleVariant?: RadioStyleVariant };\n\nexport const Radio = ({ className, styleVariant = 'default', ...props }: Props) => (\n <Item {...props} className={cn(radioVariants({ variant: styleVariant }), className)}>\n <Indicator className={cn('tw:flex', 'tw:items-center', 'tw:justify-center')}>\n {/* Lucide Circle is stroke-only — force fill to match the stroke (currentColor)\n so the indicator reads as a solid dot. */}\n <Circle className={radioIndicatorVariants({ variant: styleVariant })} />\n </Indicator>\n </Item>\n);\n","import type { ComponentProps } from 'react';\nimport { Item } from '@radix-ui/react-radio-group';\n\nimport { cn } from '../../utils';\n\nimport type { RadioStyleVariant } from './styles';\nimport { radioItemButtonVariants } from './styles';\n\ntype Props = ComponentProps<typeof Item> & { styleVariant?: RadioStyleVariant };\n\nexport const RadioGroupItemButton = ({\n ref,\n className,\n children,\n styleVariant = 'default',\n ...props\n}: Props) => (\n <Item\n ref={ref}\n {...props}\n className={cn(radioItemButtonVariants({ variant: styleVariant }), className)}\n >\n {children}\n </Item>\n);\n","import { useId } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\nimport type { Item } from '@radix-ui/react-radio-group';\n\nimport { cn } from '../../utils';\nimport { FieldBox } from '../FieldBox';\nimport { useArgoDesign } from '../ThemeProvider/context';\nimport type { Props as TooltipProps } from '../Tooltip';\nimport { Tooltip } from '../Tooltip';\n\nimport { useRadioGroupContext } from './context';\nimport { Radio } from './Radio';\nimport { RadioGroupItemButton } from './RadioGroupItemButton';\n\ntype ItemProps = Omit<ComponentProps<typeof Item>, 'asChild' | 'value'>;\n\ntype Props<T extends string = string> = ItemProps & {\n value: T;\n tooltip?: ReactNode;\n tooltipVariant?: TooltipProps['variant'];\n tooltipPlacement?: TooltipProps['placement'];\n description?: ReactNode;\n};\n\nexport const RadioGroupItem = <T extends string = string>({\n children,\n className,\n tooltip,\n tooltipVariant,\n tooltipPlacement,\n description,\n ...props\n}: Props<T>) => {\n const { variant } = useRadioGroupContext();\n const styleVariant = useArgoDesign() ? 'argo' : 'default';\n const id = useId();\n\n const item = (() => {\n if (variant === 'button')\n return (\n <RadioGroupItemButton styleVariant={styleVariant} {...props} className={className}>\n {children}\n </RadioGroupItemButton>\n );\n\n return (\n <FieldBox\n variant={variant === 'radio-block' ? 'boxed' : 'default'}\n htmlFor={id}\n control={<Radio styleVariant={styleVariant} {...props} id={id} />}\n className={cn(variant === 'radio-block' && 'tw:flex-1', className)}\n >\n <FieldBox.Title>{children}</FieldBox.Title>\n {description && <FieldBox.Description>{description}</FieldBox.Description>}\n </FieldBox>\n );\n })();\n\n if (!tooltip) {\n return item;\n }\n\n return (\n <Tooltip tooltip={tooltip} variant={tooltipVariant} placement={tooltipPlacement} triggerAsChild>\n {item}\n </Tooltip>\n );\n};\n","import { Separator } from '../Separator';\n\nimport { useRadioGroupContext } from './context';\n\nexport const RadioGroupSeparator = () => {\n const { orientation } = useRadioGroupContext();\n const invertedOrientation = orientation === 'horizontal' ? 'vertical' : 'horizontal';\n const size = orientation === 'horizontal' ? '1/2' : 'full';\n const className = orientation === 'horizontal' ? 'tw:mx-2' : 'tw:my-2';\n\n return <Separator orientation={invertedOrientation} size={size} className={className} />;\n};\n","import type { ComponentProps } from 'react';\nimport * as RRadioGroup from '@radix-ui/react-radio-group';\nimport { cva } from 'class-variance-authority';\n\nimport { cn } from '../../utils';\n\nimport type { Orientation, Variant } from './context';\nimport { RadioGroupProvider } from './context';\nimport { RadioGroupItem } from './RadioGroupItem';\nimport { RadioGroupSeparator } from './RadioGroupSeparator';\n\nconst radioGroupVariants = cva(['tw:flex'], {\n variants: {\n orientation: {\n horizontal: ['tw:gap-2'],\n vertical: ['tw:flex-col', 'tw:gap-3'],\n },\n variant: {\n button: [],\n radio: [],\n 'radio-block': ['tw:w-full'],\n },\n },\n});\n\ntype Props<Value> = {\n variant?: Variant;\n orientation?: Orientation;\n onValueChange?: (value: Value) => void;\n value?: Value | null;\n defaultValue?: Value | null;\n} & Omit<\n ComponentProps<typeof RRadioGroup.Root>,\n 'asChild' | 'orientation' | 'onValueChange' | 'onChange' | 'value' | 'defaultValue'\n>;\n\nexport const RadioGroup = <Value extends string = string>({\n variant = 'radio',\n className,\n disabled = false,\n orientation = 'horizontal',\n onValueChange,\n children,\n value,\n defaultValue,\n ...props\n}: Props<Value>) => (\n <RRadioGroup.Root\n {...props}\n onValueChange={onValueChange}\n orientation={orientation}\n className={cn(radioGroupVariants({ orientation, variant, className }))}\n disabled={disabled}\n value={value ?? void 0}\n defaultValue={defaultValue ?? void 0}\n >\n <RadioGroupProvider value={{ variant, orientation }}>{children}</RadioGroupProvider>\n </RRadioGroup.Root>\n);\n\nRadioGroup.Item = RadioGroupItem;\nRadioGroup.Separator = RadioGroupSeparator;\n"],"mappings":"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"}
1
+ {"version":3,"file":"RadioGroup-Byc2mym4.js","names":[],"sources":["../src/components/RadioGroup/context.ts","../src/components/RadioGroup/styles.ts","../src/components/RadioGroup/Radio.tsx","../src/components/RadioGroup/RadioGroupItemButton.tsx","../src/components/RadioGroup/RadioGroupItem.tsx","../src/components/RadioGroup/RadioGroupSeparator.tsx","../src/components/RadioGroup/RadioGroup.tsx"],"sourcesContent":["import { createContext, use } from 'react';\n\nexport type Variant = 'radio' | 'button' | 'radio-block';\nexport type Orientation = 'vertical' | 'horizontal';\n\nconst RadioGroupContext = createContext<{\n variant: Variant;\n orientation: Orientation;\n}>({\n variant: 'radio',\n orientation: 'horizontal',\n});\n\nexport const RadioGroupProvider = RadioGroupContext;\n\nexport const useRadioGroupContext = () => use(RadioGroupContext);\n","import { cva } from 'class-variance-authority';\n\nexport const radioVariants = cva(\n [\n // reset\n 'tw:bg-transparent',\n 'tw:p-0',\n 'tw:peer',\n 'tw:cursor-pointer',\n 'tw:whitespace-nowrap',\n 'tw:shrink-0',\n\n // position\n 'tw:flex',\n 'tw:items-center',\n 'tw:justify-center',\n\n 'tw:disabled:cursor-not-allowed',\n\n 'tw:size-4',\n\n // border\n 'tw:rounded-full',\n 'tw:border',\n 'tw:border-solid',\n ],\n {\n defaultVariants: {\n variant: 'default',\n },\n variants: {\n variant: {\n default: [\n 'tw:disabled:opacity-40',\n\n 'tw:data-[state=checked]:border-primary',\n 'tw:data-[state=unchecked]:border-neutral-200',\n 'tw:data-[state=unchecked]:hover:border-primary',\n 'tw:data-[state=unchecked]:disabled:hover:border-neutral-200',\n\n 'tw:focus-visible:ring-2',\n 'tw:focus-visible:ring-ring/30',\n ],\n argo: [\n 'tw:disabled:opacity-50',\n\n 'tw:border-input',\n 'tw:transition-colors',\n\n 'tw:data-[state=checked]:bg-primary',\n 'tw:data-[state=checked]:border-primary',\n\n 'tw:data-[state=unchecked]:not-disabled:hover:bg-accent',\n 'tw:data-[state=checked]:not-disabled:hover:bg-primary',\n\n 'tw:focus-visible:outline-hidden',\n 'tw:focus-visible:border-primary',\n 'tw:focus-visible:ring-2',\n 'tw:focus-visible:ring-ring/50',\n ],\n },\n },\n },\n);\n\nexport const radioIndicatorVariants = cva(['tw:size-2.5', 'tw:fill-current'], {\n defaultVariants: {\n variant: 'default',\n },\n variants: {\n variant: {\n default: ['tw:text-primary'],\n argo: ['tw:text-primary-foreground'],\n },\n },\n});\n\nexport const radioItemButtonVariants = cva(\n [\n // reset\n 'tw:bg-transparent',\n 'tw:p-0',\n 'tw:peer',\n 'tw:cursor-pointer',\n 'tw:whitespace-nowrap',\n\n // position\n 'tw:flex',\n 'tw:items-center',\n 'tw:justify-center',\n\n 'tw:disabled:cursor-not-allowed',\n\n // layouts\n 'tw:w-full',\n 'tw:px-2',\n 'tw:py-1.5',\n\n // fonts\n 'tw:uppercase',\n 'tw:font-semibold',\n 'tw:font-sans',\n 'tw:text-[11px]',\n 'tw:whitespace-nowrap',\n 'tw:tracking-widest',\n 'tw:leading-[18px]',\n\n // border\n 'tw:border',\n 'tw:border-solid',\n 'tw:rounded',\n ],\n {\n defaultVariants: {\n variant: 'default',\n },\n variants: {\n variant: {\n default: [\n 'tw:disabled:opacity-40',\n 'tw:text-secondary-600',\n 'tw:border-secondary-500',\n\n 'tw:data-[state=unchecked]:hover:bg-secondary-500',\n 'tw:data-[state=unchecked]:hover:text-white',\n\n 'tw:data-[state=unchecked]:disabled:hover:bg-white',\n 'tw:data-[state=unchecked]:disabled:hover:text-secondary-500',\n 'tw:data-[state=checked]:disabled:cursor-not-allowed',\n\n 'tw:data-[state=unchecked]:bg-white',\n 'tw:data-[state=checked]:bg-secondary-500',\n 'tw:data-[state=checked]:text-white',\n 'tw:data-[state=checked]:cursor-default',\n\n 'tw:focus-visible:outline',\n 'tw:focus-visible:outline-ring',\n 'tw:focus-visible:ring-4',\n 'tw:focus-visible:ring-ring/30',\n ],\n argo: [\n 'tw:disabled:opacity-50',\n 'tw:text-foreground',\n 'tw:border-input',\n 'tw:transition-colors',\n\n // muted filled control surface — gray, distinct from white containers; not the app-background token\n 'tw:data-[state=unchecked]:bg-muted',\n 'tw:data-[state=unchecked]:not-disabled:hover:bg-accent',\n 'tw:data-[state=unchecked]:not-disabled:hover:text-accent-foreground',\n\n 'tw:data-[state=checked]:bg-primary',\n 'tw:data-[state=checked]:border-primary',\n 'tw:data-[state=checked]:text-primary-foreground',\n 'tw:data-[state=checked]:not-disabled:cursor-default',\n\n 'tw:focus-visible:outline-hidden',\n 'tw:focus-visible:border-primary',\n 'tw:focus-visible:ring-2',\n 'tw:focus-visible:ring-ring/50',\n ],\n },\n },\n },\n);\n\nexport type RadioStyleVariant = 'default' | 'argo';\n","import type { ComponentProps } from 'react';\nimport { Indicator, Item } from '@radix-ui/react-radio-group';\n\nimport { Circle } from '../../icons';\nimport { cn } from '../../utils';\n\nimport type { RadioStyleVariant } from './styles';\nimport { radioIndicatorVariants, radioVariants } from './styles';\n\ntype Props = ComponentProps<typeof Item> & { styleVariant?: RadioStyleVariant };\n\nexport const Radio = ({ className, styleVariant = 'default', ...props }: Props) => (\n <Item {...props} className={cn(radioVariants({ variant: styleVariant }), className)}>\n <Indicator className={cn('tw:flex', 'tw:items-center', 'tw:justify-center')}>\n {/* Lucide Circle is stroke-only — force fill to match the stroke (currentColor)\n so the indicator reads as a solid dot. */}\n <Circle className={radioIndicatorVariants({ variant: styleVariant })} />\n </Indicator>\n </Item>\n);\n","import type { ComponentProps } from 'react';\nimport { Item } from '@radix-ui/react-radio-group';\n\nimport { cn } from '../../utils';\n\nimport type { RadioStyleVariant } from './styles';\nimport { radioItemButtonVariants } from './styles';\n\ntype Props = ComponentProps<typeof Item> & { styleVariant?: RadioStyleVariant };\n\nexport const RadioGroupItemButton = ({\n ref,\n className,\n children,\n styleVariant = 'default',\n ...props\n}: Props) => (\n <Item\n ref={ref}\n {...props}\n className={cn(radioItemButtonVariants({ variant: styleVariant }), className)}\n >\n {children}\n </Item>\n);\n","import { useId } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\nimport type { Item } from '@radix-ui/react-radio-group';\n\nimport { cn } from '../../utils';\nimport { FieldBox } from '../FieldBox';\nimport { useArgoDesign } from '../ThemeProvider/context';\nimport type { Props as TooltipProps } from '../Tooltip';\nimport { Tooltip } from '../Tooltip';\n\nimport { useRadioGroupContext } from './context';\nimport { Radio } from './Radio';\nimport { RadioGroupItemButton } from './RadioGroupItemButton';\n\ntype ItemProps = Omit<ComponentProps<typeof Item>, 'asChild' | 'value'>;\n\ntype Props<T extends string = string> = ItemProps & {\n value: T;\n tooltip?: ReactNode;\n tooltipVariant?: TooltipProps['variant'];\n tooltipPlacement?: TooltipProps['placement'];\n description?: ReactNode;\n};\n\nexport const RadioGroupItem = <T extends string = string>({\n children,\n className,\n tooltip,\n tooltipVariant,\n tooltipPlacement,\n description,\n ...props\n}: Props<T>) => {\n const { variant } = useRadioGroupContext();\n const styleVariant = useArgoDesign() ? 'argo' : 'default';\n const id = useId();\n\n const item = (() => {\n if (variant === 'button')\n return (\n <RadioGroupItemButton styleVariant={styleVariant} {...props} className={className}>\n {children}\n </RadioGroupItemButton>\n );\n\n return (\n <FieldBox\n variant={variant === 'radio-block' ? 'boxed' : 'default'}\n htmlFor={id}\n control={<Radio styleVariant={styleVariant} {...props} id={id} />}\n className={cn(variant === 'radio-block' && 'tw:flex-1', className)}\n >\n <FieldBox.Title>{children}</FieldBox.Title>\n {description && <FieldBox.Description>{description}</FieldBox.Description>}\n </FieldBox>\n );\n })();\n\n if (!tooltip) {\n return item;\n }\n\n return (\n <Tooltip tooltip={tooltip} variant={tooltipVariant} placement={tooltipPlacement} triggerAsChild>\n {item}\n </Tooltip>\n );\n};\n","import { Separator } from '../Separator';\n\nimport { useRadioGroupContext } from './context';\n\nexport const RadioGroupSeparator = () => {\n const { orientation } = useRadioGroupContext();\n const invertedOrientation = orientation === 'horizontal' ? 'vertical' : 'horizontal';\n const size = orientation === 'horizontal' ? '1/2' : 'full';\n const className = orientation === 'horizontal' ? 'tw:mx-2' : 'tw:my-2';\n\n return <Separator orientation={invertedOrientation} size={size} className={className} />;\n};\n","import type { ComponentProps } from 'react';\nimport * as RRadioGroup from '@radix-ui/react-radio-group';\nimport { cva } from 'class-variance-authority';\n\nimport { cn } from '../../utils';\n\nimport type { Orientation, Variant } from './context';\nimport { RadioGroupProvider } from './context';\nimport { RadioGroupItem } from './RadioGroupItem';\nimport { RadioGroupSeparator } from './RadioGroupSeparator';\n\nconst radioGroupVariants = cva(['tw:flex'], {\n variants: {\n orientation: {\n horizontal: ['tw:gap-2'],\n vertical: ['tw:flex-col', 'tw:gap-3'],\n },\n variant: {\n button: [],\n radio: [],\n 'radio-block': ['tw:w-full'],\n },\n },\n});\n\ntype Props<Value> = {\n variant?: Variant;\n orientation?: Orientation;\n onValueChange?: (value: Value) => void;\n value?: Value | null;\n defaultValue?: Value | null;\n} & Omit<\n ComponentProps<typeof RRadioGroup.Root>,\n 'asChild' | 'orientation' | 'onValueChange' | 'onChange' | 'value' | 'defaultValue'\n>;\n\nexport const RadioGroup = <Value extends string = string>({\n variant = 'radio',\n className,\n disabled = false,\n orientation = 'horizontal',\n onValueChange,\n children,\n value,\n defaultValue,\n ...props\n}: Props<Value>) => (\n <RRadioGroup.Root\n {...props}\n onValueChange={onValueChange}\n orientation={orientation}\n className={cn(radioGroupVariants({ orientation, variant, className }))}\n disabled={disabled}\n value={value ?? void 0}\n defaultValue={defaultValue ?? void 0}\n >\n <RadioGroupProvider value={{ variant, orientation }}>{children}</RadioGroupProvider>\n </RRadioGroup.Root>\n);\n\nRadioGroup.Item = RadioGroupItem;\nRadioGroup.Separator = RadioGroupSeparator;\n"],"mappings":";;;;;;;;;;;;AAKA,MAAM,oBAAoB,cAGvB;CACD,SAAS;CACT,aAAa;AACf,CAAC;AAED,MAAa,qBAAqB;AAElC,MAAa,6BAA6B,IAAI,iBAAiB;;;ACb/D,MAAa,gBAAgB,IAC3B;CAEE;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CAEA;CAEA;CAGA;CACA;CACA;AACF,GACA;CACE,iBAAiB,EACf,SAAS,UACX;CACA,UAAU,EACR,SAAS;EACP,SAAS;GACP;GAEA;GACA;GACA;GACA;GAEA;GACA;EACF;EACA,MAAM;GACJ;GAEA;GACA;GAEA;GACA;GAEA;GACA;GAEA;GACA;GACA;GACA;EACF;CACF,EACF;AACF,CACF;AAEA,MAAa,yBAAyB,IAAI,CAAC,eAAe,iBAAiB,GAAG;CAC5E,iBAAiB,EACf,SAAS,UACX;CACA,UAAU,EACR,SAAS;EACP,SAAS,CAAC,iBAAiB;EAC3B,MAAM,CAAC,4BAA4B;CACrC,EACF;AACF,CAAC;AAED,MAAa,0BAA0B,IACrC;CAEE;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CAEA;CAGA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;AACF,GACA;CACE,iBAAiB,EACf,SAAS,UACX;CACA,UAAU,EACR,SAAS;EACP,SAAS;GACP;GACA;GACA;GAEA;GACA;GAEA;GACA;GACA;GAEA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;EACF;EACA,MAAM;GACJ;GACA;GACA;GACA;GAGA;GACA;GACA;GAEA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;EACF;CACF,EACF;AACF,CACF;;;ACzJA,MAAa,SAAS,EAAE,WAAW,eAAe,WAAW,GAAG,YAC9D,oBAAC,MAAD;CAAM,GAAI;CAAO,WAAW,GAAG,cAAc,EAAE,SAAS,aAAa,CAAC,GAAG,SAAS;CAChF,UAAA,oBAAC,WAAD;EAAW,WAAW,GAAG,WAAW,mBAAmB,mBAAmB;EAGxE,UAAA,oBAAC,QAAD,EAAQ,WAAW,uBAAuB,EAAE,SAAS,aAAa,CAAC,EAAI,CAAA;CAC9D,CAAA;AACP,CAAA;;;ACRR,MAAa,wBAAwB,EACnC,KACA,WACA,UACA,eAAe,WACf,GAAG,YAEH,oBAAC,MAAD;CACO;CACL,GAAI;CACJ,WAAW,GAAG,wBAAwB,EAAE,SAAS,aAAa,CAAC,GAAG,SAAS;CAE1E;AACG,CAAA;;;ACCR,MAAa,kBAA6C,EACxD,UACA,WACA,SACA,gBACA,kBACA,aACA,GAAG,YACW;CACd,MAAM,EAAE,YAAY,qBAAqB;CACzC,MAAM,eAAe,cAAc,IAAI,SAAS;CAChD,MAAM,KAAK,MAAM;CAEjB,MAAM,cAAc;EAClB,IAAI,YAAY,UACd,OACE,oBAAC,sBAAD;GAAoC;GAAc,GAAI;GAAkB;GACrE;EACmB,CAAA;EAG1B,OACE,qBAAC,UAAD;GACE,SAAS,YAAY,gBAAgB,UAAU;GAC/C,SAAS;GACT,SAAS,oBAAC,OAAD;IAAqB;IAAc,GAAI;IAAW;GAAK,CAAA;GAChE,WAAW,GAAG,YAAY,iBAAiB,aAAa,SAAS;GAJnE,UAAA,CAME,oBAAC,SAAS,OAAV,EAAiB,SAAyB,CAAA,GACzC,eAAe,oBAAC,SAAS,aAAV,EAAA,UAAuB,YAAkC,CAAA,CACjE;;CAEd,EAAA,CAAG;CAEH,IAAI,CAAC,SACH,OAAO;CAGT,OACE,oBAAC,SAAD;EAAkB;EAAS,SAAS;EAAgB,WAAW;EAAkB,gBAAA;EAC9E,UAAA;CACM,CAAA;AAEb;;;AC/DA,MAAa,4BAA4B;CACvC,MAAM,EAAE,gBAAgB,qBAAqB;CAK7C,OAAO,oBAAC,WAAD;EAAW,aAJU,gBAAgB,eAAe,aAAa;EAIpB,MAHvC,gBAAgB,eAAe,QAAQ;EAGY,WAF9C,gBAAgB,eAAe,YAAY;CAE0B,CAAA;AACzF;;;ACAA,MAAM,qBAAqB,IAAI,CAAC,SAAS,GAAG,EAC1C,UAAU;CACR,aAAa;EACX,YAAY,CAAC,UAAU;EACvB,UAAU,CAAC,eAAe,UAAU;CACtC;CACA,SAAS;EACP,QAAQ,CAAC;EACT,OAAO,CAAC;EACR,eAAe,CAAC,WAAW;CAC7B;AACF,EACF,CAAC;AAaD,MAAa,cAA6C,EACxD,UAAU,SACV,WACA,WAAW,OACX,cAAc,cACd,eACA,UACA,OACA,cACA,GAAG,YAEH,oBAAC,YAAY,MAAb;CACE,GAAI;CACW;CACF;CACb,WAAW,GAAG,mBAAmB;EAAE;EAAa;EAAS;CAAU,CAAC,CAAC;CAC3D;CACV,OAAO,SAAS,KAAK;CACrB,cAAc,gBAAgB,KAAK;CAEnC,UAAA,oBAAC,oBAAD;EAAoB,OAAO;GAAE;GAAS;EAAY;EAAI;CAA6B,CAAA;AACnE,CAAA;AAGpB,WAAW,OAAO;AAClB,WAAW,YAAY"}
@@ -1,5 +1,5 @@
1
1
  import { cn } from "./classNames-BzrkDnOD.js";
2
- import { createPrefixedString, debounce, noop } from "./utils-DSvrhU8E.js";
2
+ import { createPrefixedString, debounce, noop } from "./utils-BW4AE8VP.js";
3
3
  import { Search as Search$1, Sparkles, X } from "./icons-Cek151jC.js";
4
4
  import { useEffect, useMemo, useState } from "react";
5
5
  import { cva } from "class-variance-authority";
@@ -181,4 +181,4 @@ const SearchForm = ({ ref, onSubmit, name = "search-field", ...props }) => {
181
181
  //#endregion
182
182
  export { Search, SearchForm };
183
183
 
184
- //# sourceMappingURL=Search-5uQAiNIP.js.map
184
+ //# sourceMappingURL=Search-Dhig_hPD.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Search-5uQAiNIP.js","names":["SearchIcon"],"sources":["../src/components/Search/ClearButton.tsx","../src/components/Search/styles.ts","../src/components/Search/utils.ts","../src/components/Search/Search.tsx","../src/components/Search/SearchForm.tsx"],"sourcesContent":["import type { MouseEventHandler } from 'react';\n\nimport { X } from '../../icons';\nimport { cn } from '../../utils';\n\ntype Props = {\n onClick: MouseEventHandler<HTMLButtonElement>;\n testId?: string;\n};\n\nexport const ClearButton = ({ onClick, testId }: Props) => {\n // Prevent default, as we do not want to lose input focus.\n const handleMouseDown: MouseEventHandler<HTMLButtonElement> = (event) => {\n event.preventDefault();\n };\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n tabIndex={-1} // clear button should not be focusable\n onMouseDown={handleMouseDown}\n className={cn(\n // reset\n 'tw:border-none',\n 'tw:bg-transparent',\n 'tw:p-0',\n\n // positioning\n 'tw:flex',\n 'tw:items-center',\n\n 'tw:cursor-pointer',\n 'tw:text-muted-foreground',\n 'tw:hover:text-foreground',\n )}\n data-testid={testId}\n >\n <X className=\"tw:size-4\" />\n </button>\n );\n};\n","import { cva } from 'class-variance-authority';\n\nexport const searchWrapperVariants = cva(\n [\n // positioning\n 'tw:flex',\n 'tw:items-center',\n 'tw:gap-2.5',\n\n // base\n 'tw:text-card-foreground',\n 'tw:transition-all',\n 'tw:font-sans',\n\n // readonly — `secondary` over `muted`, which is too close to the `card` fill to\n // read as non-editable in either scheme\n 'tw:has-[input[readonly]]:bg-secondary',\n 'tw:has-[input[readonly]]:focus-within:ring-0',\n 'tw:has-[input[readonly]]:outline-0',\n\n // disabled\n 'tw:disabled:opacity-40',\n\n // default input padding (was sizing.default)\n 'tw:[&>input]:py-[15px]',\n ],\n {\n defaultVariants: {\n variant: 'default',\n },\n variants: {\n variant: {\n default: [\n 'tw:rounded-lg',\n 'tw:px-5',\n 'tw:bg-card',\n 'tw:shadow-raised',\n // outline\n 'tw:outline',\n 'tw:outline-1',\n 'tw:outline-transparent',\n // focus\n 'tw:has-[input:focus]:outline-1',\n 'tw:has-[input:focus]:ring-4',\n 'tw:has-[input:focus]:outline-ring',\n 'tw:has-[input:focus]:ring-ring/30',\n ],\n ai: [\n 'tailwindcss-preflight',\n 'tw:relative',\n 'tw:rounded-card',\n 'tw:px-4',\n 'tw:cursor-text',\n 'tw:border-2',\n 'tw:border-transparent',\n 'tw:bg-gradient-to-br',\n 'tw:from-secondary-600',\n 'tw:to-purple-600',\n 'tw:bg-origin-border',\n // Floods the interior so the gradient shows only in the 2px border box.\n 'tw:shadow-[inset_0_100vw_rgb(var(--card))]',\n // focus\n 'tw:has-[input:focus]:ring-4',\n 'tw:has-[input:focus]:ring-ring/30',\n ],\n },\n },\n },\n);\n\nexport const searchInputClassnames = [\n // reset\n 'tw:border-none',\n 'tw:bg-transparent',\n 'tw:outline-hidden',\n 'tw:w-full',\n 'tw:p-0',\n\n // base\n 'tw:text-base',\n 'tw:leading-6',\n 'tw:font-normal',\n 'tw:font-sans',\n\n // placeholder\n 'tw:placeholder:text-muted-foreground',\n\n // disabled\n 'tw:disabled:cursor-not-allowed',\n].join(' ');\n","import { createPrefixedString } from '../../utils';\n\nexport const genSearchTestId = (prefix: string = '') => {\n const ps = createPrefixedString(prefix);\n return {\n toString: () => prefix,\n wrapper: ps`search-wrapper`,\n input: ps`search-input`,\n clearButton: ps`search-clear-button`,\n };\n};\n","import { useEffect, useMemo, useState } from 'react';\nimport type {\n ChangeEvent,\n ChangeEventHandler,\n ComponentProps,\n FocusEvent,\n FocusEventHandler,\n MouseEvent,\n MouseEventHandler,\n ReactNode,\n} from 'react';\n\nimport { Search as SearchIcon, Sparkles } from '../../icons';\nimport { cn, debounce, noop } from '../../utils';\n\nimport { ClearButton } from './ClearButton';\nimport { searchInputClassnames, searchWrapperVariants } from './styles';\nimport { genSearchTestId } from './utils';\n\ntype SearchChangeEventHandler = (\n value: string,\n event: ChangeEvent<HTMLInputElement> | MouseEvent<HTMLButtonElement>,\n) => void;\n\ntype SearchBlurEventHandler = (value: string, event: FocusEvent<HTMLInputElement, Element>) => void;\n\ntype Props = {\n suffix?: ReactNode;\n disableDebounce?: boolean;\n debounceDelay?: number;\n onChange?: SearchChangeEventHandler;\n onBlur?: SearchBlurEventHandler;\n value?: string | null;\n defaultValue?: string | null;\n testId?: string;\n onClear?: () => void;\n variant?: 'default' | 'ai';\n} & Omit<\n ComponentProps<'input'>,\n 'type' | 'onBlur' | 'onChange' | 'value' | 'defaultValue' | 'prefix' | 'suffix'\n>;\n\n/**\n * @deprecated Use `SearchInput` instead. `Search` is kept only for the legacy (non-sidebar) layout.\n */\nexport const Search = ({\n ref,\n suffix,\n className,\n onBlur,\n onChange = noop,\n disabled = false,\n readOnly = false,\n disableDebounce = false,\n debounceDelay = 300,\n value: externalValue,\n defaultValue,\n testId: prefixTestId = '',\n placeholder = 'Search',\n onClear,\n variant = 'default',\n ...rest\n}: Props) => {\n const [internalValue, setInternalValue] = useState(() =>\n externalValue != null ? externalValue : defaultValue,\n );\n const hasValue = internalValue !== '';\n\n const isClearButtonVisible = hasValue && !disabled && !readOnly;\n const testId = genSearchTestId(prefixTestId);\n\n const debouncedOnChange = useMemo(\n () => (disableDebounce ? onChange : debounce(onChange, debounceDelay)),\n [disableDebounce, debounceDelay, onChange],\n );\n\n useEffect(() => {\n if (externalValue == null) return; // uncontrolled state\n // oxlint-disable-next-line react-x/set-state-in-effect\n setInternalValue(externalValue);\n }, [externalValue]);\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n const currentValue = event.target.value;\n setInternalValue(currentValue);\n debouncedOnChange(currentValue, event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n const currentValue = event.target.value;\n setInternalValue(currentValue);\n onBlur?.(currentValue, event);\n };\n\n const handleClear: MouseEventHandler<HTMLButtonElement> = (event) => {\n setInternalValue('');\n onChange?.('', event);\n onClear?.();\n };\n\n // Clicking anywhere in the field that isn't an interactive control (the leading icon,\n // the empty chrome) focuses the input — the whole pill acts as one click target.\n const handleWrapperMouseDown: MouseEventHandler<HTMLDivElement> = (event) => {\n if (disabled || readOnly) return;\n if ((event.target as HTMLElement).closest('button, a, input, textarea, [role=\"button\"]')) {\n return;\n }\n event.preventDefault();\n event.currentTarget.querySelector('input')?.focus();\n };\n\n return (\n // Mouse-only convenience: clicking the chrome focuses the input. The input itself is the\n // real interactive/focusable target, so no extra role or key handler is needed here.\n // oxlint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n className={cn(\n searchWrapperVariants({ variant }),\n {\n 'tw:cursor-not-allowed tw:opacity-40': disabled,\n },\n className,\n )}\n data-testid={testId.wrapper}\n onMouseDown={handleWrapperMouseDown}\n >\n {variant === 'ai' ? (\n <Sparkles className=\"tw:size-4 tw:shrink-0 tw:[&_*]:stroke-aigradient-600\" />\n ) : (\n <SearchIcon className=\"tw:size-4 tw:shrink-0 tw:text-neutral-400\" />\n )}\n\n <input\n {...rest}\n ref={ref}\n placeholder={placeholder}\n data-testid={testId.input}\n type=\"text\"\n value={internalValue ?? ''}\n onChange={handleChange}\n onBlur={handleBlur}\n className={searchInputClassnames}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n {isClearButtonVisible && <ClearButton onClick={handleClear} testId={testId.clearButton} />}\n\n {suffix}\n </div>\n );\n};\n","import type { ComponentProps, FormEventHandler } from 'react';\n\nimport { Search } from './Search';\n\ntype Props = {\n onSubmit: (value: string) => void;\n} & Omit<ComponentProps<typeof Search>, 'onClear' | 'onBlur' | 'onSubmit'>;\n\nexport const SearchForm = ({ ref, onSubmit, name = 'search-field', ...props }: Props) => {\n const handleSubmit: FormEventHandler<HTMLFormElement> = (event) => {\n event.preventDefault();\n const searchEl = event.currentTarget.elements.namedItem(name) as HTMLInputElement;\n onSubmit(searchEl.value);\n };\n\n const onClear = () => {\n onSubmit('');\n };\n\n return (\n <form onSubmit={handleSubmit}>\n <Search\n {...props}\n ref={ref}\n onClear={onClear}\n name={name}\n // Debounce has no meaning when we use submit, which is triggered by pressing enter.\n disableDebounce\n />\n </form>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"Search-Dhig_hPD.js","names":["SearchIcon"],"sources":["../src/components/Search/ClearButton.tsx","../src/components/Search/styles.ts","../src/components/Search/utils.ts","../src/components/Search/Search.tsx","../src/components/Search/SearchForm.tsx"],"sourcesContent":["import type { MouseEventHandler } from 'react';\n\nimport { X } from '../../icons';\nimport { cn } from '../../utils';\n\ntype Props = {\n onClick: MouseEventHandler<HTMLButtonElement>;\n testId?: string;\n};\n\nexport const ClearButton = ({ onClick, testId }: Props) => {\n // Prevent default, as we do not want to lose input focus.\n const handleMouseDown: MouseEventHandler<HTMLButtonElement> = (event) => {\n event.preventDefault();\n };\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n tabIndex={-1} // clear button should not be focusable\n onMouseDown={handleMouseDown}\n className={cn(\n // reset\n 'tw:border-none',\n 'tw:bg-transparent',\n 'tw:p-0',\n\n // positioning\n 'tw:flex',\n 'tw:items-center',\n\n 'tw:cursor-pointer',\n 'tw:text-muted-foreground',\n 'tw:hover:text-foreground',\n )}\n data-testid={testId}\n >\n <X className=\"tw:size-4\" />\n </button>\n );\n};\n","import { cva } from 'class-variance-authority';\n\nexport const searchWrapperVariants = cva(\n [\n // positioning\n 'tw:flex',\n 'tw:items-center',\n 'tw:gap-2.5',\n\n // base\n 'tw:text-card-foreground',\n 'tw:transition-all',\n 'tw:font-sans',\n\n // readonly — `secondary` over `muted`, which is too close to the `card` fill to\n // read as non-editable in either scheme\n 'tw:has-[input[readonly]]:bg-secondary',\n 'tw:has-[input[readonly]]:focus-within:ring-0',\n 'tw:has-[input[readonly]]:outline-0',\n\n // disabled\n 'tw:disabled:opacity-40',\n\n // default input padding (was sizing.default)\n 'tw:[&>input]:py-[15px]',\n ],\n {\n defaultVariants: {\n variant: 'default',\n },\n variants: {\n variant: {\n default: [\n 'tw:rounded-lg',\n 'tw:px-5',\n 'tw:bg-card',\n 'tw:shadow-raised',\n // outline\n 'tw:outline',\n 'tw:outline-1',\n 'tw:outline-transparent',\n // focus\n 'tw:has-[input:focus]:outline-1',\n 'tw:has-[input:focus]:ring-4',\n 'tw:has-[input:focus]:outline-ring',\n 'tw:has-[input:focus]:ring-ring/30',\n ],\n ai: [\n 'tailwindcss-preflight',\n 'tw:relative',\n 'tw:rounded-card',\n 'tw:px-4',\n 'tw:cursor-text',\n 'tw:border-2',\n 'tw:border-transparent',\n 'tw:bg-gradient-to-br',\n 'tw:from-secondary-600',\n 'tw:to-purple-600',\n 'tw:bg-origin-border',\n // Floods the interior so the gradient shows only in the 2px border box.\n 'tw:shadow-[inset_0_100vw_rgb(var(--card))]',\n // focus\n 'tw:has-[input:focus]:ring-4',\n 'tw:has-[input:focus]:ring-ring/30',\n ],\n },\n },\n },\n);\n\nexport const searchInputClassnames = [\n // reset\n 'tw:border-none',\n 'tw:bg-transparent',\n 'tw:outline-hidden',\n 'tw:w-full',\n 'tw:p-0',\n\n // base\n 'tw:text-base',\n 'tw:leading-6',\n 'tw:font-normal',\n 'tw:font-sans',\n\n // placeholder\n 'tw:placeholder:text-muted-foreground',\n\n // disabled\n 'tw:disabled:cursor-not-allowed',\n].join(' ');\n","import { createPrefixedString } from '../../utils';\n\nexport const genSearchTestId = (prefix: string = '') => {\n const ps = createPrefixedString(prefix);\n return {\n toString: () => prefix,\n wrapper: ps`search-wrapper`,\n input: ps`search-input`,\n clearButton: ps`search-clear-button`,\n };\n};\n","import { useEffect, useMemo, useState } from 'react';\nimport type {\n ChangeEvent,\n ChangeEventHandler,\n ComponentProps,\n FocusEvent,\n FocusEventHandler,\n MouseEvent,\n MouseEventHandler,\n ReactNode,\n} from 'react';\n\nimport { Search as SearchIcon, Sparkles } from '../../icons';\nimport { cn, debounce, noop } from '../../utils';\n\nimport { ClearButton } from './ClearButton';\nimport { searchInputClassnames, searchWrapperVariants } from './styles';\nimport { genSearchTestId } from './utils';\n\ntype SearchChangeEventHandler = (\n value: string,\n event: ChangeEvent<HTMLInputElement> | MouseEvent<HTMLButtonElement>,\n) => void;\n\ntype SearchBlurEventHandler = (value: string, event: FocusEvent<HTMLInputElement, Element>) => void;\n\ntype Props = {\n suffix?: ReactNode;\n disableDebounce?: boolean;\n debounceDelay?: number;\n onChange?: SearchChangeEventHandler;\n onBlur?: SearchBlurEventHandler;\n value?: string | null;\n defaultValue?: string | null;\n testId?: string;\n onClear?: () => void;\n variant?: 'default' | 'ai';\n} & Omit<\n ComponentProps<'input'>,\n 'type' | 'onBlur' | 'onChange' | 'value' | 'defaultValue' | 'prefix' | 'suffix'\n>;\n\n/**\n * @deprecated Use `SearchInput` instead. `Search` is kept only for the legacy (non-sidebar) layout.\n */\nexport const Search = ({\n ref,\n suffix,\n className,\n onBlur,\n onChange = noop,\n disabled = false,\n readOnly = false,\n disableDebounce = false,\n debounceDelay = 300,\n value: externalValue,\n defaultValue,\n testId: prefixTestId = '',\n placeholder = 'Search',\n onClear,\n variant = 'default',\n ...rest\n}: Props) => {\n const [internalValue, setInternalValue] = useState(() =>\n externalValue != null ? externalValue : defaultValue,\n );\n const hasValue = internalValue !== '';\n\n const isClearButtonVisible = hasValue && !disabled && !readOnly;\n const testId = genSearchTestId(prefixTestId);\n\n const debouncedOnChange = useMemo(\n () => (disableDebounce ? onChange : debounce(onChange, debounceDelay)),\n [disableDebounce, debounceDelay, onChange],\n );\n\n useEffect(() => {\n if (externalValue == null) return; // uncontrolled state\n // oxlint-disable-next-line react-x/set-state-in-effect\n setInternalValue(externalValue);\n }, [externalValue]);\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n const currentValue = event.target.value;\n setInternalValue(currentValue);\n debouncedOnChange(currentValue, event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n const currentValue = event.target.value;\n setInternalValue(currentValue);\n onBlur?.(currentValue, event);\n };\n\n const handleClear: MouseEventHandler<HTMLButtonElement> = (event) => {\n setInternalValue('');\n onChange?.('', event);\n onClear?.();\n };\n\n // Clicking anywhere in the field that isn't an interactive control (the leading icon,\n // the empty chrome) focuses the input — the whole pill acts as one click target.\n const handleWrapperMouseDown: MouseEventHandler<HTMLDivElement> = (event) => {\n if (disabled || readOnly) return;\n if ((event.target as HTMLElement).closest('button, a, input, textarea, [role=\"button\"]')) {\n return;\n }\n event.preventDefault();\n event.currentTarget.querySelector('input')?.focus();\n };\n\n return (\n // Mouse-only convenience: clicking the chrome focuses the input. The input itself is the\n // real interactive/focusable target, so no extra role or key handler is needed here.\n // oxlint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n className={cn(\n searchWrapperVariants({ variant }),\n {\n 'tw:cursor-not-allowed tw:opacity-40': disabled,\n },\n className,\n )}\n data-testid={testId.wrapper}\n onMouseDown={handleWrapperMouseDown}\n >\n {variant === 'ai' ? (\n <Sparkles className=\"tw:size-4 tw:shrink-0 tw:[&_*]:stroke-aigradient-600\" />\n ) : (\n <SearchIcon className=\"tw:size-4 tw:shrink-0 tw:text-neutral-400\" />\n )}\n\n <input\n {...rest}\n ref={ref}\n placeholder={placeholder}\n data-testid={testId.input}\n type=\"text\"\n value={internalValue ?? ''}\n onChange={handleChange}\n onBlur={handleBlur}\n className={searchInputClassnames}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n {isClearButtonVisible && <ClearButton onClick={handleClear} testId={testId.clearButton} />}\n\n {suffix}\n </div>\n );\n};\n","import type { ComponentProps, FormEventHandler } from 'react';\n\nimport { Search } from './Search';\n\ntype Props = {\n onSubmit: (value: string) => void;\n} & Omit<ComponentProps<typeof Search>, 'onClear' | 'onBlur' | 'onSubmit'>;\n\nexport const SearchForm = ({ ref, onSubmit, name = 'search-field', ...props }: Props) => {\n const handleSubmit: FormEventHandler<HTMLFormElement> = (event) => {\n event.preventDefault();\n const searchEl = event.currentTarget.elements.namedItem(name) as HTMLInputElement;\n onSubmit(searchEl.value);\n };\n\n const onClear = () => {\n onSubmit('');\n };\n\n return (\n <form onSubmit={handleSubmit}>\n <Search\n {...props}\n ref={ref}\n onClear={onClear}\n name={name}\n // Debounce has no meaning when we use submit, which is triggered by pressing enter.\n disableDebounce\n />\n </form>\n );\n};\n"],"mappings":";;;;;;;AAUA,MAAa,eAAe,EAAE,SAAS,aAAoB;CAEzD,MAAM,mBAAyD,UAAU;EACvE,MAAM,eAAe;CACvB;CAEA,OACE,oBAAC,UAAD;EACE,MAAK;EACI;EACT,UAAU;EACV,aAAa;EACb,WAAW,GAET,kBACA,qBACA,UAGA,WACA,mBAEA,qBACA,4BACA,0BACF;EACA,eAAa;EAEb,UAAA,oBAAC,GAAD,EAAG,WAAU,YAAa,CAAA;CACpB,CAAA;AAEZ;;;ACvCA,MAAa,wBAAwB,IACnC;CAEE;CACA;CACA;CAGA;CACA;CACA;CAIA;CACA;CACA;CAGA;CAGA;AACF,GACA;CACE,iBAAiB,EACf,SAAS,UACX;CACA,UAAU,EACR,SAAS;EACP,SAAS;GACP;GACA;GACA;GACA;GAEA;GACA;GACA;GAEA;GACA;GACA;GACA;EACF;EACA,IAAI;GACF;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GAEA;GACA;EACF;CACF,EACF;AACF,CACF;AAEA,MAAa,wBAAwB;CAEnC;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CAGA;CAGA;AACF,CAAC,CAAC,KAAK,GAAG;;;ACvFV,MAAa,mBAAmB,SAAiB,OAAO;CACtD,MAAM,KAAK,qBAAqB,MAAM;CACtC,OAAO;EACL,gBAAgB;EAChB,SAAS,EAAE;EACX,OAAO,EAAE;EACT,aAAa,EAAE;CACjB;AACF;;;;;;ACmCA,MAAa,UAAU,EACrB,KACA,QACA,WACA,QACA,WAAW,MACX,WAAW,OACX,WAAW,OACX,kBAAkB,OAClB,gBAAgB,KAChB,OAAO,eACP,cACA,QAAQ,eAAe,IACvB,cAAc,UACd,SACA,UAAU,WACV,GAAG,WACQ;CACX,MAAM,CAAC,eAAe,oBAAoB,eACxC,iBAAiB,OAAO,gBAAgB,YAC1C;CAGA,MAAM,uBAFW,kBAAkB,MAEM,CAAC,YAAY,CAAC;CACvD,MAAM,SAAS,gBAAgB,YAAY;CAE3C,MAAM,oBAAoB,cACjB,kBAAkB,WAAW,SAAS,UAAU,aAAa,GACpE;EAAC;EAAiB;EAAe;CAAQ,CAC3C;CAEA,gBAAgB;EACd,IAAI,iBAAiB,MAAM;EAE3B,iBAAiB,aAAa;CAChC,GAAG,CAAC,aAAa,CAAC;CAElB,MAAM,gBAAsD,UAAU;EACpE,MAAM,eAAe,MAAM,OAAO;EAClC,iBAAiB,YAAY;EAC7B,kBAAkB,cAAc,KAAK;CACvC;CAEA,MAAM,cAAmD,UAAU;EACjE,MAAM,eAAe,MAAM,OAAO;EAClC,iBAAiB,YAAY;EAC7B,SAAS,cAAc,KAAK;CAC9B;CAEA,MAAM,eAAqD,UAAU;EACnE,iBAAiB,EAAE;EACnB,WAAW,IAAI,KAAK;EACpB,UAAU;CACZ;CAIA,MAAM,0BAA6D,UAAU;EAC3E,IAAI,YAAY,UAAU;EAC1B,IAAK,MAAM,OAAuB,QAAQ,+CAA6C,GACrF;EAEF,MAAM,eAAe;EACrB,MAAM,cAAc,cAAc,OAAO,CAAC,EAAE,MAAM;CACpD;CAEA,OAIE,qBAAC,OAAD;EACE,WAAW,GACT,sBAAsB,EAAE,QAAQ,CAAC,GACjC,EACE,uCAAuC,SACzC,GACA,SACF;EACA,eAAa,OAAO;EACpB,aAAa;EATf,UAAA;GAWG,YAAY,OACX,oBAAC,UAAD,EAAU,WAAU,uDAAwD,CAAA,IAE5E,oBAACA,UAAD,EAAY,WAAU,4CAA6C,CAAA;GAGrE,oBAAC,SAAD;IACE,GAAI;IACC;IACQ;IACb,eAAa,OAAO;IACpB,MAAK;IACL,OAAO,iBAAiB;IACxB,UAAU;IACV,QAAQ;IACR,WAAW;IACD;IACA;GACX,CAAA;GAEA,wBAAwB,oBAAC,aAAD;IAAa,SAAS;IAAa,QAAQ,OAAO;GAAc,CAAA;GAExF;EACE;;AAET;;;AC/IA,MAAa,cAAc,EAAE,KAAK,UAAU,OAAO,gBAAgB,GAAG,YAAmB;CACvF,MAAM,gBAAmD,UAAU;EACjE,MAAM,eAAe;EAErB,SADiB,MAAM,cAAc,SAAS,UAAU,IACxC,CAAC,CAAC,KAAK;CACzB;CAEA,MAAM,gBAAgB;EACpB,SAAS,EAAE;CACb;CAEA,OACE,oBAAC,QAAD;EAAM,UAAU;EACd,UAAA,oBAAC,QAAD;GACE,GAAI;GACC;GACI;GACH;GAEN,iBAAA;EACD,CAAA;CACG,CAAA;AAEV"}
@@ -1,6 +1,6 @@
1
- import { debounce } from "./utils-DSvrhU8E.js";
1
+ import { debounce } from "./utils-BW4AE8VP.js";
2
2
  import { Search, X } from "./icons-Cek151jC.js";
3
- import { InputGroup } from "./InputGroup-DcZRlVnN.js";
3
+ import { InputGroup } from "./InputGroup-Do8K2hvD.js";
4
4
  import { useEffect, useMemo, useRef, useState } from "react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/blocks/SearchInput/SearchInput.tsx
@@ -99,4 +99,4 @@ const SearchInput = ({ ref, state, variant, focusVariant, sizing, className, val
99
99
  //#endregion
100
100
  export { SearchInput };
101
101
 
102
- //# sourceMappingURL=SearchInput-D4UgAXJK.js.map
102
+ //# sourceMappingURL=SearchInput-92r2bkA7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SearchInput-D4UgAXJK.js","names":[],"sources":["../src/blocks/SearchInput/SearchInput.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\nimport type { ChangeEventHandler, ComponentProps, FocusEventHandler } from 'react';\n\nimport { InputGroup } from '../../components/InputGroup';\nimport { Search, X } from '../../icons';\nimport { debounce } from '../../utils';\n\ntype InputGroupProps = Pick<\n ComponentProps<typeof InputGroup>,\n 'variant' | 'focusVariant' | 'state' | 'sizing'\n>;\n\ntype InputGroupInputProps = Omit<ComponentProps<typeof InputGroup.Input>, 'value' | 'defaultValue'>;\n\n/**\n * Props for `SearchInput`. `onValueChange` is debounced by default (300ms) so callers can wire it directly\n * to expensive filter / fetch operations without `useMemo` plumbing. `value={null}` / `value={undefined}`\n * is treated as \"not provided\" — the component falls back to `defaultValue` (or, if absent, internal\n * state initialized to empty). `value={\"\"}` is controlled-empty.\n */\ntype Props = InputGroupProps &\n InputGroupInputProps & {\n value?: string | null;\n defaultValue?: string | null;\n /** Called with the latest string value after the debounce window (default 300ms). Fires synchronously on clear and when `disableDebounce` is set. For sync echo of every keystroke use `onChange`. */\n onValueChange?: (value: string) => void;\n /** Called with the string value on blur. */\n onValueBlur?: (value: string) => void;\n /** Called when the user clicks the clear button. Receives no arguments — the value is reset to \"\". */\n onClear?: () => void;\n /** Render the trailing clear (x) button when there's a non-empty value. */\n allowClear?: boolean;\n /** Bypass the debounce — `onValueChange` fires synchronously on every keystroke. */\n disableDebounce?: boolean;\n /** Debounce window in ms. Default 300. Ignored when `disableDebounce` is set. */\n debounceDelay?: number;\n };\n\n/**\n * Debounced search input with a leading magnifying-glass icon and optional clear button.\n *\n * **When to use:** the search field inside `PageToolbar.Search`, list / table search, combobox-less\n * free-text filters. `onValueChange` is debounced so callers can wire it directly to fetches without\n * `useMemo` plumbing.\n * **When NOT to use:** for a plain string input use `TextInput`; for selecting from a known enumerated\n * list use `Combobox` (which has its own search built in).\n * **Composition:** typically rendered in `PageToolbar.Search` next to `MultiCombobox` filter pills. Use\n * `allowClear` for the canonical x-to-reset affordance.\n *\n * @see RECIPES.md#filter-toolbar — for the search + filter chips toolbar pattern\n */\nexport const SearchInput = ({\n ref,\n\n // group props\n state,\n variant,\n focusVariant,\n sizing,\n className,\n\n // own props\n value: valueProp,\n defaultValue,\n onValueChange,\n onValueBlur,\n onChange,\n onBlur,\n onClear,\n allowClear = false,\n disableDebounce = false,\n debounceDelay = 300,\n\n // input props\n disabled,\n readOnly,\n ...restInputProps\n}: Props) => {\n const [internalValue, setInternalValue] = useState<string>(\n valueProp != null ? valueProp : (defaultValue ?? ''),\n );\n\n // Tracks whether a debounced call is pending so the controlled-value sync\n // effect doesn't overwrite characters the user typed during the debounce window.\n const debounceInFlightRef = useRef(false);\n const cancelRef = useRef<() => void>(() => {});\n\n const debouncedOnValueChange = useMemo(() => {\n if (!onValueChange || disableDebounce) {\n cancelRef.current = () => {};\n return onValueChange;\n }\n const d = debounce((val: string) => {\n debounceInFlightRef.current = false;\n onValueChange(val);\n }, debounceDelay);\n cancelRef.current = d.cancel;\n return d;\n }, [onValueChange, disableDebounce, debounceDelay]);\n\n // Cancel any pending debounced call when the debounced fn changes or on unmount.\n useEffect(() => {\n return () => cancelRef.current();\n }, [debouncedOnValueChange]);\n\n // Sync controlled value — but skip while a debounced call is in flight to\n // avoid snapping the input back to the old value mid-typing.\n useEffect(() => {\n if (valueProp == null) return;\n if (debounceInFlightRef.current) return;\n setInternalValue(valueProp);\n }, [valueProp]);\n\n const canClear = allowClear && !!internalValue && !disabled && !readOnly;\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n const val = event.target.value;\n setInternalValue(val);\n if (!disableDebounce && debouncedOnValueChange) debounceInFlightRef.current = true;\n debouncedOnValueChange?.(val);\n onChange?.(event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n onValueBlur?.(event.target.value);\n onBlur?.(event);\n };\n\n const handleClear = () => {\n cancelRef.current();\n debounceInFlightRef.current = false;\n setInternalValue('');\n onValueChange?.('');\n onClear?.();\n };\n\n return (\n <InputGroup\n state={state}\n variant={variant}\n sizing={sizing}\n focusVariant={focusVariant}\n className={className}\n >\n <InputGroup.Addon align=\"inline-start\">\n <Search className=\"tw:size-4 tw:shrink-0 tw:text-muted-foreground\" />\n </InputGroup.Addon>\n\n <InputGroup.Input\n {...restInputProps}\n ref={ref}\n value={internalValue}\n onChange={handleChange}\n onBlur={handleBlur}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n {canClear && (\n <InputGroup.Addon align=\"inline-end\">\n <InputGroup.Button\n aria-label=\"Clear search\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n >\n <X className=\"tw:size-4\" />\n </InputGroup.Button>\n </InputGroup.Addon>\n )}\n </InputGroup>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmDA,MAAa,eAAe,EAC1B,KAGA,OACA,SACA,cACA,QACA,WAGA,OAAO,WACP,cACA,eACA,aACA,UACA,QACA,SACA,aAAa,OACb,kBAAkB,OAClB,gBAAgB,KAGhB,UACA,UACA,GAAG,qBACQ;CACX,MAAM,CAAC,eAAe,oBAAoB,SACxC,aAAa,OAAO,YAAa,gBAAgB,EACnD;CAIA,MAAM,sBAAsB,OAAO,KAAK;CACxC,MAAM,YAAY,aAAyB,CAAC,CAAC;CAE7C,MAAM,yBAAyB,cAAc;EAC3C,IAAI,CAAC,iBAAiB,iBAAiB;GACrC,UAAU,gBAAgB,CAAC;GAC3B,OAAO;EACT;EACA,MAAM,IAAI,UAAU,QAAgB;GAClC,oBAAoB,UAAU;GAC9B,cAAc,GAAG;EACnB,GAAG,aAAa;EAChB,UAAU,UAAU,EAAE;EACtB,OAAO;CACT,GAAG;EAAC;EAAe;EAAiB;CAAa,CAAC;CAGlD,gBAAgB;EACd,aAAa,UAAU,QAAQ;CACjC,GAAG,CAAC,sBAAsB,CAAC;CAI3B,gBAAgB;EACd,IAAI,aAAa,MAAM;EACvB,IAAI,oBAAoB,SAAS;EACjC,iBAAiB,SAAS;CAC5B,GAAG,CAAC,SAAS,CAAC;CAEd,MAAM,WAAW,cAAc,CAAC,CAAC,iBAAiB,CAAC,YAAY,CAAC;CAEhE,MAAM,gBAAsD,UAAU;EACpE,MAAM,MAAM,MAAM,OAAO;EACzB,iBAAiB,GAAG;EACpB,IAAI,CAAC,mBAAmB,wBAAwB,oBAAoB,UAAU;EAC9E,yBAAyB,GAAG;EAC5B,WAAW,KAAK;CAClB;CAEA,MAAM,cAAmD,UAAU;EACjE,cAAc,MAAM,OAAO,KAAK;EAChC,SAAS,KAAK;CAChB;CAEA,MAAM,oBAAoB;EACxB,UAAU,QAAQ;EAClB,oBAAoB,UAAU;EAC9B,iBAAiB,EAAE;EACnB,gBAAgB,EAAE;EAClB,UAAU;CACZ;CAEA,OACE,qBAAC,YAAD;EACS;EACE;EACD;EACM;EACH;EALb,UAAA;GAOE,oBAAC,WAAW,OAAZ;IAAkB,OAAM;IACtB,UAAA,oBAAC,QAAD,EAAQ,WAAU,iDAAkD,CAAA;GACpD,CAAA;GAElB,oBAAC,WAAW,OAAZ;IACE,GAAI;IACC;IACL,OAAO;IACP,UAAU;IACV,QAAQ;IACE;IACA;GACX,CAAA;GAEA,YACC,oBAAC,WAAW,OAAZ;IAAkB,OAAM;IACtB,UAAA,oBAAC,WAAW,QAAZ;KACE,cAAW;KACX,cAAc,UAAU,MAAM,eAAe;KAC7C,SAAS;KAET,UAAA,oBAAC,GAAD,EAAG,WAAU,YAAa,CAAA;IACT,CAAA;GACH,CAAA;EAEV;;AAEhB"}
1
+ {"version":3,"file":"SearchInput-92r2bkA7.js","names":[],"sources":["../src/blocks/SearchInput/SearchInput.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\nimport type { ChangeEventHandler, ComponentProps, FocusEventHandler } from 'react';\n\nimport { InputGroup } from '../../components/InputGroup';\nimport { Search, X } from '../../icons';\nimport { debounce } from '../../utils';\n\ntype InputGroupProps = Pick<\n ComponentProps<typeof InputGroup>,\n 'variant' | 'focusVariant' | 'state' | 'sizing'\n>;\n\ntype InputGroupInputProps = Omit<ComponentProps<typeof InputGroup.Input>, 'value' | 'defaultValue'>;\n\n/**\n * Props for `SearchInput`. `onValueChange` is debounced by default (300ms) so callers can wire it directly\n * to expensive filter / fetch operations without `useMemo` plumbing. `value={null}` / `value={undefined}`\n * is treated as \"not provided\" — the component falls back to `defaultValue` (or, if absent, internal\n * state initialized to empty). `value={\"\"}` is controlled-empty.\n */\ntype Props = InputGroupProps &\n InputGroupInputProps & {\n value?: string | null;\n defaultValue?: string | null;\n /** Called with the latest string value after the debounce window (default 300ms). Fires synchronously on clear and when `disableDebounce` is set. For sync echo of every keystroke use `onChange`. */\n onValueChange?: (value: string) => void;\n /** Called with the string value on blur. */\n onValueBlur?: (value: string) => void;\n /** Called when the user clicks the clear button. Receives no arguments — the value is reset to \"\". */\n onClear?: () => void;\n /** Render the trailing clear (x) button when there's a non-empty value. */\n allowClear?: boolean;\n /** Bypass the debounce — `onValueChange` fires synchronously on every keystroke. */\n disableDebounce?: boolean;\n /** Debounce window in ms. Default 300. Ignored when `disableDebounce` is set. */\n debounceDelay?: number;\n };\n\n/**\n * Debounced search input with a leading magnifying-glass icon and optional clear button.\n *\n * **When to use:** the search field inside `PageToolbar.Search`, list / table search, combobox-less\n * free-text filters. `onValueChange` is debounced so callers can wire it directly to fetches without\n * `useMemo` plumbing.\n * **When NOT to use:** for a plain string input use `TextInput`; for selecting from a known enumerated\n * list use `Combobox` (which has its own search built in).\n * **Composition:** typically rendered in `PageToolbar.Search` next to `MultiCombobox` filter pills. Use\n * `allowClear` for the canonical x-to-reset affordance.\n *\n * @see RECIPES.md#filter-toolbar — for the search + filter chips toolbar pattern\n */\nexport const SearchInput = ({\n ref,\n\n // group props\n state,\n variant,\n focusVariant,\n sizing,\n className,\n\n // own props\n value: valueProp,\n defaultValue,\n onValueChange,\n onValueBlur,\n onChange,\n onBlur,\n onClear,\n allowClear = false,\n disableDebounce = false,\n debounceDelay = 300,\n\n // input props\n disabled,\n readOnly,\n ...restInputProps\n}: Props) => {\n const [internalValue, setInternalValue] = useState<string>(\n valueProp != null ? valueProp : (defaultValue ?? ''),\n );\n\n // Tracks whether a debounced call is pending so the controlled-value sync\n // effect doesn't overwrite characters the user typed during the debounce window.\n const debounceInFlightRef = useRef(false);\n const cancelRef = useRef<() => void>(() => {});\n\n const debouncedOnValueChange = useMemo(() => {\n if (!onValueChange || disableDebounce) {\n cancelRef.current = () => {};\n return onValueChange;\n }\n const d = debounce((val: string) => {\n debounceInFlightRef.current = false;\n onValueChange(val);\n }, debounceDelay);\n cancelRef.current = d.cancel;\n return d;\n }, [onValueChange, disableDebounce, debounceDelay]);\n\n // Cancel any pending debounced call when the debounced fn changes or on unmount.\n useEffect(() => {\n return () => cancelRef.current();\n }, [debouncedOnValueChange]);\n\n // Sync controlled value — but skip while a debounced call is in flight to\n // avoid snapping the input back to the old value mid-typing.\n useEffect(() => {\n if (valueProp == null) return;\n if (debounceInFlightRef.current) return;\n setInternalValue(valueProp);\n }, [valueProp]);\n\n const canClear = allowClear && !!internalValue && !disabled && !readOnly;\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n const val = event.target.value;\n setInternalValue(val);\n if (!disableDebounce && debouncedOnValueChange) debounceInFlightRef.current = true;\n debouncedOnValueChange?.(val);\n onChange?.(event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n onValueBlur?.(event.target.value);\n onBlur?.(event);\n };\n\n const handleClear = () => {\n cancelRef.current();\n debounceInFlightRef.current = false;\n setInternalValue('');\n onValueChange?.('');\n onClear?.();\n };\n\n return (\n <InputGroup\n state={state}\n variant={variant}\n sizing={sizing}\n focusVariant={focusVariant}\n className={className}\n >\n <InputGroup.Addon align=\"inline-start\">\n <Search className=\"tw:size-4 tw:shrink-0 tw:text-muted-foreground\" />\n </InputGroup.Addon>\n\n <InputGroup.Input\n {...restInputProps}\n ref={ref}\n value={internalValue}\n onChange={handleChange}\n onBlur={handleBlur}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n {canClear && (\n <InputGroup.Addon align=\"inline-end\">\n <InputGroup.Button\n aria-label=\"Clear search\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n >\n <X className=\"tw:size-4\" />\n </InputGroup.Button>\n </InputGroup.Addon>\n )}\n </InputGroup>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmDA,MAAa,eAAe,EAC1B,KAGA,OACA,SACA,cACA,QACA,WAGA,OAAO,WACP,cACA,eACA,aACA,UACA,QACA,SACA,aAAa,OACb,kBAAkB,OAClB,gBAAgB,KAGhB,UACA,UACA,GAAG,qBACQ;CACX,MAAM,CAAC,eAAe,oBAAoB,SACxC,aAAa,OAAO,YAAa,gBAAgB,EACnD;CAIA,MAAM,sBAAsB,OAAO,KAAK;CACxC,MAAM,YAAY,aAAyB,CAAC,CAAC;CAE7C,MAAM,yBAAyB,cAAc;EAC3C,IAAI,CAAC,iBAAiB,iBAAiB;GACrC,UAAU,gBAAgB,CAAC;GAC3B,OAAO;EACT;EACA,MAAM,IAAI,UAAU,QAAgB;GAClC,oBAAoB,UAAU;GAC9B,cAAc,GAAG;EACnB,GAAG,aAAa;EAChB,UAAU,UAAU,EAAE;EACtB,OAAO;CACT,GAAG;EAAC;EAAe;EAAiB;CAAa,CAAC;CAGlD,gBAAgB;EACd,aAAa,UAAU,QAAQ;CACjC,GAAG,CAAC,sBAAsB,CAAC;CAI3B,gBAAgB;EACd,IAAI,aAAa,MAAM;EACvB,IAAI,oBAAoB,SAAS;EACjC,iBAAiB,SAAS;CAC5B,GAAG,CAAC,SAAS,CAAC;CAEd,MAAM,WAAW,cAAc,CAAC,CAAC,iBAAiB,CAAC,YAAY,CAAC;CAEhE,MAAM,gBAAsD,UAAU;EACpE,MAAM,MAAM,MAAM,OAAO;EACzB,iBAAiB,GAAG;EACpB,IAAI,CAAC,mBAAmB,wBAAwB,oBAAoB,UAAU;EAC9E,yBAAyB,GAAG;EAC5B,WAAW,KAAK;CAClB;CAEA,MAAM,cAAmD,UAAU;EACjE,cAAc,MAAM,OAAO,KAAK;EAChC,SAAS,KAAK;CAChB;CAEA,MAAM,oBAAoB;EACxB,UAAU,QAAQ;EAClB,oBAAoB,UAAU;EAC9B,iBAAiB,EAAE;EACnB,gBAAgB,EAAE;EAClB,UAAU;CACZ;CAEA,OACE,qBAAC,YAAD;EACS;EACE;EACD;EACM;EACH;EALb,UAAA;GAOE,oBAAC,WAAW,OAAZ;IAAkB,OAAM;IACtB,UAAA,oBAAC,QAAD,EAAQ,WAAU,iDAAkD,CAAA;GACpD,CAAA;GAElB,oBAAC,WAAW,OAAZ;IACE,GAAI;IACC;IACL,OAAO;IACP,UAAU;IACV,QAAQ;IACE;IACA;GACX,CAAA;GAEA,YACC,oBAAC,WAAW,OAAZ;IAAkB,OAAM;IACtB,UAAA,oBAAC,WAAW,QAAZ;KACE,cAAW;KACX,cAAc,UAAU,MAAM,eAAe;KAC7C,SAAS;KAET,UAAA,oBAAC,GAAD,EAAG,WAAU,YAAa,CAAA;IACT,CAAA;GACH,CAAA;EAEV;;AAEhB"}
@@ -1,9 +1,9 @@
1
1
  import { cn } from "./classNames-BzrkDnOD.js";
2
- import { noop } from "./utils-DSvrhU8E.js";
2
+ import { noop } from "./utils-BW4AE8VP.js";
3
3
  import { ChevronDown } from "./icons-Cek151jC.js";
4
4
  import { Button } from "./Button-DsRrU5F1.js";
5
- import { DropdownMenu } from "./DropdownMenu-CASr-jgl.js";
6
- import { Badge } from "./Badge-D0pXdekt.js";
5
+ import { DropdownMenu } from "./DropdownMenu-CgVwhDvl.js";
6
+ import { Badge } from "./Badge-o5jURtpB.js";
7
7
  import { Collapsible } from "./Collapsible-BQXWEOBC.js";
8
8
  import { useState } from "react";
9
9
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -273,4 +273,4 @@ const SectionNav = ({ groups, activeId, renderItem, showDescriptions = false, la
273
273
  //#endregion
274
274
  export { SectionNav };
275
275
 
276
- //# sourceMappingURL=SectionNav-OkKCjSA-.js.map
276
+ //# sourceMappingURL=SectionNav-CNLJsiVG.js.map