@aleph-alpha/chat-kit 1.17.2 → 1.18.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 (38) hide show
  1. package/dist/{CkInput.vue_vue_type_script_setup_true_lang-DxUWj4Vh.js → CkInput.vue_vue_type_script_setup_true_lang-BGlztr2p.js} +212 -99
  2. package/dist/chat-kit.css +5 -5
  3. package/dist/components/base/CkFeedbackDialog/CkFeedbackDialog.stories.d.ts +6 -0
  4. package/dist/components/base/CkFeedbackDialog/CkFeedbackDialog.stories.d.ts.map +1 -1
  5. package/dist/components/base/CkFeedbackDialog/CkFeedbackDialog.vue.d.ts.map +1 -1
  6. package/dist/components/base/CkModelSelector/CkModelSelector.stories.d.ts +20 -0
  7. package/dist/components/base/CkModelSelector/CkModelSelector.stories.d.ts.map +1 -0
  8. package/dist/components/base/CkModelSelector/CkModelSelector.vue.d.ts +16 -0
  9. package/dist/components/base/CkModelSelector/CkModelSelector.vue.d.ts.map +1 -0
  10. package/dist/components/base/CkModelSelector/index.d.ts +3 -0
  11. package/dist/components/base/CkModelSelector/index.d.ts.map +1 -0
  12. package/dist/components/base/CkModelSelector/types.d.ts +54 -0
  13. package/dist/components/base/CkModelSelector/types.d.ts.map +1 -0
  14. package/dist/components/base/index.d.ts +2 -0
  15. package/dist/components/base/index.d.ts.map +1 -1
  16. package/dist/components/index.d.ts +2 -2
  17. package/dist/components/index.d.ts.map +1 -1
  18. package/dist/components/index.js +9 -8
  19. package/dist/handlers/index.js +1 -1
  20. package/dist/handlers/useChatKitLabels.d.ts +6 -0
  21. package/dist/handlers/useChatKitLabels.d.ts.map +1 -1
  22. package/dist/index.d.ts +2 -2
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +11 -10
  25. package/dist/{useChatKitLabels-BC6ItJc6.js → useChatKitLabels-ZutacPad.js} +3 -0
  26. package/package.json +2 -2
  27. package/src/components/base/CkFeedbackDialog/CkFeedbackDialog.stories.ts +35 -0
  28. package/src/components/base/CkFeedbackDialog/CkFeedbackDialog.vue +2 -2
  29. package/src/components/base/CkModelSelector/CkModelSelector.spec.ts +60 -0
  30. package/src/components/base/CkModelSelector/CkModelSelector.stories.ts +101 -0
  31. package/src/components/base/CkModelSelector/CkModelSelector.vue +109 -0
  32. package/src/components/base/CkModelSelector/index.ts +6 -0
  33. package/src/components/base/CkModelSelector/types.ts +55 -0
  34. package/src/components/base/index.ts +6 -0
  35. package/src/components/index.ts +4 -0
  36. package/src/handlers/useChatKitLabels.spec.ts +5 -28
  37. package/src/handlers/useChatKitLabels.ts +9 -0
  38. package/src/index.ts +4 -0
