@aleph-alpha/chat-kit 2.3.0 → 3.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 (98) hide show
  1. package/dist/{CkInput.vue_vue_type_script_setup_true_lang-DYTizPsB.js → CkInput.vue_vue_type_script_setup_true_lang-DKzc21Yp.js} +239 -154
  2. package/dist/chat-kit.css +33 -6
  3. package/dist/components/base/CkAgentMessage/CkAgentMessage.vue.d.ts.map +1 -1
  4. package/dist/components/base/CkConversationLayout/CkConversationLayout.vue.d.ts.map +1 -1
  5. package/dist/components/base/CkDropZoneOverlay/CkDropZoneOverlay.vue.d.ts.map +1 -1
  6. package/dist/components/base/CkMarkdownRenderer/CkMarkdownRenderer.vue.d.ts.map +1 -1
  7. package/dist/components/base/CkMarkdownRenderer/defaultMarkdownClasses.d.ts.map +1 -1
  8. package/dist/components/base/CkModelSelector/CkModelSelector.vue.d.ts.map +1 -1
  9. package/dist/components/base/CkModelSelector/types.d.ts +1 -1
  10. package/dist/components/base/CkPromptInput/CkPromptInput.stories.d.ts +48 -5
  11. package/dist/components/base/CkPromptInput/CkPromptInput.stories.d.ts.map +1 -1
  12. package/dist/components/base/CkPromptInput/CkPromptInput.vue.d.ts +7 -6
  13. package/dist/components/base/CkPromptInput/CkPromptInput.vue.d.ts.map +1 -1
  14. package/dist/components/base/CkPromptInput/types.d.ts +11 -12
  15. package/dist/components/base/CkPromptInput/types.d.ts.map +1 -1
  16. package/dist/components/base/CkPromptMenuButton/CkPromptMenuButton.stories.d.ts +18 -0
  17. package/dist/components/base/CkPromptMenuButton/CkPromptMenuButton.stories.d.ts.map +1 -0
  18. package/dist/components/base/CkPromptMenuButton/CkPromptMenuButton.vue.d.ts +18 -0
  19. package/dist/components/base/CkPromptMenuButton/CkPromptMenuButton.vue.d.ts.map +1 -0
  20. package/dist/components/base/CkPromptMenuButton/index.d.ts +3 -0
  21. package/dist/components/base/CkPromptMenuButton/index.d.ts.map +1 -0
  22. package/dist/components/base/CkPromptMenuButton/types.d.ts +30 -0
  23. package/dist/components/base/CkPromptMenuButton/types.d.ts.map +1 -0
  24. package/dist/components/base/{CkPromptActionButton/CkPromptActionButton.stories.d.ts → CkPromptSendButton/CkPromptSendButton.stories.d.ts} +5 -5
  25. package/dist/components/base/CkPromptSendButton/CkPromptSendButton.stories.d.ts.map +1 -0
  26. package/dist/components/base/{CkPromptActionButton/CkPromptActionButton.vue.d.ts → CkPromptSendButton/CkPromptSendButton.vue.d.ts} +3 -3
  27. package/dist/components/base/CkPromptSendButton/CkPromptSendButton.vue.d.ts.map +1 -0
  28. package/dist/components/base/CkPromptSendButton/index.d.ts +3 -0
  29. package/dist/components/base/CkPromptSendButton/index.d.ts.map +1 -0
  30. package/dist/components/base/CkPromptSendButton/types.d.ts +34 -0
  31. package/dist/components/base/CkPromptSendButton/types.d.ts.map +1 -0
  32. package/dist/components/base/CkPromptStopButton/CkPromptStopButton.stories.d.ts +1 -1
  33. package/dist/components/base/CkPromptStopButton/CkPromptStopButton.vue.d.ts.map +1 -1
  34. package/dist/components/base/CkPromptStopButton/types.d.ts +6 -4
  35. package/dist/components/base/CkPromptStopButton/types.d.ts.map +1 -1
  36. package/dist/components/base/icons/CkSendIcon.vue.d.ts.map +1 -1
  37. package/dist/components/base/index.d.ts +3 -1
  38. package/dist/components/base/index.d.ts.map +1 -1
  39. package/dist/components/composed/CkHistory/CkHistory.vue.d.ts +1 -1
  40. package/dist/components/composed/CkInput/CkInput.stories.d.ts.map +1 -1
  41. package/dist/components/composed/CkInput/CkInput.vue.d.ts +9 -8
  42. package/dist/components/composed/CkInput/CkInput.vue.d.ts.map +1 -1
  43. package/dist/components/composed/CkInput/types.d.ts +2 -7
  44. package/dist/components/composed/CkInput/types.d.ts.map +1 -1
  45. package/dist/components/index.d.ts +2 -2
  46. package/dist/components/index.d.ts.map +1 -1
  47. package/dist/components/index.js +9 -8
  48. package/dist/handlers/index.js +1 -1
  49. package/dist/handlers/useChatKitLabels.d.ts +6 -0
  50. package/dist/handlers/useChatKitLabels.d.ts.map +1 -1
  51. package/dist/index.d.ts +2 -2
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +11 -10
  54. package/dist/{useChatKitLabels-ZutacPad.js → useChatKitLabels-CLsWWwgG.js} +1 -0
  55. package/package.json +1 -1
  56. package/src/components/base/CkAgentMessage/CkAgentMessage.vue +2 -2
  57. package/src/components/base/CkConversationLayout/CkConversationLayout.vue +3 -2
  58. package/src/components/base/CkDropZoneOverlay/CkDropZoneOverlay.vue +2 -7
  59. package/src/components/base/CkMarkdownRenderer/CkMarkdownRenderer.vue +36 -4
  60. package/src/components/base/CkMarkdownRenderer/defaultMarkdownClasses.ts +2 -1
  61. package/src/components/base/CkModelSelector/CkModelSelector.vue +8 -3
  62. package/src/components/base/CkModelSelector/types.ts +1 -1
  63. package/src/components/base/CkPromptInput/CkPromptInput.spec.ts +206 -11
  64. package/src/components/base/CkPromptInput/CkPromptInput.stories.ts +1068 -43
  65. package/src/components/base/CkPromptInput/CkPromptInput.vue +137 -28
  66. package/src/components/base/CkPromptInput/types.ts +11 -12
  67. package/src/components/base/CkPromptMenuButton/CkPromptMenuButton.spec.ts +62 -0
  68. package/src/components/base/CkPromptMenuButton/CkPromptMenuButton.stories.ts +75 -0
  69. package/src/components/base/CkPromptMenuButton/CkPromptMenuButton.vue +26 -0
  70. package/src/components/base/CkPromptMenuButton/index.ts +2 -0
  71. package/src/components/base/CkPromptMenuButton/types.ts +29 -0
  72. package/src/components/base/{CkPromptActionButton/CkPromptActionButton.spec.ts → CkPromptSendButton/CkPromptSendButton.spec.ts} +11 -11
  73. package/src/components/base/CkPromptSendButton/CkPromptSendButton.stories.ts +117 -0
  74. package/src/components/base/{CkPromptActionButton/CkPromptActionButton.vue → CkPromptSendButton/CkPromptSendButton.vue} +4 -4
  75. package/src/components/base/CkPromptSendButton/index.ts +2 -0
  76. package/src/components/base/CkPromptSendButton/types.ts +33 -0
  77. package/src/components/base/CkPromptStopButton/CkPromptStopButton.spec.ts +5 -5
  78. package/src/components/base/CkPromptStopButton/CkPromptStopButton.stories.ts +1 -1
  79. package/src/components/base/CkPromptStopButton/CkPromptStopButton.vue +3 -2
  80. package/src/components/base/CkPromptStopButton/types.ts +6 -4
  81. package/src/components/base/icons/CkSendIcon.vue +3 -16
  82. package/src/components/base/icons/CkStopIcon.vue +1 -1
  83. package/src/components/base/index.ts +3 -1
  84. package/src/components/composed/CkInput/CkInput.stories.ts +0 -4
  85. package/src/components/composed/CkInput/CkInput.vue +7 -5
  86. package/src/components/composed/CkInput/types.ts +2 -7
  87. package/src/components/index.ts +3 -1
  88. package/src/handlers/useChatKitLabels.ts +7 -0
  89. package/src/index.ts +3 -1
  90. package/dist/components/base/CkPromptActionButton/CkPromptActionButton.stories.d.ts.map +0 -1
  91. package/dist/components/base/CkPromptActionButton/CkPromptActionButton.vue.d.ts.map +0 -1
  92. package/dist/components/base/CkPromptActionButton/index.d.ts +0 -3
  93. package/dist/components/base/CkPromptActionButton/index.d.ts.map +0 -1
  94. package/dist/components/base/CkPromptActionButton/types.d.ts +0 -33
  95. package/dist/components/base/CkPromptActionButton/types.d.ts.map +0 -1
  96. package/src/components/base/CkPromptActionButton/CkPromptActionButton.stories.ts +0 -126
  97. package/src/components/base/CkPromptActionButton/index.ts +0 -2
  98. package/src/components/base/CkPromptActionButton/types.ts +0 -32
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Drop-in chat input: combines `CkPromptInput`, a `CkPromptActionButton` send
2
+ * Drop-in chat input: combines `CkPromptInput`, a `CkPromptSendButton` send
3
3
  * button, and a `CkPromptInputDisclaimer`. Supports `v-model`, loading and
