@keboola/design 11.6.1 → 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 (153) hide show
  1. package/AGENTS.md +16 -1
  2. package/CHANGELOG.md +86 -0
  3. package/COMPONENT-API.md +47 -46
  4. package/README.md +1 -1
  5. package/dist/{AIKit-CQxVwyAk.js → AIKit-ELIsegJz.js} +550 -103
  6. package/dist/AIKit-ELIsegJz.js.map +1 -0
  7. package/dist/{Alert-C4Y9IwMI.js → Alert-BsIM_oFK.js} +2 -2
  8. package/dist/{Alert-C4Y9IwMI.js.map → Alert-BsIM_oFK.js.map} +1 -1
  9. package/dist/{BrandEditor-CS9P4r2p.js → BrandEditor-BsTBM3s6.js} +4 -4
  10. package/dist/{BrandEditor-CS9P4r2p.js.map → BrandEditor-BsTBM3s6.js.map} +1 -1
  11. package/dist/{Breadcrumb-D1id7YXd.js → Breadcrumb-xqEUxfwn.js} +2 -2
  12. package/dist/{Breadcrumb-D1id7YXd.js.map → Breadcrumb-xqEUxfwn.js.map} +1 -1
  13. package/dist/{Checkbox-Bqr6zXcW.js → Checkbox-Dq5fPNrO.js} +2 -2
  14. package/dist/{Checkbox-Bqr6zXcW.js.map → Checkbox-Dq5fPNrO.js.map} +1 -1
  15. package/dist/{Clipboard-C2YBRfD8.js → Clipboard-BZitKiSA.js} +2 -2
  16. package/dist/{Clipboard-C2YBRfD8.js.map → Clipboard-BZitKiSA.js.map} +1 -1
  17. package/dist/{ClipboardButton-CrljClL1.js → ClipboardButton-KHQnPEh_.js} +2 -2
  18. package/dist/{ClipboardButton-CrljClL1.js.map → ClipboardButton-KHQnPEh_.js.map} +1 -1
  19. package/dist/{CodeEditor-C9AS8Ch0.js → CodeEditor-BJKJXA0c.js} +4 -4
  20. package/dist/{CodeEditor-C9AS8Ch0.js.map → CodeEditor-BJKJXA0c.js.map} +1 -1
  21. package/dist/{ColorInput-Dg87lKcR.js → ColorInput-Bj3dfPFA.js} +3 -3
  22. package/dist/{ColorInput-Dg87lKcR.js.map → ColorInput-Bj3dfPFA.js.map} +1 -1
  23. package/dist/{ColorModeSwitch-CsWLiTBX.js → ColorModeSwitch-CWt-DZGC.js} +2 -2
  24. package/dist/{ColorModeSwitch-CsWLiTBX.js.map → ColorModeSwitch-CWt-DZGC.js.map} +1 -1
  25. package/dist/{Combobox-BfanUAqY.js → Combobox-D8PrEqTG.js} +3 -3
  26. package/dist/{Combobox-BfanUAqY.js.map → Combobox-D8PrEqTG.js.map} +1 -1
  27. package/dist/{Command-CqxoI_De.js → Command-BDU3C1gg.js} +2 -2
  28. package/dist/{Command-CqxoI_De.js.map → Command-BDU3C1gg.js.map} +1 -1
  29. package/dist/{CopyField-Rx9HPTbJ.js → CopyField-BHRQUyuF.js} +2 -2
  30. package/dist/{CopyField-Rx9HPTbJ.js.map → CopyField-BHRQUyuF.js.map} +1 -1
  31. package/dist/{DateInput-DpifECUQ.js → DateInput-B6N8g0ra.js} +3 -3
  32. package/dist/{DateInput-DpifECUQ.js.map → DateInput-B6N8g0ra.js.map} +1 -1
  33. package/dist/{DateRangeInput-9MIw7P6L.js → DateRangeInput-7M9Z4cVO.js} +3 -3
  34. package/dist/{DateRangeInput-9MIw7P6L.js.map → DateRangeInput-7M9Z4cVO.js.map} +1 -1
  35. package/dist/{DropdownMenu-CASr-jgl.js → DropdownMenu-CgVwhDvl.js} +9 -4
  36. package/dist/DropdownMenu-CgVwhDvl.js.map +1 -0
  37. package/dist/{FieldItem-DtPTzNef.js → FieldItem-DZGIdiXE.js} +3 -3
  38. package/dist/{FieldItem-DtPTzNef.js.map → FieldItem-DZGIdiXE.js.map} +1 -1
  39. package/dist/{Form-DAaatlBk.js → Form-CcK7dRrC.js} +5 -5
  40. package/dist/{Form-DAaatlBk.js.map → Form-CcK7dRrC.js.map} +1 -1
  41. package/dist/{FormGroup-Bl8JmnzJ.js → FormGroup-DR_gZ25-.js} +3 -3
  42. package/dist/{FormGroup-Bl8JmnzJ.js.map → FormGroup-DR_gZ25-.js.map} +1 -1
  43. package/dist/{InputGroup-DcZRlVnN.js → InputGroup-Do8K2hvD.js} +2 -1
  44. package/dist/InputGroup-Do8K2hvD.js.map +1 -0
  45. package/dist/{Kbd-D1Azcc4g.js → Kbd-LCFMumoq.js} +2 -2
  46. package/dist/{Kbd-D1Azcc4g.js.map → Kbd-LCFMumoq.js.map} +1 -1
  47. package/dist/{MermaidDiagram-CujFxVzk.js → MermaidDiagram-ZG0iiDV_.js} +2 -2
  48. package/dist/{MermaidDiagram-CujFxVzk.js.map → MermaidDiagram-ZG0iiDV_.js.map} +1 -1
  49. package/dist/{Modal-Coj-H02o.js → Modal-I3VWk2oo.js} +2 -2
  50. package/dist/{Modal-Coj-H02o.js.map → Modal-I3VWk2oo.js.map} +1 -1
  51. package/dist/{ModalTitle-C76ke2eo.js → ModalTitle-CeLM_mX9.js} +2 -2
  52. package/dist/ModalTitle-CeLM_mX9.js.map +1 -0
  53. package/dist/{MultiActionButtonGroup-CNNoBQbv.js → MultiActionButtonGroup-CYZ8IgSf.js} +2 -2
  54. package/dist/{MultiActionButtonGroup-CNNoBQbv.js.map → MultiActionButtonGroup-CYZ8IgSf.js.map} +1 -1
  55. package/dist/{RadioGroup-CUBsuP7r.js → RadioGroup-Byc2mym4.js} +2 -2
  56. package/dist/{RadioGroup-CUBsuP7r.js.map → RadioGroup-Byc2mym4.js.map} +1 -1
  57. package/dist/{Search-DVpJuzr9.js → Search-Dhig_hPD.js} +2 -2
  58. package/dist/{Search-DVpJuzr9.js.map → Search-Dhig_hPD.js.map} +1 -1
  59. package/dist/{SearchInput-Q85p8Ews.js → SearchInput-92r2bkA7.js} +3 -3
  60. package/dist/{SearchInput-Q85p8Ews.js.map → SearchInput-92r2bkA7.js.map} +1 -1
  61. package/dist/{SectionNav-mpmSM3OC.js → SectionNav-CNLJsiVG.js} +3 -3
  62. package/dist/{SectionNav-mpmSM3OC.js.map → SectionNav-CNLJsiVG.js.map} +1 -1
  63. package/dist/{Sheet-Chf0kX1E.js → Sheet-OparjIi-.js} +2 -2
  64. package/dist/{Sheet-Chf0kX1E.js.map → Sheet-OparjIi-.js.map} +1 -1
  65. package/dist/{Sidebar-CTWsHZhF.js → Sidebar-CLEbBtNY.js} +190 -25
  66. package/dist/Sidebar-CLEbBtNY.js.map +1 -0
  67. package/dist/{Slider-Bv0B6lI0.js → Slider-DLclvRws.js} +2 -2
  68. package/dist/{Slider-Bv0B6lI0.js.map → Slider-DLclvRws.js.map} +1 -1
  69. package/dist/{TextInput-DiEMxVF6.js → TextInput-CFTf4Cz1.js} +5 -4
  70. package/dist/TextInput-CFTf4Cz1.js.map +1 -0
  71. package/dist/{ThemeProvider-BI6JWBdJ.js → ThemeProvider-DAmNn9Sd.js} +2 -2
  72. package/dist/{ThemeProvider-BI6JWBdJ.js.map → ThemeProvider-DAmNn9Sd.js.map} +1 -1
  73. package/dist/{Timeline-BG5Xogxh.js → Timeline-C8-wnRRr.js} +2 -2
  74. package/dist/{Timeline-BG5Xogxh.js.map → Timeline-C8-wnRRr.js.map} +1 -1
  75. package/dist/{ZoomableSvg-U_VH3QRO.js → ZoomableSvg-BZlk3PFJ.js} +3 -3
  76. package/dist/{ZoomableSvg-U_VH3QRO.js.map → ZoomableSvg-BZlk3PFJ.js.map} +1 -1
  77. package/dist/editors.js +2 -2
  78. package/dist/flint.js +1 -1
  79. package/dist/index.d.ts +900 -561
  80. package/dist/index.js +36 -34
  81. package/dist/internal/blocks/AIKit.js +2 -2
  82. package/dist/internal/blocks/BrandEditor.js +1 -1
  83. package/dist/internal/blocks/ChipEditor.js +137 -0
  84. package/dist/internal/blocks/ChipEditor.js.map +1 -0
  85. package/dist/internal/blocks/ClipboardButton.js +1 -1
  86. package/dist/internal/blocks/ColorInput.js +1 -1
  87. package/dist/internal/blocks/ColorModeSwitch.js +1 -1
  88. package/dist/internal/blocks/Command.js +1 -1
  89. package/dist/internal/blocks/CopyField.js +1 -1
  90. package/dist/internal/blocks/DateInput.js +1 -1
  91. package/dist/internal/blocks/DateRangeInput.js +1 -1
  92. package/dist/internal/blocks/ExportMenu.js +2 -2
  93. package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +1 -1
  94. package/dist/internal/blocks/Form.js +1 -1
  95. package/dist/internal/blocks/FormGroup.js +1 -1
  96. package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
  97. package/dist/internal/blocks/MultiCombobox.js +18 -28
  98. package/dist/internal/blocks/MultiCombobox.js.map +1 -1
  99. package/dist/internal/blocks/NumberInput.js +1 -1
  100. package/dist/internal/blocks/PasswordInput.js +2 -2
  101. package/dist/internal/blocks/SearchInput.js +1 -1
  102. package/dist/internal/blocks/SearchInputWithNavigation.js +2 -2
  103. package/dist/internal/blocks/SectionNav.js +1 -1
  104. package/dist/internal/blocks/SplitButton.js +1 -1
  105. package/dist/internal/blocks/TextInput.js +1 -1
  106. package/dist/internal/blocks/Textarea.js +1 -1
  107. package/dist/internal/blocks/TimeInput.js +2 -2
  108. package/dist/internal/components/Alert.js +1 -1
  109. package/dist/internal/components/Avatar.js +1 -1
  110. package/dist/internal/components/Breadcrumb.js +1 -1
  111. package/dist/internal/components/Checkbox.js +1 -1
  112. package/dist/internal/components/Clipboard.js +1 -1
  113. package/dist/internal/components/CollapsiblePanel.js +1 -1
  114. package/dist/internal/components/Combobox.js +1 -1
  115. package/dist/internal/components/DropdownMenu.js +1 -1
  116. package/dist/internal/components/InputGroup.js +1 -1
  117. package/dist/internal/components/Kbd.js +1 -1
  118. package/dist/internal/components/Modal.js +1 -1
  119. package/dist/internal/components/RadioGroup.js +1 -1
  120. package/dist/internal/components/Search.js +1 -1
  121. package/dist/internal/components/Sheet.js +1 -1
  122. package/dist/internal/components/Sidebar.js +1 -1
  123. package/dist/internal/components/Slider.js +1 -1
  124. package/dist/internal/components/StatusDot.js +67 -0
  125. package/dist/internal/components/StatusDot.js.map +1 -0
  126. package/dist/internal/components/ThemeProvider.js +1 -1
  127. package/dist/internal/components/Timeline.js +1 -1
  128. package/dist/internal/components/Tooltip.js +2 -2
  129. package/dist/internal/components/Truncated.js +1 -1
  130. package/dist/internal/components/ZoomableSvg.js +1 -1
  131. package/dist/internal/hooks/useScrollbarPosition.js +1 -1
  132. package/dist/internal/utils/mergeRefs.js +27 -9
  133. package/dist/internal/utils/mergeRefs.js.map +1 -1
  134. package/dist/internal/utils.js +2 -2
  135. package/dist/markdown-editor.js +5 -5
  136. package/dist/mermaid.js +1 -1
  137. package/dist/rjsf.js +9 -9
  138. package/dist/styles.css +1 -1
  139. package/dist/testing.js +1 -1
  140. package/dist/useElement-BK3AAiIf.js +24 -0
  141. package/dist/useElement-BK3AAiIf.js.map +1 -0
  142. package/dist/{utils-DnkrFYqY.js → utils-BW4AE8VP.js} +31 -3
  143. package/dist/utils-BW4AE8VP.js.map +1 -0
  144. package/package.json +2 -1
  145. package/dist/AIKit-CQxVwyAk.js.map +0 -1
  146. package/dist/DropdownMenu-CASr-jgl.js.map +0 -1
  147. package/dist/InputGroup-DcZRlVnN.js.map +0 -1
  148. package/dist/ModalTitle-C76ke2eo.js.map +0 -1
  149. package/dist/Sidebar-CTWsHZhF.js.map +0 -1
  150. package/dist/TextInput-DiEMxVF6.js.map +0 -1
  151. package/dist/useElement-DkF6esWL.js +0 -15
  152. package/dist/useElement-DkF6esWL.js.map +0 -1
  153. package/dist/utils-DnkrFYqY.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"MultiCombobox.js","names":["BaseCombobox","Combobox"],"sources":["../../../src/blocks/MultiCombobox/MultiCombobox.tsx"],"sourcesContent":["import { type ComponentProps, Fragment, type ReactNode, useMemo, useState } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { Combobox } from '../../components/Combobox';\nimport { namedLabel } from '../../components/Combobox/blankValues';\nimport { sanitizeTypedInput, useQueryReporter } from '../../components/Combobox/query';\nimport type { CreatableItem, Group } from '../../components/Combobox/types';\nimport {\n createCreatableItem,\n defaultGroupToLabel,\n defaultItemToDisabled,\n defaultItemToIcon,\n defaultItemToLabel,\n defaultQueryToCreateLabel,\n defaultToCreateValue,\n isCreatableItem,\n isGroupItem,\n isGroupItems,\n isSelectAllItem,\n selectAllItem,\n toItemEquality,\n toLabel,\n} from '../../components/Combobox/utils';\nimport { InputGroup } from '../../components/InputGroup';\nimport { useArgoDesign } from '../../components/ThemeProvider/context';\nimport { ChevronDown, Plus, X } from '../../icons';\n\ntype ComboboxProps<Value> = BaseCombobox.Root.Props<Value, true>;\ntype ComboboxInputProps = ComponentProps<typeof Combobox.Input>;\ntype ComboboxInputGroupProps = ComponentProps<typeof Combobox.InputGroup>;\ntype ComboboxItemProps = ComponentProps<typeof Combobox.Item>;\ntype ComboboxChipsProps<Value> = ComponentProps<typeof Combobox.Chips<Value>>;\n\ntype Indicator = NonNullable<ComboboxItemProps['indicator']>;\n\n/**\n * The strings one creatable entry stands for.\n *\n * - `id1, id2,` is two values: the blanks a stray separator leaves are dropped.\n * - A repeat collapses to its first occurrence, case-insensitively, as everything the control\n * matches by display string does — one entry cannot add the same value twice.\n * - A `null` separator yields the entry itself.\n */\nconst DEFAULT_CREATE_SEPARATOR = ',';\n\n/**\n * How the create row lists the values it adds: each separated by the entry's own separator, then\n * a space. A `RegExp` stands for many strings, so the default separator stands in for it.\n */\nconst joinCreateParts = (parts: string[], separator: string | RegExp | null) =>\n parts.join(`${typeof separator === 'string' ? separator : DEFAULT_CREATE_SEPARATOR} `);\n\nconst splitCreateEntry = (entry: string, separator: string | RegExp | null): string[] => {\n if (separator === null) return [entry];\n\n const seen = new Set<string>();\n return entry\n .split(separator)\n .map((part) => part.trim())\n .filter((part) => {\n if (part === '') return false;\n const key = part.toLowerCase();\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n};\n\ntype CreatableProps<Value> = {\n allowCreate?: boolean;\n /**\n * Words the create row. Receives the values committing the row will add — an entry standing for\n * several values arrives trimmed and re-joined with its own separator, not as typed.\n */\n queryToCreateLabel?: (query: string) => ReactNode;\n /**\n * Projects one entered string into an item. Called once per value, so a split entry calls it\n * several times, each with an already-trimmed part.\n */\n queryToCreateValue?: (query: string) => Value;\n /**\n * Gate on each value the entry stands for, for `allowCreate`.\n *\n * - Returning `false` drops that value, so an entry left with none hides the create row and the\n * empty state shows instead.\n * - Only called for a value that matches no item and nothing already selected — one naming an\n * item is selected rather than minted, so its format is not this gate's business.\n * - Reach for it when a free-form value has a format (a column name, an email address).\n */\n canCreate?: (query: string) => boolean;\n /**\n * Separator that makes one creatable entry stand for several values. Defaults to **`','`**, so\n * pasting `id1, id2, id3` adds three chips.\n *\n * - Pass a string or a non-capturing `RegExp` for another convention: `';'` for an Outlook\n * address list, `/[\\s,]+/` where a value can never contain a space. A capture group would be\n * handed back as a value of its own — that is `String.prototype.split`'s own behaviour.\n * - Pass `null` where a value legitimately contains the separator — a free-text label, a\n * sentence — and one entry must stay one chip.\n * - Whitespace is deliberately not part of the default: tags and column names contain spaces,\n * and each part is trimmed anyway, so `id1, id2` needs nothing more than the comma.\n */\n createSeparator?: string | RegExp | null;\n};\n\n/**\n * Props for `MultiCombobox`. Generic over `Value` (the item shape) and `GroupShape` (optional group wrapper).\n * Use `itemToLabel` / `itemToIcon` / `itemToDisabled` to project custom item shapes; use `filter` to override\n * the default substring matcher. Pass `isItemEqualToValue` when the items are objects a store recreates —\n * without it Base UI matches `value` against `items` by reference. Pass `allowCreate` to let the user add\n * free-form values not in `items`.\n */\ntype Props<Value, GroupShape extends Group<Value> = Group<Value>> = Pick<\n ComboboxInputProps,\n // `name`, `onBlur` and the `aria-*` set are forwarded to the input so a form connector can hand\n // over the wiring it derives from the field — without the `aria-*` set the control cannot be linked\n // to its own help and error text, and without `onBlur` the field never registers as blurred, which\n // is the gate `FieldItem` reveals errors on.\n 'placeholder' | 'id' | 'name' | 'onBlur' | 'aria-describedby' | 'aria-invalid' | 'aria-required'\n> &\n Pick<ComboboxInputGroupProps, 'variant' | 'focusVariant' | 'sizing' | 'state' | 'className'> &\n Pick<\n ComboboxProps<Value>,\n | 'disabled'\n | 'inputRef'\n | 'value'\n | 'defaultValue'\n | 'onValueChange'\n | 'itemToStringLabel'\n | 'itemToStringValue'\n | 'filter'\n | 'isItemEqualToValue'\n > &\n Pick<\n ComboboxChipsProps<Value>,\n 'itemToChipLabel' | 'itemToChipColor' | 'pinnedChipLabels' | 'maxVisible'\n > &\n CreatableProps<Value> & {\n items?: readonly (Value | GroupShape)[];\n\n // root specific\n /**\n * Offer a clear-all button once something is selected. Defaults to **`true`**.\n *\n * - `BaseCombobox.Clear` only mounts while chips exist, so an empty control renders identically\n * either way. Individual chips stay removable regardless.\n * - Pass `false` where emptying the whole selection must not be one click away.\n */\n allowClear?: boolean;\n /**\n * Adds a \"Select All\" row that selects the whole item set.\n *\n * - The row is hidden while a query narrows the list — it never means \"everything matching\".\n * - Selecting it while everything is already selected clears the selection.\n */\n allowSelectAll?: boolean;\n empty?: ReactNode;\n indicator?: Indicator;\n\n // query specific\n /**\n * Rewrites what the user types before the control adopts it.\n *\n * - The query the list filters by is the rewritten text, and so is every value a created entry\n * is split into — a character the user cannot type is one they cannot create.\n * - Reach for it where a created value has a character set: a column name, a scope, an\n * identifier. `canCreate` is the gate for a format the user must get right themselves.\n * - It has to rewrite rather than drop: it sees the whole text on every keystroke, so one\n * calling `trim()` swallows the space before the next word.\n */\n inputValueSanitizer?: (input: string) => string;\n /**\n * Reports the query the list filters by, `inputValueSanitizer` already applied.\n *\n * - For an owner that needs the query for itself: a server-side search, an option order, the\n * text a synthetic row is offered for. The mount render reports too, so a search driven by\n * this needs no first fetch of its own.\n * - Notification only, and deliberately not Base UI's own `onInputValueChange`: the control\n * keeps ownership of the text — a pick clears it — so there is no controlled `inputValue`\n * to hold in sync.\n */\n onQueryChange?: (query: string) => void;\n\n // item specific\n /**\n * The item's row in the list, and its chip unless `itemToChipLabel` overrides it.\n *\n * - Defaults to `itemToStringLabel`, so a control that projects its items — ids carrying the\n * selection, the label looked up beside them — states the projection once.\n * - Pass it separately only where the row is richer than the input's own text.\n */\n itemToLabel?: (item: Value) => ReactNode;\n itemToIcon?: (item: Value) => ReactNode;\n itemToDisabled?: (item: Value) => boolean;\n\n // chip specific\n /**\n * Renders the chip area from the selected values, in place of the default chips.\n *\n * - For the case no per-value accessor can express: one node standing for the whole selection\n * (\"3 tables selected\"), or a chip count that is not the value count.\n * - A chip that merely holds richer content — a link, an action of its own — needs no slot:\n * `itemToChipLabel` returns a `ReactNode` and the chip lets it take the keyboard.\n * - The chip props above go unused while this is set, `maxVisible` and its `+N` chip included.\n * - `Combobox.Chip` builds a removable chip.\n */\n renderChips?: (values: Value[]) => ReactNode;\n\n // group specific\n groupToLabel?: (group: GroupShape) => ReactNode;\n };\n\n/**\n * Multi-selection combobox with chip display and search. Built on Base UI Combobox.\n *\n * **When to use:** picking several items from a searchable enumerated list (filter by tags, assign labels).\n * Items render as chips above the input; `maxVisible` collapses excess into a `+N more` chip.\n * **When NOT to use:** for single selection use `Combobox`; for short enums without search use `Select`.\n * **Composition:** wrap in `FormGroup` for label + help text, or use `useAppForm` for form integration.\n * Pass `allowSelectAll` for a \"Select All\" item when the full enum is small — it covers the whole set\n * and hides itself while a query is active. Pass `allowCreate` to let the user add free-form values\n * that are not in `items` (e.g. entering column names by hand).\n *\n * @see RECIPES.md#creatable-multi-combobox — for free-form-plus-enumerated patterns\n * @see RECIPES.md#filter-toolbar — for combining multi-select with other filter chips\n */\nexport const MultiCombobox = <Value, GroupShape extends Group<Value> = Group<Value>>({\n // root props\n items: _itemsProp,\n value: _valueProp,\n defaultValue,\n onValueChange,\n itemToStringLabel,\n itemToStringValue,\n disabled,\n filter: filterProp,\n isItemEqualToValue: isItemEqualToValueProp,\n inputRef,\n\n // input props\n variant,\n sizing,\n focusVariant,\n state,\n placeholder,\n allowClear = true,\n id,\n name,\n onBlur,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n className,\n\n // own props\n allowSelectAll = false,\n empty = 'No items',\n indicator,\n\n // query\n inputValueSanitizer,\n onQueryChange,\n\n // creatable\n allowCreate,\n canCreate,\n queryToCreateValue,\n queryToCreateLabel = defaultQueryToCreateLabel,\n createSeparator = DEFAULT_CREATE_SEPARATOR,\n\n // own item props\n itemToDisabled = defaultItemToDisabled,\n itemToLabel: itemToLabelProp,\n itemToIcon = defaultItemToIcon,\n groupToLabel = defaultGroupToLabel,\n itemToChipLabel,\n itemToChipColor,\n pinnedChipLabels,\n renderChips,\n // Nothing chose 3: value editors override it to `Infinity` (a chip inside `+N` can be neither\n // read nor removed) and single-row filters to `1`. Changing it moves eleven call sites at once,\n // so it waits for a PR that can look at them.\n maxVisible = 3,\n}: Props<Value, GroupShape>) => {\n const itemsProp = _itemsProp ?? [];\n const valueProp = _valueProp ?? [];\n // `itemToStringLabel` is a projection, not a display accessor, so a blank it returns still needs\n // naming — rows and chips are where a blank value would otherwise render as nothing.\n const itemToLabel =\n itemToLabelProp ??\n (itemToStringLabel ? (item: Value) => namedLabel(itemToStringLabel(item)) : defaultItemToLabel);\n const renderArgo = useArgoDesign();\n const chipVariant = renderArgo ? 'pill' : 'default';\n\n const [inputValue, setInputValue] = useState('');\n const [createdItems, setCreatedItems] = useState<Value[]>([]);\n const query = inputValue.trim();\n\n useQueryReporter(query, onQueryChange);\n\n // Who holds the input's text. Base UI keeps it unless something here needs to read or rewrite\n // it, because taking it means re-rendering this component on every keystroke — a cost the many\n // controls that only pick from a list should not pay.\n const ownsInput = Boolean(allowCreate || inputValueSanitizer || onQueryChange);\n\n // Created values are appended to `items` so Base UI can keep resolving them (as chips and as\n // list options) once the query clears — otherwise a value that isn't in `items` gets dropped.\n // `handleValueChange` drops the ones the selection no longer holds, so this list tracks the\n // selection rather than every value ever typed.\n const baseItems = (() => {\n if (createdItems.length === 0) return itemsProp;\n if (isGroupItems(itemsProp))\n return [...itemsProp, { items: createdItems } as unknown as GroupShape];\n return [...itemsProp, ...createdItems];\n })();\n\n const allFlatItems = baseItems.flatMap((item) => (isGroupItem(item) ? item.items : item));\n const sampleItem = allFlatItems[0] as Value | undefined;\n // An empty item set has no Select All row: there is nothing to select all of, and reading\n // `0 === 0` as \"everything is selected\" would put the row's own entry into `value`.\n const hasSelectAllRow = allowSelectAll && allFlatItems.length > 0;\n const isAllSelected = hasSelectAllRow && allFlatItems.length === (valueProp?.length ?? 0);\n\n const defaultFilter = BaseCombobox.useFilter({\n multiple: true,\n value: valueProp,\n });\n\n const itemsWithSelectAllItem = hasSelectAllRow ? [selectAllItem, ...baseItems] : baseItems;\n\n const itemToString = (item: Value) => itemToStringLabel?.(item) ?? toLabel(item);\n // An item's display string, case-folded — the key an entered value is matched against.\n const labelKey = (item: Value) => itemToString(item).toLowerCase();\n\n // The values the current entry stands for. Everything the create row is decided from hangs off\n // this, so an empty entry costs a creatable control nothing.\n const createParts =\n !allowCreate || disabled || !query ? [] : splitCreateEntry(query, createSeparator);\n\n const selectedKeys = new Set<string>();\n if (createParts.length > 0) for (const item of valueProp) selectedKeys.add(labelKey(item));\n\n // Does an item carry this display string? `canCreate` asks it per value, so there it earns a\n // set; without the gate only a single-value entry asks, and an early-exiting scan is cheaper.\n const itemKeys = new Set<string>();\n if (createParts.length > 0 && canCreate) {\n for (const item of allFlatItems) itemKeys.add(labelKey(item));\n }\n const namesAnItem = (key: string) =>\n canCreate ? itemKeys.has(key) : allFlatItems.some((item) => labelKey(item) === key);\n\n /**\n * What the entry adds to the selection: its values the selection does not already hold.\n *\n * - The create row is named from this and committing it adds exactly this, so the row cannot\n * promise something else. A value naming an existing item counts — committing selects it.\n * - `canCreate` drops a value the control would mint and the gate rejects. One naming an item\n * is selected rather than minted, so its format is not that gate's business.\n * - `value` is the whole selection (it is never `undefined`, so the control is always the\n * controlled one), which is why the commit path re-derives nothing.\n */\n const addedCreateParts = createParts.filter((part) => {\n const key = part.toLowerCase();\n if (selectedKeys.has(key)) return false;\n return !canCreate || namesAnItem(key) || canCreate(part);\n });\n\n // The one value a single-value entry stands for, keyed — `undefined` for a split entry.\n const soleValueKey = createParts.length === 1 ? createParts[0]!.toLowerCase() : undefined;\n\n // A single value naming an item needs no create row: the list already offers that item's own\n // row, which the default substring filter matches for a single-value entry but not for a split\n // one. The item scan runs only for an entry that would otherwise show the row.\n const showCreateRow =\n addedCreateParts.length > 0 && (soleValueKey === undefined || !namesAnItem(soleValueKey));\n\n const items = (() => {\n const base = itemsWithSelectAllItem;\n if (!showCreateRow) return base;\n\n const creatable = createCreatableItem(query);\n return isGroupItems(base)\n ? [...base, { items: [creatable] } as unknown as GroupShape]\n : [...base, creatable as unknown as Value];\n })();\n\n const filter = (item: Value, query: string, itemToString?: (value: Value) => string) => {\n // Select All covers the whole item set, so it exists only while no query narrows the list.\n if (isSelectAllItem(item)) return query.trim() === '';\n // always offer the transient \"create\" option\n if (isCreatableItem(item)) return true;\n\n if (filterProp) return filterProp(item, query, itemToString);\n return defaultFilter.contains(item, query, itemToString);\n };\n\n // Base UI stores the comparer and lists it in an effect's deps, so a fresh identity per render\n // re-renders every option row and rescans the item list.\n const isItemEqualToValue = useMemo(\n () => toItemEquality(isItemEqualToValueProp),\n [isItemEqualToValueProp],\n );\n\n const wrappedItemToStringLabel: ComboboxProps<Value>['itemToStringLabel'] = !allowCreate\n ? itemToStringLabel\n : (item) => (isCreatableItem(item) ? item.value : itemToString(item));\n\n const wrappedItemToStringValue: ComboboxProps<Value>['itemToStringValue'] =\n !allowCreate || !itemToStringValue\n ? itemToStringValue\n : (item) => (isCreatableItem(item) ? item.value : itemToStringValue(item));\n\n const value = isAllSelected ? [...valueProp, selectAllItem as Value] : valueProp;\n\n const handleInputValueChange: NonNullable<ComboboxProps<Value>['onInputValueChange']> = (\n next,\n { reason },\n ) => {\n setInputValue(sanitizeTypedInput(next, reason, inputValueSanitizer));\n };\n\n const handleValueChange: ComboboxProps<Value>['onValueChange'] = (next, event) => {\n // Emptying the input once the selection changes is this component's job while it holds the\n // text; Base UI does it itself otherwise. React bails out when the text is already empty.\n if (ownsInput) setInputValue((prev) => (prev === '' ? prev : ''));\n if (!onValueChange) return;\n\n const created: Value[] = [];\n const converted = (() => {\n if (!allowCreate || !next.some(isCreatableItem)) return next;\n\n // Items by display string, so a value naming one selects it rather than minting a twin that\n // would be a second chip for one value. Built per commit — the render path only needs to\n // know whether a single value names an item.\n const itemsByLabel = new Map<string, Value>();\n for (const item of allFlatItems) itemsByLabel.set(labelKey(item), item);\n\n return next.flatMap((item) => {\n if (!isCreatableItem(item)) return [item];\n\n return addedCreateParts.map((part) => {\n const existing = itemsByLabel.get(part.toLowerCase());\n if (existing !== undefined) return existing;\n\n const value = defaultToCreateValue(part, sampleItem, queryToCreateValue) as Value;\n created.push(value);\n return value;\n });\n });\n })();\n\n const hasSelectAll = converted.some((item) => isSelectAllItem(item));\n const newValue = (() => {\n if (!hasSelectAllRow) return converted;\n if (!hasSelectAll) return isAllSelected ? [] : converted;\n return isAllSelected ? converted.filter((item) => !isSelectAllItem(item)) : allFlatItems;\n })();\n\n if (allowCreate) {\n // Keep only the created values the selection being emitted still holds — `valueProp` is the\n // selection before this change, so a value created right now is not in it yet.\n const selected = new Set(newValue.map(itemToString));\n setCreatedItems((prev) =>\n [...prev, ...created].filter((item) => selected.has(itemToString(item))),\n );\n }\n\n onValueChange(newValue, event);\n };\n\n /**\n * The create row.\n *\n * - `queryToCreateLabel` receives the values committing the row adds, rather than the entry as\n * typed — so the row cannot name a value it drops as a stray separator, a repeat, or one the\n * selection already holds, nor stay silent about one it selects from `items`.\n * - For an entry standing for a single value that string is the entry itself.\n */\n const renderCreatableItem = (item: CreatableItem) => (\n <Combobox.Item value={item} icon={<Plus />}>\n {queryToCreateLabel(joinCreateParts(addedCreateParts, createSeparator))}\n </Combobox.Item>\n );\n\n const renderItem = (item: Value) => {\n return (\n <Combobox.Item\n value={item}\n indicator={indicator}\n icon={itemToIcon(item)}\n disabled={itemToDisabled(item)}\n >\n {itemToLabel(item)}\n </Combobox.Item>\n );\n };\n\n return (\n <Combobox.Root<Value, true>\n multiple\n // Base UI highlights nothing until ArrowDown, so Enter after typing would drop the query\n // silently — no selection, and the popup closes. Highlighting the first match makes Enter\n // commit it, including the creatable row when `allowCreate` is on.\n autoHighlight\n items={items}\n value={value}\n defaultValue={defaultValue}\n filter={filter}\n isItemEqualToValue={isItemEqualToValue}\n onValueChange={handleValueChange}\n itemToStringLabel={wrappedItemToStringLabel}\n itemToStringValue={wrappedItemToStringValue}\n disabled={disabled}\n inputRef={inputRef}\n {...(ownsInput ? { inputValue, onInputValueChange: handleInputValueChange } : {})}\n >\n <BaseCombobox.Chips render={<Fragment />}>\n <Combobox.InputGroup\n variant={variant}\n sizing={sizing}\n state={state}\n focusVariant={focusVariant}\n className={className}\n >\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-wrap tw:items-center tw:gap-1.5 tw:px-4 tw:py-1.5\">\n <Combobox.Chips<Value>\n maxVisible={maxVisible}\n variant={chipVariant}\n itemToChipLabel={itemToChipLabel ?? itemToLabel}\n itemToChipColor={itemToChipColor}\n pinnedChipLabels={pinnedChipLabels}\n >\n {renderChips}\n </Combobox.Chips>\n <div className=\"tw:flex tw:flex-1 tw:items-center tw:gap-1\">\n <Combobox.Input\n id={id}\n name={name}\n onBlur={onBlur}\n aria-describedby={ariaDescribedBy}\n aria-invalid={ariaInvalid}\n aria-required={ariaRequired}\n placeholder={placeholder}\n disabled={disabled}\n // This row already owns its own edge padding above, and chips share the row with\n // the input rather than sitting outside it — cancel the group's own `&_input`\n // padding so it doesn't double up on top of this row's.\n className=\"tw:w-auto tw:min-w-[120px] tw:flex-1 tw:!px-0 tw:!py-0\"\n />\n {allowClear && (\n <InputGroup.Button asChild aria-label=\"Clear\" disabled={disabled}>\n <BaseCombobox.Clear>\n <X className=\"tw:size-4\" />\n </BaseCombobox.Clear>\n </InputGroup.Button>\n )}\n <InputGroup.Button disabled={disabled} asChild aria-label=\"Open combobox\">\n <BaseCombobox.Trigger>\n <ChevronDown className=\"tw:size-4\" />\n </BaseCombobox.Trigger>\n </InputGroup.Button>\n </div>\n </div>\n </Combobox.InputGroup>\n </BaseCombobox.Chips>\n <Combobox.Content>\n <Combobox.Empty>{empty}</Combobox.Empty>\n <Combobox.List>\n {(itemOrGroup: Value | GroupShape) => {\n if (isSelectAllItem(itemOrGroup)) {\n return (\n <Combobox.Item value={itemOrGroup} indicator=\"checkbox\">\n {itemOrGroup.label}\n </Combobox.Item>\n );\n }\n\n if (isCreatableItem(itemOrGroup)) {\n return renderCreatableItem(itemOrGroup);\n }\n\n if (isGroupItem(itemOrGroup)) {\n const maybeCreatable = itemOrGroup.items[0];\n\n if (isCreatableItem(maybeCreatable)) {\n return renderCreatableItem(maybeCreatable);\n }\n\n const groupLabel = groupToLabel(itemOrGroup);\n return (\n <Combobox.Group items={itemOrGroup.items}>\n {groupLabel && <Combobox.GroupLabel>{groupLabel}</Combobox.GroupLabel>}\n <Combobox.GroupList>{renderItem}</Combobox.GroupList>\n </Combobox.Group>\n );\n }\n\n return renderItem(itemOrGroup);\n }}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"MultiCombobox.js","names":["BaseCombobox","Combobox"],"sources":["../../../src/blocks/MultiCombobox/MultiCombobox.tsx"],"sourcesContent":["import { type ComponentProps, Fragment, type ReactNode, useMemo, useState } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { Combobox } from '../../components/Combobox';\nimport { namedLabel } from '../../components/Combobox/blankValues';\nimport { sanitizeTypedInput, useQueryReporter } from '../../components/Combobox/query';\nimport type { CreatableItem, Group } from '../../components/Combobox/types';\nimport {\n createCreatableItem,\n defaultGroupToLabel,\n defaultItemToDisabled,\n defaultItemToIcon,\n defaultItemToLabel,\n defaultQueryToCreateLabel,\n defaultToCreateValue,\n isCreatableItem,\n isGroupItem,\n isGroupItems,\n isSelectAllItem,\n selectAllItem,\n toItemEquality,\n toLabel,\n} from '../../components/Combobox/utils';\nimport { InputGroup } from '../../components/InputGroup';\nimport { useArgoDesign } from '../../components/ThemeProvider/context';\nimport { ChevronDown, Plus, X } from '../../icons';\nimport { DEFAULT_ENTRY_SEPARATOR, splitEntry } from '../../utils';\n\ntype ComboboxProps<Value> = BaseCombobox.Root.Props<Value, true>;\ntype ComboboxInputProps = ComponentProps<typeof Combobox.Input>;\ntype ComboboxInputGroupProps = ComponentProps<typeof Combobox.InputGroup>;\ntype ComboboxItemProps = ComponentProps<typeof Combobox.Item>;\ntype ComboboxChipsProps<Value> = ComponentProps<typeof Combobox.Chips<Value>>;\n\ntype Indicator = NonNullable<ComboboxItemProps['indicator']>;\n\n/**\n * How the create row lists the values it adds: each separated by the entry's own separator, then\n * a space. A `RegExp` stands for many strings, so the default separator stands in for it.\n */\nconst joinCreateParts = (parts: string[], separator: string | RegExp | null) =>\n parts.join(`${typeof separator === 'string' ? separator : DEFAULT_ENTRY_SEPARATOR} `);\n\ntype CreatableProps<Value> = {\n allowCreate?: boolean;\n /**\n * Words the create row. Receives the values committing the row will add — an entry standing for\n * several values arrives trimmed and re-joined with its own separator, not as typed.\n */\n queryToCreateLabel?: (query: string) => ReactNode;\n /**\n * Projects one entered string into an item. Called once per value, so a split entry calls it\n * several times, each with an already-trimmed part.\n */\n queryToCreateValue?: (query: string) => Value;\n /**\n * Gate on each value the entry stands for, for `allowCreate`.\n *\n * - Returning `false` drops that value, so an entry left with none hides the create row and the\n * empty state shows instead.\n * - Only called for a value that matches no item and nothing already selected — one naming an\n * item is selected rather than minted, so its format is not this gate's business.\n * - Reach for it when a free-form value has a format (a column name, an email address).\n */\n canCreate?: (query: string) => boolean;\n /**\n * Separator that makes one creatable entry stand for several values. Defaults to **`','`**, so\n * pasting `id1, id2, id3` adds three chips.\n *\n * - Pass a string or a non-capturing `RegExp` for another convention: `';'` for an Outlook\n * address list, `/[\\s,]+/` where a value can never contain a space. A capture group would be\n * handed back as a value of its own — that is `String.prototype.split`'s own behaviour.\n * - Pass `null` where a value legitimately contains the separator — a free-text label, a\n * sentence — and one entry must stay one chip.\n * - Whitespace is deliberately not part of the default: tags and column names contain spaces,\n * and each part is trimmed anyway, so `id1, id2` needs nothing more than the comma.\n */\n createSeparator?: string | RegExp | null;\n};\n\n/**\n * Props for `MultiCombobox`. Generic over `Value` (the item shape) and `GroupShape` (optional group wrapper).\n * Use `itemToLabel` / `itemToIcon` / `itemToDisabled` to project custom item shapes; use `filter` to override\n * the default substring matcher. Pass `isItemEqualToValue` when the items are objects a store recreates —\n * without it Base UI matches `value` against `items` by reference. Pass `allowCreate` to let the user add\n * free-form values not in `items`.\n */\ntype Props<Value, GroupShape extends Group<Value> = Group<Value>> = Pick<\n ComboboxInputProps,\n // `name`, `onBlur` and the `aria-*` set are forwarded to the input so a form connector can hand\n // over the wiring it derives from the field — without the `aria-*` set the control cannot be linked\n // to its own help and error text, and without `onBlur` the field never registers as blurred, which\n // is the gate `FieldItem` reveals errors on.\n 'placeholder' | 'id' | 'name' | 'onBlur' | 'aria-describedby' | 'aria-invalid' | 'aria-required'\n> &\n Pick<ComboboxInputGroupProps, 'variant' | 'focusVariant' | 'sizing' | 'state' | 'className'> &\n Pick<\n ComboboxProps<Value>,\n | 'disabled'\n | 'inputRef'\n | 'value'\n | 'defaultValue'\n | 'onValueChange'\n | 'itemToStringLabel'\n | 'itemToStringValue'\n | 'filter'\n | 'isItemEqualToValue'\n > &\n Pick<\n ComboboxChipsProps<Value>,\n 'itemToChipLabel' | 'itemToChipColor' | 'pinnedChipLabels' | 'maxVisible'\n > &\n CreatableProps<Value> & {\n items?: readonly (Value | GroupShape)[];\n\n // root specific\n /**\n * Offer a clear-all button once something is selected. Defaults to **`true`**.\n *\n * - `BaseCombobox.Clear` only mounts while chips exist, so an empty control renders identically\n * either way. Individual chips stay removable regardless.\n * - Pass `false` where emptying the whole selection must not be one click away.\n */\n allowClear?: boolean;\n /**\n * Adds a \"Select All\" row that selects the whole item set.\n *\n * - The row is hidden while a query narrows the list — it never means \"everything matching\".\n * - Selecting it while everything is already selected clears the selection.\n */\n allowSelectAll?: boolean;\n empty?: ReactNode;\n indicator?: Indicator;\n\n // query specific\n /**\n * Rewrites what the user types before the control adopts it.\n *\n * - The query the list filters by is the rewritten text, and so is every value a created entry\n * is split into — a character the user cannot type is one they cannot create.\n * - Reach for it where a created value has a character set: a column name, a scope, an\n * identifier. `canCreate` is the gate for a format the user must get right themselves.\n * - It has to rewrite rather than drop: it sees the whole text on every keystroke, so one\n * calling `trim()` swallows the space before the next word.\n */\n inputValueSanitizer?: (input: string) => string;\n /**\n * Reports the query the list filters by, `inputValueSanitizer` already applied.\n *\n * - For an owner that needs the query for itself: a server-side search, an option order, the\n * text a synthetic row is offered for. The mount render reports too, so a search driven by\n * this needs no first fetch of its own.\n * - Notification only, and deliberately not Base UI's own `onInputValueChange`: the control\n * keeps ownership of the text — a pick clears it — so there is no controlled `inputValue`\n * to hold in sync.\n */\n onQueryChange?: (query: string) => void;\n\n // item specific\n /**\n * The item's row in the list, and its chip unless `itemToChipLabel` overrides it.\n *\n * - Defaults to `itemToStringLabel`, so a control that projects its items — ids carrying the\n * selection, the label looked up beside them — states the projection once.\n * - Pass it separately only where the row is richer than the input's own text.\n */\n itemToLabel?: (item: Value) => ReactNode;\n itemToIcon?: (item: Value) => ReactNode;\n itemToDisabled?: (item: Value) => boolean;\n\n // chip specific\n /**\n * Renders the chip area from the selected values, in place of the default chips.\n *\n * - For the case no per-value accessor can express: one node standing for the whole selection\n * (\"3 tables selected\"), or a chip count that is not the value count.\n * - A chip that merely holds richer content — a link, an action of its own — needs no slot:\n * `itemToChipLabel` returns a `ReactNode` and the chip lets it take the keyboard.\n * - The chip props above go unused while this is set, `maxVisible` and its `+N` chip included.\n * - `Combobox.Chip` builds a removable chip.\n */\n renderChips?: (values: Value[]) => ReactNode;\n\n // group specific\n groupToLabel?: (group: GroupShape) => ReactNode;\n };\n\n/**\n * Multi-selection combobox with chip display and search. Built on Base UI Combobox.\n *\n * **When to use:** picking several items from a searchable enumerated list (filter by tags, assign labels).\n * Items render as chips above the input; `maxVisible` collapses excess into a `+N more` chip.\n * **When NOT to use:** for single selection use `Combobox`; for short enums without search use `Select`.\n * **Composition:** wrap in `FormGroup` for label + help text, or use `useAppForm` for form integration.\n * Pass `allowSelectAll` for a \"Select All\" item when the full enum is small — it covers the whole set\n * and hides itself while a query is active. Pass `allowCreate` to let the user add free-form values\n * that are not in `items` (e.g. entering column names by hand).\n *\n * @see RECIPES.md#creatable-multi-combobox — for free-form-plus-enumerated patterns\n * @see RECIPES.md#filter-toolbar — for combining multi-select with other filter chips\n */\nexport const MultiCombobox = <Value, GroupShape extends Group<Value> = Group<Value>>({\n // root props\n items: _itemsProp,\n value: _valueProp,\n defaultValue,\n onValueChange,\n itemToStringLabel,\n itemToStringValue,\n disabled,\n filter: filterProp,\n isItemEqualToValue: isItemEqualToValueProp,\n inputRef,\n\n // input props\n variant,\n sizing,\n focusVariant,\n state,\n placeholder,\n allowClear = true,\n id,\n name,\n onBlur,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n className,\n\n // own props\n allowSelectAll = false,\n empty = 'No items',\n indicator,\n\n // query\n inputValueSanitizer,\n onQueryChange,\n\n // creatable\n allowCreate,\n canCreate,\n queryToCreateValue,\n queryToCreateLabel = defaultQueryToCreateLabel,\n createSeparator = DEFAULT_ENTRY_SEPARATOR,\n\n // own item props\n itemToDisabled = defaultItemToDisabled,\n itemToLabel: itemToLabelProp,\n itemToIcon = defaultItemToIcon,\n groupToLabel = defaultGroupToLabel,\n itemToChipLabel,\n itemToChipColor,\n pinnedChipLabels,\n renderChips,\n // Nothing chose 3: value editors override it to `Infinity` (a chip inside `+N` can be neither\n // read nor removed) and single-row filters to `1`. Changing it moves eleven call sites at once,\n // so it waits for a PR that can look at them.\n maxVisible = 3,\n}: Props<Value, GroupShape>) => {\n const itemsProp = _itemsProp ?? [];\n const valueProp = _valueProp ?? [];\n const itemToString = (item: Value) => itemToStringLabel?.(item) ?? toLabel(item);\n /**\n * The node a row or a chip shows for an item.\n *\n * - `itemToStringLabel` is a projection, not a display accessor, so a blank it returns still\n * needs naming — rows and chips are where a blank value would otherwise render as nothing.\n * - It reads through `itemToString`, so an item the projection has no answer for falls back to\n * the item's own string: Base UI reports the outgoing selection for the render after `items`\n * and `itemToStringLabel` change together.\n */\n const itemToLabel =\n itemToLabelProp ??\n (itemToStringLabel ? (item: Value) => namedLabel(itemToString(item)) : defaultItemToLabel);\n const renderArgo = useArgoDesign();\n const chipVariant = renderArgo ? 'pill' : 'default';\n\n const [inputValue, setInputValue] = useState('');\n const [createdItems, setCreatedItems] = useState<Value[]>([]);\n const query = inputValue.trim();\n\n useQueryReporter(query, onQueryChange);\n\n // Who holds the input's text. Base UI keeps it unless something here needs to read or rewrite\n // it, because taking it means re-rendering this component on every keystroke — a cost the many\n // controls that only pick from a list should not pay.\n const ownsInput = Boolean(allowCreate || inputValueSanitizer || onQueryChange);\n\n // Created values are appended to `items` so Base UI can keep resolving them (as chips and as\n // list options) once the query clears — otherwise a value that isn't in `items` gets dropped.\n // `handleValueChange` drops the ones the selection no longer holds, so this list tracks the\n // selection rather than every value ever typed.\n const baseItems = (() => {\n if (createdItems.length === 0) return itemsProp;\n if (isGroupItems(itemsProp))\n return [...itemsProp, { items: createdItems } as unknown as GroupShape];\n return [...itemsProp, ...createdItems];\n })();\n\n const allFlatItems = baseItems.flatMap((item) => (isGroupItem(item) ? item.items : item));\n const sampleItem = allFlatItems[0] as Value | undefined;\n // An empty item set has no Select All row: there is nothing to select all of, and reading\n // `0 === 0` as \"everything is selected\" would put the row's own entry into `value`.\n const hasSelectAllRow = allowSelectAll && allFlatItems.length > 0;\n const isAllSelected = hasSelectAllRow && allFlatItems.length === (valueProp?.length ?? 0);\n\n const defaultFilter = BaseCombobox.useFilter({\n multiple: true,\n value: valueProp,\n });\n\n const itemsWithSelectAllItem = hasSelectAllRow ? [selectAllItem, ...baseItems] : baseItems;\n\n // An item's display string, case-folded — the key an entered value is matched against.\n const labelKey = (item: Value) => itemToString(item).toLowerCase();\n\n // The values the current entry stands for. Everything the create row is decided from hangs off\n // this, so an empty entry costs a creatable control nothing.\n const createParts = !allowCreate || disabled || !query ? [] : splitEntry(query, createSeparator);\n\n const selectedKeys = new Set<string>();\n if (createParts.length > 0) for (const item of valueProp) selectedKeys.add(labelKey(item));\n\n // Does an item carry this display string? `canCreate` asks it per value, so there it earns a\n // set; without the gate only a single-value entry asks, and an early-exiting scan is cheaper.\n const itemKeys = new Set<string>();\n if (createParts.length > 0 && canCreate) {\n for (const item of allFlatItems) itemKeys.add(labelKey(item));\n }\n const namesAnItem = (key: string) =>\n canCreate ? itemKeys.has(key) : allFlatItems.some((item) => labelKey(item) === key);\n\n /**\n * What the entry adds to the selection: its values the selection does not already hold.\n *\n * - The create row is named from this and committing it adds exactly this, so the row cannot\n * promise something else. A value naming an existing item counts — committing selects it.\n * - `canCreate` drops a value the control would mint and the gate rejects. One naming an item\n * is selected rather than minted, so its format is not that gate's business.\n * - `value` is the whole selection (it is never `undefined`, so the control is always the\n * controlled one), which is why the commit path re-derives nothing.\n */\n const addedCreateParts = createParts.filter((part) => {\n const key = part.toLowerCase();\n if (selectedKeys.has(key)) return false;\n return !canCreate || namesAnItem(key) || canCreate(part);\n });\n\n // The one value a single-value entry stands for, keyed — `undefined` for a split entry.\n const soleValueKey = createParts.length === 1 ? createParts[0]!.toLowerCase() : undefined;\n\n // A single value naming an item needs no create row: the list already offers that item's own\n // row, which the default substring filter matches for a single-value entry but not for a split\n // one. The item scan runs only for an entry that would otherwise show the row.\n const showCreateRow =\n addedCreateParts.length > 0 && (soleValueKey === undefined || !namesAnItem(soleValueKey));\n\n const items = (() => {\n const base = itemsWithSelectAllItem;\n if (!showCreateRow) return base;\n\n const creatable = createCreatableItem(query);\n return isGroupItems(base)\n ? [...base, { items: [creatable] } as unknown as GroupShape]\n : [...base, creatable as unknown as Value];\n })();\n\n const filter = (item: Value, query: string, itemToString?: (value: Value) => string) => {\n // Select All covers the whole item set, so it exists only while no query narrows the list.\n if (isSelectAllItem(item)) return query.trim() === '';\n // always offer the transient \"create\" option\n if (isCreatableItem(item)) return true;\n\n if (filterProp) return filterProp(item, query, itemToString);\n return defaultFilter.contains(item, query, itemToString);\n };\n\n // Base UI stores the comparer and lists it in an effect's deps, so a fresh identity per render\n // re-renders every option row and rescans the item list.\n const isItemEqualToValue = useMemo(\n () => toItemEquality(isItemEqualToValueProp),\n [isItemEqualToValueProp],\n );\n\n const wrappedItemToStringLabel: ComboboxProps<Value>['itemToStringLabel'] = !allowCreate\n ? // Guarded like `itemToLabel`, and only when the caller gave a projection — an owner that\n // gave none keeps Base UI's own accessor rather than this component's.\n itemToStringLabel && itemToString\n : (item) => (isCreatableItem(item) ? item.value : itemToString(item));\n\n const wrappedItemToStringValue: ComboboxProps<Value>['itemToStringValue'] =\n !allowCreate || !itemToStringValue\n ? itemToStringValue\n : (item) => (isCreatableItem(item) ? item.value : itemToStringValue(item));\n\n const value = isAllSelected ? [...valueProp, selectAllItem as Value] : valueProp;\n\n const handleInputValueChange: NonNullable<ComboboxProps<Value>['onInputValueChange']> = (\n next,\n { reason },\n ) => {\n setInputValue(sanitizeTypedInput(next, reason, inputValueSanitizer));\n };\n\n const handleValueChange: ComboboxProps<Value>['onValueChange'] = (next, event) => {\n // Emptying the input once the selection changes is this component's job while it holds the\n // text; Base UI does it itself otherwise. React bails out when the text is already empty.\n if (ownsInput) setInputValue((prev) => (prev === '' ? prev : ''));\n if (!onValueChange) return;\n\n const created: Value[] = [];\n const converted = (() => {\n if (!allowCreate || !next.some(isCreatableItem)) return next;\n\n // Items by display string, so a value naming one selects it rather than minting a twin that\n // would be a second chip for one value. Built per commit — the render path only needs to\n // know whether a single value names an item.\n const itemsByLabel = new Map<string, Value>();\n for (const item of allFlatItems) itemsByLabel.set(labelKey(item), item);\n\n return next.flatMap((item) => {\n if (!isCreatableItem(item)) return [item];\n\n return addedCreateParts.map((part) => {\n const existing = itemsByLabel.get(part.toLowerCase());\n if (existing !== undefined) return existing;\n\n const value = defaultToCreateValue(part, sampleItem, queryToCreateValue) as Value;\n created.push(value);\n return value;\n });\n });\n })();\n\n const hasSelectAll = converted.some((item) => isSelectAllItem(item));\n const newValue = (() => {\n if (!hasSelectAllRow) return converted;\n if (!hasSelectAll) return isAllSelected ? [] : converted;\n return isAllSelected ? converted.filter((item) => !isSelectAllItem(item)) : allFlatItems;\n })();\n\n if (allowCreate) {\n // Keep only the created values the selection being emitted still holds — `valueProp` is the\n // selection before this change, so a value created right now is not in it yet.\n const selected = new Set(newValue.map(itemToString));\n setCreatedItems((prev) =>\n [...prev, ...created].filter((item) => selected.has(itemToString(item))),\n );\n }\n\n onValueChange(newValue, event);\n };\n\n /**\n * The create row.\n *\n * - `queryToCreateLabel` receives the values committing the row adds, rather than the entry as\n * typed — so the row cannot name a value it drops as a stray separator, a repeat, or one the\n * selection already holds, nor stay silent about one it selects from `items`.\n * - For an entry standing for a single value that string is the entry itself.\n */\n const renderCreatableItem = (item: CreatableItem) => (\n <Combobox.Item value={item} icon={<Plus />}>\n {queryToCreateLabel(joinCreateParts(addedCreateParts, createSeparator))}\n </Combobox.Item>\n );\n\n const renderItem = (item: Value) => {\n return (\n <Combobox.Item\n value={item}\n indicator={indicator}\n icon={itemToIcon(item)}\n disabled={itemToDisabled(item)}\n >\n {itemToLabel(item)}\n </Combobox.Item>\n );\n };\n\n return (\n <Combobox.Root<Value, true>\n multiple\n // Base UI highlights nothing until ArrowDown, so Enter after typing would drop the query\n // silently — no selection, and the popup closes. Highlighting the first match makes Enter\n // commit it, including the creatable row when `allowCreate` is on.\n autoHighlight\n items={items}\n value={value}\n defaultValue={defaultValue}\n filter={filter}\n isItemEqualToValue={isItemEqualToValue}\n onValueChange={handleValueChange}\n itemToStringLabel={wrappedItemToStringLabel}\n itemToStringValue={wrappedItemToStringValue}\n disabled={disabled}\n inputRef={inputRef}\n {...(ownsInput ? { inputValue, onInputValueChange: handleInputValueChange } : {})}\n >\n <BaseCombobox.Chips render={<Fragment />}>\n <Combobox.InputGroup\n variant={variant}\n sizing={sizing}\n state={state}\n focusVariant={focusVariant}\n className={className}\n >\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-wrap tw:items-center tw:gap-1.5 tw:px-4 tw:py-1.5\">\n <Combobox.Chips<Value>\n maxVisible={maxVisible}\n variant={chipVariant}\n itemToChipLabel={itemToChipLabel ?? itemToLabel}\n itemToChipColor={itemToChipColor}\n pinnedChipLabels={pinnedChipLabels}\n >\n {renderChips}\n </Combobox.Chips>\n <div className=\"tw:flex tw:flex-1 tw:items-center tw:gap-1\">\n <Combobox.Input\n id={id}\n name={name}\n onBlur={onBlur}\n aria-describedby={ariaDescribedBy}\n aria-invalid={ariaInvalid}\n aria-required={ariaRequired}\n placeholder={placeholder}\n disabled={disabled}\n // This row already owns its own edge padding above, and chips share the row with\n // the input rather than sitting outside it — cancel the group's own `&_input`\n // padding so it doesn't double up on top of this row's.\n className=\"tw:w-auto tw:min-w-[120px] tw:flex-1 tw:!px-0 tw:!py-0\"\n />\n {allowClear && (\n <InputGroup.Button asChild aria-label=\"Clear\" disabled={disabled}>\n <BaseCombobox.Clear>\n <X className=\"tw:size-4\" />\n </BaseCombobox.Clear>\n </InputGroup.Button>\n )}\n <InputGroup.Button disabled={disabled} asChild aria-label=\"Open combobox\">\n <BaseCombobox.Trigger>\n <ChevronDown className=\"tw:size-4\" />\n </BaseCombobox.Trigger>\n </InputGroup.Button>\n </div>\n </div>\n </Combobox.InputGroup>\n </BaseCombobox.Chips>\n <Combobox.Content>\n <Combobox.Empty>{empty}</Combobox.Empty>\n <Combobox.List>\n {(itemOrGroup: Value | GroupShape) => {\n if (isSelectAllItem(itemOrGroup)) {\n return (\n <Combobox.Item value={itemOrGroup} indicator=\"checkbox\">\n {itemOrGroup.label}\n </Combobox.Item>\n );\n }\n\n if (isCreatableItem(itemOrGroup)) {\n return renderCreatableItem(itemOrGroup);\n }\n\n if (isGroupItem(itemOrGroup)) {\n const maybeCreatable = itemOrGroup.items[0];\n\n if (isCreatableItem(maybeCreatable)) {\n return renderCreatableItem(maybeCreatable);\n }\n\n const groupLabel = groupToLabel(itemOrGroup);\n return (\n <Combobox.Group items={itemOrGroup.items}>\n {groupLabel && <Combobox.GroupLabel>{groupLabel}</Combobox.GroupLabel>}\n <Combobox.GroupList>{renderItem}</Combobox.GroupList>\n </Combobox.Group>\n );\n }\n\n return renderItem(itemOrGroup);\n }}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n );\n};\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { InputGroup } from "../../InputGroup-DcZRlVnN.js";
1
+ import { InputGroup } from "../../InputGroup-Do8K2hvD.js";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  //#region src/blocks/NumberInput/NumberInput.tsx
4
4
  const toNumberOrNull = (event) => Number.isNaN(event.target.valueAsNumber) ? null : event.target.valueAsNumber;
@@ -1,7 +1,7 @@
1
- import { createChangeInputEvent } from "../../utils-DnkrFYqY.js";
1
+ import { createChangeInputEvent } from "../../utils-BW4AE8VP.js";
2
2
  import { mergeRefs } from "../utils/mergeRefs.js";
3
3
  import { ArrowBigUpDash, Eye, EyeOff, X } from "../../icons-Cek151jC.js";
4
- import { InputGroup } from "../../InputGroup-DcZRlVnN.js";
4
+ import { InputGroup } from "../../InputGroup-Do8K2hvD.js";
5
5
  import { useControllableState } from "../../useControllableState-M6494mCT.js";
6
6
  import { useRef, useState } from "react";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,2 +1,2 @@
1
- import { SearchInput } from "../../SearchInput-Q85p8Ews.js";
1
+ import { SearchInput } from "../../SearchInput-92r2bkA7.js";
2
2
  export { SearchInput };
@@ -1,10 +1,10 @@
1
1
  import { cn } from "../../classNames-BzrkDnOD.js";
2
- import { keyCodes } from "../../utils-DnkrFYqY.js";
2
+ import { keyCodes } from "../../utils-BW4AE8VP.js";
3
3
  import { ChevronDown, ChevronUp, Search } from "../../icons-Cek151jC.js";
4
4
  import { Button } from "../../Button-DsRrU5F1.js";
5
5
  import { ButtonGroup } from "../components/ButtonGroup.js";
6
6
  import { Separator } from "../components/Separator.js";
7
- import { TextInput } from "../../TextInput-DiEMxVF6.js";
7
+ import { TextInput } from "../../TextInput-CFTf4Cz1.js";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  //#region src/blocks/SearchInputWithNavigation/SearchInputWithNavigation.tsx
10
10
  const SearchInputWithNavigation = ({ ref, value, onValueChange, placeholder = "Search...", variant = "secondary", onClear, focusVariant, currentIndex, totalResults, onNavigateNext, onNavigatePrevious, className }) => {
@@ -1,2 +1,2 @@
1
- import { SectionNav } from "../../SectionNav-mpmSM3OC.js";
1
+ import { SectionNav } from "../../SectionNav-CNLJsiVG.js";
2
2
  export { SectionNav };
@@ -1,7 +1,7 @@
1
1
  import { ChevronDown } from "../../icons-Cek151jC.js";
2
2
  import { Button } from "../../Button-DsRrU5F1.js";
3
3
  import { ButtonGroup } from "../components/ButtonGroup.js";
4
- import { DropdownMenu } from "../../DropdownMenu-CASr-jgl.js";
4
+ import { DropdownMenu } from "../../DropdownMenu-CgVwhDvl.js";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/blocks/SplitButton/SplitButton.tsx
7
7
  const iconSizeMap = {
@@ -1,2 +1,2 @@
1
- import { TextInput } from "../../TextInput-DiEMxVF6.js";
1
+ import { TextInput } from "../../TextInput-CFTf4Cz1.js";
2
2
  export { TextInput };
@@ -1,4 +1,4 @@
1
- import { InputGroup } from "../../InputGroup-DcZRlVnN.js";
1
+ import { InputGroup } from "../../InputGroup-Do8K2hvD.js";
2
2
  import { useControllableState } from "../../useControllableState-M6494mCT.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region src/blocks/Textarea/Textarea.tsx
@@ -1,7 +1,7 @@
1
- import { createChangeInputEvent } from "../../utils-DnkrFYqY.js";
1
+ import { createChangeInputEvent } from "../../utils-BW4AE8VP.js";
2
2
  import { mergeRefs } from "../utils/mergeRefs.js";
3
3
  import { Clock, X } from "../../icons-Cek151jC.js";
4
- import { InputGroup } from "../../InputGroup-DcZRlVnN.js";
4
+ import { InputGroup } from "../../InputGroup-Do8K2hvD.js";
5
5
  import { useControllableState } from "../../useControllableState-M6494mCT.js";
6
6
  import { TimePicker } from "../../TimePicker-BGeqc-Ed.js";
7
7
  import { useRef, useState } from "react";
@@ -1,2 +1,2 @@
1
- import { Alert } from "../../Alert-C4Y9IwMI.js";
1
+ import { Alert } from "../../Alert-BsIM_oFK.js";
2
2
  export { Alert };
@@ -1,5 +1,5 @@
1
1
  import { cn } from "../../classNames-BzrkDnOD.js";
2
- import { useSHA256 } from "../../utils-DnkrFYqY.js";
2
+ import { useSHA256 } from "../../utils-BW4AE8VP.js";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  import BoringAvatar from "boring-avatars";
5
5
  //#region src/components/Avatar.tsx
@@ -1,2 +1,2 @@
1
- import { Breadcrumb } from "../../Breadcrumb-D1id7YXd.js";
1
+ import { Breadcrumb } from "../../Breadcrumb-xqEUxfwn.js";
2
2
  export { Breadcrumb };
@@ -1,2 +1,2 @@
1
- import { Checkbox } from "../../Checkbox-Bqr6zXcW.js";
1
+ import { Checkbox } from "../../Checkbox-Dq5fPNrO.js";
2
2
  export { Checkbox };
@@ -1,2 +1,2 @@
1
- import { Clipboard } from "../../Clipboard-C2YBRfD8.js";
1
+ import { Clipboard } from "../../Clipboard-BZitKiSA.js";
2
2
  export { Clipboard };
@@ -1,5 +1,5 @@
1
1
  import { cn } from "../../classNames-BzrkDnOD.js";
2
- import { keyCodes } from "../../utils-DnkrFYqY.js";
2
+ import { keyCodes } from "../../utils-BW4AE8VP.js";
3
3
  import { ChevronDown } from "../../icons-Cek151jC.js";
4
4
  import { Collapsible } from "../../Collapsible-BQXWEOBC.js";
5
5
  import { useState } from "react";
@@ -1,2 +1,2 @@
1
- import { Combobox, filterByWords, matchByWords, namedLabel, withBlankValues } from "../../Combobox-BfanUAqY.js";
1
+ import { Combobox, filterByWords, matchByWords, namedLabel, withBlankValues } from "../../Combobox-D8PrEqTG.js";
2
2
  export { Combobox, filterByWords, matchByWords, namedLabel, withBlankValues };
@@ -1,2 +1,2 @@
1
- import { DropdownMenu } from "../../DropdownMenu-CASr-jgl.js";
1
+ import { DropdownMenu } from "../../DropdownMenu-CgVwhDvl.js";
2
2
  export { DropdownMenu };
@@ -1,2 +1,2 @@
1
- import { InputGroup } from "../../InputGroup-DcZRlVnN.js";
1
+ import { InputGroup } from "../../InputGroup-Do8K2hvD.js";
2
2
  export { InputGroup };
@@ -1,2 +1,2 @@
1
- import { Kbd, kbdVariants, keys } from "../../Kbd-D1Azcc4g.js";
1
+ import { Kbd, kbdVariants, keys } from "../../Kbd-LCFMumoq.js";
2
2
  export { Kbd, kbdVariants, keys };
@@ -1,2 +1,2 @@
1
- import { Modal } from "../../Modal-Coj-H02o.js";
1
+ import { Modal } from "../../Modal-I3VWk2oo.js";
2
2
  export { Modal };
@@ -1,2 +1,2 @@
1
- import { RadioGroup } from "../../RadioGroup-CUBsuP7r.js";
1
+ import { RadioGroup } from "../../RadioGroup-Byc2mym4.js";
2
2
  export { RadioGroup };
@@ -1,2 +1,2 @@
1
- import { Search, SearchForm } from "../../Search-DVpJuzr9.js";
1
+ import { Search, SearchForm } from "../../Search-Dhig_hPD.js";
2
2
  export { Search, SearchForm };
@@ -1,2 +1,2 @@
1
- import { Sheet } from "../../Sheet-Chf0kX1E.js";
1
+ import { Sheet } from "../../Sheet-OparjIi-.js";
2
2
  export { Sheet };
@@ -1,2 +1,2 @@
1
- import { Sidebar, SidebarProvider, useOptionalSidebar, useSidebar } from "../../Sidebar-CTWsHZhF.js";
1
+ import { Sidebar, SidebarProvider, useOptionalSidebar, useSidebar } from "../../Sidebar-CLEbBtNY.js";
2
2
  export { Sidebar, SidebarProvider, useOptionalSidebar, useSidebar };
@@ -1,2 +1,2 @@
1
- import { Slider } from "../../Slider-Bv0B6lI0.js";
1
+ import { Slider } from "../../Slider-DLclvRws.js";
2
2
  export { Slider };
@@ -0,0 +1,67 @@
1
+ import { cn } from "../../classNames-BzrkDnOD.js";
2
+ import { cva } from "class-variance-authority";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/components/StatusDot/StatusDot.tsx
5
+ /**
6
+ * The dot's fill.
7
+ *
8
+ * - One class per state, each a brand-overridable status token — never a primitive hue.
9
+ * - `neutral` is chrome, not a status: an entity that has no state yet, or one the caller cannot
10
+ * resolve.
11
+ * - A solid fill is the whole mark, so the "tint + legible foreground" rule for status _surfaces_
12
+ * does not apply — there is no foreground on top of it.
13
+ */
14
+ const statusDotVariants = cva([
15
+ "tw:inline-block",
16
+ "tw:shrink-0",
17
+ "tw:rounded-full"
18
+ ], {
19
+ defaultVariants: {
20
+ status: "neutral",
21
+ size: "default"
22
+ },
23
+ variants: {
24
+ status: {
25
+ success: ["tw:bg-success"],
26
+ warning: ["tw:bg-warning"],
27
+ info: ["tw:bg-info"],
28
+ destructive: ["tw:bg-destructive"],
29
+ neutral: ["tw:bg-muted-foreground"]
30
+ },
31
+ size: {
32
+ default: ["tw:size-1.5"],
33
+ large: ["tw:size-2"]
34
+ }
35
+ }
36
+ });
37
+ /**
38
+ * A small round state mark — the one way the platform paints status as a colour.
39
+ *
40
+ * **When to use:** an entity's state beside its name in a row, a header or a chip — running,
41
+ * failed, stale, idle. `status` is the whole colour API, so a customer brand recolours every dot
42
+ * on the platform at once.
43
+ * **When NOT to use:** as the only carrier of meaning where colour is the sole difference between
44
+ * two rows — pair it with text, or use `Badge` (a labelled pill) / `Alert` (a contextual message).
45
+ * For an in-flight *step* use `Stepper`, and for indeterminate background work `DotsLoader`.
46
+ * **Composition:** `tw:flex tw:items-center tw:gap-2` with the label next to it. An overlay dot on
47
+ * top of an icon needs a ring in the surface's own colour (`tw:ring-2 tw:ring-card`) — pass it in
48
+ * `className` at the call site, since only the call site knows what it overlaps.
49
+ */
50
+ const StatusDot = ({ ref, status, size, pulse = false, label, className, ...rest }) => /* @__PURE__ */ jsx("span", {
51
+ ...rest,
52
+ ref,
53
+ "data-slot": "status-dot",
54
+ "data-status": status ?? "neutral",
55
+ ...label == null ? { "aria-hidden": true } : {
56
+ role: "img",
57
+ "aria-label": label
58
+ },
59
+ className: cn(statusDotVariants({
60
+ status,
61
+ size
62
+ }), pulse && "tw:animate-pulse", className)
63
+ });
64
+ //#endregion
65
+ export { StatusDot, statusDotVariants };
66
+
67
+ //# sourceMappingURL=StatusDot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusDot.js","names":[],"sources":["../../../src/components/StatusDot/StatusDot.tsx"],"sourcesContent":["import type { ComponentProps } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '../../utils';\n\n/**\n * The dot's fill.\n *\n * - One class per state, each a brand-overridable status token — never a primitive hue.\n * - `neutral` is chrome, not a status: an entity that has no state yet, or one the caller cannot\n * resolve.\n * - A solid fill is the whole mark, so the \"tint + legible foreground\" rule for status _surfaces_\n * does not apply — there is no foreground on top of it.\n */\nexport const statusDotVariants = cva(['tw:inline-block', 'tw:shrink-0', 'tw:rounded-full'], {\n defaultVariants: {\n status: 'neutral',\n size: 'default',\n },\n variants: {\n status: {\n success: ['tw:bg-success'],\n warning: ['tw:bg-warning'],\n info: ['tw:bg-info'],\n destructive: ['tw:bg-destructive'],\n neutral: ['tw:bg-muted-foreground'],\n },\n size: {\n default: ['tw:size-1.5'],\n large: ['tw:size-2'],\n },\n },\n});\n\ntype Props = Omit<ComponentProps<'span'>, 'children'> &\n VariantProps<typeof statusDotVariants> & {\n /** Animates the dot. Reserve it for work that is still running. */\n pulse?: boolean;\n /**\n * What the dot says on its own.\n *\n * - Omitted, the dot is decorative (`aria-hidden`) — the right choice whenever a visible label\n * sits beside it, which would otherwise be announced twice.\n * - Given, the dot becomes an image with that name: the only state a screen reader gets.\n */\n label?: string;\n };\n\n/**\n * A small round state mark — the one way the platform paints status as a colour.\n *\n * **When to use:** an entity's state beside its name in a row, a header or a chip — running,\n * failed, stale, idle. `status` is the whole colour API, so a customer brand recolours every dot\n * on the platform at once.\n * **When NOT to use:** as the only carrier of meaning where colour is the sole difference between\n * two rows — pair it with text, or use `Badge` (a labelled pill) / `Alert` (a contextual message).\n * For an in-flight *step* use `Stepper`, and for indeterminate background work `DotsLoader`.\n * **Composition:** `tw:flex tw:items-center tw:gap-2` with the label next to it. An overlay dot on\n * top of an icon needs a ring in the surface's own colour (`tw:ring-2 tw:ring-card`) — pass it in\n * `className` at the call site, since only the call site knows what it overlaps.\n */\nexport const StatusDot = ({\n ref,\n status,\n size,\n pulse = false,\n label,\n className,\n ...rest\n}: Props) => (\n <span\n {...rest}\n ref={ref}\n data-slot=\"status-dot\"\n data-status={status ?? 'neutral'}\n {...(label == null ? { 'aria-hidden': true } : { role: 'img', 'aria-label': label })}\n className={cn(statusDotVariants({ status, size }), pulse && 'tw:animate-pulse', className)}\n />\n);\n"],"mappings":";;;;;;;;;;;;;AAcA,MAAa,oBAAoB,IAAI;CAAC;CAAmB;CAAe;AAAiB,GAAG;CAC1F,iBAAiB;EACf,QAAQ;EACR,MAAM;CACR;CACA,UAAU;EACR,QAAQ;GACN,SAAS,CAAC,eAAe;GACzB,SAAS,CAAC,eAAe;GACzB,MAAM,CAAC,YAAY;GACnB,aAAa,CAAC,mBAAmB;GACjC,SAAS,CAAC,wBAAwB;EACpC;EACA,MAAM;GACJ,SAAS,CAAC,aAAa;GACvB,OAAO,CAAC,WAAW;EACrB;CACF;AACF,CAAC;;;;;;;;;;;;;;AA6BD,MAAa,aAAa,EACxB,KACA,QACA,MACA,QAAQ,OACR,OACA,WACA,GAAG,WAEH,oBAAC,QAAD;CACE,GAAI;CACC;CACL,aAAU;CACV,eAAa,UAAU;CACvB,GAAK,SAAS,OAAO,EAAE,eAAe,KAAK,IAAI;EAAE,MAAM;EAAO,cAAc;CAAM;CAClF,WAAW,GAAG,kBAAkB;EAAE;EAAQ;CAAK,CAAC,GAAG,SAAS,oBAAoB,SAAS;AAC1F,CAAA"}
@@ -1,4 +1,4 @@
1
1
  import { DEFAULT_BRAND_ID, DEFAULT_COLOR_SCHEME } from "../../defaults-i_xG2F_1.js";
2
2
  import { ArgoDesignContext, useArgoDesign, useTheme } from "../../context-D7X470dy.js";
3
- import { ThemeProvider, ThemeScope, brandSchema, exampleCustomer, keboola, keboolaLegacySidebar, keboolaLegacyTopnav, useThemeScopeContainer } from "../../ThemeProvider-BI6JWBdJ.js";
3
+ import { ThemeProvider, ThemeScope, brandSchema, exampleCustomer, keboola, keboolaLegacySidebar, keboolaLegacyTopnav, useThemeScopeContainer } from "../../ThemeProvider-DAmNn9Sd.js";
4
4
  export { ArgoDesignContext, DEFAULT_COLOR_SCHEME, DEFAULT_BRAND_ID as DEFAULT_KEBOOLA_BRAND_ID, ThemeProvider, ThemeScope, brandSchema, exampleCustomer, keboola, keboolaLegacySidebar, keboolaLegacyTopnav, useArgoDesign, useTheme, useThemeScopeContainer };
@@ -1,2 +1,2 @@
1
- import { Timeline } from "../../Timeline-BG5Xogxh.js";
1
+ import { Timeline } from "../../Timeline-C8-wnRRr.js";
2
2
  export { Timeline };
@@ -1,2 +1,2 @@
1
- import { Tooltip, TooltipProvider } from "../../utils-DnkrFYqY.js";
2
- export { Tooltip, TooltipProvider };
1
+ import { HINT_UNDERLINE_CLASS_NAME, Tooltip, TooltipProvider } from "../../utils-BW4AE8VP.js";
2
+ export { HINT_UNDERLINE_CLASS_NAME, Tooltip, TooltipProvider };
@@ -1,5 +1,5 @@
1
1
  import { cn } from "../../classNames-BzrkDnOD.js";
2
- import { Tooltip } from "../../utils-DnkrFYqY.js";
2
+ import { Tooltip } from "../../utils-BW4AE8VP.js";
3
3
  import { useState } from "react";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/components/Truncated.tsx
@@ -1,2 +1,2 @@
1
- import { ZoomableSvg, svgToPngBlob, toSvgFileContent } from "../../ZoomableSvg-U_VH3QRO.js";
1
+ import { ZoomableSvg, svgToPngBlob, toSvgFileContent } from "../../ZoomableSvg-BZlk3PFJ.js";
2
2
  export { ZoomableSvg, svgToPngBlob, toSvgFileContent };
@@ -1,4 +1,4 @@
1
- import { useElement } from "../../useElement-DkF6esWL.js";
1
+ import { useElement } from "../../useElement-BK3AAiIf.js";
2
2
  import { useEffect, useState } from "react";
3
3
  //#region src/hooks/useScrollbarPosition.ts
4
4
  const calcPosition = ({ scrollHeight, clientHeight, scrollTop }) => {
@@ -1,18 +1,36 @@
1
1
  //#region src/utils/mergeRefs.ts
2
2
  /**
3
- * Set a given ref to a given value
4
- * This utility takes care of different types of refs: callback refs and RefObject(s)
3
+ * Attach a node to one ref, and hand back the way to detach it.
4
+ *
5
+ * - A callback ref that returns its own cleanup gets that cleanup back; React 19 owns the
6
+ * contract, and a hook using it never sees the legacy `null` call.
7
+ * - One that returns nothing is detached the legacy way instead, with a `null` call.
8
+ * - An object ref's `current` is cleared.
5
9
  */
6
- function setRef(ref, value) {
7
- if (typeof ref === "function") ref(value);
8
- else if (ref != null) ref.current = value;
9
- }
10
+ const attachRef = (ref, node) => {
11
+ if (typeof ref === "function") {
12
+ const cleanup = ref(node);
13
+ return typeof cleanup === "function" ? cleanup : () => ref(null);
14
+ }
15
+ if (ref == null) return () => {};
16
+ ref.current = node;
17
+ return () => {
18
+ ref.current = null;
19
+ };
20
+ };
10
21
  /**
11
- * A utility to compose multiple refs together
12
- * Accepts callback refs and RefObject(s)
22
+ * Compose several refs into the one a component can hand to an element.
23
+ *
24
+ * - Accepts callback refs and ref objects, in any mix.
25
+ * - Returns a cleanup of its own, so a callback ref's cleanup survives the merge. Dropping it
26
+ * would leave a hook that detaches through its cleanup — `useElement` does — holding a node
27
+ * that is no longer in the document.
13
28
  */
14
29
  const mergeRefs = (...refs) => {
15
- return (node) => refs.forEach((ref) => setRef(ref, node));
30
+ return (node) => {
31
+ const cleanups = refs.map((ref) => attachRef(ref, node));
32
+ return () => cleanups.forEach((cleanup) => cleanup());
33
+ };
16
34
  };
17
35
  //#endregion
18
36
  export { mergeRefs };
@@ -1 +1 @@
1
- {"version":3,"file":"mergeRefs.js","names":[],"sources":["../../../src/utils/mergeRefs.ts"],"sourcesContent":["import type { MutableRefObject, RefCallback } from 'react';\n\ntype PossibleRef<T> = MutableRefObject<T> | RefCallback<T> | null;\n\n/**\n * Set a given ref to a given value\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n */\nfunction setRef<T>(ref: PossibleRef<T>, value: T) {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref != null) {\n ref.current = value;\n }\n}\n\n/**\n * A utility to compose multiple refs together\n * Accepts callback refs and RefObject(s)\n */\nexport const mergeRefs = <T>(...refs: PossibleRef<T>[]) => {\n return (node: T) => refs.forEach((ref) => setRef(ref, node));\n};\n"],"mappings":";;;;;AAQA,SAAS,OAAU,KAAqB,OAAU;CAChD,IAAI,OAAO,QAAQ,YACjB,IAAI,KAAK;MACJ,IAAI,OAAO,MAChB,IAAI,UAAU;AAElB;;;;;AAMA,MAAa,aAAgB,GAAG,SAA2B;CACzD,QAAQ,SAAY,KAAK,SAAS,QAAQ,OAAO,KAAK,IAAI,CAAC;AAC7D"}
1
+ {"version":3,"file":"mergeRefs.js","names":[],"sources":["../../../src/utils/mergeRefs.ts"],"sourcesContent":["import type { Ref, RefCallback } from 'react';\n\ntype PossibleRef<T> = Ref<T> | undefined;\n\n/**\n * Attach a node to one ref, and hand back the way to detach it.\n *\n * - A callback ref that returns its own cleanup gets that cleanup back; React 19 owns the\n * contract, and a hook using it never sees the legacy `null` call.\n * - One that returns nothing is detached the legacy way instead, with a `null` call.\n * - An object ref's `current` is cleared.\n */\nconst attachRef = <T>(ref: PossibleRef<T>, node: T): (() => void) => {\n if (typeof ref === 'function') {\n const cleanup = ref(node);\n return typeof cleanup === 'function' ? cleanup : () => ref(null);\n }\n\n if (ref == null) return () => {};\n\n ref.current = node;\n return () => {\n ref.current = null;\n };\n};\n\n/**\n * Compose several refs into the one a component can hand to an element.\n *\n * - Accepts callback refs and ref objects, in any mix.\n * - Returns a cleanup of its own, so a callback ref's cleanup survives the merge. Dropping it\n * would leave a hook that detaches through its cleanup — `useElement` does — holding a node\n * that is no longer in the document.\n */\nexport const mergeRefs = <T>(...refs: PossibleRef<T>[]): RefCallback<T> => {\n return (node) => {\n const cleanups = refs.map((ref) => attachRef(ref, node));\n return () => cleanups.forEach((cleanup) => cleanup());\n };\n};\n"],"mappings":";;;;;;;;;AAYA,MAAM,aAAgB,KAAqB,SAA0B;CACnE,IAAI,OAAO,QAAQ,YAAY;EAC7B,MAAM,UAAU,IAAI,IAAI;EACxB,OAAO,OAAO,YAAY,aAAa,gBAAgB,IAAI,IAAI;CACjE;CAEA,IAAI,OAAO,MAAM,aAAa,CAAC;CAE/B,IAAI,UAAU;CACd,aAAa;EACX,IAAI,UAAU;CAChB;AACF;;;;;;;;;AAUA,MAAa,aAAgB,GAAG,SAA2C;CACzE,QAAQ,SAAS;EACf,MAAM,WAAW,KAAK,KAAK,QAAQ,UAAU,KAAK,IAAI,CAAC;EACvD,aAAa,SAAS,SAAS,YAAY,QAAQ,CAAC;CACtD;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { cn } from "../classNames-BzrkDnOD.js";
2
- import { copyToClipboard, createChangeInputEvent, createPrefixedString, debounce, isMac, noop, useSHA256, withHiddenFullscreen, withTooltipProvider, withVisualSettle } from "../utils-DnkrFYqY.js";
2
+ import { DEFAULT_ENTRY_SEPARATOR, copyToClipboard, createChangeInputEvent, createPrefixedString, debounce, isMac, noop, splitEntry, useSHA256, withHiddenFullscreen, withTooltipProvider, withVisualSettle } from "../utils-BW4AE8VP.js";
3
3
  import { findLiteralMatches, findLiteralTermMatches, hasLiteralMatch } from "../findLiteralMatches-BGBw8Vbl.js";
4
4
  import { mergeRefs } from "./utils/mergeRefs.js";
5
- export { cn, copyToClipboard, createChangeInputEvent, createPrefixedString, debounce, findLiteralMatches, findLiteralTermMatches, hasLiteralMatch, isMac, mergeRefs, noop, useSHA256, withHiddenFullscreen, withTooltipProvider, withVisualSettle };
5
+ export { DEFAULT_ENTRY_SEPARATOR, cn, copyToClipboard, createChangeInputEvent, createPrefixedString, debounce, findLiteralMatches, findLiteralTermMatches, hasLiteralMatch, isMac, mergeRefs, noop, splitEntry, useSHA256, withHiddenFullscreen, withTooltipProvider, withVisualSettle };
@@ -1,13 +1,13 @@
1
1
  import { cn } from "./classNames-BzrkDnOD.js";
2
- import { Tooltip } from "./utils-DnkrFYqY.js";
2
+ import { Tooltip } from "./utils-BW4AE8VP.js";
3
3
  import { AlignCenter, AlignJustify, AlignLeft, AlignRight, Bold, ChevronDown, Code, Heading1, Heading2, Heading3, Italic, Link, List, ListOrdered, Quote, SquareCode, Strikethrough, Type, Underline } from "./icons-Cek151jC.js";
4
4
  import { Button } from "./Button-DsRrU5F1.js";
5
5
  import { ButtonGroup } from "./internal/components/ButtonGroup.js";
6
- import { DropdownMenu } from "./DropdownMenu-CASr-jgl.js";
6
+ import { DropdownMenu } from "./DropdownMenu-CgVwhDvl.js";
7
7
  import { Label } from "./internal/components/Label.js";
8
8
  import { useStableCallback } from "./internal/hooks/useStableCallback.js";
9
- import { TextInput } from "./TextInput-DiEMxVF6.js";
10
- import { FormGroup } from "./FormGroup-Bl8JmnzJ.js";
9
+ import { TextInput } from "./TextInput-CFTf4Cz1.js";
10
+ import { FormGroup } from "./FormGroup-DR_gZ25-.js";
11
11
  import { Skeleton } from "./internal/components/Skeleton/Skeleton.js";
12
12
  import { toast } from "./toast-DIC0iNRf.js";
13
13
  import { Suspense, createContext, lazy, use, useCallback, useEffect, useRef, useState } from "react";
@@ -141,7 +141,7 @@ const $isImageNode = (node) => {
141
141
  };
142
142
  //#endregion
143
143
  //#region src/blocks/MarkdownEditor/nodes/MermaidNodeComponent.tsx
144
- const MermaidDiagram = lazy(() => import("./MermaidDiagram-CujFxVzk.js").then((n) => n.MermaidDiagram_exports).then((m) => ({ default: m.MermaidDiagram }), (error) => {
144
+ const MermaidDiagram = lazy(() => import("./MermaidDiagram-ZG0iiDV_.js").then((n) => n.MermaidDiagram_exports).then((m) => ({ default: m.MermaidDiagram }), (error) => {
145
145
  console.error("[MarkdownEditor] failed to load MermaidDiagram chunk", error);
146
146
  return { default: ({ code }) => /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: code }) }) };
147
147
  }));
package/dist/mermaid.js CHANGED
@@ -1,2 +1,2 @@
1
- import { MermaidDiagram } from "./MermaidDiagram-CujFxVzk.js";
1
+ import { MermaidDiagram } from "./MermaidDiagram-ZG0iiDV_.js";
2
2
  export { MermaidDiagram };
package/dist/rjsf.js CHANGED
@@ -1,22 +1,22 @@
1
- import { Tooltip, debounce } from "./utils-DnkrFYqY.js";
1
+ import { Tooltip, debounce } from "./utils-BW4AE8VP.js";
2
2
  import { BookOpen, Info, Trash2 } from "./icons-Cek151jC.js";
3
3
  import { Button } from "./Button-DsRrU5F1.js";
4
4
  import { Label } from "./internal/components/Label.js";
5
5
  import { Link } from "./internal/components/Link.js";
6
6
  import { useStableCallback } from "./internal/hooks/useStableCallback.js";
7
- import { TextInput } from "./TextInput-DiEMxVF6.js";
8
- import { RadioGroup } from "./RadioGroup-CUBsuP7r.js";
9
- import { Checkbox } from "./Checkbox-Bqr6zXcW.js";
10
- import { Combobox } from "./Combobox-BfanUAqY.js";
11
- import { FormGroup } from "./FormGroup-Bl8JmnzJ.js";
7
+ import { TextInput } from "./TextInput-CFTf4Cz1.js";
8
+ import { RadioGroup } from "./RadioGroup-Byc2mym4.js";
9
+ import { Checkbox } from "./Checkbox-Dq5fPNrO.js";
10
+ import { Combobox } from "./Combobox-D8PrEqTG.js";
11
+ import { FormGroup } from "./FormGroup-DR_gZ25-.js";
12
12
  import { NumberInput } from "./internal/blocks/NumberInput.js";
13
13
  import { Textarea } from "./internal/blocks/Textarea.js";
14
- import { DateInput } from "./DateInput-DpifECUQ.js";
14
+ import { DateInput } from "./DateInput-B6N8g0ra.js";
15
15
  import { PasswordInput } from "./internal/blocks/PasswordInput.js";
16
- import { Alert } from "./Alert-C4Y9IwMI.js";
16
+ import { Alert } from "./Alert-BsIM_oFK.js";
17
17
  import { CollapsiblePanel } from "./internal/components/CollapsiblePanel.js";
18
18
  import { Tabs, TabsContent } from "./Tabs-eB974xJf.js";
19
- import { CodeEditor, isLanguageMode } from "./CodeEditor-C9AS8Ch0.js";
19
+ import { CodeEditor, isLanguageMode } from "./CodeEditor-BJKJXA0c.js";
20
20
  import { createContext, isValidElement, use, useCallback, useEffect, useMemo, useRef, useState } from "react";
21
21
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
22
22
  import DOMPurify from "dompurify";