@keboola/design 15.0.0 → 15.1.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 (108) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/{AIKit-CaAW4GLx.js → AIKit-BR6jfsdI.js} +60 -21
  3. package/dist/AIKit-BR6jfsdI.js.map +1 -0
  4. package/dist/{AlertModal-D4AtpvLS.js → AlertModal-DMsn62JJ.js} +3 -3
  5. package/dist/AlertModal-DMsn62JJ.js.map +1 -0
  6. package/dist/{Badge-5GHIsgRS.js → Badge-CqlOE5A2.js} +10 -10
  7. package/dist/Badge-CqlOE5A2.js.map +1 -0
  8. package/dist/{BrandEditor-CTGtQUFZ.js → BrandEditor-D61pzWRq.js} +3 -3
  9. package/dist/{BrandEditor-CTGtQUFZ.js.map → BrandEditor-D61pzWRq.js.map} +1 -1
  10. package/dist/{Breadcrumb-B2YSNON4.js → Breadcrumb-DbqvDnYl.js} +2 -2
  11. package/dist/{Breadcrumb-B2YSNON4.js.map → Breadcrumb-DbqvDnYl.js.map} +1 -1
  12. package/dist/{ColorModeSwitch-B6UEzG0H.js → ColorModeSwitch-BlrH8jAi.js} +2 -2
  13. package/dist/{ColorModeSwitch-B6UEzG0H.js.map → ColorModeSwitch-BlrH8jAi.js.map} +1 -1
  14. package/dist/{Combobox-CaKqgstG.js → Combobox-BLqX-Tdh.js} +3 -3
  15. package/dist/Combobox-BLqX-Tdh.js.map +1 -0
  16. package/dist/{DateInput-BgbMDJkm.js → DateInput-duinbI9_.js} +2 -2
  17. package/dist/{DateInput-BgbMDJkm.js.map → DateInput-duinbI9_.js.map} +1 -1
  18. package/dist/{DatePicker-BXpDRo-R.js → DatePicker-Cg_aG_N4.js} +2 -2
  19. package/dist/{DatePicker-BXpDRo-R.js.map → DatePicker-Cg_aG_N4.js.map} +1 -1
  20. package/dist/{DateRangeInput-BW0-_jV0.js → DateRangeInput-BYVHf9zo.js} +2 -2
  21. package/dist/{DateRangeInput-BW0-_jV0.js.map → DateRangeInput-BYVHf9zo.js.map} +1 -1
  22. package/dist/{DateRangePicker-C4-DoWac.js → DateRangePicker-m47cSV1r.js} +3 -3
  23. package/dist/{DateRangePicker-C4-DoWac.js.map → DateRangePicker-m47cSV1r.js.map} +1 -1
  24. package/dist/{DropdownMenu-CcVbZ_5u.js → DropdownMenu-Bum99mVf.js} +2 -2
  25. package/dist/DropdownMenu-Bum99mVf.js.map +1 -0
  26. package/dist/{Form-CAofWyMI.js → Form-Dqbt_tIs.js} +2 -2
  27. package/dist/{Form-CAofWyMI.js.map → Form-Dqbt_tIs.js.map} +1 -1
  28. package/dist/HoverCard-Cf9iYyaW.js +26 -0
  29. package/dist/HoverCard-Cf9iYyaW.js.map +1 -0
  30. package/dist/{MermaidDiagram-Te-5gOCU.js → MermaidDiagram-2-EuNu1i.js} +2 -2
  31. package/dist/{MermaidDiagram-Te-5gOCU.js.map → MermaidDiagram-2-EuNu1i.js.map} +1 -1
  32. package/dist/{Modal-CbUz-5YH.js → Modal-DwuvuiUx.js} +3 -3
  33. package/dist/Modal-DwuvuiUx.js.map +1 -0
  34. package/dist/{ModalTitle-cy0Ht9VY.js → ModalTitle-RGWwIMU6.js} +2 -2
  35. package/dist/ModalTitle-RGWwIMU6.js.map +1 -0
  36. package/dist/{PageToolbar-DJ5tdYla.js → PageToolbar-LKP6PiP_.js} +3 -3
  37. package/dist/{PageToolbar-DJ5tdYla.js.map → PageToolbar-LKP6PiP_.js.map} +1 -1
  38. package/dist/{Popconfirm-DwLCYNaF.js → Popconfirm-p72DiagN.js} +2 -2
  39. package/dist/{Popconfirm-DwLCYNaF.js.map → Popconfirm-p72DiagN.js.map} +1 -1
  40. package/dist/{Popover-DtUDwUVO.js → Popover-DnBw5Uay.js} +2 -2
  41. package/dist/Popover-DnBw5Uay.js.map +1 -0
  42. package/dist/{SectionNav-tLK3iF6c.js → SectionNav-6hcIpZLO.js} +3 -3
  43. package/dist/{SectionNav-tLK3iF6c.js.map → SectionNav-6hcIpZLO.js.map} +1 -1
  44. package/dist/{Select-B22hB_-w.js → Select-C6zKeip5.js} +2 -2
  45. package/dist/Select-C6zKeip5.js.map +1 -0
  46. package/dist/{Sheet-0TWKTqid.js → Sheet-DKG20J7W.js} +3 -3
  47. package/dist/Sheet-DKG20J7W.js.map +1 -0
  48. package/dist/{Sidebar-C5hdANBU.js → Sidebar-BlYqasnX.js} +4 -4
  49. package/dist/{Sidebar-C5hdANBU.js.map → Sidebar-BlYqasnX.js.map} +1 -1
  50. package/dist/{TimePicker-CoRpiEM3.js → TimePicker-lk3NGqeK.js} +2 -2
  51. package/dist/{TimePicker-CoRpiEM3.js.map → TimePicker-lk3NGqeK.js.map} +1 -1
  52. package/dist/Workbench-CxgNCs3I.js.map +1 -1
  53. package/dist/{ZoomableSvg-DnFXo2L4.js → ZoomableSvg-CxXKanUR.js} +2 -2
  54. package/dist/{ZoomableSvg-DnFXo2L4.js.map → ZoomableSvg-CxXKanUR.js.map} +1 -1
  55. package/dist/flint.js +1 -1
  56. package/dist/index.d.ts +42 -8
  57. package/dist/index.js +26 -25
  58. package/dist/internal/blocks/AIKit.js +1 -1
  59. package/dist/internal/blocks/BrandEditor.js +1 -1
  60. package/dist/internal/blocks/ChipEditor.js +1 -1
  61. package/dist/internal/blocks/ColorModeSwitch.js +1 -1
  62. package/dist/internal/blocks/DateInput.js +1 -1
  63. package/dist/internal/blocks/DateRangeInput.js +1 -1
  64. package/dist/internal/blocks/ExportMenu.js +1 -1
  65. package/dist/internal/blocks/Form/connectors/ComboboxField.js +1 -1
  66. package/dist/internal/blocks/Form.js +1 -1
  67. package/dist/internal/blocks/MultiCombobox.js +1 -1
  68. package/dist/internal/blocks/PageToolbar.js +1 -1
  69. package/dist/internal/blocks/SectionNav.js +1 -1
  70. package/dist/internal/blocks/SplitButton.js +1 -1
  71. package/dist/internal/blocks/TimeInput.js +1 -1
  72. package/dist/internal/components/AlertModal.js +1 -1
  73. package/dist/internal/components/Badge.js +1 -1
  74. package/dist/internal/components/Breadcrumb.js +1 -1
  75. package/dist/internal/components/Combobox.js +1 -1
  76. package/dist/internal/components/DatePicker.js +1 -1
  77. package/dist/internal/components/DateRangePicker.js +1 -1
  78. package/dist/internal/components/DropdownMenu.js +1 -1
  79. package/dist/internal/components/HoverCard.js +1 -1
  80. package/dist/internal/components/Modal.js +1 -1
  81. package/dist/internal/components/Popconfirm.js +1 -1
  82. package/dist/internal/components/Popover.js +1 -1
  83. package/dist/internal/components/Select.js +1 -1
  84. package/dist/internal/components/Sheet.js +1 -1
  85. package/dist/internal/components/Sidebar.js +1 -1
  86. package/dist/internal/components/TimePicker.js +1 -1
  87. package/dist/internal/components/ZoomableSvg.js +1 -1
  88. package/dist/internal/hooks/useTimeout.js +19 -0
  89. package/dist/internal/hooks/useTimeout.js.map +1 -0
  90. package/dist/markdown-editor.js +3 -3
  91. package/dist/mermaid.js +1 -1
  92. package/dist/rjsf.js +2 -2
  93. package/dist/styles.css +1 -1
  94. package/dist/utils-DwC9u0tM.js.map +1 -1
  95. package/package.json +1 -1
  96. package/src/theme.css +4 -0
  97. package/dist/AIKit-CaAW4GLx.js.map +0 -1
  98. package/dist/AlertModal-D4AtpvLS.js.map +0 -1
  99. package/dist/Badge-5GHIsgRS.js.map +0 -1
  100. package/dist/Combobox-CaKqgstG.js.map +0 -1
  101. package/dist/DropdownMenu-CcVbZ_5u.js.map +0 -1
  102. package/dist/HoverCard-Cv5rmvJq.js +0 -26
  103. package/dist/HoverCard-Cv5rmvJq.js.map +0 -1
  104. package/dist/Modal-CbUz-5YH.js.map +0 -1
  105. package/dist/ModalTitle-cy0Ht9VY.js.map +0 -1
  106. package/dist/Popover-DtUDwUVO.js.map +0 -1
  107. package/dist/Select-B22hB_-w.js.map +0 -1
  108. package/dist/Sheet-0TWKTqid.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # @keboola/design