4
4
  * disabled states, and slots to customize the toolbar and footer.
5
5
  *
6
6
  * @category Form Inputs
7
7
  * @useCases chat compose input, prompt box with send button, llm input with disclaimer, quick-start chat input, turnkey chat input
8
8
  * @keywords input, prompt, chat, send, compose, disclaimer, loading, v-model, textarea
9
- * @related CkPromptInput, CkPromptActionButton, CkPromptInputDisclaimer, CkConversation
9
+ * @related CkPromptInput, CkPromptSendButton, CkPromptInputDisclaimer, CkConversation
10
10
  */
11
11
  export interface CkInputProps {
12
12
  /**
@@ -30,11 +30,6 @@ export interface CkInputProps {
30
30
  * @default false
31
31
  */
32
32
  loading?: boolean;
33
- /**
34
- * Max height (in px) of the underlying textarea before it becomes scrollable.
35
- * @default 200
36
- */
37
- maxHeight?: number;
38
33
  /**
39
34
  * Accessible label for the input.
40
35
  * @default 'Chat message input'
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/composed/CkInput/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,kCAAkC;IAClC,CAAC,CAAC,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,kEAAkE;IAClE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/composed/CkInput/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,kCAAkC;IAClC,CAAC,CAAC,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,kEAAkE;IAClE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC"}
@@ -1,5 +1,5 @@
1
- export { CkAgentMessage, CkConversationLayout, CkCopyMessageActionButton, CkDropZoneOverlay, CkFeedbackButton, CkFeedbackDialog, CkFileItemsList, CkHistoryItem, CkHistoryWrapper, CkMarkdownRenderer, CkMessageActionButton, CkModelSelector, CkPromptActionButton, CkPromptStopButton, CkPromptInput, CkPromptInputDisclaimer, CkSendIcon, CkStopIcon, CkUserMessage, } from './base';
2
- export type { CkConversationLayoutProps, CkDropZoneOverlayProps, CkDropZoneOverlayEmits, CkDropZoneRejection, CkDropZoneRejectionReason, CkFeedbackButtonProps, CkFeedbackDialogEmits, CkFeedbackDialogProps, CkFeedbackDialogSubmitPayload, CkFeedbackReason, CkFeedbackSentiment, CkFeedbackValue, CkFileEntry, CkFileItemsListEmits, CkFileItemsListProps, CkHistoryItemEmits, CkHistoryItemProps, CkHistoryWrapperProps, CkMarkdownElementClasses, CkMarkdownRendererProps, CkModelOption, CkModelSelectorProps, CkModelSelectorEmits, CkUserMessageProps, } from './base';
1
+ export { CkAgentMessage, CkConversationLayout, CkCopyMessageActionButton, CkDropZoneOverlay, CkFeedbackButton, CkFeedbackDialog, CkFileItemsList, CkHistoryItem, CkHistoryWrapper, CkMarkdownRenderer, CkMessageActionButton, CkModelSelector, CkPromptSendButton, CkPromptMenuButton, CkPromptStopButton, CkPromptInput, CkPromptInputDisclaimer, CkSendIcon, CkStopIcon, CkUserMessage, } from './base';
2
+ export type { CkConversationLayoutProps, CkDropZoneOverlayProps, CkDropZoneOverlayEmits, CkDropZoneRejection, CkDropZoneRejectionReason, CkFeedbackButtonProps, CkFeedbackDialogEmits, CkFeedbackDialogProps, CkFeedbackDialogSubmitPayload, CkFeedbackReason, CkFeedbackSentiment, CkFeedbackValue, CkFileEntry, CkFileItemsListEmits, CkFileItemsListProps, CkHistoryItemEmits, CkHistoryItemProps, CkHistoryWrapperProps, CkMarkdownElementClasses, CkMarkdownRendererProps, CkModelOption, CkModelSelectorProps, CkModelSelectorEmits, CkPromptMenuButtonProps, CkUserMessageProps, } from './base';
3
3
  export { CkConversation, CkHistory, CkInput } from './composed';
4
4
  export type { CkConversationProps, CkHistoryEmits, CkHistoryProps, } from './composed';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,uBAAuB,EACvB,UAAU,EACV,UAAU,EACV,aAAa,GACd,MAAM,QAAQ,CAAC;AAChB,YAAY,EACV,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,6BAA6B,EAC7B,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,QAAQ,CAAC;AAGhB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAChE,YAAY,EACV,mBAAmB,EACnB,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,uBAAuB,EACvB,UAAU,EACV,UAAU,EACV,aAAa,GACd,MAAM,QAAQ,CAAC;AAChB,YAAY,EACV,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,6BAA6B,EAC7B,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,QAAQ,CAAC;AAGhB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAChE,YAAY,EACV,mBAAmB,EACnB,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC"}
@@ -1,4 +1,4 @@
1
- import { _, a, b, C, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t } from "../CkInput.vue_vue_type_script_setup_true_lang-DYTizPsB.js";
1
+ import { _, a, b, C, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u } from "../CkInput.vue_vue_type_script_setup_true_lang-DKzc21Yp.js";
2
2
  export {
3
3
  _ as CkAgentMessage,
4
4
  a as CkConversation,
@@ -15,11 +15,12 @@ export {
15
15
  k as CkMarkdownRenderer,
16
16
  l as CkMessageActionButton,
17
17
  m as CkModelSelector,
18
- n as CkPromptActionButton,
19
- o as CkPromptInput,
20
- p as CkPromptInputDisclaimer,
21
- q as CkPromptStopButton,
22
- r as CkSendIcon,
23
- s as CkStopIcon,
24
- t as CkUserMessage
18
+ n as CkPromptInput,
19
+ o as CkPromptInputDisclaimer,
20
+ p as CkPromptMenuButton,
21
+ q as CkPromptSendButton,
22
+ r as CkPromptStopButton,
23
+ s as CkSendIcon,
24
+ t as CkStopIcon,
25
+ u as CkUserMessage
25
26
  };
@@ -1,5 +1,5 @@
1
1
  import { u } from "../useMessageHandler-CMdy-lm0.js";
2
- import { C, d, p, u as u2, a } from "../useChatKitLabels-ZutacPad.js";
2
+ import { C, d, p, u as u2, a } from "../useChatKitLabels-CLsWWwgG.js";
3
3
  export {
4
4
  C as CHAT_KIT_LABELS,
5
5
  d as defaultChatKitLabels,
@@ -73,6 +73,12 @@ export type ChatKitLabels = {
73
73
  modelSelectorListAriaLabel?: string;
74
74
  /** Trigger text shown by `CkModelSelector` when no model is selected. */
75
75
  modelSelectorPlaceholder?: string;
76
+ /**
77
+ * Accessible label for the horizontally scrollable wrapper around markdown
78
+ * tables in `CkMarkdownRenderer` (the wrapper is focusable so keyboard users
79
+ * can scroll wide tables). Falls back to `defaultChatKitLabels` when omitted.
80
+ */
81
+ markdownTableLabel?: string;
76
82
  /** Fallback title used by `CkHistory` when a conversation has no `title`. */
77
83
  historyItemUntitled: string;
78
84
  /** Accessible name for the trailing kebab trigger on each `CkHistory` row. */
@@ -1 +1 @@
1
- {"version":3,"file":"useChatKitLabels.d.ts","sourceRoot":"","sources":["../../src/handlers/useChatKitLabels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAG1D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,0CAA0C;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gDAAgD;IAChD,gBAAgB,EAAE,MAAM,CAAC;IACzB,sFAAsF;IACtF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,4FAA4F;IAC5F,uBAAuB,EAAE,MAAM,CAAC;IAChC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,+DAA+D;IAC/D,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,gEAAgE;IAChE,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,kFAAkF;IAClF,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,qEAAqE;IACrE,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,qEAAqE;IACrE,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,iEAAiE;IACjE,iCAAiC,CAAC,EAAE,MAAM,CAAC;IAC3C,iDAAiD;IACjD,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,iDAAiD;IACjD,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,0EAA0E;IAC1E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iEAAiE;IACjE,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,+DAA+D;IAC/D,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,yEAAyE;IACzE,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,6EAA6E;IAC7E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,8EAA8E;IAC9E,0BAA0B,EAAE,MAAM,CAAC;IACnC,uEAAuE;IACvE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,yEAAyE;IACzE,uBAAuB,EAAE,MAAM,CAAC;IAChC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,oBAAoB,EAAE,aA8BlC,CAAC;AAEF,4CAA4C;AAC5C,eAAO,MAAM,eAAe,EAAE,YAAY,CAAC,WAAW,CAAC,aAAa,CAAC,CAC1C,CAAC;AAE5B,KAAK,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5C,yFAAyF;AACzF,KAAK,cAAc,GACf,GAAG,CAAC,aAAa,CAAC,GAClB,WAAW,CAAC,aAAa,CAAC,GAC1B,CAAC,MAAM,aAAa,CAAC,CAAC;AAE1B;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAKjE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAAC,aAAa,CAAC,CAK7D"}
1
+ {"version":3,"file":"useChatKitLabels.d.ts","sourceRoot":"","sources":["../../src/handlers/useChatKitLabels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAG1D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,0CAA0C;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gDAAgD;IAChD,gBAAgB,EAAE,MAAM,CAAC;IACzB,sFAAsF;IACtF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,4FAA4F;IAC5F,uBAAuB,EAAE,MAAM,CAAC;IAChC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,+DAA+D;IAC/D,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,gEAAgE;IAChE,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,kFAAkF;IAClF,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,qEAAqE;IACrE,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,qEAAqE;IACrE,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,iEAAiE;IACjE,iCAAiC,CAAC,EAAE,MAAM,CAAC;IAC3C,iDAAiD;IACjD,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,iDAAiD;IACjD,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,0EAA0E;IAC1E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iEAAiE;IACjE,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,+DAA+D;IAC/D,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,yEAAyE;IACzE,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,6EAA6E;IAC7E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,8EAA8E;IAC9E,0BAA0B,EAAE,MAAM,CAAC;IACnC,uEAAuE;IACvE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,yEAAyE;IACzE,uBAAuB,EAAE,MAAM,CAAC;IAChC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,oBAAoB,EAAE,aA+BlC,CAAC;AAEF,4CAA4C;AAC5C,eAAO,MAAM,eAAe,EAAE,YAAY,CAAC,WAAW,CAAC,aAAa,CAAC,CAC1C,CAAC;AAE5B,KAAK,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5C,yFAAyF;AACzF,KAAK,cAAc,GACf,GAAG,CAAC,aAAa,CAAC,GAClB,WAAW,CAAC,aAAa,CAAC,GAC1B,CAAC,MAAM,aAAa,CAAC,CAAC;AAE1B;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAKjE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAAC,aAAa,CAAC,CAK7D"}
package/dist/index.d.ts CHANGED
@@ -5,8 +5,8 @@ export { useChat, useConversationSessions, useConversations, } from './composabl
5
5
  export type { ChatActions, ChatState, ConversationSession, CreateConversationInput, MessageHandler, MutationOptions, UseChatReturn, UseConversationSessionsReturn, UseConversationsOptions, UseConversationsReturn, } from './composables';
6
6
  export { SdkError, createDocumentUploadProvider, defaultDocumentUploadConfig, defaultEndpoints, useDocumentUploadWithDefaultConfig, } from './composables/fileUpload';
7
7
  export type { DocumentUploadConfig, DocumentUploadProvider, FileEntry, FileStatus, } from './composables/fileUpload';
8
- export { CkAgentMessage, CkConversation, CkConversationLayout, CkCopyMessageActionButton, CkDropZoneOverlay, CkFeedbackButton, CkFeedbackDialog, CkFileItemsList, CkHistory, CkHistoryItem, CkHistoryWrapper, CkInput, CkMarkdownRenderer, CkMessageActionButton, CkModelSelector, CkPromptActionButton, CkPromptStopButton, CkPromptInput, CkPromptInputDisclaimer, CkSendIcon, CkStopIcon, CkUserMessage, } from './components';
9
- export type { CkConversationLayoutProps, CkConversationProps, CkDropZoneOverlayProps, CkDropZoneOverlayEmits, CkDropZoneRejection, CkDropZoneRejectionReason, CkFeedbackButtonProps, CkFeedbackDialogEmits, CkFeedbackDialogProps, CkFeedbackDialogSubmitPayload, CkFeedbackReason, CkFeedbackSentiment, CkFeedbackValue, CkFileEntry, CkFileItemsListEmits, CkFileItemsListProps, CkHistoryEmits, CkHistoryItemEmits, CkHistoryItemProps, CkHistoryProps, CkHistoryWrapperProps, CkMarkdownElementClasses, CkMarkdownRendererProps, CkModelOption, CkModelSelectorProps, CkModelSelectorEmits, CkUserMessageProps, } from './components';
8
+ export { CkAgentMessage, CkConversation, CkConversationLayout, CkCopyMessageActionButton, CkDropZoneOverlay, CkFeedbackButton, CkFeedbackDialog, CkFileItemsList, CkHistory, CkHistoryItem, CkHistoryWrapper, CkInput, CkMarkdownRenderer, CkMessageActionButton, CkModelSelector, CkPromptSendButton, CkPromptMenuButton, CkPromptStopButton, CkPromptInput, CkPromptInputDisclaimer, CkSendIcon, CkStopIcon, CkUserMessage, } from './components';
9
+ export type { CkConversationLayoutProps, CkConversationProps, CkDropZoneOverlayProps, CkDropZoneOverlayEmits, CkDropZoneRejection, CkDropZoneRejectionReason, CkFeedbackButtonProps, CkFeedbackDialogEmits, CkFeedbackDialogProps, CkFeedbackDialogSubmitPayload, CkFeedbackReason, CkFeedbackSentiment, CkFeedbackValue, CkFileEntry, CkFileItemsListEmits, CkFileItemsListProps, CkHistoryEmits, CkHistoryItemEmits, CkHistoryItemProps, CkHistoryProps, CkHistoryWrapperProps, CkMarkdownElementClasses, CkMarkdownRendererProps, CkModelOption, CkModelSelectorProps, CkModelSelectorEmits, CkPromptMenuButtonProps, CkUserMessageProps, } from './components';
10
10
  export { formatRelativeTime } from './helpers';
11
11
  export type { BaseMessage, Conversation, ConversationTree, MessageContent, MessageContentStatus, MessageMetadata, MessageReasoningContent, MessageRole, MessageStatus, MessageTextContent, MessageToolContent, TreeMessage, } from './types';
12
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AASpB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,OAAO,EACL,OAAO,EACP,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,EACd,eAAe,EACf,aAAa,EACb,6BAA6B,EAC7B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,QAAQ,EACR,4BAA4B,EAC5B,2BAA2B,EAC3B,gBAAgB,EAChB,kCAAkC,GACnC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,UAAU,GACX,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,OAAO,EACP,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,uBAAuB,EACvB,UAAU,EACV,UAAU,EACV,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,6BAA6B,EAC7B,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAG/C,YAAY,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,uBAAuB,EACvB,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,GACZ,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AASpB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,OAAO,EACL,OAAO,EACP,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,EACd,eAAe,EACf,aAAa,EACb,6BAA6B,EAC7B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,QAAQ,EACR,4BAA4B,EAC5B,2BAA2B,EAC3B,gBAAgB,EAChB,kCAAkC,GACnC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,UAAU,GACX,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,OAAO,EACP,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,uBAAuB,EACvB,UAAU,EACV,UAAU,EACV,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,6BAA6B,EAC7B,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAG/C,YAAY,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,uBAAuB,EACvB,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,GACZ,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { u } from "./useMessageHandler-CMdy-lm0.js";
2
- import { C, d, p, u as u2, a } from "./useChatKitLabels-ZutacPad.js";
2
+ import { C, d, p, u as u2, a } from "./useChatKitLabels-CLsWWwgG.js";
3
3
  import { S, c, d as d2, a as a2, u as u3, b, e, f } from "./index-THzZwfMU.js";
4
- import { _, a as a3, b as b2, C as C2, c as c2, d as d3, e as e2, f as f2, g, h, i, j, k, l, m, n, o, p as p2, q, r, s, t, u as u4 } from "./CkInput.vue_vue_type_script_setup_true_lang-DYTizPsB.js";
4
+ import { _, a as a3, b as b2, C as C2, c as c2, d as d3, e as e2, f as f2, g, h, i, j, k, l, m, n, o, p as p2, q, r, s, t, u as u4, v } from "./CkInput.vue_vue_type_script_setup_true_lang-DKzc21Yp.js";
5
5
  export {
6
6
  C as CHAT_KIT_LABELS,
7
7
  _ as CkAgentMessage,
@@ -19,19 +19,20 @@ export {
19
19
  k as CkMarkdownRenderer,
20
20
  l as CkMessageActionButton,
21
21
  m as CkModelSelector,
22
- n as CkPromptActionButton,
23
- o as CkPromptInput,
24
- p2 as CkPromptInputDisclaimer,
25
- q as CkPromptStopButton,
26
- r as CkSendIcon,
27
- s as CkStopIcon,
28
- t as CkUserMessage,
22
+ n as CkPromptInput,
23
+ o as CkPromptInputDisclaimer,
24
+ p2 as CkPromptMenuButton,
25
+ q as CkPromptSendButton,
26
+ r as CkPromptStopButton,
27
+ s as CkSendIcon,
28
+ t as CkStopIcon,
29
+ u4 as CkUserMessage,
29
30
  S as SdkError,
30
31
  c as createDocumentUploadProvider,
31
32
  d as defaultChatKitLabels,
32
33
  d2 as defaultDocumentUploadConfig,
33
34
  a2 as defaultEndpoints,
34
- u4 as formatRelativeTime,
35
+ v as formatRelativeTime,
35
36
  p as provideChatKitLabels,
36
37
  u3 as useChat,
37
38
  u2 as useChatKitLabels,
@@ -12722,6 +12722,7 @@ const defaultChatKitLabels = {
12722
12722
  modelSelectorAriaLabel: "Select model",
12723
12723
  modelSelectorListAriaLabel: "Models",
12724
12724
  modelSelectorPlaceholder: "Select model",
12725
+ markdownTableLabel: "Table",
12725
12726
  historyItemUntitled: "Untitled conversation",
12726
12727
  historyItemActionAriaLabel: "Conversation options",
12727
12728
  historyItemEditAction: "Edit",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aleph-alpha/chat-kit",
3
- "version": "2.3.0",
3
+ "version": "3.1.0",
4
4
  "description": "Chat kit package for building chat interfaces with Vue",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -3,7 +3,7 @@ defineOptions({ name: 'CkAgentMessage' });
3
3
  </script>
4
4
 
5
5
  <template>
6
- <div class="flex w-full flex-col gap-6 pb-6">
6
+ <div class="flex w-full min-w-0 flex-col gap-6 pb-6">
7
7
  <div v-if="$slots.icon || $slots.header" class="flex items-start gap-3">
8
8
  <div
9
9
  v-if="$slots.icon"
@@ -21,7 +21,7 @@ defineOptions({ name: 'CkAgentMessage' });
21
21
  </span>
22
22
  </div>
23
23
 
24
- <div class="text-content-on-surface-primary text-base leading-7">
24
+ <div class="text-content-on-surface-primary min-w-0 text-base leading-7">
25
25
  <slot />
26
26
  </div>
27
27
 
@@ -188,11 +188,12 @@ watch(
188
188
  v-for="message in messages"
189
189
  :key="message.id"
190
190
  :data-message-row="message.role"
191
+ class="min-w-0"
191
192
  >
192
- <div v-if="message.role === 'user'" class="flex justify-end">
193
+ <div v-if="message.role === 'user'" class="flex min-w-0 justify-end">
193
194
  <slot name="user-message" :message="message" />
194
195
  </div>
195
- <div v-else class="flex justify-start">
196
+ <div v-else class="flex min-w-0 justify-start">
196
197
  <slot name="agent-message" :message="message" />
197
198
  </div>
198
199
  </div>
@@ -1,5 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
3
+ import { formatFileSize } from '@aleph-alpha/ui-library';
3
4
 
4
5
  import CkDropZoneIllustration from './CkDropZoneIllustration.vue';
5
6
  import type {
@@ -76,12 +77,6 @@ function fileMatchesAccept(file: File): boolean {
76
77
  return false;
77
78
  }
78
79
 
79
- function formatBytes(bytes: number): string {
80
- const mb = bytes / (1024 * 1024);
81
- if (mb >= 1) return `${mb.toFixed(0)} MB`;
82
- return `${Math.max(1, Math.round(bytes / 1024))} KB`;
83
- }
84
-
85
80
  const isSingle = computed(() => props.maxFiles === 1);
86
81
 
87
82
  const resolvedHeading = computed(
@@ -156,7 +151,7 @@ function onOverlayDrop(e: DragEvent) {
156
151
  rejected.push({
157
152
  file,
158
153
  reason: 'too-large',
159
- message: `"${file.name}" — exceeds ${formatBytes(props.maxFileSizeBytes)} limit`,
154
+ message: `"${file.name}" — exceeds ${formatFileSize(props.maxFileSizeBytes)} limit`,
160
155
  });
161
156
  continue;
162
157
  }
@@ -10,13 +10,22 @@ import {
10
10
  } from 'vue';
11
11
  import type { PluggableList } from 'unified';
12
12
  import { useMarkdownParser } from '../../../handlers/useMarkdownParser';
13
+ import {
14
+ defaultChatKitLabels,
15
+ useChatKitLabels,
16
+ } from '../../../handlers/useChatKitLabels';
13
17
  import type { CkMarkdownElementClasses } from './types';
14
18
  import { defaultMarkdownClasses } from './defaultMarkdownClasses';
15
19
 
20
+ // Tables are wrapped in a horizontally scrollable container so wide content
21
+ // never forces the whole message column wider on narrow viewports.
22
+ const TABLE_WRAPPER_CLASS = 'max-w-full overflow-x-auto';
23
+
16
24
  function domToVNode(
17
25
  node: Node,
18
26
  slots: Slots,
19
27
  classes: CkMarkdownElementClasses,
28
+ tableLabel: string,
20
29
  ): VNode | string | null {
21
30
  if (node.nodeType === Node.TEXT_NODE) return node.textContent;
22
31
  if (node.nodeType !== Node.ELEMENT_NODE) return null;
@@ -34,7 +43,7 @@ function domToVNode(
34
43
  }
35
44
 
36
45
  const children = Array.from(node.childNodes)
37
- .map((child) => domToVNode(child, slots, classes))
46
+ .map((child) => domToVNode(child, slots, classes, tableLabel))
38
47
  .filter((c): c is VNode | string => c != null);
39
48
 
40
49
  const attrs: Record<string, string> = {};
@@ -48,7 +57,22 @@ function domToVNode(
48
57
  attrs.class = attrs.class ? `${attrs.class} ${customClass}` : customClass;
49
58
  }
50
59
 
51
- return h(tag, attrs, children);
60
+ const vnode = h(tag, attrs, children);
61
+
62
+ if (tag === 'table') {
63
+ return h(
64
+ 'div',
65
+ {
66
+ class: TABLE_WRAPPER_CLASS,
67
+ tabindex: '0',
68
+ role: 'region',
69
+ 'aria-label': tableLabel,
70
+ },
71
+ [vnode],
72
+ );
73
+ }
74
+
75
+ return vnode;
52
76
  }
53
77
 
54
78
  export default defineComponent({
@@ -64,6 +88,7 @@ export default defineComponent({
64
88
  setup(props, { slots }) {
65
89
  const { content, plugins } = toRefs(props);
66
90
  const { html } = useMarkdownParser(content, plugins);
91
+ const labels = useChatKitLabels();
67
92
 
68
93
  const parsedNodes = computed(() => {
69
94
  const raw = html.value;
@@ -79,10 +104,17 @@ export default defineComponent({
79
104
 
80
105
  return () => {
81
106
  const elementClasses = mergedClasses.value;
107
+ const tableLabel =
108
+ labels.value.markdownTableLabel ??
109
+ defaultChatKitLabels.markdownTableLabel!;
82
110
  const children = parsedNodes.value
83
- .map((node) => domToVNode(node, slots, elementClasses))
111
+ .map((node) => domToVNode(node, slots, elementClasses, tableLabel))
84
112
  .filter((c): c is VNode | string => c != null);
85
- return h('div', { class: 'markdown-renderer' }, children);
113
+ return h(
114
+ 'div',
115
+ { class: 'markdown-renderer min-w-0 break-words' },
116
+ children,
117
+ );
86
118
  };
87
119
  },
88
120
  });
@@ -3,13 +3,14 @@ import type { CkMarkdownElementClasses } from './types';
3
3
  export const defaultMarkdownClasses: CkMarkdownElementClasses = {
4
4
  p: 'my-1 leading-7',
5
5
  a: 'underline underline-offset-4',
6
+ img: 'max-w-full h-auto',
6
7
  h1: 'mt-4 mb-2 text-2xl font-bold',
7
8
  h2: 'mt-3 mb-2 text-xl font-semibold',
8
9
  h3: 'mt-3 mb-1 text-lg font-semibold',
9
10
  ul: 'my-1 ml-6 list-disc',
10
11
  ol: 'my-1 ml-6 list-decimal',
11
12
  li: 'my-0.5',
12
- pre: 'my-2 overflow-x-auto rounded-lg p-4',
13
+ pre: 'my-2 max-w-full overflow-x-auto rounded-lg p-4',
13
14
  code: 'rounded px-1.5 py-0.5',
14
15
  blockquote: 'my-2 border-l-2 pl-4 italic',
15
16
  table: 'my-2 w-full border-collapse',
@@ -63,14 +63,19 @@ function select(id: string) {
63
63
  <UiPopoverTrigger as-child>
64
64
  <button
65
65
  type="button"
66
- class="ck-model-selector__trigger inline-flex h-9 shrink-0 items-center gap-1 rounded-3xl px-3 label-14-medium text-content-on-surface-primary outline-none transition-colors hover:bg-background-surface-muted focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50"
66
+ class="ck-model-selector__trigger inline-flex h-9 min-w-0 items-center gap-1 rounded-3xl px-3 label-14-medium text-content-on-surface-primary outline-none transition-colors hover:bg-background-surface-muted focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50"
67
67
  :disabled="disabled"
68
68
  aria-haspopup="listbox"
69
69
  :aria-expanded="open"
70
70
  :aria-label="triggerAriaLabel"
71
71
  >
72
- <span class="max-w-[10rem] truncate">{{ selectedLabel }}</span>
73
- <UiIcon name="chevron-down" :size="16" aria-hidden="true" />
72
+ <span class="min-w-0 max-w-[10rem] truncate">{{ selectedLabel }}</span>
73
+ <UiIcon
74
+ name="chevron-down"
75
+ :size="16"
76
+ class="shrink-0"
77
+ aria-hidden="true"
78
+ />
74
79
  </button>
75
80
  </UiPopoverTrigger>
76
81
  <UiPopoverContent
@@ -9,7 +9,7 @@
9
9
  * @category Actions
10
10
  * @useCases select model, choose LLM, model picker in prompt field, switch model mid-conversation
11
11
  * @keywords model, selector, picker, dropdown, llm, prompt, choose, switch
12
- * @related CkPromptInput, CkPromptActionButton
12
+ * @related CkPromptInput, CkPromptSendButton
13
13
  */
14
14
  export interface CkModelOption {
15
15
  /**
@@ -1,5 +1,29 @@
1
1
  import CkPromptInput from './CkPromptInput.vue';
2
2
  import { render, screen, fireEvent } from '@testing-library/vue';
3
+ import { defineComponent, nextTick, ref } from 'vue';
4
+
5
+ // Mock the textarea's scrollHeight (jsdom always returns 0). The auto-grow +
6
+ // multi-line latch logic in CkPromptInput depends on scrollHeight; tests that
7
+ // exercise that path call this helper to stage a measured value.
8
+ function mockScrollHeight(value: number): void {
9
+ Object.defineProperty(HTMLTextAreaElement.prototype, 'scrollHeight', {
10
+ configurable: true,
11
+ get() {
12
+ return value;
13
+ },
14
+ });
15
+ }
16
+
17
+ function restoreScrollHeight(): void {
18
+ // Re-installing a property descriptor with a getter returning 0 mirrors
19
+ // jsdom's default (`HTMLElement.scrollHeight` returns 0 by spec there).
20
+ Object.defineProperty(HTMLTextAreaElement.prototype, 'scrollHeight', {
21
+ configurable: true,
22
+ get() {
23
+ return 0;
24
+ },
25
+ });
26
+ }
3
27
 
4
28
  describe('CkPromptInput', () => {
5
29
  describe('rendering', () => {
@@ -122,13 +146,10 @@ describe('CkPromptInput', () => {
122
146
  expect(screen.getByText('Express')).toBeInTheDocument();
123
147
  });
124
148
 
125
- it('does not render toolbar-left container when slot is not provided', () => {
149
+ it('renders no toolbar buttons when slots are not provided', () => {
126
150
  const { container } = render(CkPromptInput);
127
151
 
128
- const toolbarDivs = container.querySelectorAll(
129
- 'form > div:last-child > div',
130
- );
131
- expect(toolbarDivs[0]?.children.length).toBe(0);
152
+ expect(container.querySelectorAll('button')).toHaveLength(0);
132
153
  });
133
154
 
134
155
  it('renders toolbar-right slot content', () => {
@@ -139,13 +160,12 @@ describe('CkPromptInput', () => {
139
160
  expect(screen.getByText('Custom Send')).toBeInTheDocument();
140
161
  });
141
162
 
142
- it('renders nothing in toolbar-right by default', () => {
143
- const { container } = render(CkPromptInput);
163
+ it('renders toolbar-top slot content', () => {
164
+ render(CkPromptInput, {
165
+ slots: { 'toolbar-top': '<span>Toolbar-top content</span>' },
166
+ });
144
167
 
145
- const toolbarRight = container.querySelector(
146
- 'form > div:last-child > div.ml-auto',
147
- );
148
- expect(toolbarRight?.children.length).toBe(0);
168
+ expect(screen.getByText('Toolbar-top content')).toBeInTheDocument();
149
169
  });
150
170
 
151
171
  it('renders footer slot content', () => {
@@ -178,4 +198,179 @@ describe('CkPromptInput', () => {
178
198
  expect(screen.getByRole('textbox')).toBeDisabled();
179
199
  });
180
200
  });
201
+
202
+ // The form switches between compact (single-row, rounded-3xl) and stacked
203
+ // (multi-row, rounded-2xl) layouts based on (a) the presence of the
204
+ // `toolbar-top` slot and (b) whether the textarea content exceeds one line.
205
+ // These tests regression-guard the slot reactivity fix and the multi-line
206
+ // latch threshold.
207
+ describe('layout transitions', () => {
208
+ afterEach(() => {
209
+ restoreScrollHeight();
210
+ });
211
+
212
+ it('reacts to toolbar-top slot becoming available after mount', async () => {
213
+ const Parent = defineComponent({
214
+ components: { CkPromptInput },
215
+ setup() {
216
+ return { show: ref(false) };
217
+ },
218
+ template: `
219
+ <div>
220
+ <button data-testid="toggle" @click="show = !show">toggle</button>
221
+ <CkPromptInput model-value="">
222
+ <template v-if="show" #toolbar-top>
223
+ <span data-testid="top">attached files</span>
224
+ </template>
225
+ </CkPromptInput>
226
+ </div>
227
+ `,
228
+ });
229
+ const { container } = render(Parent);
230
+
231
+ expect(container.querySelector('[data-testid="top"]')).toBeNull();
232
+ expect(container.querySelector('form')?.className).toContain(
233
+ 'rounded-3xl',
234
+ );
235
+
236
+ await fireEvent.click(screen.getByTestId('toggle'));
237
+
238
+ // Parent re-render → `useSlots()` flips → computed re-evaluates → top
239
+ // row renders AND the form swaps to the smaller multi-row radius.
240
+ expect(
241
+ container.querySelector('[data-testid="top"]'),
242
+ ).toBeInTheDocument();
243
+ expect(container.querySelector('form')?.className).toContain(
244
+ 'rounded-2xl',
245
+ );
246
+ });
247
+
248
+ it('also reacts to toolbar-top slot becoming unavailable', async () => {
249
+ const Parent = defineComponent({
250
+ components: { CkPromptInput },
251
+ setup() {
252
+ return { show: ref(true) };
253
+ },
254
+ template: `
255
+ <div>
256
+ <button data-testid="toggle" @click="show = !show">toggle</button>
257
+ <CkPromptInput model-value="">
258
+ <template v-if="show" #toolbar-top>
259
+ <span data-testid="top">attached files</span>
260
+ </template>
261
+ </CkPromptInput>
262
+ </div>
263
+ `,
264
+ });
265
+ const { container } = render(Parent);
266
+
267
+ expect(container.querySelector('form')?.className).toContain(
268
+ 'rounded-2xl',
269
+ );
270
+
271
+ await fireEvent.click(screen.getByTestId('toggle'));
272
+
273
+ expect(container.querySelector('[data-testid="top"]')).toBeNull();
274
+ expect(container.querySelector('form')?.className).toContain(
275
+ 'rounded-3xl',
276
+ );
277
+ });
278
+
279
+ it('latches to multi-line layout when scrollHeight exceeds 2× line-height', async () => {
280
+ mockScrollHeight(48); // exactly 2 × LINE_HEIGHT
281
+ const Parent = defineComponent({
282
+ components: { CkPromptInput },
283
+ setup() {
284
+ return { text: ref('one') };
285
+ },
286
+ template: `
287
+ <CkPromptInput :model-value="text" @update:model-value="text = $event" />
288
+ `,
289
+ });
290
+ const { container, rerender } = render(Parent);
291
+ // Initial render mounted with scrollHeight=48 but modelValue='one' (no
292
+ // newline) — single line latches to multi when scrollHeight ≥ 48.
293
+ await nextTick();
294
+ // The grid template should now include the input-on-top + toolbar-row
295
+ // shape used for multi-line mode.
296
+ const form = container.querySelector('form');
297
+ expect(form?.style.gridTemplateAreas).toContain('"left . right"');
298
+
299
+ // Rerender to a different value to confirm the latch persists.
300
+ await rerender({});
301
+ await nextTick();
302
+ expect(form?.style.gridTemplateAreas).toContain('"left . right"');
303
+ });
304
+
305
+ it('does NOT latch on borderline scrollHeight (single emoji-line @ 36 px)', async () => {
306
+ mockScrollHeight(36); // 1.5 × LINE_HEIGHT — emoji/CJK sub-pixel rendering
307
+ const Parent = defineComponent({
308
+ components: { CkPromptInput },
309
+ setup() {
310
+ return { text: ref('hi 👋') };
311
+ },
312
+ template: `<CkPromptInput :model-value="text" />`,
313
+ });
314
+ const { container } = render(Parent);
315
+ await nextTick();
316
+ // Single-line layout: textarea + toolbars on the same row.
317
+ const form = container.querySelector('form');
318
+ expect(form?.style.gridTemplateAreas).toContain('"left input right"');
319
+ expect(form?.style.gridTemplateAreas).not.toContain('"left . right"');
320
+ });
321
+
322
+ it('latches when the user inserts an explicit newline (Shift+Enter)', async () => {
323
+ mockScrollHeight(24); // jsdom never reports >24 reliably; rely on \n
324
+ const Parent = defineComponent({
325
+ components: { CkPromptInput },
326
+ setup() {
327
+ return { text: ref('line one') };
328
+ },
329
+ template: `
330
+ <CkPromptInput :model-value="text" @update:model-value="text = $event" />
331
+ `,
332
+ });
333
+ const { container } = render(Parent);
334
+ await nextTick();
335
+ const form = container.querySelector('form');
336
+ expect(form?.style.gridTemplateAreas).toContain('"left input right"');
337
+
338
+ // Now the modelValue contains a newline.
339
+ const ParentTwoLines = defineComponent({
340
+ components: { CkPromptInput },
341
+ setup() {
342
+ return { text: ref('line one\nline two') };
343
+ },
344
+ template: `<CkPromptInput :model-value="text" />`,
345
+ });
346
+ const { container: c2 } = render(ParentTwoLines);
347
+ await nextTick();
348
+ expect(c2.querySelector('form')?.style.gridTemplateAreas).toContain(
349
+ '"left . right"',
350
+ );
351
+ });
352
+
353
+ it('un-latches multi-line state when the field is emptied', async () => {
354
+ mockScrollHeight(48);
355
+ const Parent = defineComponent({
356
+ components: { CkPromptInput },
357
+ setup() {
358
+ return { text: ref('something') };
359
+ },
360
+ template: `
361
+ <CkPromptInput :model-value="text" @update:model-value="text = $event" />
362
+ `,
363
+ });
364
+ const { container, getByRole } = render(Parent);
365
+ await nextTick();
366
+ const form = container.querySelector('form');
367
+ expect(form?.style.gridTemplateAreas).toContain('"left . right"');
368
+
369
+ mockScrollHeight(24);
370
+ await fireEvent.update(getByRole('textbox'), '');
371
+ await nextTick();
372
+
373
+ expect(form?.style.gridTemplateAreas).toContain('"left input right"');
374
+ });
375
+ });
181
376
  });