@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.
- package/dist/{CkInput.vue_vue_type_script_setup_true_lang-DxUWj4Vh.js → CkInput.vue_vue_type_script_setup_true_lang-BGlztr2p.js} +212 -99
- package/dist/chat-kit.css +5 -5
- package/dist/components/base/CkFeedbackDialog/CkFeedbackDialog.stories.d.ts +6 -0
- package/dist/components/base/CkFeedbackDialog/CkFeedbackDialog.stories.d.ts.map +1 -1
- package/dist/components/base/CkFeedbackDialog/CkFeedbackDialog.vue.d.ts.map +1 -1
- package/dist/components/base/CkModelSelector/CkModelSelector.stories.d.ts +20 -0
- package/dist/components/base/CkModelSelector/CkModelSelector.stories.d.ts.map +1 -0
- package/dist/components/base/CkModelSelector/CkModelSelector.vue.d.ts +16 -0
- package/dist/components/base/CkModelSelector/CkModelSelector.vue.d.ts.map +1 -0
- package/dist/components/base/CkModelSelector/index.d.ts +3 -0
- package/dist/components/base/CkModelSelector/index.d.ts.map +1 -0
- package/dist/components/base/CkModelSelector/types.d.ts +54 -0
- package/dist/components/base/CkModelSelector/types.d.ts.map +1 -0
- package/dist/components/base/index.d.ts +2 -0
- package/dist/components/base/index.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +9 -8
- package/dist/handlers/index.js +1 -1
- package/dist/handlers/useChatKitLabels.d.ts +6 -0
- package/dist/handlers/useChatKitLabels.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -10
- package/dist/{useChatKitLabels-BC6ItJc6.js → useChatKitLabels-ZutacPad.js} +3 -0
- package/package.json +2 -2
- package/src/components/base/CkFeedbackDialog/CkFeedbackDialog.stories.ts +35 -0
- package/src/components/base/CkFeedbackDialog/CkFeedbackDialog.vue +2 -2
- package/src/components/base/CkModelSelector/CkModelSelector.spec.ts +60 -0
- package/src/components/base/CkModelSelector/CkModelSelector.stories.ts +101 -0
- package/src/components/base/CkModelSelector/CkModelSelector.vue +109 -0
- package/src/components/base/CkModelSelector/index.ts +6 -0
- package/src/components/base/CkModelSelector/types.ts +55 -0
- package/src/components/base/index.ts +6 -0
- package/src/components/index.ts +4 -0
- package/src/handlers/useChatKitLabels.spec.ts +5 -28
- package/src/handlers/useChatKitLabels.ts +9 -0
- 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,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';
|
package/src/components/index.ts
CHANGED
|
@@ -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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|