2
2
 
3
+ ## 15.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - `Badge` `color` gains status values — `success`, `warning`, `info`, `destructive`, `neutral`, each with a pastel `-subtle` twin — read from the brand's status tokens, so a status badge re-skins with the brand and follows dark mode. Keep the hue colours for categorical labels. New pastel tokens `bg-<status>-subtle` / `text-<status>-subtle-foreground` back the `-subtle` values; set `--<status>-subtle` / `--<status>-subtle-foreground` to override them. `color="red-inverse"` adds the missing pastel error hue, with a dark-mode pair.
8
+
9
+ - `useTimeout(callback, delayMs)` runs a callback once after a delay and clears the timer on unmount; a new callback identity does not restart it (UT-5890)
10
+
11
+ - AIKit: `AttachmentChip` takes `lead` and `label`, `ContextChip` takes `number` and an optional `excerpt` and `onRemove`, `JumpToLatest` takes `tooltip`.
12
+
13
+ - `PromptInput` takes `shellClassName` for the element around its frame and `onFocusChange`; that element carries `data-focused` while focus is inside.
14
+
15
+ - `AnswerActions` takes `extraActions` (`{ id, label, icon, onSelect, disabled? }[]`), drawn in the style of copy and thumbs; `actions` stays for a raw node.
16
+
17
+ - `PromptInput` takes `mentionInsert`: the text a picked `@` mention leaves at the caret, in the same update that removes the token.
18
+
19
+ ### Patch Changes
20
+
21
+ - Dark mode sits quieter: solid `Badge` colours drop to a deeper rung and `Modal` gets a hairline edge.
22
+ - `Badge` `green`, `green-darker`, `blue`, `red`, `orange`, `amber`, `teal`, `purple` and `cyan` keep their light fill and take a deeper fill in dark (`green-darker` one rung deeper than `green`), white text where it clears 4.5:1.
23
+ - `Modal.Content` draws a hairline ring in dark, so its edge no longer depends on the scrim.
24
+ - `InlineStepLabel` meta text reads `muted-foreground` at full strength, which clears 4.5:1 in dark and reads clearer in light.
25
+
26
+ - `Modal`, `AlertModal`, `Sheet`, `HoverCard` and the `ZoomableSvg` fullscreen overlay share one layer with `DropdownMenu`, `Popover`, `Select` and `Combobox`: the `z-overlay` utility, backed by the `--z-index-overlay` theme token (`1055`). The one opened last paints on top, so a modal opened from a menu item covers that menu, and anything opened inside a modal sits above it. `Tooltip` (`z-[1060]`) stays above the layer.
27
+
3
28
  ## 15.0.0
