@keboola/design 13.2.0 → 14.0.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 (172) hide show
  1. package/AGENTS.md +5 -1
  2. package/CHANGELOG.md +161 -0
  3. package/COMPONENT-API.md +52 -42
  4. package/dist/{AIKit-C5FbKjwa.js → AIKit-BRSZ3nY7.js} +2216 -302
  5. package/dist/AIKit-BRSZ3nY7.js.map +1 -0
  6. package/dist/{Alert-DuAGeYyM.js → Alert-CZ0dDsuk.js} +2 -2
  7. package/dist/{Alert-DuAGeYyM.js.map → Alert-CZ0dDsuk.js.map} +1 -1
  8. package/dist/{BrandEditor-Dq168RJc.js → BrandEditor-CN2HJ_12.js} +5 -5
  9. package/dist/{BrandEditor-Dq168RJc.js.map → BrandEditor-CN2HJ_12.js.map} +1 -1
  10. package/dist/{Breadcrumb-CUyYu5Bi.js → Breadcrumb-BnIlsoIH.js} +54 -12
  11. package/dist/Breadcrumb-BnIlsoIH.js.map +1 -0
  12. package/dist/{Checkbox-D9rafoKh.js → Checkbox-uFE8XLT_.js} +2 -2
  13. package/dist/{Checkbox-D9rafoKh.js.map → Checkbox-uFE8XLT_.js.map} +1 -1
  14. package/dist/{Clipboard-BHWUodAx.js → Clipboard-D-9XOqy4.js} +2 -2
  15. package/dist/{Clipboard-BHWUodAx.js.map → Clipboard-D-9XOqy4.js.map} +1 -1
  16. package/dist/{ClipboardButton-Urg-kZbh.js → ClipboardButton-DxvZG_H0.js} +2 -2
  17. package/dist/{ClipboardButton-Urg-kZbh.js.map → ClipboardButton-DxvZG_H0.js.map} +1 -1
  18. package/dist/{CodeEditor-Y0iE-SwV.js → CodeEditor-BfRSCKEs.js} +5 -5
  19. package/dist/{CodeEditor-Y0iE-SwV.js.map → CodeEditor-BfRSCKEs.js.map} +1 -1
  20. package/dist/{ColorInput-D1nC0X6i.js → ColorInput-CDKH8q_f.js} +2 -2
  21. package/dist/{ColorInput-D1nC0X6i.js.map → ColorInput-CDKH8q_f.js.map} +1 -1
  22. package/dist/{ColorModeSwitch-Cxee8jnB.js → ColorModeSwitch-DR6J2U6M.js} +2 -2
  23. package/dist/{ColorModeSwitch-Cxee8jnB.js.map → ColorModeSwitch-DR6J2U6M.js.map} +1 -1
  24. package/dist/{Combobox-B1Kjoy5J.js → Combobox-CEesMe2M.js} +240 -38
  25. package/dist/Combobox-CEesMe2M.js.map +1 -0
  26. package/dist/{Command-BuOA3V18.js → Command-T3MLRaen.js} +8 -4
  27. package/dist/Command-T3MLRaen.js.map +1 -0
  28. package/dist/{CopyField-DsOVtV2Q.js → CopyField-CNbCHw9a.js} +2 -2
  29. package/dist/{CopyField-DsOVtV2Q.js.map → CopyField-CNbCHw9a.js.map} +1 -1
  30. package/dist/{DateInput-BlKkequE.js → DateInput-ClK1lCxz.js} +2 -2
  31. package/dist/{DateInput-BlKkequE.js.map → DateInput-ClK1lCxz.js.map} +1 -1
  32. package/dist/{DateRangeInput-DOxJHw8V.js → DateRangeInput-DtlAffS1.js} +2 -2
  33. package/dist/{DateRangeInput-DOxJHw8V.js.map → DateRangeInput-DtlAffS1.js.map} +1 -1
  34. package/dist/{DropdownMenu-DtRYcKEx.js → DropdownMenu-B1gGvZoh.js} +2 -2
  35. package/dist/{DropdownMenu-DtRYcKEx.js.map → DropdownMenu-B1gGvZoh.js.map} +1 -1
  36. package/dist/{FieldItem-Cf1E3rfQ.js → FieldItem-CYvJyjiI.js} +3 -3
  37. package/dist/{FieldItem-Cf1E3rfQ.js.map → FieldItem-CYvJyjiI.js.map} +1 -1
  38. package/dist/{Form-CuaAn-lR.js → Form-CD55zJiy.js} +5 -5
  39. package/dist/{Form-CuaAn-lR.js.map → Form-CD55zJiy.js.map} +1 -1
  40. package/dist/{FormGroup-D4O96YPm.js → FormGroup-DiYFdEhH.js} +3 -3
  41. package/dist/{FormGroup-D4O96YPm.js.map → FormGroup-DiYFdEhH.js.map} +1 -1
  42. package/dist/{HoverCard-Cy6nhg4u.js → HoverCard-BBdPYqEf.js} +2 -2
  43. package/dist/HoverCard-BBdPYqEf.js.map +1 -0
  44. package/dist/{InlineEdit-DSMIEUUa.js → InlineEdit-D5RdunZo.js} +3 -3
  45. package/dist/{InlineEdit-DSMIEUUa.js.map → InlineEdit-D5RdunZo.js.map} +1 -1
  46. package/dist/{Kbd-Du93F3o4.js → Kbd-3YM7NQO4.js} +2 -2
  47. package/dist/{Kbd-Du93F3o4.js.map → Kbd-3YM7NQO4.js.map} +1 -1
  48. package/dist/MermaidDiagram-CeiOkI60.js +199 -0
  49. package/dist/MermaidDiagram-CeiOkI60.js.map +1 -0
  50. package/dist/{Modal-DQIauzar.js → Modal-DMZRswk4.js} +4 -3
  51. package/dist/Modal-DMZRswk4.js.map +1 -0
  52. package/dist/{MultiActionButtonGroup-xKqiucAN.js → MultiActionButtonGroup-CEv_txvz.js} +2 -2
  53. package/dist/{MultiActionButtonGroup-xKqiucAN.js.map → MultiActionButtonGroup-CEv_txvz.js.map} +1 -1
  54. package/dist/{RadioGroup-C2vk5acr.js → RadioGroup-C8EC3fqO.js} +2 -2
  55. package/dist/{RadioGroup-C2vk5acr.js.map → RadioGroup-C8EC3fqO.js.map} +1 -1
  56. package/dist/{Search-CVrv3hqf.js → Search-aaUMI4ix.js} +2 -2
  57. package/dist/{Search-CVrv3hqf.js.map → Search-aaUMI4ix.js.map} +1 -1
  58. package/dist/{SearchInput-BnU6YHgT.js → SearchInput-Dxi2GK4n.js} +2 -2
  59. package/dist/{SearchInput-BnU6YHgT.js.map → SearchInput-Dxi2GK4n.js.map} +1 -1
  60. package/dist/{SectionNav-XlhvXXdF.js → SectionNav-BnHOMLtE.js} +3 -3
  61. package/dist/{SectionNav-XlhvXXdF.js.map → SectionNav-BnHOMLtE.js.map} +1 -1
  62. package/dist/Sheet-utw4_rUa.js.map +1 -1
  63. package/dist/{Sidebar-CKaxOPwY.js → Sidebar-BAmux2Uj.js} +5 -5
  64. package/dist/{Sidebar-CKaxOPwY.js.map → Sidebar-BAmux2Uj.js.map} +1 -1
  65. package/dist/{Slider-Rcc2qVct.js → Slider-DbzzSDRV.js} +2 -2
  66. package/dist/{Slider-Rcc2qVct.js.map → Slider-DbzzSDRV.js.map} +1 -1
  67. package/dist/{Table-CgSC-fSo.js → Table-CilEvpMq.js} +62 -3
  68. package/dist/Table-CilEvpMq.js.map +1 -0
  69. package/dist/{TextInput-B5TDDOty.js → TextInput-K2DSDs5O.js} +2 -2
  70. package/dist/{TextInput-B5TDDOty.js.map → TextInput-K2DSDs5O.js.map} +1 -1
  71. package/dist/{ThemeProvider-Dt9b67sW.js → ThemeProvider-C8yaKlM1.js} +2 -2
  72. package/dist/{ThemeProvider-Dt9b67sW.js.map → ThemeProvider-C8yaKlM1.js.map} +1 -1
  73. package/dist/ToggleAllTooltip-Dlmq-yqS.js +37 -0
  74. package/dist/ToggleAllTooltip-Dlmq-yqS.js.map +1 -0
  75. package/dist/{ZoomableSvg-D8sXKpoV.js → ZoomableSvg-Dh1OstPN.js} +84 -80
  76. package/dist/ZoomableSvg-Dh1OstPN.js.map +1 -0
  77. package/dist/editors.js +3 -3
  78. package/dist/flint.js +10 -45
  79. package/dist/flint.js.map +1 -1
  80. package/dist/highlightCode-D354tCXO.js +81 -0
  81. package/dist/highlightCode-D354tCXO.js.map +1 -0
  82. package/dist/index.d.ts +792 -346
  83. package/dist/index.js +35 -35
  84. package/dist/internal/blocks/AIKit.js +2 -2
  85. package/dist/internal/blocks/BrandEditor.js +1 -1
  86. package/dist/internal/blocks/ChipEditor.js +1 -1
  87. package/dist/internal/blocks/ClipboardButton.js +1 -1
  88. package/dist/internal/blocks/ColorInput.js +1 -1
  89. package/dist/internal/blocks/ColorModeSwitch.js +1 -1
  90. package/dist/internal/blocks/Command.js +1 -1
  91. package/dist/internal/blocks/CopyField.js +1 -1
  92. package/dist/internal/blocks/DateInput.js +1 -1
  93. package/dist/internal/blocks/DateRangeInput.js +1 -1
  94. package/dist/internal/blocks/DiagramShared/DiagramSkeleton.js.map +1 -1
  95. package/dist/internal/blocks/ExportMenu.js +2 -2
  96. package/dist/internal/blocks/Form/connectors/ComboboxField.js +2 -2
  97. package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +1 -1
  98. package/dist/internal/blocks/Form.js +1 -1
  99. package/dist/internal/blocks/FormGroup.js +1 -1
  100. package/dist/internal/blocks/InlineEdit.js +1 -1
  101. package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
  102. package/dist/internal/blocks/MultiCombobox.js +204 -68
  103. package/dist/internal/blocks/MultiCombobox.js.map +1 -1
  104. package/dist/internal/blocks/PasswordInput.js +1 -1
  105. package/dist/internal/blocks/SearchInput.js +1 -1
  106. package/dist/internal/blocks/SearchInputWithNavigation.js +2 -2
  107. package/dist/internal/blocks/SectionNav.js +1 -1
  108. package/dist/internal/blocks/SplitButton.js +1 -1
  109. package/dist/internal/blocks/TextInput.js +1 -1
  110. package/dist/internal/blocks/TimeInput.js +1 -1
  111. package/dist/internal/components/Alert.js +1 -1
  112. package/dist/internal/components/Avatar.js +1 -1
  113. package/dist/internal/components/Breadcrumb.js +1 -1
  114. package/dist/internal/components/Checkbox.js +1 -1
  115. package/dist/internal/components/Clipboard.js +1 -1
  116. package/dist/internal/components/CollapsiblePanel.js +1 -1
  117. package/dist/internal/components/Combobox.js +1 -1
  118. package/dist/internal/components/DropdownMenu.js +1 -1
  119. package/dist/internal/components/HoverCard.js +1 -1
  120. package/dist/internal/components/Kbd.js +1 -1
  121. package/dist/internal/components/Modal.js +1 -1
  122. package/dist/internal/components/RadioGroup.js +1 -1
  123. package/dist/internal/components/Search.js +1 -1
  124. package/dist/internal/components/Sidebar.js +1 -1
  125. package/dist/internal/components/Skeleton/Skeleton.js +1 -1
  126. package/dist/internal/components/Skeleton/Skeleton.js.map +1 -1
  127. package/dist/internal/components/Slider.js +1 -1
  128. package/dist/internal/components/Table.js +1 -1
  129. package/dist/internal/components/ThemeProvider.js +1 -1
  130. package/dist/internal/components/Tooltip.js +1 -1
  131. package/dist/internal/components/Truncated.js +1 -1
  132. package/dist/internal/components/ZoomableSvg.js +1 -1
  133. package/dist/internal/utils.js +1 -1
  134. package/dist/markdown-editor.js +6 -6
  135. package/dist/mermaid.d.ts +1 -2
  136. package/dist/mermaid.js +1 -1
  137. package/dist/rjsf.js +98 -11
  138. package/dist/rjsf.js.map +1 -1
  139. package/dist/styles.css +1 -1
  140. package/dist/svgCache-Dhmbe-7i.js +26 -0
  141. package/dist/svgCache-Dhmbe-7i.js.map +1 -0
  142. package/dist/svgTransforms-Hnvev3Vs.js +38 -0
  143. package/dist/svgTransforms-Hnvev3Vs.js.map +1 -0
  144. package/dist/testing.js +1 -1
  145. package/dist/{themeTokens-7DEab0kp.js → themeTokens-l2Fsfcs7.js} +3 -12
  146. package/dist/themeTokens-l2Fsfcs7.js.map +1 -0
  147. package/dist/{utils-p6tjltbX.js → utils-LQ4jJA-9.js} +18 -2
  148. package/dist/utils-LQ4jJA-9.js.map +1 -0
  149. package/dist/vega.js +1 -1
  150. package/dist/vegaTheme-BrmVoPEz.js +49 -0
  151. package/dist/vegaTheme-BrmVoPEz.js.map +1 -0
  152. package/dist/{vegaTheme-VQMWTlBw.js → vegaTokens-Ce07C0DH.js} +36 -44
  153. package/dist/vegaTokens-Ce07C0DH.js.map +1 -0
  154. package/package.json +3 -4
  155. package/src/styles.css +4 -4
  156. package/dist/AIKit-C5FbKjwa.js.map +0 -1
  157. package/dist/Breadcrumb-CUyYu5Bi.js.map +0 -1
  158. package/dist/Combobox-B1Kjoy5J.js.map +0 -1
  159. package/dist/Command-BuOA3V18.js.map +0 -1
  160. package/dist/DiagramSource-jTwmmi9g.js +0 -11
  161. package/dist/DiagramSource-jTwmmi9g.js.map +0 -1
  162. package/dist/HoverCard-Cy6nhg4u.js.map +0 -1
  163. package/dist/MermaidDiagram-D2ThT8Q-.js +0 -302
  164. package/dist/MermaidDiagram-D2ThT8Q-.js.map +0 -1
  165. package/dist/Modal-DQIauzar.js.map +0 -1
  166. package/dist/Table-CgSC-fSo.js.map +0 -1
  167. package/dist/ZoomableSvg-D8sXKpoV.js.map +0 -1
  168. package/dist/svgTransforms-Dw2hRA-i.js +0 -51
  169. package/dist/svgTransforms-Dw2hRA-i.js.map +0 -1
  170. package/dist/themeTokens-7DEab0kp.js.map +0 -1
  171. package/dist/utils-p6tjltbX.js.map +0 -1
  172. package/dist/vegaTheme-VQMWTlBw.js.map +0 -1
