@fusion.dev/helix-headless 0.144.0 → 0.146.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/custom-elements.json +15195 -4240
- package/dist/accordion/item/accordion-item.d.ts +62 -12
- package/dist/accordion/item/accordion-item.js +41 -10
- package/dist/accordion/root/accordion-root.d.ts +14 -5
- package/dist/accordion/root/accordion-root.js +7 -1
- package/dist/announcement/root/announcement-root.d.ts +24 -3
- package/dist/announcement/root/announcement-root.js +39 -2
- package/dist/app-header/root/app-header-root.d.ts +12 -0
- package/dist/app-header/root/app-header-root.js +13 -1
- package/dist/app-header/sectioning.d.ts +9 -0
- package/dist/app-header/sectioning.js +27 -0
- package/dist/avatar/group/avatar-group.d.ts +20 -14
- package/dist/avatar/group/avatar-group.js +17 -19
- package/dist/badge/root/badge-root.d.ts +3 -1
- package/dist/badge/root/badge-root.js +2 -2
- package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
- package/dist/bar-chart/root/bar-chart-root.js +52 -15
- package/dist/bar-chart/stack.d.ts +15 -0
- package/dist/bar-chart/stack.js +19 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +57 -1
- package/dist/breadcrumbs/root/breadcrumbs-root.js +73 -3
- package/dist/button/root/button-root.d.ts +26 -0
- package/dist/button/root/button-root.js +38 -18
- package/dist/button-group/root/button-group-root.d.ts +2 -1
- package/dist/button-group/root/button-group-root.js +5 -1
- package/dist/canvas/node/canvas-node.d.ts +4 -3
- package/dist/canvas/node/canvas-node.js +3 -2
- package/dist/canvas/root/canvas-root.d.ts +38 -3
- package/dist/canvas/root/canvas-root.js +123 -42
- package/dist/card/root/card-root.d.ts +24 -3
- package/dist/card/root/card-root.js +20 -8
- package/dist/carousel/root/carousel-root.d.ts +133 -4
- package/dist/carousel/root/carousel-root.js +174 -24
- package/dist/carousel/stops.d.ts +20 -0
- package/dist/carousel/stops.js +30 -0
- package/dist/chat/composer/chat-composer.d.ts +38 -6
- package/dist/chat/composer/chat-composer.js +42 -9
- package/dist/chat/message/chat-message.d.ts +32 -1
- package/dist/chat/message/chat-message.js +27 -10
- package/dist/chat/naming.d.ts +26 -0
- package/dist/chat/naming.js +14 -0
- package/dist/chat/root/chat-root.d.ts +58 -0
- package/dist/chat/root/chat-root.js +43 -3
- package/dist/checkbox/root/checkbox-root.d.ts +20 -0
- package/dist/checkbox/root/checkbox-root.js +14 -1
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
- package/dist/checkbox-group/select-all.d.ts +27 -0
- package/dist/checkbox-group/select-all.js +12 -0
- package/dist/code-block/highlight.d.ts +15 -0
- package/dist/code-block/highlight.js +4 -0
- package/dist/code-block/root/code-block-root.d.ts +57 -2
- package/dist/code-block/root/code-block-root.js +63 -8
- package/dist/color-input/root/color-input-root.d.ts +3 -0
- package/dist/color-input/root/color-input-root.js +6 -3
- package/dist/color-picker/root/color-picker-root.d.ts +33 -4
- package/dist/color-picker/root/color-picker-root.js +80 -21
- package/dist/color-picker/swatches.d.ts +12 -0
- package/dist/color-picker/swatches.js +26 -0
- package/dist/combobox/root/combobox-root.d.ts +43 -0
- package/dist/combobox/root/combobox-root.js +79 -15
- package/dist/command/root/command-root.d.ts +16 -1
- package/dist/command/root/command-root.js +22 -4
- package/dist/copy-button/root/copy-button-root.d.ts +26 -1
- package/dist/copy-button/root/copy-button-root.js +12 -5
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +1 -1
- package/dist/data-table/keys.d.ts +24 -0
- package/dist/data-table/keys.js +24 -0
- package/dist/data-table/root/data-table-root.d.ts +170 -13
- package/dist/data-table/root/data-table-root.js +294 -52
- package/dist/data-table/tree.d.ts +55 -0
- package/dist/data-table/tree.js +54 -0
- package/dist/date-input/root/date-input-root.d.ts +3 -1
- package/dist/date-input/root/date-input-root.js +18 -7
- package/dist/date-picker/root/date-picker-root.js +12 -6
- package/dist/description-list/item/description-list-item.d.ts +17 -2
- package/dist/description-list/item/description-list-item.js +15 -2
- package/dist/description-list/root/description-list-root.d.ts +27 -1
- package/dist/description-list/root/description-list-root.js +26 -1
- package/dist/dialog/description.js +15 -1
- package/dist/dialog/root/dialog-root.d.ts +8 -2
- package/dist/dialog/root/dialog-root.js +16 -1
- package/dist/divider/root/divider-root.d.ts +3 -0
- package/dist/divider/root/divider-root.js +2 -1
- package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
- package/dist/donut-chart/root/donut-chart-root.js +48 -1
- package/dist/drawer/reveal.d.ts +8 -0
- package/dist/drawer/reveal.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +59 -0
- package/dist/drawer/root/drawer-root.js +63 -4
- package/dist/drilldown/item/drilldown-item.d.ts +11 -6
- package/dist/drilldown/item/drilldown-item.js +8 -5
- package/dist/drilldown/root/drilldown-root.d.ts +29 -0
- package/dist/drilldown/root/drilldown-root.js +28 -5
- package/dist/element-events.generated.js +83 -12
- package/dist/empty/root/empty-root.d.ts +3 -1
- package/dist/empty/root/empty-root.js +3 -2
- package/dist/file-input/root/file-input-root.d.ts +69 -6
- package/dist/file-input/root/file-input-root.js +82 -19
- package/dist/file-input/screen.d.ts +2 -1
- package/dist/filter-input/menu/filter-menu.d.ts +5 -0
- package/dist/filter-input/menu/filter-menu.js +16 -4
- package/dist/filter-input/root/filter-input-root.d.ts +30 -6
- package/dist/filter-input/root/filter-input-root.js +1 -1
- package/dist/filter-input/suggest.d.ts +28 -3
- package/dist/filter-input/suggest.js +18 -8
- package/dist/format-date/root/format-date-root.d.ts +9 -16
- package/dist/format-date/root/format-date-root.js +10 -27
- package/dist/heatmap/root/heatmap-root.d.ts +24 -13
- package/dist/heatmap/root/heatmap-root.js +34 -12
- package/dist/icon/root/icon-root.d.ts +12 -1
- package/dist/icon/root/icon-root.js +21 -10
- package/dist/icon/settle.d.ts +7 -0
- package/dist/icon/settle.js +10 -0
- package/dist/icon-button/root/icon-button-root.d.ts +2 -0
- package/dist/image/root/image-root.d.ts +5 -1
- package/dist/image/root/image-root.js +10 -2
- package/dist/input/root/input-root.d.ts +13 -3
- package/dist/input/root/input-root.js +12 -3
- package/dist/kbd/root/kbd-root.d.ts +35 -1
- package/dist/kbd/root/kbd-root.js +23 -4
- package/dist/legend/root/legend-root.d.ts +55 -8
- package/dist/legend/root/legend-root.js +55 -13
- package/dist/lightbox/root/lightbox-root.d.ts +49 -6
- package/dist/lightbox/root/lightbox-root.js +86 -19
- package/dist/lightbox/zoom-controller.d.ts +59 -0
- package/dist/lightbox/zoom-controller.js +128 -0
- package/dist/lightbox/zoom.d.ts +22 -0
- package/dist/lightbox/zoom.js +16 -0
- package/dist/line-chart/root/line-chart-root.d.ts +22 -1
- package/dist/line-chart/root/line-chart-root.js +21 -1
- package/dist/list/item/list-item.d.ts +70 -1
- package/dist/list/item/list-item.js +77 -6
- package/dist/list/numbering.d.ts +14 -0
- package/dist/list/numbering.js +8 -0
- package/dist/list/root/list-root.d.ts +155 -9
- package/dist/list/root/list-root.js +246 -4
- package/dist/list/selection.d.ts +49 -0
- package/dist/list/selection.js +30 -0
- package/dist/listbox/root/listbox-root.d.ts +37 -1
- package/dist/listbox/root/listbox-root.js +49 -4
- package/dist/loader/busy.d.ts +10 -0
- package/dist/loader/busy.js +11 -0
- package/dist/loader/root/loader-root.d.ts +9 -2
- package/dist/loader/root/loader-root.js +23 -3
- package/dist/map/root/map-root.d.ts +6 -2
- package/dist/map/root/map-root.js +5 -2
- package/dist/megamenu/root/megamenu-root.d.ts +62 -0
- package/dist/megamenu/root/megamenu-root.js +90 -5
- package/dist/menu/index.d.ts +1 -0
- package/dist/menu/index.js +1 -0
- package/dist/menu/item/menu-item.d.ts +87 -11
- package/dist/menu/item/menu-item.js +78 -22
- package/dist/menu/root/menu-root.d.ts +39 -1
- package/dist/menu/root/menu-root.js +65 -8
- package/dist/menu/section/menu-section.d.ts +55 -0
- package/dist/menu/section/menu-section.js +60 -0
- package/dist/meter/root/meter-root.d.ts +20 -1
- package/dist/meter/root/meter-root.js +11 -15
- package/dist/navigation/root/navigation-root.d.ts +18 -2
- package/dist/navigation/root/navigation-root.js +29 -3
- package/dist/notifications/root/notifications-root.d.ts +25 -0
- package/dist/notifications/root/notifications-root.js +33 -5
- package/dist/number-input/root/number-input-root.d.ts +17 -8
- package/dist/number-input/root/number-input-root.js +2 -7
- package/dist/object-inspector/root/object-inspector-root.d.ts +161 -32
- package/dist/object-inspector/root/object-inspector-root.js +264 -123
- package/dist/object-inspector/rows.d.ts +75 -0
- package/dist/object-inspector/rows.js +119 -0
- package/dist/option/root/option-root.d.ts +5 -3
- package/dist/outline/levels.d.ts +31 -0
- package/dist/outline/levels.js +23 -0
- package/dist/outline/root/outline-root.d.ts +86 -3
- package/dist/outline/root/outline-root.js +95 -12
- package/dist/pagination/size/pagination-size.d.ts +12 -2
- package/dist/pagination/size/pagination-size.js +20 -5
- package/dist/pin-input/code.d.ts +10 -0
- package/dist/pin-input/code.js +13 -0
- package/dist/pin-input/root/pin-input-root.d.ts +25 -1
- package/dist/pin-input/root/pin-input-root.js +10 -11
- package/dist/popover/hide-outside.d.ts +14 -0
- package/dist/popover/hide-outside.js +41 -0
- package/dist/popover/root/popover-root.d.ts +57 -7
- package/dist/popover/root/popover-root.js +58 -3
- package/dist/progress/root/progress-root.d.ts +20 -0
- package/dist/progress/root/progress-root.js +15 -15
- package/dist/qr-code/export.d.ts +26 -1
- package/dist/qr-code/export.js +14 -0
- package/dist/qr-code/root/qr-code-root.d.ts +19 -5
- package/dist/qr-code/root/qr-code-root.js +58 -9
- package/dist/quote/marks.d.ts +8 -0
- package/dist/quote/marks.js +5 -0
- package/dist/quote/root/quote-root.d.ts +14 -2
- package/dist/quote/root/quote-root.js +23 -1
- package/dist/radio/group/radio-group.d.ts +4 -10
- package/dist/radio/group/radio-group.js +5 -10
- package/dist/radio/root/radio-root.d.ts +6 -2
- package/dist/radio/root/radio-root.js +6 -1
- package/dist/rating/root/rating-root.d.ts +10 -5
- package/dist/rating/root/rating-root.js +32 -8
- package/dist/rating/steps.d.ts +7 -0
- package/dist/rating/steps.js +9 -0
- package/dist/scatter-chart/fit.d.ts +15 -0
- package/dist/scatter-chart/fit.js +35 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +21 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
- package/dist/scroll-area/root/scroll-area-root.d.ts +84 -0
- package/dist/scroll-area/root/scroll-area-root.js +106 -7
- package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
- package/dist/scroll-area/scrollbar-controller.js +172 -0
- package/dist/scroll-area/scrollbar.d.ts +92 -0
- package/dist/scroll-area/scrollbar.js +33 -0
- package/dist/select/root/select-root.d.ts +15 -0
- package/dist/select/root/select-root.js +18 -6
- package/dist/skeleton/root/skeleton-root.d.ts +3 -0
- package/dist/skeleton/root/skeleton-root.js +4 -2
- package/dist/skip-link/root/skip-link-root.js +2 -2
- package/dist/slider/root/slider-root.d.ts +41 -4
- package/dist/slider/root/slider-root.js +23 -3
- package/dist/sparkline/readings.d.ts +18 -0
- package/dist/sparkline/readings.js +19 -0
- package/dist/sparkline/root/sparkline-root.d.ts +78 -7
- package/dist/sparkline/root/sparkline-root.js +118 -23
- package/dist/speed-dial/root/speed-dial-root.js +2 -2
- package/dist/splitter/root/splitter-root.d.ts +20 -12
- package/dist/splitter/root/splitter-root.js +226 -203
- package/dist/splitter/snap.d.ts +9 -0
- package/dist/splitter/snap.js +12 -0
- package/dist/stat/root/stat-root.d.ts +14 -5
- package/dist/stat/root/stat-root.js +21 -5
- package/dist/steps/reach.d.ts +20 -0
- package/dist/steps/reach.js +15 -0
- package/dist/steps/root/steps-root.d.ts +76 -0
- package/dist/steps/root/steps-root.js +93 -1
- package/dist/steps/step/step.d.ts +45 -2
- package/dist/steps/step/step.js +33 -6
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +11 -10
- package/dist/table/column/table-column.js +8 -19
- package/dist/table/root/table-root.d.ts +126 -4
- package/dist/table/root/table-root.js +156 -6
- package/dist/table/row/table-row.d.ts +47 -1
- package/dist/table/row/table-row.js +39 -2
- package/dist/tabs/panel/tab-panel.d.ts +22 -5
- package/dist/tabs/panel/tab-panel.js +34 -6
- package/dist/tabs/root/tabs-root.d.ts +37 -1
- package/dist/tabs/root/tabs-root.js +22 -4
- package/dist/tabs/tab/tab.d.ts +41 -4
- package/dist/tabs/tab/tab.js +49 -3
- package/dist/tag/group/tag-group.d.ts +31 -4
- package/dist/tag/group/tag-group.js +46 -7
- package/dist/tag/root/tag-root.js +9 -2
- package/dist/textarea/root/textarea-root.d.ts +28 -1
- package/dist/textarea/root/textarea-root.js +40 -1
- package/dist/time-input/root/time-input-root.d.ts +5 -1
- package/dist/time-input/root/time-input-root.js +16 -8
- package/dist/time-picker/root/time-picker-root.d.ts +18 -4
- package/dist/time-picker/root/time-picker-root.js +7 -10
- package/dist/time-picker/wheel-name.d.ts +9 -0
- package/dist/time-picker/wheel-name.js +15 -0
- package/dist/timeline/group/timeline-group.d.ts +46 -0
- package/dist/timeline/group/timeline-group.js +37 -0
- package/dist/timeline/index.d.ts +1 -0
- package/dist/timeline/index.js +1 -0
- package/dist/timeline/root/timeline-root.d.ts +10 -3
- package/dist/toast/item/toast-item.d.ts +24 -18
- package/dist/toast/item/toast-item.js +36 -40
- package/dist/toast/root/toast-root.d.ts +6 -0
- package/dist/toast/root/toast-root.js +16 -1
- package/dist/toggle/group/toggle-group.d.ts +24 -3
- package/dist/toggle/group/toggle-group.js +34 -5
- package/dist/toolbar/root/toolbar-root.d.ts +13 -0
- package/dist/toolbar/root/toolbar-root.js +15 -5
- package/dist/tooltip/root/tooltip-root.d.ts +13 -2
- package/dist/tooltip/root/tooltip-root.js +9 -1
- package/dist/tour/back.d.ts +10 -0
- package/dist/tour/back.js +8 -0
- package/dist/tour/root/tour-root.d.ts +30 -2
- package/dist/tour/root/tour-root.js +34 -8
- package/dist/tree/item/tree-item.d.ts +61 -4
- package/dist/tree/item/tree-item.js +92 -20
- package/dist/tree/root/tree-root.d.ts +58 -0
- package/dist/tree/root/tree-root.js +80 -16
- package/dist/tree/selection.d.ts +24 -0
- package/dist/tree/selection.js +13 -0
- package/dist/trend/root/trend-root.d.ts +43 -18
- package/dist/trend/root/trend-root.js +31 -6
- package/dist/video/media-events.d.ts +44 -0
- package/dist/video/media-events.js +35 -0
- package/dist/video/root/video-root.d.ts +117 -18
- package/dist/video/root/video-root.js +93 -47
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +5 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +3 -1
- package/dist/video-playlist/order.d.ts +41 -0
- package/dist/video-playlist/order.js +34 -0
- package/dist/video-playlist/root/video-playlist-root.d.ts +77 -3
- package/dist/video-playlist/root/video-playlist-root.js +60 -16
- package/dist/virtual-list/controls.d.ts +4 -0
- package/dist/virtual-list/controls.js +30 -0
- package/dist/virtual-list/fill.d.ts +22 -0
- package/dist/virtual-list/fill.js +23 -0
- package/dist/virtual-list/keys.d.ts +15 -0
- package/dist/virtual-list/keys.js +24 -0
- package/dist/virtual-list/plan.d.ts +49 -0
- package/dist/virtual-list/plan.js +16 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +259 -26
- package/dist/virtual-list/root/virtual-list-root.js +333 -49
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +8113 -1394
- package/types/svelte.d.ts +2 -0
- package/types/vue.d.ts +1678 -353
- package/dist/data-table/root/order.d.ts +0 -141
- package/dist/data-table/root/order.js +0 -76
- package/dist/listbox/range.d.ts +0 -17
- package/dist/listbox/range.js +0 -5
- package/dist/tag/selection.d.ts +0 -10
- package/dist/tag/selection.js +0 -12
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HelixFormElement } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/**
|
|
4
4
|
* @summary A field for writing a turn in a conversation.
|
|
@@ -15,6 +15,16 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
15
15
|
* The composer clears only when no listener cancels the send, so the text is
|
|
16
16
|
* kept when you cancel a send that failed.
|
|
17
17
|
*
|
|
18
|
+
* **In a form, the draft is the composer's value**, submitted under `name`. A
|
|
19
|
+
* form reset puts back the `value` the markup declared, and a `<fieldset
|
|
20
|
+
* disabled>` turns the composer off. Sending is still `helix-send`, and it
|
|
21
|
+
* does not submit the form.
|
|
22
|
+
*
|
|
23
|
+
* **`typing` says whether the user is writing**, and `helix-typing` is sent
|
|
24
|
+
* each time it changes: when they start, and when they send or stop for
|
|
25
|
+
* `typing-timeout` milliseconds. Pass it on to show "is typing" to the other
|
|
26
|
+
* side.
|
|
27
|
+
*
|
|
18
28
|
* @since 0.1.0
|
|
19
29
|
* @status stable
|
|
20
30
|
* @category forms
|
|
@@ -25,6 +35,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
25
35
|
* @slot start - Content under the field at the leading edge, such as an attachment button or a model picker.
|
|
26
36
|
*
|
|
27
37
|
* @event {HelixSendEvent} helix-send - Fired when the user sends their turn, and cancelable.
|
|
38
|
+
* @event {HelixTypingEvent} helix-typing - The user started or stopped writing, with `typing` saying which, as the composer's `typing` does.
|
|
28
39
|
* @event {Event} input - The user changed the text. Read it from `value`, for a typing indicator or a saved draft. Sent on the composer and does not bubble.
|
|
29
40
|
*
|
|
30
41
|
* @csspart composer - The whole composer.
|
|
@@ -35,11 +46,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
35
46
|
* @csspart start - The box around the `start` slot.
|
|
36
47
|
* @csspart tools - The row under the field.
|
|
37
48
|
*/
|
|
38
|
-
export declare class HelixHeadlessChatComposer extends
|
|
39
|
-
/**
|
|
40
|
-
* Whether the composer blocks input, such as while a turn is being sent.
|
|
41
|
-
*/
|
|
42
|
-
disabled: boolean;
|
|
49
|
+
export declare class HelixHeadlessChatComposer extends HelixFormElement {
|
|
43
50
|
/**
|
|
44
51
|
* The field's name, read by screen readers.
|
|
45
52
|
*/
|
|
@@ -67,6 +74,11 @@ export declare class HelixHeadlessChatComposer extends HelixElement {
|
|
|
67
74
|
* has to mean a new line and nothing else.
|
|
68
75
|
*/
|
|
69
76
|
submitOn: 'button' | 'enter';
|
|
77
|
+
/**
|
|
78
|
+
* How long after the last keystroke the user still counts as typing, in
|
|
79
|
+
* milliseconds.
|
|
80
|
+
*/
|
|
81
|
+
typingTimeout: number;
|
|
70
82
|
/**
|
|
71
83
|
* The text the user has written.
|
|
72
84
|
*
|
|
@@ -78,6 +90,17 @@ export declare class HelixHeadlessChatComposer extends HelixElement {
|
|
|
78
90
|
* @internal Read by the transcript to find the composer among its children.
|
|
79
91
|
*/
|
|
80
92
|
readonly isChatComposer = true;
|
|
93
|
+
/** Whether the user is writing, which `helix-typing` announces. */
|
|
94
|
+
private writing;
|
|
95
|
+
/** The pause after which the user has stopped writing. */
|
|
96
|
+
private readonly pause;
|
|
97
|
+
/**
|
|
98
|
+
* Whether the user is writing: true from their first keystroke until they
|
|
99
|
+
* send, clear the field, or pause for `typing-timeout` milliseconds.
|
|
100
|
+
*/
|
|
101
|
+
get typing(): boolean;
|
|
102
|
+
/** Records whether the user is writing, and says so when that changed. */
|
|
103
|
+
private markTyping;
|
|
81
104
|
/**
|
|
82
105
|
* Sends what is written, and returns whether the send went through.
|
|
83
106
|
*
|
|
@@ -86,6 +109,15 @@ export declare class HelixHeadlessChatComposer extends HelixElement {
|
|
|
86
109
|
* a reasonable way to send.
|
|
87
110
|
*/
|
|
88
111
|
send(): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* The value the markup declared, which a form reset and an empty restore go
|
|
114
|
+
* back to. `value` does not reflect, so its attribute stays as written.
|
|
115
|
+
*/
|
|
116
|
+
private get declared();
|
|
117
|
+
/** Puts back the draft the markup declared when the form is reset. */
|
|
118
|
+
formResetCallback(): void;
|
|
119
|
+
/** Brings back the draft when the browser restores the form. */
|
|
120
|
+
formStateRestoreCallback(state: string | File | FormData | null): void;
|
|
89
121
|
/**
|
|
90
122
|
* Says on each tool box whether anything is in it.
|
|
91
123
|
*
|
|
@@ -4,27 +4,30 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement,
|
|
7
|
+
import { customElement, DelayController, HelixFormElement, HelixSendEvent, HelixTypingEvent, hostAria, markRegion, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { arrowElbowDownLeft } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
11
11
|
import { live } from 'lit/directives/live.js';
|
|
12
12
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
13
|
-
let HelixHeadlessChatComposer = class HelixHeadlessChatComposer extends
|
|
13
|
+
let HelixHeadlessChatComposer = class HelixHeadlessChatComposer extends HelixFormElement {
|
|
14
14
|
constructor() {
|
|
15
15
|
super(...arguments);
|
|
16
|
-
this.disabled = false;
|
|
17
16
|
this.label = 'Message';
|
|
18
17
|
this.placeholder = '';
|
|
19
18
|
this.rows = 1;
|
|
20
19
|
this.sendLabel = 'Send';
|
|
21
20
|
this.submitOn = 'enter';
|
|
21
|
+
this.typingTimeout = 3000;
|
|
22
22
|
this.value = '';
|
|
23
23
|
this.isChatComposer = true;
|
|
24
|
+
this.writing = false;
|
|
25
|
+
this.pause = new DelayController(this, { renders: false });
|
|
24
26
|
this.handleInput = (event) => {
|
|
25
27
|
event.stopPropagation();
|
|
26
28
|
this.value = event.target.value;
|
|
27
29
|
this.dispatchEvent(new Event('input'));
|
|
30
|
+
this.markTyping(this.value !== '');
|
|
28
31
|
};
|
|
29
32
|
this.handleSend = () => {
|
|
30
33
|
this.send();
|
|
@@ -40,17 +43,44 @@ let HelixHeadlessChatComposer = class HelixHeadlessChatComposer extends HelixEle
|
|
|
40
43
|
this.send();
|
|
41
44
|
};
|
|
42
45
|
}
|
|
46
|
+
get typing() {
|
|
47
|
+
return this.writing;
|
|
48
|
+
}
|
|
49
|
+
markTyping(typing) {
|
|
50
|
+
if (typing) {
|
|
51
|
+
this.pause.start(Math.max(0, this.typingTimeout), () => this.markTyping(false));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
this.pause.cancel();
|
|
55
|
+
}
|
|
56
|
+
if (typing === this.writing) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.writing = typing;
|
|
60
|
+
this.dispatchEvent(new HelixTypingEvent({ typing }));
|
|
61
|
+
}
|
|
43
62
|
send() {
|
|
44
63
|
const value = this.value.trim();
|
|
45
|
-
if (value === '' || this.
|
|
64
|
+
if (value === '' || this.isDisabled) {
|
|
46
65
|
return false;
|
|
47
66
|
}
|
|
48
67
|
if (!this.dispatchEvent(new HelixSendEvent({ value }))) {
|
|
49
68
|
return false;
|
|
50
69
|
}
|
|
51
70
|
this.value = '';
|
|
71
|
+
this.markTyping(false);
|
|
52
72
|
return true;
|
|
53
73
|
}
|
|
74
|
+
get declared() {
|
|
75
|
+
return this.getAttribute('value') ?? '';
|
|
76
|
+
}
|
|
77
|
+
formResetCallback() {
|
|
78
|
+
super.formResetCallback();
|
|
79
|
+
this.value = this.declared;
|
|
80
|
+
}
|
|
81
|
+
formStateRestoreCallback(state) {
|
|
82
|
+
this.value = typeof state === 'string' ? state : this.declared;
|
|
83
|
+
}
|
|
54
84
|
markEmpty() {
|
|
55
85
|
for (const name of ['start', 'end']) {
|
|
56
86
|
markRegion(this.renderRoot, name, [name]);
|
|
@@ -59,6 +89,9 @@ let HelixHeadlessChatComposer = class HelixHeadlessChatComposer extends HelixEle
|
|
|
59
89
|
updated(changed) {
|
|
60
90
|
super.updated(changed);
|
|
61
91
|
this.markEmpty();
|
|
92
|
+
if (changed.has('value')) {
|
|
93
|
+
this.internals.setFormValue(this.value === '' ? null : this.value);
|
|
94
|
+
}
|
|
62
95
|
}
|
|
63
96
|
willUpdate(changed) {
|
|
64
97
|
super.willUpdate(changed);
|
|
@@ -69,7 +102,7 @@ let HelixHeadlessChatComposer = class HelixHeadlessChatComposer extends HelixEle
|
|
|
69
102
|
part="send"
|
|
70
103
|
type="button"
|
|
71
104
|
aria-label=${this.sendLabel}
|
|
72
|
-
?disabled=${this.
|
|
105
|
+
?disabled=${this.isDisabled}
|
|
73
106
|
@click=${this.handleSend}
|
|
74
107
|
>
|
|
75
108
|
<svg
|
|
@@ -90,7 +123,7 @@ let HelixHeadlessChatComposer = class HelixHeadlessChatComposer extends HelixEle
|
|
|
90
123
|
aria-label=${this.label}
|
|
91
124
|
placeholder=${this.placeholder}
|
|
92
125
|
rows=${this.rows}
|
|
93
|
-
?disabled=${this.
|
|
126
|
+
?disabled=${this.isDisabled}
|
|
94
127
|
@input=${this.handleInput}
|
|
95
128
|
@keydown=${this.handleKey}
|
|
96
129
|
></textarea>
|
|
@@ -102,9 +135,6 @@ let HelixHeadlessChatComposer = class HelixHeadlessChatComposer extends HelixEle
|
|
|
102
135
|
</div>`;
|
|
103
136
|
}
|
|
104
137
|
};
|
|
105
|
-
__decorate([
|
|
106
|
-
property({ reflect: true, type: Boolean })
|
|
107
|
-
], HelixHeadlessChatComposer.prototype, "disabled", void 0);
|
|
108
138
|
__decorate([
|
|
109
139
|
property()
|
|
110
140
|
], HelixHeadlessChatComposer.prototype, "label", void 0);
|
|
@@ -120,6 +150,9 @@ __decorate([
|
|
|
120
150
|
__decorate([
|
|
121
151
|
property({ attribute: 'submit-on' })
|
|
122
152
|
], HelixHeadlessChatComposer.prototype, "submitOn", void 0);
|
|
153
|
+
__decorate([
|
|
154
|
+
property({ attribute: 'typing-timeout', type: Number })
|
|
155
|
+
], HelixHeadlessChatComposer.prototype, "typingTimeout", void 0);
|
|
123
156
|
__decorate([
|
|
124
157
|
property()
|
|
125
158
|
], HelixHeadlessChatComposer.prototype, "value", void 0);
|
|
@@ -19,6 +19,13 @@ export declare const FAILED_LABEL = "Not sent";
|
|
|
19
19
|
* and announced once when it settles. A screen reader cannot follow a stream
|
|
20
20
|
* read out character by character.
|
|
21
21
|
*
|
|
22
|
+
* A screen reader names the turn by its author and its time, such as "You, 2
|
|
23
|
+
* minutes ago". The author is `author-label`, or "You" for `me`, or the
|
|
24
|
+
* `author` itself where it is a name; give a turn by `them` an `author-label`
|
|
25
|
+
* to name it. The chat it sits in holds the sentence and the word for `me`, so
|
|
26
|
+
* a page in another language sets them once there. The time moves on by
|
|
27
|
+
* itself, so "now" becomes "1 minute ago" while the page is open.
|
|
28
|
+
*
|
|
22
29
|
* @since 0.1.0
|
|
23
30
|
* @status stable
|
|
24
31
|
* @category feedback
|
|
@@ -62,6 +69,14 @@ export declare class HelixHeadlessChatMessage extends HelixElement {
|
|
|
62
69
|
* anything else is a name the consumer styles.
|
|
63
70
|
*/
|
|
64
71
|
author?: string;
|
|
72
|
+
/**
|
|
73
|
+
* The author's name, as a screen reader says it at the start of the turn,
|
|
74
|
+
* such as "Support" or "Ada Lovelace".
|
|
75
|
+
*
|
|
76
|
+
* Empty reads "You" for `me`, the `author` itself where it is a name, and
|
|
77
|
+
* nothing for `them`.
|
|
78
|
+
*/
|
|
79
|
+
authorLabel: string;
|
|
65
80
|
/**
|
|
66
81
|
* Label for a message that did not send.
|
|
67
82
|
*/
|
|
@@ -93,15 +108,31 @@ export declare class HelixHeadlessChatMessage extends HelixElement {
|
|
|
93
108
|
* holds the reason. Everything else that moves it is the consumer's.
|
|
94
109
|
*/
|
|
95
110
|
state?: 'failed' | 'sending' | 'sent' | 'streaming';
|
|
111
|
+
/**
|
|
112
|
+
* @internal Set by the chat: the word for `me` and the sentence that names a
|
|
113
|
+
* turn with both an author and a time, in the chat's language.
|
|
114
|
+
*/
|
|
115
|
+
turnWords: import("../naming.js").TurnWords;
|
|
96
116
|
/**
|
|
97
117
|
* @internal Read by the transcript to identify its children across the light
|
|
98
118
|
* DOM, which is cheaper than `instanceof`. Not a consumer's to read or set.
|
|
99
119
|
*/
|
|
100
120
|
readonly isChatMessage = true;
|
|
101
|
-
|
|
121
|
+
/** The time the reading is drawn against, moved on when the words go stale. */
|
|
122
|
+
private readonly clock;
|
|
102
123
|
/** The timestamp, or nothing where there is not one to read. */
|
|
103
124
|
private get moment();
|
|
104
125
|
protected willUpdate(changed: PropertyValues): void;
|
|
126
|
+
/** The time as it reads now, or nothing where the turn has none. */
|
|
127
|
+
private get reading();
|
|
128
|
+
/**
|
|
129
|
+
* What a screen reader calls the turn: who wrote it, and when.
|
|
130
|
+
*
|
|
131
|
+
* **The name of an `article` is never its content**, so without one a reader
|
|
132
|
+
* moving through a transcript heard "article" for every turn and had to read
|
|
133
|
+
* each to learn who wrote it.
|
|
134
|
+
*/
|
|
135
|
+
private get name();
|
|
105
136
|
private renderTime;
|
|
106
137
|
/**
|
|
107
138
|
* The status glyph, behind a seam so a tier can draw its own.
|
|
@@ -4,21 +4,29 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, HelixElement, HelixSendEvent, hostAria, markRegion, relativeTime, requestChange, TONE_MARKS, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, HelixElement, HelixSendEvent, hostAria, markRegion, RelativeClockController, relativeTime, requestChange, TONE_MARKS, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
|
-
import { property
|
|
9
|
+
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
11
|
+
import { authorWords, TURN_WORDS, turnName } from '../naming.js';
|
|
11
12
|
export const FAILED_LABEL = 'Not sent';
|
|
12
13
|
let HelixHeadlessChatMessage = class HelixHeadlessChatMessage extends HelixElement {
|
|
13
14
|
constructor() {
|
|
14
15
|
super(...arguments);
|
|
15
16
|
this.at = '';
|
|
17
|
+
this.authorLabel = '';
|
|
16
18
|
this.failedLabel = FAILED_LABEL;
|
|
17
19
|
this.locale = '';
|
|
18
20
|
this.retryLabel = 'Try again';
|
|
19
21
|
this.sendingLabel = 'Sending';
|
|
22
|
+
this.turnWords = TURN_WORDS;
|
|
20
23
|
this.isChatMessage = true;
|
|
21
|
-
this.clock =
|
|
24
|
+
this.clock = new RelativeClockController(this, {
|
|
25
|
+
expires: (now) => {
|
|
26
|
+
const moment = this.moment;
|
|
27
|
+
return moment ? relativeTime(this.locale)(moment, now).next : undefined;
|
|
28
|
+
},
|
|
29
|
+
});
|
|
22
30
|
this.handleFill = () => {
|
|
23
31
|
this.markEmpty();
|
|
24
32
|
};
|
|
@@ -50,19 +58,25 @@ let HelixHeadlessChatMessage = class HelixHeadlessChatMessage extends HelixEleme
|
|
|
50
58
|
}
|
|
51
59
|
willUpdate(changed) {
|
|
52
60
|
super.willUpdate(changed);
|
|
53
|
-
if (changed.has('at')) {
|
|
54
|
-
this.clock
|
|
61
|
+
if (changed.has('at') || changed.has('locale')) {
|
|
62
|
+
this.clock.tick();
|
|
55
63
|
}
|
|
56
|
-
hostAria(this.internals, { role: 'article' });
|
|
64
|
+
hostAria(this.internals, { label: this.name, role: 'article' });
|
|
57
65
|
this.internals.ariaBusy = this.state === 'streaming' ? 'true' : null;
|
|
58
66
|
}
|
|
67
|
+
get reading() {
|
|
68
|
+
const moment = this.moment;
|
|
69
|
+
return moment ? relativeTime(this.locale)(moment, new Date(this.clock.now)).text : '';
|
|
70
|
+
}
|
|
71
|
+
get name() {
|
|
72
|
+
return turnName(authorWords(this.author, this.authorLabel, this.turnWords), this.reading, this.turnWords);
|
|
73
|
+
}
|
|
59
74
|
renderTime() {
|
|
60
75
|
const moment = this.moment;
|
|
61
76
|
if (!moment) {
|
|
62
77
|
return nothing;
|
|
63
78
|
}
|
|
64
|
-
|
|
65
|
-
return html `<time part="time" datetime=${moment.toISOString()}>${text}</time>`;
|
|
79
|
+
return html `<time part="time" datetime=${moment.toISOString()}>${this.reading}</time>`;
|
|
66
80
|
}
|
|
67
81
|
renderMark() {
|
|
68
82
|
const { icon, label } = TONE_MARKS.danger;
|
|
@@ -124,6 +138,9 @@ __decorate([
|
|
|
124
138
|
__decorate([
|
|
125
139
|
property({ reflect: true })
|
|
126
140
|
], HelixHeadlessChatMessage.prototype, "author", void 0);
|
|
141
|
+
__decorate([
|
|
142
|
+
property({ attribute: 'author-label' })
|
|
143
|
+
], HelixHeadlessChatMessage.prototype, "authorLabel", void 0);
|
|
127
144
|
__decorate([
|
|
128
145
|
property({ attribute: 'failed-label' })
|
|
129
146
|
], HelixHeadlessChatMessage.prototype, "failedLabel", void 0);
|
|
@@ -140,8 +157,8 @@ __decorate([
|
|
|
140
157
|
property({ reflect: true })
|
|
141
158
|
], HelixHeadlessChatMessage.prototype, "state", void 0);
|
|
142
159
|
__decorate([
|
|
143
|
-
|
|
144
|
-
], HelixHeadlessChatMessage.prototype, "
|
|
160
|
+
property({ attribute: false })
|
|
161
|
+
], HelixHeadlessChatMessage.prototype, "turnWords", void 0);
|
|
145
162
|
HelixHeadlessChatMessage = __decorate([
|
|
146
163
|
customElement('helix-headless-chat-message')
|
|
147
164
|
], HelixHeadlessChatMessage);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** What the chat names its turns with, which it hands to each of them. */
|
|
2
|
+
export interface TurnWords {
|
|
3
|
+
/** The word for `me`, such as "You". */
|
|
4
|
+
me: string;
|
|
5
|
+
/** The sentence for a turn with an author and a time, with `{author}` and `{time}`. */
|
|
6
|
+
sentence: string;
|
|
7
|
+
/** The name of a turn with neither an author a reader can be told nor a time. */
|
|
8
|
+
turn: string;
|
|
9
|
+
}
|
|
10
|
+
/** The words a chat says its turns with, where nobody said otherwise. */
|
|
11
|
+
export declare const TURN_WORDS: TurnWords;
|
|
12
|
+
/**
|
|
13
|
+
* Who wrote a turn, in words: its `author-label`, or else the chat's word for
|
|
14
|
+
* `me`, or else the `author` itself where it is a name.
|
|
15
|
+
*
|
|
16
|
+
* `them` is the other side of a two-sided conversation and not a name, so it
|
|
17
|
+
* says nothing until it is given an `author-label`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const authorWords: (author: string | undefined, authorLabel: string, words: TurnWords) => string;
|
|
20
|
+
/**
|
|
21
|
+
* The turn's accessible name: the sentence where it has an author and a time,
|
|
22
|
+
* and whichever of the two it has otherwise. Where it has neither, a turn by
|
|
23
|
+
* `them` with no `author-label` and no time, the chat's word for a turn, so
|
|
24
|
+
* no turn is an `article` with no name.
|
|
25
|
+
*/
|
|
26
|
+
export declare const turnName: (author: string, time: string, words: TurnWords) => string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { fillTemplate } from '@fusion.dev/helix-core';
|
|
2
|
+
export const TURN_WORDS = { me: 'You', sentence: '{author}, {time}', turn: 'Message' };
|
|
3
|
+
export const authorWords = (author, authorLabel, words) => {
|
|
4
|
+
if (authorLabel !== '') {
|
|
5
|
+
return authorLabel;
|
|
6
|
+
}
|
|
7
|
+
if (author === 'me') {
|
|
8
|
+
return words.me;
|
|
9
|
+
}
|
|
10
|
+
return author === undefined || author === 'them' ? '' : author;
|
|
11
|
+
};
|
|
12
|
+
export const turnName = (author, time, words) => author !== '' && time !== ''
|
|
13
|
+
? fillTemplate(words.sentence, { author, time })
|
|
14
|
+
: author || time || words.turn;
|
|
@@ -7,6 +7,8 @@ export interface ChatTurn {
|
|
|
7
7
|
at?: string;
|
|
8
8
|
/** Who said it: `me`, `them`, or a name the consumer styles. */
|
|
9
9
|
author?: string;
|
|
10
|
+
/** Who said it, as a screen reader names the turn, as on `ChatMessage`. */
|
|
11
|
+
authorLabel?: string;
|
|
10
12
|
/**
|
|
11
13
|
* What identifies it across changes to the set.
|
|
12
14
|
*
|
|
@@ -44,6 +46,23 @@ declare const HelixHeadlessChat_base: (new (...args: any[]) => import("@fusion.d
|
|
|
44
46
|
* render from the server and suit most conversations. `turns` draws a long
|
|
45
47
|
* transcript one window at a time, so the log needs a block size of its own.
|
|
46
48
|
*
|
|
49
|
+
* **A conversation is built from three elements.** The chat holds the
|
|
50
|
+
* transcript, a `Chat.Message` stands for each turn, and a `Chat.Composer` sits
|
|
51
|
+
* in the `composer` slot. When the user sends, `helix-send` reaches the chat:
|
|
52
|
+
* add their turn with `author="me"` and `state="sending"`, then set `state` to
|
|
53
|
+
* `sent` or `failed` when your server answers. Add the reply as a turn with
|
|
54
|
+
* `state="streaming"`, write its text as it arrives, and set `state` to `sent`
|
|
55
|
+
* when it is complete. While the user types, the composer sends
|
|
56
|
+
* `helix-typing`, which you can pass on to the other side. When the other side
|
|
57
|
+
* types, set `typing` to their name: the status band draws three dots and
|
|
58
|
+
* "Ada is typing" (`typing-label`), which a screen reader hears, and clearing
|
|
59
|
+
* it takes them away. Anything slotted into `status` is drawn first.
|
|
60
|
+
*
|
|
61
|
+
* A screen reader names each turn by its author and its time, such as "You, 2
|
|
62
|
+
* minutes ago". Set `me-label` and `message-label` to say it in your language,
|
|
63
|
+
* and give each turn by `them` an `author-label`. A turn with neither an author
|
|
64
|
+
* label nor a time is named by `turn-label`, "Message".
|
|
65
|
+
*
|
|
47
66
|
* A turn from `turns` is drawn in the chat's shadow root, so style it through
|
|
48
67
|
* the forwarded `message-*` parts. A turn by `me` also gets each part with
|
|
49
68
|
* `-mine` added, and the turn's state adds `message-meta-failed`,
|
|
@@ -75,6 +94,7 @@ declare const HelixHeadlessChat_base: (new (...args: any[]) => import("@fusion.d
|
|
|
75
94
|
* @csspart empty - Shown when the conversation has no turns.
|
|
76
95
|
* @csspart header - The region above the transcript.
|
|
77
96
|
* @csspart history - Shown at the top of the transcript while older turns load.
|
|
97
|
+
* @csspart indicator - The three dots before the words that say who is typing, which the styled tier animates as a message's are. Hidden from screen readers.
|
|
78
98
|
* @csspart live - The region where screen readers announce each turn once it has arrived.
|
|
79
99
|
* @csspart loading - Shown while the history loads.
|
|
80
100
|
* @csspart log - The transcript, which scrolls.
|
|
@@ -101,6 +121,7 @@ declare const HelixHeadlessChat_base: (new (...args: any[]) => import("@fusion.d
|
|
|
101
121
|
* @csspart resume - The control shown while the user is scrolled away from the bottom.
|
|
102
122
|
* @csspart status - The status region, outside the log.
|
|
103
123
|
* @csspart turn - The wrapper around the message drawn for one turn from `turns`.
|
|
124
|
+
* @csspart typing - The words that say who is typing, in the status band, while `typing` names someone.
|
|
104
125
|
*/
|
|
105
126
|
export declare class HelixHeadlessChat extends HelixHeadlessChat_base {
|
|
106
127
|
/**
|
|
@@ -141,6 +162,16 @@ export declare class HelixHeadlessChat extends HelixHeadlessChat_base {
|
|
|
141
162
|
* The conversation's name, read by screen readers.
|
|
142
163
|
*/
|
|
143
164
|
label: string;
|
|
165
|
+
/**
|
|
166
|
+
* The word a screen reader says for `me` when it names a turn.
|
|
167
|
+
*/
|
|
168
|
+
meLabel: string;
|
|
169
|
+
/**
|
|
170
|
+
* The name a screen reader gives a turn with both an author and a time.
|
|
171
|
+
* `{author}` is who wrote it and `{time}` is when, as the turn shows it. A
|
|
172
|
+
* turn with only one of the two is named by that one.
|
|
173
|
+
*/
|
|
174
|
+
messageLabel: string;
|
|
144
175
|
/**
|
|
145
176
|
* Whether the transcript follows new turns to the bottom.
|
|
146
177
|
*
|
|
@@ -171,6 +202,11 @@ export declare class HelixHeadlessChat extends HelixHeadlessChat_base {
|
|
|
171
202
|
* history.
|
|
172
203
|
*/
|
|
173
204
|
threshold: number;
|
|
205
|
+
/**
|
|
206
|
+
* The name a screen reader gives a turn with neither an author it can say
|
|
207
|
+
* nor a time: a turn by `them` with no `author-label`, say.
|
|
208
|
+
*/
|
|
209
|
+
turnLabel: string;
|
|
174
210
|
/**
|
|
175
211
|
* The turns as data, for a transcript too long to hold as elements.
|
|
176
212
|
*
|
|
@@ -182,10 +218,27 @@ export declare class HelixHeadlessChat extends HelixHeadlessChat_base {
|
|
|
182
218
|
* element to look again.
|
|
183
219
|
*/
|
|
184
220
|
turns: readonly ChatTurn[];
|
|
221
|
+
/**
|
|
222
|
+
* Who on the other side is typing, by name, or empty while nobody is.
|
|
223
|
+
*
|
|
224
|
+
* Set it from your connection, and clear it when they stop or send. The
|
|
225
|
+
* status band says it with `typing-label`.
|
|
226
|
+
*/
|
|
227
|
+
typing: string;
|
|
228
|
+
/**
|
|
229
|
+
* What the status band says while someone is typing. `{author}` is the
|
|
230
|
+
* name in `typing`.
|
|
231
|
+
*/
|
|
232
|
+
typingLabel: string;
|
|
185
233
|
private pinnedState;
|
|
186
234
|
/** The last thing said, and how many times something has been. */
|
|
187
235
|
private announcement;
|
|
188
236
|
private said;
|
|
237
|
+
/**
|
|
238
|
+
* The words every turn is named with, kept as one object between changes so
|
|
239
|
+
* a turn is told again only when they change.
|
|
240
|
+
*/
|
|
241
|
+
private words;
|
|
189
242
|
/** Watches for turns arriving, since a manual slot hears nothing about them. */
|
|
190
243
|
private watcher;
|
|
191
244
|
/** Watches the turns' own `state`, which is when one of them settles. */
|
|
@@ -353,6 +406,11 @@ export declare class HelixHeadlessChat extends HelixHeadlessChat_base {
|
|
|
353
406
|
*/
|
|
354
407
|
private follow;
|
|
355
408
|
protected updated(changed: PropertyValues): void;
|
|
409
|
+
/**
|
|
410
|
+
* Hands each turn written as a child the words it is named with, once it
|
|
411
|
+
* has hydrated, so its first render is the server's.
|
|
412
|
+
*/
|
|
413
|
+
private tellTurns;
|
|
356
414
|
private readonly handleSlotChange;
|
|
357
415
|
private readonly handleSettle;
|
|
358
416
|
/**
|
|
@@ -5,13 +5,14 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
var HelixHeadlessChat_1;
|
|
8
|
-
import { customElement, HelixBeforePinEvent, HelixElement, HelixHistoryEvent, HelixPinEvent, hostAria, MixinCollection, onUnlessFalse, requestChange, VirtualizeController, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { customElement, fillTemplate, HelixBeforePinEvent, HelixElement, HelixHistoryEvent, HelixPinEvent, hostAria, MixinCollection, onUnlessFalse, requestChange, VirtualizeController, whenHydrated, } from '@fusion.dev/helix-core';
|
|
9
9
|
import { nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { keyed } from 'lit/directives/keyed.js';
|
|
12
12
|
import { repeat } from 'lit/directives/repeat.js';
|
|
13
13
|
import { html } from 'lit/static-html.js';
|
|
14
14
|
import { FAILED_LABEL } from '../message/chat-message.js';
|
|
15
|
+
import { TURN_WORDS } from '../naming.js';
|
|
15
16
|
const REGIONS = ['header', 'actions', 'resume', 'status', 'composer'];
|
|
16
17
|
const SECOND_NAMES = {
|
|
17
18
|
author: {
|
|
@@ -39,11 +40,17 @@ let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixEle
|
|
|
39
40
|
this.history = '';
|
|
40
41
|
this.historyText = 'Loading earlier messages';
|
|
41
42
|
this.label = '';
|
|
43
|
+
this.meLabel = 'You';
|
|
44
|
+
this.messageLabel = '{author}, {time}';
|
|
42
45
|
this.threshold = 48;
|
|
46
|
+
this.turnLabel = 'Message';
|
|
43
47
|
this.turns = [];
|
|
48
|
+
this.typing = '';
|
|
49
|
+
this.typingLabel = '{author} is typing';
|
|
44
50
|
this.pinnedState = undefined;
|
|
45
51
|
this.announcement = '';
|
|
46
52
|
this.said = 0;
|
|
53
|
+
this.words = TURN_WORDS;
|
|
47
54
|
this.watcher = undefined;
|
|
48
55
|
this.settling = undefined;
|
|
49
56
|
this.grower = undefined;
|
|
@@ -361,6 +368,9 @@ let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixEle
|
|
|
361
368
|
willUpdate(changed) {
|
|
362
369
|
super.willUpdate(changed);
|
|
363
370
|
hostAria(this.internals, { label: this.label || 'Conversation', role: 'region' });
|
|
371
|
+
if (changed.has('meLabel') || changed.has('messageLabel') || changed.has('turnLabel')) {
|
|
372
|
+
this.words = { me: this.meLabel, sentence: this.messageLabel, turn: this.turnLabel };
|
|
373
|
+
}
|
|
364
374
|
this.countRegions();
|
|
365
375
|
if (changed.has('history')) {
|
|
366
376
|
this.asked = false;
|
|
@@ -389,6 +399,7 @@ let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixEle
|
|
|
389
399
|
updated(changed) {
|
|
390
400
|
super.updated(changed);
|
|
391
401
|
this.assign();
|
|
402
|
+
this.tellTurns();
|
|
392
403
|
if (this.pinned) {
|
|
393
404
|
this.stick();
|
|
394
405
|
}
|
|
@@ -403,6 +414,13 @@ let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixEle
|
|
|
403
414
|
this.reachHistory();
|
|
404
415
|
this.announce();
|
|
405
416
|
}
|
|
417
|
+
tellTurns() {
|
|
418
|
+
for (const message of this.messages) {
|
|
419
|
+
whenHydrated(message, () => {
|
|
420
|
+
message.turnWords = this.words;
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
}
|
|
406
424
|
renderTurns() {
|
|
407
425
|
const { after, before, first, last } = this.virtualize.window;
|
|
408
426
|
const message = this.tag('chat-message');
|
|
@@ -414,7 +432,9 @@ let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixEle
|
|
|
414
432
|
meta: message-meta, retry: message-retry, sources: message-sources,
|
|
415
433
|
state: message-state, time: message-time${secondNames(SECOND_NAMES.author, turn.author)}${secondNames(SECOND_NAMES.state, turn.state)}"
|
|
416
434
|
author=${turn.author ?? nothing}
|
|
435
|
+
author-label=${turn.authorLabel ?? nothing}
|
|
417
436
|
at=${turn.at ?? nothing}
|
|
437
|
+
.turnWords=${this.words}
|
|
418
438
|
state=${turn.state ?? nothing}
|
|
419
439
|
>${turn.text}</${message}>
|
|
420
440
|
</div>`)}
|
|
@@ -449,8 +469,13 @@ let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixEle
|
|
|
449
469
|
<div part="resume" ?hidden=${!away || !this.has('resume')} @click=${this.handleResume}>
|
|
450
470
|
<slot name="resume"></slot>
|
|
451
471
|
</div>
|
|
452
|
-
<div part="status" role="status" ?data-empty=${!this.has('status')}>
|
|
453
|
-
<slot name="status"></slot
|
|
472
|
+
<div part="status" role="status" ?data-empty=${!this.has('status') && this.typing === ''}>
|
|
473
|
+
<slot name="status"></slot>${this.typing === ''
|
|
474
|
+
? nothing
|
|
475
|
+
: html `<span part="typing"
|
|
476
|
+
><span part="indicator" aria-hidden="true"></span
|
|
477
|
+
>${fillTemplate(this.typingLabel, { author: this.typing })}</span
|
|
478
|
+
>`}
|
|
454
479
|
</div>
|
|
455
480
|
<div part="composer" ?hidden=${!this.has('composer')}>
|
|
456
481
|
<slot name="composer"></slot>
|
|
@@ -469,15 +494,30 @@ __decorate([
|
|
|
469
494
|
__decorate([
|
|
470
495
|
property()
|
|
471
496
|
], HelixHeadlessChat.prototype, "label", void 0);
|
|
497
|
+
__decorate([
|
|
498
|
+
property({ attribute: 'me-label' })
|
|
499
|
+
], HelixHeadlessChat.prototype, "meLabel", void 0);
|
|
500
|
+
__decorate([
|
|
501
|
+
property({ attribute: 'message-label' })
|
|
502
|
+
], HelixHeadlessChat.prototype, "messageLabel", void 0);
|
|
472
503
|
__decorate([
|
|
473
504
|
property({ type: Boolean })
|
|
474
505
|
], HelixHeadlessChat.prototype, "pinned", null);
|
|
475
506
|
__decorate([
|
|
476
507
|
property({ type: Number })
|
|
477
508
|
], HelixHeadlessChat.prototype, "threshold", void 0);
|
|
509
|
+
__decorate([
|
|
510
|
+
property({ attribute: 'turn-label' })
|
|
511
|
+
], HelixHeadlessChat.prototype, "turnLabel", void 0);
|
|
478
512
|
__decorate([
|
|
479
513
|
property({ attribute: false })
|
|
480
514
|
], HelixHeadlessChat.prototype, "turns", void 0);
|
|
515
|
+
__decorate([
|
|
516
|
+
property()
|
|
517
|
+
], HelixHeadlessChat.prototype, "typing", void 0);
|
|
518
|
+
__decorate([
|
|
519
|
+
property({ attribute: 'typing-label' })
|
|
520
|
+
], HelixHeadlessChat.prototype, "typingLabel", void 0);
|
|
481
521
|
__decorate([
|
|
482
522
|
state()
|
|
483
523
|
], HelixHeadlessChat.prototype, "pinnedState", void 0);
|