4
29
 
5
30
  ### Major Changes
@@ -7,10 +7,10 @@ import { ClipboardButton } from "./ClipboardButton-B1Hr_n_Z.js";
7
7
  import { FullScreenModal, FullScreenModalBody, FullScreenModalHeader } from "./FullScreenModal-DAvvlGOz.js";
8
8
  import { Truncated } from "./internal/components/Truncated.js";
9
9
  import { useStableCallback } from "./internal/hooks/useStableCallback.js";
10
- import { HoverCard } from "./HoverCard-Cv5rmvJq.js";
10
+ import { HoverCard } from "./HoverCard-Cf9iYyaW.js";
11
11
  import { Command } from "./Command-DhXmqFLT.js";
12
12
  import { TextInput } from "./TextInput-CR0_USaY.js";
13
- import { Badge } from "./Badge-5GHIsgRS.js";
13
+ import { Badge } from "./Badge-CqlOE5A2.js";
14
14
  import { Textarea } from "./internal/blocks/Textarea.js";
15
15
  import { Kbd, keys } from "./Kbd-CflKthfu.js";
16
16
  import { Collapsible } from "./Collapsible-DD4xTL75.js";
@@ -18,7 +18,7 @@ import { Alert } from "./Alert-Chz6KZ7e.js";
18
18
  import { Table as Table$1, tableAriaSort } from "./Table-CilEvpMq.js";