@@ -0,0 +1,109 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref } from 'vue';
3
+ import {
4
+ UiIcon,
5
+ UiPopover,
6
+ UiPopoverContent,
7
+ UiPopoverTrigger,
8
+ } from '@aleph-alpha/ui-library';
9
+
10
+ import {
11
+ defaultChatKitLabels,
12
+ useChatKitLabels,
13
+ } from '../../../handlers/useChatKitLabels';
14
+ import type { CkModelSelectorEmits, CkModelSelectorProps } from './types';
15
+
16
+ defineOptions({ name: 'CkModelSelector' });
17
+
18
+ const props = withDefaults(defineProps<CkModelSelectorProps>(), {
19
+ models: () => [],
20
+ selectedModelId: null,
21
+ disabled: false,
22
+ side: 'top',
23
+ align: 'end',
24
+ sideOffset: 8,
25
+ });
26
+
27
+ const emit = defineEmits<CkModelSelectorEmits>();
28
+
29
+ const labels = useChatKitLabels();
30
+
31
+ // Resolution order: injected label, English default.
32
+ const triggerAriaLabel = computed(
33
+ () =>
34
+ labels.value.modelSelectorAriaLabel ??
35
+ defaultChatKitLabels.modelSelectorAriaLabel!,
36
+ );
37
+ const listAriaLabel = computed(
38
+ () =>
39
+ labels.value.modelSelectorListAriaLabel ??
40
+ defaultChatKitLabels.modelSelectorListAriaLabel!,
41
+ );
42
+ const placeholderLabel = computed(
43
+ () =>
44
+ labels.value.modelSelectorPlaceholder ??
45
+ defaultChatKitLabels.modelSelectorPlaceholder!,
46
+ );
47
+
48
+ const open = ref(false);
49
+
50
+ const selectedLabel = computed(() => {
51
+ const match = props.models.find((m) => m.id === props.selectedModelId);
52
+ return match?.label ?? placeholderLabel.value;
53
+ });
54
+
55
+ function select(id: string) {
56
+ open.value = false;
57
+ if (id !== props.selectedModelId) emit('update:selectedModelId', id);
58
+ }
59
+ </script>
60
+
61
+ <template>
62
+ <UiPopover v-model:open="open">
63
+ <UiPopoverTrigger as-child>
64
+ <button
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"
67
+ :disabled="disabled"
68
+ aria-haspopup="listbox"
69
+ :aria-expanded="open"
70
+ :aria-label="triggerAriaLabel"
71
+ >
72
+ <span class="max-w-[10rem] truncate">{{ selectedLabel }}</span>
73
+ <UiIcon name="chevron-down" :size="16" aria-hidden="true" />
74
+ </button>
75
+ </UiPopoverTrigger>
76
+ <UiPopoverContent
77
+ :side="side"
78
+ :align="align"
79
+ :side-offset="sideOffset"
80
+ class="max-h-72 w-56 overflow-y-auto rounded-xl border border-border-surface-default bg-background-surface-floating p-2 text-content-on-surface-primary shadow-md"
81
+ @open-auto-focus.prevent
82
+ >
83
+ <ul
84
+ class="flex flex-col gap-1"
85
+ role="listbox"
86
+ :aria-label="listAriaLabel"
87
+ >
88
+ <li v-for="model in models" :key="model.id" role="presentation">
89
+ <button
90
+ type="button"
91
+ role="option"
92
+ :aria-selected="model.id === selectedModelId"
93
+ class="relative flex w-full items-center gap-2 rounded-sm py-2 pr-8 pl-3 text-left body-14-regular text-content-on-surface-primary outline-none hover:bg-background-surface-muted-subtle focus-visible:ring-2 focus-visible:ring-ring"
94
+ @click="select(model.id)"
95
+ >
96
+ <span class="min-w-0 flex-1 truncate">{{ model.label }}</span>
97
+ <UiIcon
98
+ v-if="model.id === selectedModelId"
99
+ name="check"
100
+ :size="16"
101
+ class="absolute right-2 text-content-on-surface-primary"
102
+ aria-hidden="true"
103
+ />
104
+ </button>
105
+ </li>
106
+ </ul>
107
+ </UiPopoverContent>
108
+ </UiPopover>
109
+ </template>
@@ -0,0 +1,6 @@
1
+ export { default as CkModelSelector } from './CkModelSelector.vue';
2
+ export type {
3
+ CkModelOption,
4
+ CkModelSelectorProps,
5
+ CkModelSelectorEmits,
6
+ } from './types';
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Compact dropdown for choosing the active model, sized to sit inline in a
3
+ * prompt field next to the send button. Controlled component: pass the
4
+ * available `models` and the `selectedModelId`, and react to
5
+ * `update:selectedModelId` (so it works with `v-model:selected-model-id`).
6
+ * Purely presentational — fetching the list and persisting the choice are the
7
+ * consumer's responsibility.
8
+ *
9
+ * @category Actions
10
+ * @useCases select model, choose LLM, model picker in prompt field, switch model mid-conversation
11
+ * @keywords model, selector, picker, dropdown, llm, prompt, choose, switch
12
+ * @related CkPromptInput, CkPromptActionButton
13
+ */
14
+ export interface CkModelOption {
15
+ /**
16
+ * Stable identifier for the model. Emitted on selection and compared
17
+ * against `selectedModelId` to mark the active row.
18
+ */
19
+ id: string;
20
+ /** Display name shown in the trigger and the option row. */
21
+ label: string;
22
+ }
23
+
24
+ export interface CkModelSelectorProps {
25
+ /** Models to choose from. The dropdown trigger is still rendered when empty. */
26
+ models?: readonly CkModelOption[];
27
+ /** Id of the currently selected model. */
28
+ selectedModelId?: string | null;
29
+ /** Disable the trigger (e.g. while a model list is loading). */
30
+ disabled?: boolean;
31
+ /**
32
+ * Which side of the trigger the dropdown opens on.
33
+ * @default 'top'
34
+ */
35
+ side?: 'top' | 'right' | 'bottom' | 'left';
36
+ /**
37
+ * Alignment of the dropdown relative to the trigger.
38
+ * @default 'end'
39
+ */
40
+ align?: 'start' | 'center' | 'end';
41
+ /**
42
+ * Gap in pixels between the trigger and the dropdown.
43
+ * @default 8
44
+ */
45
+ sideOffset?: number;
46
+ }
47
+
48
+ /** Emitted events for `CkModelSelector`. */
49
+ export interface CkModelSelectorEmits {
50
+ /**
51
+ * Fired with the chosen model id when the selection changes. Pairs with
52
+ * `v-model:selected-model-id`.
53
+ */
54
+ 'update:selectedModelId': [id: string];
55
+ }
@@ -32,6 +32,12 @@ export type {
32
32
  CkMarkdownElementClasses,
33
33
  } from './CkMarkdownRenderer';