package/AGENTS.md CHANGED
@@ -79,6 +79,8 @@ This file answers **which** component to use; [`COMPONENT-API.md`](./COMPONENT-A
79
79
 
80
80
  **Never** use `Popover` for destructive confirmations (use `Popconfirm`) or hover-only previews (use `HoverCard`). **Never** hand-roll a confirmation from `Modal` + buttons — use `AlertModal`, which owns the confirm/cancel actions and the async loading state.
81
81
 
82
+ **`Modal.Content` is centred by default.** Pass `align="top"` when the content changes height while in use (fields appear or drop as the user picks), so the modal stops re-centring and moving the field under the pointer. The legacy brand ignores it: its modals are always top-anchored.
83
+
82
84
  **Filters in a menu are menu items:** `DropdownMenu.RadioItem indicator="check"` for one value, `DropdownMenu.CheckboxItem indicator="checkbox"` for several, both `indicatorAlign="end"`. Never `RadioGroup` or `Checkbox` in a `DropdownMenu` or `Popover`.
83
85
 
84
86
  ### Inputs
@@ -743,10 +745,12 @@ takes the node, and the chip lets it have the keyboard.
743
745
  />
744
746
  ```
745
747
 
746
- - A query overrides folding: every match shows, and a group with none disappears — so the group's row always stands for something the user can see.
748
+ - A query opens every group with a match, and a group with none disappears — so the group's row always stands for something the user can see. A fold made under a query lasts until the query changes.
747
749
  - `value` holds items only. The row reads checked / mixed from them and never becomes a chip, so `allowSelectAll` and `renderChips` count what they always count.
748
750
  - Without `selectableGroups` / `groupToValue` a press on the row folds the group; with them, the chevron and `ArrowRight` / `ArrowLeft` do.
749
751
  - Don't hand-roll it from a flat list and an `onValueChange` that expands a parent into its children — the control owns the fold, the query override and the mixed state.
752
+ - An item the user picked elsewhere and can't remove here (a table another mapping uses) is `itemToLocked`, not `itemToDisabled`: a locked row looks disabled but still takes the highlight, so `renderAside` describes it and its group still folds; a disabled row takes neither.
753
+ - `renderAside={(highlighted) => …}` adds an inspector beside the list about the last row the pointer or the arrow keys were on — `{ kind: 'item' }`, `{ kind: 'group' }` or `null` before any. A button in the popup hides it (`asideOpen` / `onAsideOpenChange` to persist that), and it stays hidden while the popup is under 40rem. Reach for it when a row needs more detail than fits on it.
750
754
 
751
755
  **Long lists** — a `Combobox` or `MultiCombobox` whose options can run into the hundreds (tables, configurations, users) takes `virtualized="auto"`: past 30 options, grouped or not, only the rows in view reach the DOM. It is opt-in because a test that clicks a far row needs every option rendered.
752
756
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,166 @@
1
1
  # @keboola/design
2
2
 
3
+ ## 14.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - `ToolCallApproval` v2 — redesigned around what an agent chat's approval card needs. It had no consumers, so the old API is replaced outright.
8
+ - Removed: `enableShortcuts` (Enter approve / Escape reject) and the `actions` override; `toolName` is now optional.
9
+ - Actions: `approveLabel` / `rejectLabel`, `approveVariant` (`'primary' | 'danger'`), an optional `extraAction` (e.g. "Always allow"), `pendingAction` (that button spins, every action disables), `isDisabled`.
10
+ - Header: `eyebrow` slot, optional `toolName`, `title`.
11
+ - Terminal states: `approved`, `rejected`, `expired`, `timed-out`, `cancelled`, `unattended`, with `statusLabel` / `statusMessage`, `resolvedBy` / `resolvedAt`, and `density="record"` for a one-line resolved record.
12
+ - Body: `children`, `notices` (warning / destructive / info rows), `aside` (beside the detail, stacked in a narrow container), `error`.
13
+ - Keyboard: `shortcutKey` (`'enter' | 'mod-enter' | 'none'`) approves from anywhere and shows the key on the button; `isShortcutHintOnly` shows it for an app that owns the shortcut.
14
+ - Stable test ids: `tool-call-approval`, `tool-approve-button`, `tool-decline-button`, `tool-extra-action-button`.
15
+
16
+ ### Minor Changes
17
+
18
+ - `AnswerSources` and `SourceChip`: the provenance row under an answer. Chips carry a `verified` / `unverified` / `neutral` verdict and render as a link, button or label; the row collapses past six chips, summarises unverified ones once, states when none were declared and takes a `footnote` slot.
19
+
20
+ - `ChatNotice`: a transcript notice row over `Alert` with `tone` (`error` / `warn` / `info`), an `action` slot, collapsible "Technical details" and an optional `retryAfter` countdown.
21
+
22
+ - AI Kit composer chips: `AttachmentChip` (uploading / ready / error file chip with remove), `ContextChip` (quoted excerpt with "Show all" and images), `ModeChip` (removable animated mode pill) and `JumpToLatest` (scroll-to-latest button that pulses while the agent is working).
23
+
24
+ - `SuggestedPrompt` takes `description` (a secondary line under the label), `trailing` (content pinned to the row's end, e.g. a badge) and `aria-label`. Without them it renders as before.
25
+
26
+ - `PlanApproval` and `AnswerSummary` take an `expired` state for a card closed with no decision.
27
+ - `PlanApproval`: `status="expired"` (orange `Expired` pill, no actions), plus `statusLabel` to rename the pill and `statusMessage` shown under the title.
28
+ - `AnswerSummary`: `variant="expired"` (header ends `Expired`), plus `statusLabel` and a `statusMessage` shown first once expanded.
29
+
30
+ - `PromptInput` takes `allowSendWhileBusy`: with it, a non-empty box sends while the conversation is `streaming` or `submitted` instead of refusing the keystroke, and Stop moves to a control of its own so cancelling never means emptying the box first. Off by default, so every existing composer behaves exactly as before.
31
+
32
+ Kai's composer turns that on. A message typed while Kai is working is queued and shown waiting rather than silently dropped, and a message typed under an open question answers it.
33
+
34
+ - `AnswerActions` takes opt-in `onDownComment` (+ `commentPlaceholder`), a one-line comment input after a thumbs-down, and `onRegenerate` (+ `regenerateLabel`), an "Ask again" button; both are off by default
35
+
36
+ - `FileDownloadChip` takes opt-in `onPreview` (split chip) and `actions`; new `FileGallery` block for image thumbnails (lazy, host-owned URLs and loading, capped with "+N more"). The default chip renders as before
37
+
38
+ - `MessageBubble` takes opt-in `timestamp="visible"`, `quote`, `status` + `onRetry`, `author`, `collapseAfterPx` and `avatar`; without them it renders as before
39
+
40
+ - `Modal.Content` takes `align="top"`: a new-design modal pinned to the top instead of centred, for a form whose height changes while it is in use. The legacy modal is always top-anchored.
41
+
42
+ - `MultiCombobox` takes `renderAside`, a pane beside the list that describes the highlighted row, a group's own row included.
43
+
44
+ A combobox row's label fills the row, so content inside it can align to the row's end.
45
+
46
+ `MultiCombobox` takes `groupAppearance="banded"`, which puts each group, its row and open items, on a white card over a grey list.
47
+
48
+ A selectable group row reads checked or mixed from its locked items that are already selected.
49
+
50
+ `MultiCombobox` takes `collapseSelectedGroups`: each time the popup opens, a group whose items are all selected starts folded. A disabled group row still folds from its chevron.
51
+
52
+ `MultiCombobox` takes `asideOpen` and `onAsideOpenChange`: a button with a tooltip in the popup's bottom-right corner hides and shows the `renderAside` inspector. It is a grid column going from `0fr` to `1fr`, so the list narrows beside it rather than being covered, it keeps describing the last highlighted row until the popup closes, and it stays hidden, button included, while the popup is under 40rem wide.
53
+
54
+ A collapsible group's items fade and slide in as it unfolds and out as it folds, except under reduced motion. Banded rows are square inside their card, the first and last taking its corners, and enabled rows show a pointer.
55
+
56
+ `MultiCombobox` takes `defaultOpen` and `onOpenChange`, for a picker shown on demand with its list already open.
57
+
58
+ `MultiCombobox` takes `anchor`: with it there is no field, and the popup opens against that element with its search at the top. A banded popup is grey throughout, inspector included, with 8px of real space between group cards.
59
+
60
+ `MultiCombobox` takes `query`: search text typed elsewhere. With `anchor`, the popup then has no search of its own, and the host forwards the list keys to its hidden combobox input.
61
+
62
+ `Breadcrumb.Dropdown` takes `panelClassName`, for a panel background its search row shares with the list; the search row carries `data-slot="breadcrumb-dropdown-search"`.
63
+
64
+ A collapsible group's chevron, in `Combobox` / `MultiCombobox` and in `Breadcrumb.Dropdown.Group`, has a tooltip, and Cmd-click (Ctrl elsewhere) expands or collapses every group at once.
65
+
66
+ When a combobox group folds or unfolds, including all at once, the groups under it slide to their new place, and a windowed list keeps each row's measured height across a fold.
67
+
68
+ A query opens every collapsible group with a match, in `Combobox` / `MultiCombobox` and `Breadcrumb.Dropdown.Group`; a group folded under it stays folded until the query changes.
69
+
70
+ `MultiCombobox` takes `itemToLocked`: a selected item the user cannot remove looks disabled but still takes the highlight, so `renderAside` describes it and its group still folds; a group of only locked items locks its row.
71
+
72
+ An open `Combobox` / `MultiCombobox` popup marks `<body>` with `data-combobox-open`, counted across popups, so an app can lift the tooltips of the rows it lists. Combobox row labels carry `data-slot="combobox-item-label"`.
73
+
74
+ - `PromptInput` takes `canSubmitEmpty`, so a composer whose attachments are the message can send with no text. Off by default.
75
+
76
+ - `PromptInput` takes `blurOnEscape`, an `onKeyDown` that runs after its own key handling, `onPasteFiles` for files on the clipboard, and `busy` to hold the composer read-only while keeping focus. All opt-in.
77
+
78
+ - `PromptInput`'s `/` menu picks the highlighted command on Tab, and opens with an empty or loading row (`commandsLoading`, `commandsEmptyText`) when `commands` is an empty list. New opt-in `slashTrigger="typed"` opens it only for a `/` typed into an empty composer.
79
+
80
+ - Interaction-state and surface-corner tokens, so a theme can tell a hovered item from a selected one and round cards, menus and dialogs apart from controls. Unset, every token resolves to the value it replaced, so nothing changes until a theme sets one.
81
+ - `tw:bg-hover` / `tw:text-hover-foreground` (`--hover`, `--hover-foreground`) paint hover and keyboard highlight in Select, Combobox, Command, Breadcrumb, RadioGroup, Toggle, Calendar, DiffView, FileUpload, the markdown toolbar and AIKit. Unset: `accent` / `accent-foreground`. Argo `DropdownMenu` items, `Table` rows and `SectionNav` follow `--hover` too and, unset, keep their own `primary` / `muted` tint.
82
+ - `tw:bg-selected` / `tw:text-selected-foreground` (`--selected`, `--selected-foreground`) paint selected, checked and current in Table, Pagination, a checked `FieldBox`, the Calendar range, the active Breadcrumb item, SectionNav and a checked Command item. Unset: `accent` / `accent-foreground`. A checked argo `DropdownMenu` item follows `--selected` and, unset, keeps its `primary` tint.
83
+ - `tw:bg-pressed` (`--pressed`) is available for a pressed wash; no component paints it yet. Unset: `accent` a step towards its foreground.
84
+ - `tw:bg-scrim` (`--scrim`) is the `Modal`, `AlertModal` and `Sheet` backdrop. Unset: black at 50%.
85
+ - `tw:opacity-disabled` (`--disabled-opacity`) replaces every disabled `opacity-50`, `FieldBox` labels and `InputGroup` included. Unset: `0.5`. Controls disabled at 30%, 40% or 60% keep their own value.
86
+ - `--radius-card` rounds `Card`, `DashboardHero` and `tw:rounded-card`; unset, `Card` keeps `--radius-lg` and `rounded-card` keeps 10px. `--radius-popover` (`tw:rounded-popover`) rounds argo menus, popovers, hover cards and tooltips (unset 1rem). `--radius-modal` (`tw:rounded-modal`) rounds argo `Modal` and `AlertModal` (unset 1.5rem). `--radius-sheet` (`tw:rounded-sheet`) rounds the inner edge of an argo `Sheet` and `--radius-toast` (`tw:rounded-toast`) a `Toast`; unset, both keep `--radius-lg`.
87
+ - `tw:bg-sidebar-hover` / `tw:bg-sidebar-selected` (+ `-foreground`) split the `Sidebar` and `Navbar` hover from the current page, which both painted `sidebar-accent`. Unset, both are `sidebar-accent`; a current item keeps its selected fill while hovered.
88
+ - `ThemeProvider` emits all of them from a brand's `colors` / `colorsDark`, `radii` and `opacity`, and `BrandEditor` edits them.
89
+
90
+ - `InlineStepLabel` takes opt-in `meta`, and `detail` + `defaultExpanded` for a collapsible per-row detail; `InlineStepGroup` takes an opt-in `footer`. Both render as before without them
91
+
92
+ - `Tooltip.Title` heads a rich tooltip, and every floating overlay carries its own layer.
93
+ - `Tooltip.Title` is a small uppercase heading in the tooltip's text colour.
94
+ - `Tooltip` content spaces a nested `hr` and drops the last paragraph's bottom margin; on the legacy chrome a link takes the tooltip's text colour.
95
+ - `Tooltip` sits above `Modal` and every popup (1060); `HoverCard` sits with `Modal` (1051); a `DropdownMenu` submenu sits with its menu (1055).
96
+ - `Combobox` leaves `<body>` untouched while its popup is open.
97
+
98
+ - `Markdown` gains opt-in streaming and code features; every default renders as before:
99
+ - `splitSealedBlocks(text)` and `withholdOpenTail(text, { diagram, tableHead })` — pure helpers for streaming an answer through `Markdown.Root` / memoised `Markdown.Block`s.
100
+ - `highlight` — colours fenced SQL, Python, JS/TS, JSON, shell and YAML through a lazily loaded highlighter.
101
+ - `sortable` (also on `MarkdownTable`) — header presses sort rows, numeric-aware, with `aria-sort`.
102
+ - `diagramActions` and `diagramDownload` — extra diagram toolbar controls and a built-in "Download SVG" action; `DiagramBlock` forwards `renderActions`.
103
+ - `ChatInlineIcon` also draws Lucide names (`icon:info`, `icon:trash-2`, …).
104
+
105
+ - `Markdown` takes an opt-in `allowSvgFences`: an `svg fence, or an `xml / ```html fence whose body is a single SVG document, renders as a responsive chart instead of code. The SVG is sanitized with DOMPurify's SVG profile and loses scripts, event handlers, `foreignObject`, SMIL animation, `<style>` elements and every non-`#` reference. Raw inline HTML stays escaped, and the default is unchanged.
106
+
107
+ `ZoomableSvg` takes an opt-in `allowUse` to keep `<use>` (matplotlib draws every glyph with it) for markup whose `href`s are already limited to `#` references.
108
+
109
+ - `PromptInput` takes `history`: the prompts already sent, oldest first. ↑ with the caret at the start of the text recalls them, newest first; ↓ steps back to the draft. Open `/` and `@` menus keep the arrows.
110
+
111
+ - `Question` takes what an agent chat's question card needs. Additive; existing callers are unchanged.
112
+ - `isSubmitDisabled` keeps the answer from being sent, by click or ⌘/Ctrl+Enter.
113
+ - `isSubmitting` spins Submit and disables Skip.
114
+ - `error` shows why the last send failed, above the footer.
115
+ - `customAnswerMaxLength` caps the "Other" answer.
116
+ - An option's `badge` (e.g. `Recommended`) follows its label.
117
+ - `skipTooltip` replaces the Skip button's `Space` hint; `null` drops it.
118
+
119
+ - `Table.Header` puts its row on the card surface, and `Table.SkeletonRows` draws placeholder rows in a table's own columns while its rows load.
120
+ - The header is `bg-card` with an `h-11` row and a border under it; `withShadow` and `className` work as before.
121
+ - The surface sits on `thead`, so `className="tw:bg-table-header"` (the former default tint) or any other `bg-*` replaces it at rest and on hover.
122
+ - `Table.SkeletonRows` takes `columns`, `noun` and `rows` (5 by default); the first row announces `Loading {noun}` to screen readers.
123
+ - Each column takes the real cell's `className` and `colSpan` and draws a `text` line, a `name` (icon, name and description lines) or nothing (`empty`).
124
+ - A width class can be a list, cycled over the rows; the name line varies in width from row to row unless given one.
125
+
126
+ - `MermaidDiagram` renders with Pele, a dependency-free Mermaid renderer, in place of `mermaid` and `beautiful-mermaid`.
127
+ - Every Mermaid 12.1 diagram type; each type's code loads on first use, after which a diagram renders synchronously.
128
+ - Colours and font come from the DS tokens for the active scheme and are written into the SVG, so an exported SVG or PNG keeps them.
129
+ - `lucide:<name>` icons draw from the bundled Lucide pack; other icon packs draw no icon.
130
+ - A diagram cut off mid-stream shows the skeleton, and its source after 2 s without more input; invalid syntax shows the source.
131
+ - Layout and look follow Pele, not Mermaid.
132
+
133
+ - `Table` puts its body on the card surface, the same `bg-card` as `Table.Header`.
134
+ - The fill sits on `<table>`, so a caller's `bg-*` in `className` replaces it.
135
+ - Row hover and selection tints draw over it as before.
136
+
137
+ - `RjsfSchemaEditor` draws a `format: 'checkbox'` array as a group of DS `Checkbox`es.
138
+ - Each option toggles its value in the array; `readOnly` and `options.enumDisabled` disable them.
139
+ - `options.inline` lays the options out in a wrapping row.
140
+
141
+ - `RjsfSchemaEditor` renders an array of enum values (`uniqueItems` + `items.enum`, no `format: 'checkbox'`) as a `MultiCombobox`.
142
+ - The default `async-multi-select` widget offers the `items.enum` options, labelled by `items.options.enum_titles`, and writes the selection back as an array of the typed enum values.
143
+ - A stored value outside `items.enum` shows as a chip labelled by the value and survives an edit.
144
+ - `readOnly` and `ui:disabled` disable it; options in `ui:enumDisabled` cannot be picked.
145
+ - It does not load `async` options, create `tags` / `creatable` values or read `enumSource`; a host widget passed under `async-multi-select` replaces it for that.
146
+
147
+ ### Patch Changes
148
+
149
+ - `MultiCombobox`: while nothing matches, the inspector and its button go at once and the list takes the whole width, so the inspector never describes a row the list no longer shows.
150
+
151
+ - `MultiCombobox`: with the inspector hidden, the list ends above the inspector button, so the button never covers a row at any scroll position.
152
+
153
+ - `Markdown`'s `allowSvgFences` keeps only an allowlist of paint and text declarations in a fenced chart's `style` attributes, so `image-set()` can no longer load a URL and `position: fixed` can no longer lay an overlay over the page.
154
+
155
+ - `Markdown`'s `allowSvgFences` caps the nodes a fence's `<use>` elements clone (20,000), not their count, so a few `<use>` aimed at a large group can no longer multiply into millions of rendered nodes.
156
+
157
+ - `Table.SkeletonRows` takes `gapClassName` on a `name` column, the gap between its icon and lines (`tw:gap-3.5` by default), so a table's placeholder name starts where its real name does.
158
+
159
+ - `Command.Item`'s keyboard highlight is the only row fill: a `checked` row shows a trailing check (or its checkbox / radio indicator), and rows no longer cross-fade on ↑/↓. The project switcher and Kai's chat history mark the current row this way (UT-5894)
160
+
161
+ - Updated dependencies:
162
+ - @keboola/brand-registry@2.1.0
163
+
3
164
  ## 13.2.0
4
165
 
5
166
  ### Minor Changes
package/COMPONENT-API.md CHANGED
@@ -363,48 +363,58 @@ Source: `src/blocks/Form/connectors/MultiComboboxField.tsx`
363
363
 
364
364
  > Several values from a searchable list — state is `string[]`, never objects, so the form value stays what gets submitted. Project labels with `itemToLabel`; add `allowCreate` for an enum the user may extend. Imported by name from `@keboola/design`, composed inside `form.AppField` — NOT reachable as `field.MultiComboboxField`.
365
365
 
366
- | Prop | Type | Required | Default | Description |
367
- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
368
- | `action` | `ReactNode` | no | — | Trailing node on the label row (e.g. a `Link`); not part of the accessible name. |
369
- | `allowClear` | `boolean` | no | — | Clear-all button, shown only while chips exist. Chips stay removable either way. |
370
- | `allowCreate` | `boolean` | no | — | |
371
- | `allowSelectAll` | `boolean` | no | — | "Select All" row for the whole set; hidden while a query is active, clears when all are selected. |
372
- | `aria-describedby` | `string` | no | — | |
373
- | `canCreate` | `((query: string) => boolean)` | no | — | Rejects a value `allowCreate` would mint; values naming an item or already selected skip it. |
374
- | `className` | `string` | no | — | |
375
- | `collapsibleGroups` | `boolean` | no | — | A row per group that folds it. A query shows every match regardless; state is keyed by position. |
376
- | `createSeparator` | `string \| RegExp \| null` | no | — | Splits one entry into several values (default `','`). A `RegExp` must not capture; `null` never splits. |
377
- | `empty` | `ReactNode` | no | — | |
378
- | `focusVariant` | `"off" \| "on" \| "default" \| null` | no | — | |
379
- | `groupToLabel` | `((group: Group<string>) => ReactNode)` | no | — | Defaults to the group's `label`, as `Select` shows it. |
380
- | `help` | `ReactNode` | no | — | |
381
- | `indicator` | `Indicator` | no | — | |
382
- | `inputClassName` | `string` | no | — | |
383
- | `inputValueSanitizer` | `((input: string) => string)` | no | — | Rewrites typed text before filtering and creating. Sees the whole text per keystroke — don't `trim()`. |
384
- | `isItemEqualToValue` | `((itemValue: string, value: string) => boolean)` | no | — | Custom comparison logic used to determine if a combobox item value matches the current selected value. Useful when item values are objects without matching referentially. Defaults to `Object.is` comparison. |
385
- | `isLoading` | `boolean` | no | — | Options still arriving; doesn't disable — pass `disabled` where the user must wait. |
386
- | `items` | `readonly (string \| Group<string>)[]` | no | — | Read as immutable: pass a new array to change it; one mutated in place is not re-filtered. |
387
- | `itemToChipColor` | `((item: string) => "gray" \| "gray-darker" \| "gray-inverse" \| "green" \| "green-darker" \| "green-inverse" \| "blue" \| "blue-inverse" \| "red" \| "orange" \| "orange-inverse" \| "amber" \| ... 9 more ...)` | no | — | |
388
- | `itemToChipLabel` | `((item: string) => ReactNode)` | no | — | |
389
- | `itemToDisabled` | `((item: string) => boolean)` | no | — | |
390
- | `itemToIcon` | `((item: string) => ReactNode)` | no | — | |
391
- | `itemToLabel` | `((item: string, query: string) => ReactNode)` | no | — | Row and chip content (unless `itemToChipLabel`), `itemToStringLabel` by default. - `query` is the search text, for `MarkedText`; a chip gets `''`. |
392
- | `itemToStringLabel` | `((itemValue: string) => string)` | no | — | When the item values are objects (`<Combobox.Item value={object}>`), this function converts the object value to a string representation for display in the input. If the shape of the object is `{ value, label }`, the label will be used automatically without needing to specify this prop. |
393
- | `itemToStringValue` | `((itemValue: string) => string)` | no | — | When the item values are objects (`<Combobox.Item value={object}>`), this function converts the object value to a string representation for form submission. If the shape of the object is `{ value, label }`, the value will be used automatically without needing to specify this prop. |
394
- | `label` | `ReactNode` | no | — | |
395
- | `maxVisible` | `number` | no | — | |
396
- | `onQueryChange` | `((query: string) => void)` | no | — | Reports the sanitized query, on mount too. Notification only — the control owns the text. |
397
- | `pinnedChipLabels` | `ReactNode[]` | no | — | Non-removable chips ahead of the values, outside `maxVisible` and absent from `value`. |
398
- | `queryToCreateLabel` | `((query: string) => ReactNode)` | no | — | Words the create row. Receives the values it adds, trimmed and re-joined — not the entry as typed. |
399
- | `queryToCreateValue` | `((query: string) => string)` | no | — | Projects one entered value into an item. Called once per trimmed part of a split entry. |
400
- | `renderChips` | `((values: string[]) => ReactNode)` | no | — | Replaces the default chips; the chip props, `maxVisible` included, are then ignored. |
401
- | `required` | `boolean` | no | — | |
402
- | `requiredMark` | `RequiredMark` | no | — | Gated by `required`: `'required'` shows `*` only if required, `'optional'` shows `(optional)` only if not, `'hidden'` neither. Defaults to `'required'`. |
403
- | `selectableGroups` | `boolean` | no | — | A group's row selects its matching enabled items. The row itself never enters `value`. |
404
- | `sizing` | `"small" \| "medium" \| "default" \| null` | no | — | |
405
- | `tooltip` | `ReactNode` | no | — | |
406
- | `variant` | `"primary" \| "secondary" \| null` | no | — | |
407
- | `virtualized` | `boolean \| "auto"` | no | — | Puts only the rows in view into the DOM: `'auto'` past 30 options, grouped or not; `true` always. |
366
+ | Prop | Type | Required | Default | Description |
367
+ | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
368
+ | `action` | `ReactNode` | no | — | Trailing node on the label row (e.g. a `Link`); not part of the accessible name. |
369
+ | `allowClear` | `boolean` | no | — | Clear-all button, shown only while chips exist. Chips stay removable either way. |
370
+ | `allowCreate` | `boolean` | no | — | |
371
+ | `allowSelectAll` | `boolean` | no | — | "Select All" row for the whole set; hidden while a query is active, clears when all are selected. |
372
+ | `anchor` | `Element \| VirtualElement \| RefObject<Element \| null> \| (() => Element \| VirtualElement \| null) \| null` | no | — | No field: the popup opens against this element, its search at the top. Pair with `defaultOpen`. |
373
+ | `aria-describedby` | `string` | no | — | |
374
+ | `asideOpen` | `boolean` | no | — | Whether the inspector shows; a button in the popup toggles it. Uncontrolled, it starts open. |
375
+ | `canCreate` | `((query: string) => boolean)` | no | — | Rejects a value `allowCreate` would mint; values naming an item or already selected skip it. |
376
+ | `className` | `string` | no | — | |
377
+ | `collapseSelectedGroups` | `boolean` | no | — | Each time the popup opens, a group whose items are all selected starts folded. |
378
+ | `collapsibleGroups` | `boolean` | no | — | A row per group that folds it. A query shows every match regardless; state is keyed by position. |
379
+ | `createSeparator` | `string \| RegExp \| null` | no | — | Splits one entry into several values (default `','`). A `RegExp` must not capture; `null` never splits. |
380
+ | `defaultOpen` | `boolean` | no | — | The popup is open on mount, for a picker shown on demand. |
381
+ | `empty` | `ReactNode` | no | — | |
382
+ | `focusVariant` | `"off" \| "on" \| "default" \| null` | no | — | |
383
+ | `groupAppearance` | `"plain" \| "banded"` | no | — | `banded`: each group, its row and open items, is a white card on a grey list. |
384
+ | `groupToLabel` | `((group: Group<string>) => ReactNode)` | no | — | Defaults to the group's `label`, as `Select` shows it. |
385
+ | `help` | `ReactNode` | no | — | |
386
+ | `indicator` | `Indicator` | no | — | |
387
+ | `inputClassName` | `string` | no | — | |
388
+ | `inputValueSanitizer` | `((input: string) => string)` | no | — | Rewrites typed text before filtering and creating. Sees the whole text per keystroke — don't `trim()`. |
389
+ | `isItemEqualToValue` | `((itemValue: string, value: string) => boolean)` | no | — | Custom comparison logic used to determine if a combobox item value matches the current selected value. Useful when item values are objects without matching referentially. Defaults to `Object.is` comparison. |
390
+ | `isLoading` | `boolean` | no | — | Options still arriving; doesn't disable — pass `disabled` where the user must wait. |
391
+ | `items` | `readonly (string \| Group<string>)[]` | no | — | Read as immutable: pass a new array to change it; one mutated in place is not re-filtered. |
392
+ | `itemToChipColor` | `((item: string) => "gray" \| "gray-darker" \| "gray-inverse" \| "green" \| "green-darker" \| "green-inverse" \| "blue" \| "blue-inverse" \| "red" \| "orange" \| "orange-inverse" \| "amber" \| ... 9 more ...)` | no | — | |
393
+ | `itemToChipLabel` | `((item: string) => ReactNode)` | no | — | |
394
+ | `itemToDisabled` | `((item: string) => boolean)` | no | — | |
395
+ | `itemToIcon` | `((item: string) => ReactNode)` | no | — | |
396
+ | `itemToLabel` | `((item: string, query: string) => ReactNode)` | no | — | Row and chip content (unless `itemToChipLabel`), `itemToStringLabel` by default. - `query` is the search text, for `MarkedText`; a chip gets `''`. |
397
+ | `itemToLocked` | `((item: string) => boolean)` | no | — | A selected item no press removes: looks disabled, still highlights for `renderAside`. |
398
+ | `itemToStringLabel` | `((itemValue: string) => string)` | no | — | When the item values are objects (`<Combobox.Item value={object}>`), this function converts the object value to a string representation for display in the input. If the shape of the object is `{ value, label }`, the label will be used automatically without needing to specify this prop. |
399
+ | `itemToStringValue` | `((itemValue: string) => string)` | no | — | When the item values are objects (`<Combobox.Item value={object}>`), this function converts the object value to a string representation for form submission. If the shape of the object is `{ value, label }`, the value will be used automatically without needing to specify this prop. |
400
+ | `label` | `ReactNode` | no | — | |
401
+ | `maxVisible` | `number` | no | — | |
402
+ | `onAsideOpenChange` | `((open: boolean) => void)` | no | — | |
403
+ | `onOpenChange` | `((open: boolean) => void)` | no | — | |
404
+ | `onQueryChange` | `((query: string) => void)` | no | — | Reports the sanitized query, on mount too. Notification only — the control owns the text. |
405
+ | `pinnedChipLabels` | `ReactNode[]` | no | — | Non-removable chips ahead of the values, outside `maxVisible` and absent from `value`. |
406
+ | `query` | `string` | no | — | The search text, typed elsewhere (a chat composer): with `anchor`, the popup has no search. The host forwards ArrowUp, ArrowDown, Enter and Escape to the `combobox` input it renders. |
407
+ | `queryToCreateLabel` | `((query: string) => ReactNode)` | no | — | Words the create row. Receives the values it adds, trimmed and re-joined — not the entry as typed. |
408
+ | `queryToCreateValue` | `((query: string) => string)` | no | — | Projects one entered value into an item. Called once per trimmed part of a split entry. |
409
+ | `renderAside` | `((highlighted: MultiComboboxHighlighted<string, Group<string>>) => ReactNode)` | no | — | An inspector beside the list about the last highlighted row; `null` before any. Hidden while the popup is under 40rem wide. |
410
+ | `renderChips` | `((values: string[]) => ReactNode)` | no | — | Replaces the default chips; the chip props, `maxVisible` included, are then ignored. |
411
+ | `required` | `boolean` | no | — | |
412
+ | `requiredMark` | `RequiredMark` | no | — | Gated by `required`: `'required'` shows `*` only if required, `'optional'` shows `(optional)` only if not, `'hidden'` neither. Defaults to `'required'`. |
413
+ | `selectableGroups` | `boolean` | no | — | A group's row selects its matching enabled items. The row itself never enters `value`. |
414
+ | `sizing` | `"small" \| "medium" \| "default" \| null` | no | — | |
415
+ | `tooltip` | `ReactNode` | no | — | |
416
+ | `variant` | `"primary" \| "secondary" \| null` | no | — | |
417
+ | `virtualized` | `boolean \| "auto"` | no | — | Puts only the rows in view into the DOM: `'auto'` past 30 options, grouped or not; `true` always. |
408
418
 
409
419
  ### `field.CheckboxField`
410
420