19
19
  import { DiagramSkeleton } from "./internal/blocks/DiagramShared/DiagramSkeleton.js";
20
20
  import { DiagramSource, makeResponsive } from "./svgTransforms-Hnvev3Vs.js";
21
- import { ZoomableSvg, toSvgFileContent } from "./ZoomableSvg-DnFXo2L4.js";
21
+ import { ZoomableSvg, toSvgFileContent } from "./ZoomableSvg-CxXKanUR.js";
22
22
  import { Progress } from "./internal/components/Progress.js";
23
23
  import { digitFromKeyCode, useAltDigitHotkey } from "./internal/hooks/useAltDigitHotkey.js";
24
24
  import { createContext, isValidElement, use, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
@@ -93,7 +93,7 @@ const SIZES = {
93
93
  * - A vote can be changed but not withdrawn; pressing the pressed one re-sends it.
94
94
  * - The caller owns the recorded vote and the write.
95
95
  */
96
- const AnswerActions = ({ copyText, vote, onVote, onCopy, actions, labels = DEFAULT_LABELS, confirmation, size = "small", layout = "inline", onDownComment, commentPlaceholder = "What was wrong? (optional)", onRegenerate, regenerateLabel = "Ask again" }) => {
96
+ const AnswerActions = ({ copyText, vote, onVote, onCopy, actions, extraActions = [], labels = DEFAULT_LABELS, confirmation, size = "small", layout = "inline", onDownComment, commentPlaceholder = "What was wrong? (optional)", onRegenerate, regenerateLabel = "Ask again" }) => {
97
97
  const { button, gap } = SIZES[size];
98
98
  const votes = VOTE_BUTTONS.map(({ vote: candidate, icon }) => {
99
99
  const isRecorded = vote === candidate;
@@ -132,6 +132,19 @@ const AnswerActions = ({ copyText, vote, onVote, onCopy, actions, labels = DEFAU
132
132
  children: /* @__PURE__ */ jsx(RotateCcw, { className: "tw:size-4" })
133
133
  })
134
134
  }) : null;
135
+ const extras = extraActions.map(({ id, label, icon, onSelect, disabled }) => /* @__PURE__ */ jsx(Tooltip, {
136
+ tooltip: label,
137
+ placement: "top",
138
+ triggerAsChild: true,
139
+ children: /* @__PURE__ */ jsx(Button, {
140
+ size: button,
141
+ variant: "invisible",
142
+ "aria-label": label,
143
+ disabled,
144
+ onClick: onSelect,
145
+ children: icon
146
+ })
147
+ }, id));
135
148
  const comment = onDownComment && vote === "down" ? /* @__PURE__ */ jsx(AnswerCommentInput, {
136
149
  placeholder: commentPlaceholder,
137
150
  onSubmit: onDownComment
@@ -155,7 +168,8 @@ const AnswerActions = ({ copyText, vote, onVote, onCopy, actions, labels = DEFAU
155
168
  children: [
156
169
  actions,
157
170
  regenerate,
158
- copy
171
+ copy,
172
+ extras
159
173
  ]
160
174
  })
161
175
  ]
@@ -165,6 +179,7 @@ const AnswerActions = ({ copyText, vote, onVote, onCopy, actions, labels = DEFAU
165
179
  "aria-label": "Answer actions",
166
180
  children: [
167
181
  copy,
182
+ extras,
168
183
  votes,
169
184
  regenerate,
170
185
  actions,
@@ -380,7 +395,7 @@ const InlineStepLabel = ({ variant, children, meta, detail, defaultExpanded = fa
380
395
  children: [
381
396
  children,
382
397
  meta && /* @__PURE__ */ jsx("span", {
383
- className: "tw:font-normal tw:text-muted-foreground/70",
398
+ className: "tw:font-normal tw:text-muted-foreground",
384
399
  children: meta
385
400
  }),
386
401
  detail && /* @__PURE__ */ jsx(Button, {
@@ -467,7 +482,7 @@ const AnswerSummary = ({ items, variant = "success", statusLabel = DEFAULT_STATU
467
482
  };
468
483
  //#endregion
469
484
  //#region src/blocks/AIKit/AttachmentChip.tsx
470
- const Lead = ({ status, thumbnailUrl }) => {
485
+ const Lead = ({ status, thumbnailUrl, lead }) => {
471
486
  if (status === "uploading") return /* @__PURE__ */ jsx(LoaderCircle, {
472
487
  "aria-hidden": true,
473
488
  className: "tw:size-4 tw:shrink-0 tw:animate-spin"
@@ -476,6 +491,7 @@ const Lead = ({ status, thumbnailUrl }) => {
476
491
  "aria-hidden": true,
477
492
  className: "tw:size-4 tw:shrink-0 tw:text-destructive"
478
493
  });
494
+ if (lead) return lead;
479
495
  if (thumbnailUrl) return /* @__PURE__ */ jsx("img", {
480
496
  src: thumbnailUrl,
481
497
  alt: "",
@@ -492,16 +508,17 @@ const Lead = ({ status, thumbnailUrl }) => {
492
508
  * - Capped width with a truncating name, so a long filename cannot push the text away.
493
509
  * - `error` explains itself in a tooltip; the remove control stays available in every status.
494
510
  */
495
- const AttachmentChip = ({ name, thumbnailUrl, status, error, onRemove, trailing, className }) => {
511
+ const AttachmentChip = ({ name, thumbnailUrl, lead, label, status, error, onRemove, trailing, className }) => {
496
512
  const chip = /* @__PURE__ */ jsxs("span", {
497
513
  "data-status": status,
498
514
  className: cn("tailwindcss-preflight tw:inline-flex tw:h-6 tw:min-w-0 tw:max-w-48 tw:items-center tw:gap-1 tw:rounded-md tw:bg-muted tw:px-2 tw:text-xs tw:text-muted-foreground", status === "error" && "tw:text-destructive", className),
499
515
  children: [
500
516
  /* @__PURE__ */ jsx(Lead, {
501
517
  status,
502
- thumbnailUrl
518
+ thumbnailUrl,
519
+ lead
503
520
  }),
504
- /* @__PURE__ */ jsx("span", {
521
+ label ?? /* @__PURE__ */ jsx("span", {
505
522
  className: "tw:min-w-0 tw:truncate",
506
523
  children: name
507
524
  }),
@@ -788,7 +805,7 @@ const CONTEXT_CHIP_EXPANDABLE_LENGTH = 120;
788
805
  * - The excerpt is clamped to two lines; "Show all" appears once it is long enough to be cut.
789
806
  * - Images sit under the excerpt as small thumbnails.
790
807
  */
791
- const ContextChip = ({ label, excerpt, images = [], onRemove, className }) => {
808
+ const ContextChip = ({ label, excerpt = "", images = [], number, onRemove, className }) => {
792
809
  const [isExpanded, setIsExpanded] = useState(false);
793
810
  const isExpandable = excerpt.length > 120;
794
811
  return /* @__PURE__ */ jsxs("div", {
@@ -797,24 +814,28 @@ const ContextChip = ({ label, excerpt, images = [], onRemove, className }) => {
797
814
  /* @__PURE__ */ jsxs("div", {
798
815
  className: "tw:flex tw:items-center tw:gap-1 tw:text-muted-foreground",
799
816
  children: [
800
- /* @__PURE__ */ jsx(Quote, {
817
+ number === void 0 ? /* @__PURE__ */ jsx(Quote, {
801
818
  "aria-hidden": true,
802
819
  className: "tw:size-3.5 tw:shrink-0"
820
+ }) : /* @__PURE__ */ jsx("span", {
821
+ "aria-hidden": true,
822
+ className: "tw:inline-flex tw:size-4 tw:shrink-0 tw:items-center tw:justify-center tw:rounded-full tw:bg-primary tw:text-[10px] tw:font-semibold tw:text-primary-foreground",
823
+ children: number
803
824
  }),
804
825
  /* @__PURE__ */ jsx("span", {
805
826
  className: "tw:min-w-0 tw:flex-1 tw:truncate tw:font-medium",
806
827
  children: label
807
828
  }),
808
- /* @__PURE__ */ jsx("button", {
829
+ onRemove && /* @__PURE__ */ jsx("button", {
809
830
  type: "button",
810
- "aria-label": `Remove ${label}`,
831
+ "aria-label": number === void 0 ? `Remove ${label}` : `Remove ${number}, ${label}`,
811
832
  onClick: onRemove,
812
833
  className: "tw:shrink-0 tw:cursor-pointer tw:rounded-sm tw:border-0 tw:bg-transparent tw:p-0 tw:text-muted-foreground tw:hover:text-foreground tw:focus-visible:outline-none tw:focus-visible:ring-2 tw:focus-visible:ring-ring",
813
834
  children: /* @__PURE__ */ jsx(X, { className: "tw:size-3.5" })
814
835
  })
815
836
  ]
816
837
  }),
817
- /* @__PURE__ */ jsx("p", {
838
+ excerpt && /* @__PURE__ */ jsx("p", {
818
839
  className: cn("tw:m-0 tw:whitespace-pre-wrap tw:break-words tw:text-foreground", !isExpanded && "tw:line-clamp-2"),
819
840
  children: excerpt
820
841
  }),
@@ -1057,9 +1078,9 @@ const InlineStepGroup = ({ label, variant = "success", isExpanded, onToggle, sur
1057
1078
  * - Renders nothing while `visible` is false.
1058
1079
  * - Positioning is the host's: pass `className` to pin it over the list.
1059
1080
  */
1060
- const JumpToLatest = ({ visible, working = false, onClick, label, className }) => {
1081
+ const JumpToLatest = ({ visible, working = false, onClick, label, tooltip, className }) => {
1061
1082
  if (!visible) return null;
1062
- return /* @__PURE__ */ jsxs(Button, {
1083
+ const button = /* @__PURE__ */ jsxs(Button, {
1063
1084
  variant: "outline",
1064
1085
  size: label ? "small" : "icon-sm",
1065
1086
  "aria-label": label ?? "Scroll to bottom",
@@ -1068,6 +1089,13 @@ const JumpToLatest = ({ visible, working = false, onClick, label, className }) =
1068
1089
  className: cn("tw:rounded-full tw:shadow-md", working && "tw:animate-pulse tw:motion-reduce:animate-none", className),
1069
1090
  children: [/* @__PURE__ */ jsx(ArrowDown, { className: "tw:size-4" }), label]
1070
1091
  });
1092
+ if (!tooltip) return button;
1093
+ return /* @__PURE__ */ jsx(Tooltip, {
1094
+ tooltip,
1095
+ placement: "left",
1096
+ triggerAsChild: true,
1097
+ children: button
1098
+ });
1071
1099
  };
1072
1100
  //#endregion
1073
1101
  //#region src/blocks/AIKit/DiagramBlock.tsx
@@ -3016,11 +3044,17 @@ const wrapperVariants = cva(null, {
3016
3044
  inline: ""
3017
3045
  } }
3018
3046
  });
3019
- const PromptInput = ({ onSend, onAbort, onContinue, prefix, variant, suffix, attachments, className, disabled, disableSubmit, busy = false, blurOnEscape = false, onKeyDown, onPasteFiles, canSubmitEmpty = false, allowSendWhileBusy = false, canAbort = true, value = "", onValueChange, status = "ready", maxRows = 6, minRows, commands, commandsEmptyText = "No commands found", commandsLoading = false, slashTrigger = "value", commandsGroupAction, panel, mentions, onMentionSelect, mentionsEmptyText = "Nothing to attach", mentionsGroupHeading, mentionsMultiple = false, history, autoFocus, textareaRef: publishedRef, ...textareaProps }) => {
3047
+ const PromptInput = ({ onSend, onAbort, onContinue, prefix, variant, suffix, attachments, className, shellClassName, onFocusChange, disabled, disableSubmit, busy = false, blurOnEscape = false, onKeyDown, onPasteFiles, canSubmitEmpty = false, allowSendWhileBusy = false, canAbort = true, value = "", onValueChange, status = "ready", maxRows = 6, minRows, commands, commandsEmptyText = "No commands found", commandsLoading = false, slashTrigger = "value", commandsGroupAction, panel, mentions, onMentionSelect, mentionInsert, mentionsEmptyText = "Nothing to attach", mentionsGroupHeading, mentionsMultiple = false, history, autoFocus, textareaRef: publishedRef, ...textareaProps }) => {
3020
3048
  const defaultMinRows = variant === "inline" ? 1 : 2;
3021
3049
  const canSendWhileBusy = allowSendWhileBusy && (status === "streaming" || status === "submitted") && !busy && !disabled && !disableSubmit && value.trim() !== "";
3022
3050
  const showSeparateStop = allowSendWhileBusy && canAbort && (canSendWhileBusy || status === "submitted");
3023
3051
  const isDisabled = busy || !canSendWhileBusy && (disabled || disableSubmit || !canSubmitEmpty && !value.trim()) && status !== "streaming" && status !== "interrupted";
3052
+ const [isFocused, setIsFocused] = useState(false);
3053
+ const changeFocus = (next) => {
3054
+ if (next === isFocused) return;
3055
+ setIsFocused(next);
3056
+ onFocusChange?.(next);
3057
+ };
3024
3058
  const textareaId = useId();
3025
3059
  const textareaRef = useRef(null);
3026
3060
  const setTextareaNode = useCallback((node) => {
@@ -3104,7 +3138,7 @@ const PromptInput = ({ onSend, onAbort, onContinue, prefix, variant, suffix, att
3104
3138
  return;
3105
3139
  }
3106
3140
  if (mentionToken) {
3107
- const keep = mentionsMultiple ? "@" : "";
3141
+ const keep = mentionsMultiple ? "@" : mentionInsert?.(item) ?? "";
3108
3142
  const next = value.slice(0, mentionToken.start) + keep + value.slice(mentionToken.end);
3109
3143
  const nextCaret = mentionToken.start + keep.length;
3110
3144
  onValueChange?.(next);
@@ -3179,11 +3213,16 @@ const PromptInput = ({ onSend, onAbort, onContinue, prefix, variant, suffix, att
3179
3213
  textareaRef.current?.focus();
3180
3214
  };
3181
3215
  const formEl = /* @__PURE__ */ jsx("div", {
3182
- className: wrapperVariants({ variant }),
3216
+ className: cn(wrapperVariants({ variant }), shellClassName),
3217
+ "data-focused": isFocused ? "" : void 0,
3183
3218
  children: /* @__PURE__ */ jsxs("form", {
3184
3219
  "data-testid": "prompt-input",
3185
3220
  "data-status": status,
3186
3221
  onKeyDown: handleOnFormKeyDown,
3222
+ onFocus: () => changeFocus(true),
3223
+ onBlur: (event) => {
3224
+ if (!event.currentTarget.contains(event.relatedTarget)) changeFocus(false);
3225
+ },
3187
3226
  onMouseDown: handleOnMouseDown,
3188
3227
  onSubmit: handleOnSubmit,
3189
3228
  className: cn(promptInputVariants({ variant }), disabled && "tw:bg-none tw:border-border tw:shadow-[inset_0_100vw_rgb(var(--muted))] tw:cursor-default", className),
@@ -4438,4 +4477,4 @@ const UsageStats = ({ value, alert = false, children, className, ariaLabel, alig
4438
4477
  //#endregion
4439
4478
  export { ANSWER_SOURCES_VISIBLE, AnswerActions, AnswerSources, AnswerSummary, AttachmentChip, CONTEXT_CHIP_EXPANDABLE_LENGTH, ChatInlineIcon, ChatNotice, CollapsibleStepHeader, ContextChip, DIAGRAM_LANGUAGES, FileDownloadChip, FileGallery, InlineStepDetail, InlineStepGroup, InlineStepLabel, JumpToLatest, Markdown, MarkdownTable, MessageBubble, ModeChip, PROMPT_INPUT_CONTAINER, PlanApproval, PlanRewritingIndicator, PromptInput, Question, QuestionBlock, SourceChip, SuggestedPrompt, ThinkingIndicator, ToolCallApproval, ToolCallChip, ToolCallStatusHeader, UsageBar, UsageStats, UsageStatsRing, clampPercentage, findMentionToken, findSlashToken, formatPercentage, getChatInlineIconName, splitSealedBlocks, withholdOpenTail };
4440
4479
 
4441
- //# sourceMappingURL=AIKit-CaAW4GLx.js.map
4480
+ //# sourceMappingURL=AIKit-BR6jfsdI.js.map