34
34
  export { CkMessageActionButton } from './CkMessageActionButton';
35
+ export { CkModelSelector } from './CkModelSelector';
36
+ export type {
37
+ CkModelOption,
38
+ CkModelSelectorProps,
39
+ CkModelSelectorEmits,
40
+ } from './CkModelSelector';
35
41
  export { CkPromptActionButton } from './CkPromptActionButton';
36
42
  export { CkPromptStopButton } from './CkPromptStopButton';
37
43
  export { CkPromptInput } from './CkPromptInput';
@@ -10,6 +10,7 @@ export {
10
10
  CkHistoryWrapper,
11
11
  CkMarkdownRenderer,
12
12
  CkMessageActionButton,
13
+ CkModelSelector,
13
14
  CkPromptActionButton,
14
15
  CkPromptStopButton,
15
16
  CkPromptInput,
@@ -35,6 +36,9 @@ export type {
35
36
  CkHistoryWrapperProps,
36
37
  CkMarkdownElementClasses,
37
38
  CkMarkdownRendererProps,
39
+ CkModelOption,
40
+ CkModelSelectorProps,
41
+ CkModelSelectorEmits,
38
42
  CkUserMessageProps,
39
43
  } from './base';
40
44
 
@@ -34,34 +34,11 @@ describe('useChatKitLabels', () => {
34
34
  });
35
35
 
36
36
  it('returns provided labels when a ref is used', () => {
37
- const customLabels = ref<ChatKitLabels>({
38
- agentAvatarAlt: 'Bot-Bild',
39
- agentLoadingAvatarAlt: 'Bot lädt',
40
- inputPlaceholder: 'Nachricht eingeben...',
41
- copyMessageAction: 'Nachricht kopieren',
42
- copyMessageActionCopied: 'Kopiert',
43
- feedbackThumbsUp: 'Gute Antwort',
44
- feedbackThumbsDown: 'Schlechte Antwort',
45
- feedbackGroup: 'Antwort bewerten',
46
- feedbackDialogTitlePositive: 'Positives Feedback geben',
47
- feedbackDialogTitleNegative: 'Negatives Feedback geben',
48
- feedbackDialogResponseHeading: 'Antwort',
49
- feedbackDialogDescription:
50
- 'Wählen Sie einen Grund und fügen Sie optional einen Kommentar hinzu.',
51
- feedbackDialogOtherLabel: 'Sonstiges',
52
- feedbackDialogOtherTooltip:
53
- 'Teilen Sie weitere Details zu dieser Antwort mit.',
54
- feedbackDialogFreeTextPlaceholder: 'Zusätzliche Details eingeben',
55
- feedbackDialogCancelLabel: 'Abbrechen',
56
- feedbackDialogSubmitLabel: 'Senden',
57
- userMessageShowMore: 'Mehr anzeigen',
58
- userMessageShowLess: 'Weniger anzeigen',
59
- historyItemUntitled: 'Unbenannte Konversation',
60
- historyItemActionAriaLabel: 'Konversationsoptionen',
61
- historyItemEditAction: 'Bearbeiten',
62
- historyItemDeleteAction: 'Löschen',
63
- historyShowAll: 'Alle anzeigen',
64
- });
37
+ const customLabels = ref<ChatKitLabels>(
38
+ Object.fromEntries(
39
+ Object.keys(defaultChatKitLabels).map((key) => [key, `custom:${key}`]),
40
+ ) as ChatKitLabels,
41
+ );
65
42
 
66
43
  let result: ComputedRef<ChatKitLabels> | undefined;
67
44
 
@@ -69,6 +69,12 @@ export type ChatKitLabels = {
69
69
  userMessageShowMore?: string;
70
70
  /** Label for the `CkUserMessage` toggle when the message is expanded. */
71
71
  userMessageShowLess?: string;
72
+ /** Accessible label for the `CkModelSelector` trigger button. */
73
+ modelSelectorAriaLabel?: string;
74
+ /** Accessible label for the `CkModelSelector` options list. */
75
+ modelSelectorListAriaLabel?: string;
76
+ /** Trigger text shown by `CkModelSelector` when no model is selected. */
77
+ modelSelectorPlaceholder?: string;
72
78
  /** Fallback title used by `CkHistory` when a conversation has no `title`. */
73
79
  historyItemUntitled: string;
74
80
  /** Accessible name for the trailing kebab trigger on each `CkHistory` row. */
@@ -107,6 +113,9 @@ export const defaultChatKitLabels: ChatKitLabels = {
107
113
  feedbackDialogSubmitLabel: 'Submit',
108
114
  userMessageShowMore: 'Show more',
109
115
  userMessageShowLess: 'Show less',
116
+ modelSelectorAriaLabel: 'Select model',
117
+ modelSelectorListAriaLabel: 'Models',
118
+ modelSelectorPlaceholder: 'Select model',
110
119
  historyItemUntitled: 'Untitled conversation',
111
120
  historyItemActionAriaLabel: 'Conversation options',
112
121
  historyItemEditAction: 'Edit',
package/src/index.ts CHANGED
@@ -75,6 +75,7 @@ export {
75
75
  CkInput,
76
76
  CkMarkdownRenderer,
77
77
  CkMessageActionButton,
78
+ CkModelSelector,
78
79
  CkPromptActionButton,
79
80
  CkPromptStopButton,
80
81
  CkPromptInput,
@@ -103,6 +104,9 @@ export type {
103
104
  CkHistoryWrapperProps,
104
105
  CkMarkdownElementClasses,
105
106
  CkMarkdownRendererProps,
107
+ CkModelOption,
108
+ CkModelSelectorProps,
109
+ CkModelSelectorEmits,
106
110
  CkUserMessageProps,
107
111
  } from './components';
108
112