rift-ds 1.9.0 → 1.10.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/README.md +3 -3
- package/bin/templates/chat/app/api/chat/route.ts +3 -0
- package/chat/AssistantTurn.js +5 -2
- package/chat/ChatWidget.css +5 -4
- package/chat/ChatWidget.d.ts +10 -1
- package/chat/ChatWidget.js +17 -4
- package/chat/DemoWelcome.js +17 -5
- package/chat/FollowupSuggestions.d.ts +7 -4
- package/chat/FollowupSuggestions.js +5 -3
- package/chat/TurnQuestion.d.ts +19 -0
- package/chat/TurnQuestion.js +38 -0
- package/chat/demo-script.js +256 -50
- package/chat/followups.d.ts +2 -2
- package/chat/followups.js +1 -0
- package/chat/index.d.ts +2 -1
- package/chat/index.js +11 -0
- package/chat/queries.d.ts +2 -2
- package/chat/queries.js +3 -2
- package/chat/questions.d.ts +97 -0
- package/chat/questions.js +140 -0
- package/chat/registry.json.d.ts +3 -2
- package/chat/registry.json.js +1 -1
- package/chat/server.d.ts +19 -0
- package/chat/server.js +45 -1
- package/chat/sim.d.ts +12 -1
- package/chat/sim.js +19 -3
- package/chat/types.d.ts +58 -1
- package/chat/types.js +1 -0
- package/chat/useChat.d.ts +16 -1
- package/chat/useChat.js +39 -2
- package/components/AlertDialog/AlertDialog.css +1 -1
- package/components/AnchorNav/AnchorNav.css +1 -1
- package/components/AppSidebar/AppSidebar.css +5 -5
- package/components/AppSidebar/AppSidebar.js +3 -2
- package/components/Attachment/Attachment.css +3 -1
- package/components/BottomNav/BottomNav.css +1 -1
- package/components/Chart/Chart.css +1 -0
- package/components/ChatThread/ChatThread.css +21 -0
- package/components/ChatThread/ChatThread.d.ts +12 -1
- package/components/ChatThread/ChatThread.js +40 -1
- package/components/ColorPicker/ColorPicker.css +1 -1
- package/components/Combobox/Combobox.css +1 -1
- package/components/CommandPalette/CommandPalette.css +1 -1
- package/components/Composer/Composer.css +1 -1
- package/components/ContextMenu/ContextMenu.css +1 -1
- package/components/Dialog/Dialog.css +1 -1
- package/components/Drawer/Drawer.css +1 -1
- package/components/Dropdown/Dropdown.css +1 -1
- package/components/DropdownMenu/DropdownMenu.css +1 -1
- package/components/FilterBar/FilterBar.css +1 -1
- package/components/HoverCard/HoverCard.css +1 -1
- package/components/Lightbox/Lightbox.css +1 -1
- package/components/ModelPicker/ModelPicker.css +1 -1
- package/components/Popover/Popover.css +1 -1
- package/components/PromptSuggestions/PromptSuggestions.css +67 -0
- package/components/PromptSuggestions/PromptSuggestions.d.ts +8 -0
- package/components/PromptSuggestions/PromptSuggestions.js +34 -26
- package/components/QuestionCard/QuestionCard.css +358 -0
- package/components/QuestionCard/QuestionCard.d.ts +136 -0
- package/components/QuestionCard/QuestionCard.js +371 -0
- package/components/RichDropdown/RichDropdown.css +1 -1
- package/components/SourceChip/SourceChip.css +1 -1
- package/components/TimePicker/TimePicker.css +1 -1
- package/components/Toast/Toast.css +1 -1
- package/components/Tooltip/Tooltip.css +1 -1
- package/components/TopAppBar/TopAppBar.css +1 -1
- package/components/registry.json +8 -0
- package/components/registry.json.d.ts +8 -0
- package/components/registry.json.js +1 -1
- package/index.d.ts +1 -0
- package/index.js +3 -0
- package/package.json +5 -1
- package/tokens/breakpoints.d.ts +60 -0
- package/tokens/breakpoints.js +92 -0
- package/tokens/registry.d.ts +1 -1
- package/tokens/registry.json +14 -0
- package/tokens/registry.json.d.ts +14 -0
- package/tokens/registry.json.js +1 -1
- package/tokens/tokens-light.css +22 -0
|
@@ -4,6 +4,7 @@ import React, { useState, useRef, useEffect, useCallback, useId } from "react";
|
|
|
4
4
|
import { useLayer } from "../../behaviors/useLayer.js";
|
|
5
5
|
import { useFocusScope } from "../../behaviors/useFocusScope.js";
|
|
6
6
|
import { useScrollLock } from "../../behaviors/useScrollLock.js";
|
|
7
|
+
import { mediaAbove, mediaBelow, BREAKPOINT_TABLET_PX, BREAKPOINT_MOBILE_PX } from "../../tokens/breakpoints.js";
|
|
7
8
|
import { Avatar } from "../Avatar/Avatar.js";
|
|
8
9
|
import { PixelAvatar } from "../PixelAvatar/PixelAvatar.js";
|
|
9
10
|
import { SidebarPanel } from "../SidebarPanel/SidebarPanel.js";
|
|
@@ -71,7 +72,7 @@ const AppSidebar = ({
|
|
|
71
72
|
onExpandedChange?.(next);
|
|
72
73
|
}, [isExpanded, onExpandedChange]);
|
|
73
74
|
useEffect(() => {
|
|
74
|
-
const band = window.matchMedia(
|
|
75
|
+
const band = window.matchMedia(`${mediaAbove(BREAKPOINT_MOBILE_PX)} and ${mediaBelow(BREAKPOINT_TABLET_PX)}`);
|
|
75
76
|
const onChange = () => {
|
|
76
77
|
if (band.matches) {
|
|
77
78
|
setInternalExpanded(false);
|
|
@@ -91,7 +92,7 @@ const AppSidebar = ({
|
|
|
91
92
|
useScrollLock(mobileOpen);
|
|
92
93
|
useEffect(() => {
|
|
93
94
|
if (!mobileOpen) return;
|
|
94
|
-
const query = window.matchMedia(
|
|
95
|
+
const query = window.matchMedia(mediaAbove(BREAKPOINT_MOBILE_PX));
|
|
95
96
|
const onChange = () => {
|
|
96
97
|
if (query.matches) setMobileOpen(false);
|
|
97
98
|
};
|
|
@@ -703,7 +703,7 @@ button.ds-attachment-group__single:focus-visible {
|
|
|
703
703
|
.ds-attachment-viewer {
|
|
704
704
|
position: fixed;
|
|
705
705
|
inset: 0;
|
|
706
|
-
z-index:
|
|
706
|
+
z-index: var(--layer-modal);
|
|
707
707
|
display: flex;
|
|
708
708
|
align-items: center;
|
|
709
709
|
justify-content: center;
|
|
@@ -934,6 +934,7 @@ button.ds-attachment-group__single:focus-visible {
|
|
|
934
934
|
Below 30rem there is no room for a floating dialog and its margin, so
|
|
935
935
|
the panel takes the whole viewport. */
|
|
936
936
|
|
|
937
|
+
/* ds-allow(breakpoint): a rem query, so a reader with a larger default font gets the full-screen sheet sooner; it is the sheet step (480px) at the default size, and rewriting it in px would change when a large-text reader sees it. */
|
|
937
938
|
@media (max-width: 30rem) {
|
|
938
939
|
.ds-attachment-viewer {
|
|
939
940
|
padding: 0;
|
|
@@ -966,6 +967,7 @@ button.ds-attachment-group__single:focus-visible {
|
|
|
966
967
|
/* Flush with the surface it covers, corners and all, so the edge reads
|
|
967
968
|
as the surface's own outline lighting up */
|
|
968
969
|
inset: 0;
|
|
970
|
+
/* ds-allow(stacking): local order, above the surface the drop zone covers; it never leaves that surface's stacking context. */
|
|
969
971
|
z-index: 10;
|
|
970
972
|
display: flex;
|
|
971
973
|
align-items: center;
|
|
@@ -201,6 +201,7 @@
|
|
|
201
201
|
RESPONSIVE — stack header on small screens
|
|
202
202
|
============================================ */
|
|
203
203
|
|
|
204
|
+
/* ds-allow(breakpoint): the phone step on its other edge (below 600px, not at or below it); aligning it would change this rule at exactly 600px. */
|
|
204
205
|
@media (max-width: 599px) {
|
|
205
206
|
.ds-chart {
|
|
206
207
|
padding: var(--padding-400);
|
|
@@ -169,3 +169,24 @@
|
|
|
169
169
|
.ds-chat-thread__jump-icon {
|
|
170
170
|
--icon-size: var(--icon-size-600);
|
|
171
171
|
}
|
|
172
|
+
|
|
173
|
+
/* ============================================
|
|
174
|
+
BOTTOM-UP — the classic message thread
|
|
175
|
+
Turns stack from the bottom edge: a short
|
|
176
|
+
conversation sits just above the composer
|
|
177
|
+
rather than at the top of an empty column.
|
|
178
|
+
The content fills the viewport at least and
|
|
179
|
+
pushes its turns to the end of it.
|
|
180
|
+
============================================ */
|
|
181
|
+
|
|
182
|
+
.ds-chat-thread--bottom-up {
|
|
183
|
+
display: flex;
|
|
184
|
+
flex-direction: column;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.ds-chat-thread--bottom-up .ds-chat-thread__content {
|
|
188
|
+
box-sizing: border-box;
|
|
189
|
+
flex: 1 0 auto;
|
|
190
|
+
justify-content: flex-end;
|
|
191
|
+
width: 100%;
|
|
192
|
+
}
|
|
@@ -10,6 +10,16 @@ type ChatThreadOwnProps = {
|
|
|
10
10
|
* edit-last-turn) neither re-anchors nor resizes the spacer.
|
|
11
11
|
*/
|
|
12
12
|
anchor?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Which way the conversation reads. `top-down` (the default) is the send
|
|
15
|
+
* choreography above: each new turn floats to the top of the viewport and
|
|
16
|
+
* the answer streams in below it. `bottom-up` is the classic message
|
|
17
|
+
* thread: turns stack from the bottom edge, the newest always just above
|
|
18
|
+
* the composer, and the view follows a streaming answer down for as long
|
|
19
|
+
* as the reader stays at the bottom. Scrolling up to reread lets go;
|
|
20
|
+
* returning to the bottom, or the next send, takes hold again.
|
|
21
|
+
*/
|
|
22
|
+
flow?: 'top-down' | 'bottom-up';
|
|
13
23
|
/** Accessible name for the scrollable conversation region. */
|
|
14
24
|
ariaLabel?: string;
|
|
15
25
|
/** Accessible name for the scroll-to-bottom control. */
|
|
@@ -26,7 +36,8 @@ export interface ChatThreadProps extends ChatThreadOwnProps, Omit<React.Componen
|
|
|
26
36
|
* pure-CSS fade at either end so content scrolling out passes through it,
|
|
27
37
|
* and the send choreography — a newly appended turn floats to the top of
|
|
28
38
|
* the viewport while the prior conversation is pushed upward, leaving the
|
|
29
|
-
* response room to stream in below.
|
|
39
|
+
* response room to stream in below. `flow="bottom-up"` swaps that for the
|
|
40
|
+
* classic thread, stacked from the bottom and following the newest turn.
|
|
30
41
|
*
|
|
31
42
|
* A trailing spacer grows just enough that even a short newest exchange can
|
|
32
43
|
* reach the top, so the anchor position never depends on how much has been
|
|
@@ -8,6 +8,7 @@ const JUMP_THRESHOLD_PX = 24;
|
|
|
8
8
|
const ChatThread = React.forwardRef(
|
|
9
9
|
({
|
|
10
10
|
anchor = true,
|
|
11
|
+
flow = "top-down",
|
|
11
12
|
ariaLabel = "Conversation",
|
|
12
13
|
jumpLabel = "Scroll to the latest message",
|
|
13
14
|
className = "",
|
|
@@ -22,6 +23,18 @@ const ChatThread = React.forwardRef(
|
|
|
22
23
|
const prevCount = useRef(0);
|
|
23
24
|
const mounted = useRef(false);
|
|
24
25
|
const anchorTop = useRef(null);
|
|
26
|
+
const bottomUp = flow === "bottom-up";
|
|
27
|
+
const flowRef = useRef(flow);
|
|
28
|
+
flowRef.current = flow;
|
|
29
|
+
const stuck = useRef(true);
|
|
30
|
+
const lastScrollTop = useRef(0);
|
|
31
|
+
const scrollToEnd = (behavior) => {
|
|
32
|
+
const container = scrollRef.current;
|
|
33
|
+
if (!container) return;
|
|
34
|
+
const top = container.scrollHeight - container.clientHeight;
|
|
35
|
+
if (behavior) container.scrollTo({ top, behavior });
|
|
36
|
+
else container.scrollTo({ top });
|
|
37
|
+
};
|
|
25
38
|
const sizeSpacer = () => {
|
|
26
39
|
const container = scrollRef.current;
|
|
27
40
|
const content = contentRef.current;
|
|
@@ -45,6 +58,7 @@ const ChatThread = React.forwardRef(
|
|
|
45
58
|
const wasClamped = top != null && container.scrollTop < top && container.scrollTop >= container.scrollHeight - container.clientHeight - 1;
|
|
46
59
|
sizeSpacer();
|
|
47
60
|
if (top != null && wasClamped) container.scrollTo({ top, behavior: "instant" });
|
|
61
|
+
if (flowRef.current === "bottom-up" && stuck.current) scrollToEnd("instant");
|
|
48
62
|
updateJump();
|
|
49
63
|
});
|
|
50
64
|
observer.observe(container);
|
|
@@ -78,6 +92,19 @@ const ChatThread = React.forwardRef(
|
|
|
78
92
|
mounted.current = true;
|
|
79
93
|
if (childCount === previous) return;
|
|
80
94
|
prevCount.current = childCount;
|
|
95
|
+
if (bottomUp) {
|
|
96
|
+
anchorTop.current = null;
|
|
97
|
+
spacer.style.height = "0px";
|
|
98
|
+
if (childCount < previous) {
|
|
99
|
+
container.scrollTo({ top: 0 });
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (childCount === 0 || !anchor) return;
|
|
103
|
+
stuck.current = true;
|
|
104
|
+
scrollToEnd(isFirstRun ? "instant" : void 0);
|
|
105
|
+
updateJump();
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
81
108
|
if (childCount < previous) {
|
|
82
109
|
anchorTop.current = null;
|
|
83
110
|
spacer.style.height = "0px";
|
|
@@ -124,6 +151,13 @@ const ChatThread = React.forwardRef(
|
|
|
124
151
|
useEffect(updateJump);
|
|
125
152
|
const handleScroll = (e) => {
|
|
126
153
|
onScroll?.(e);
|
|
154
|
+
if (bottomUp) {
|
|
155
|
+
const container = e.currentTarget;
|
|
156
|
+
const atEnd = container.scrollHeight - container.scrollTop - container.clientHeight <= JUMP_THRESHOLD_PX;
|
|
157
|
+
if (atEnd) stuck.current = true;
|
|
158
|
+
else if (container.scrollTop < lastScrollTop.current) stuck.current = false;
|
|
159
|
+
lastScrollTop.current = container.scrollTop;
|
|
160
|
+
}
|
|
127
161
|
updateJump();
|
|
128
162
|
setScrolling(true);
|
|
129
163
|
window.clearTimeout(settleTimer.current);
|
|
@@ -139,7 +173,12 @@ const ChatThread = React.forwardRef(
|
|
|
139
173
|
container.scrollTo({ top: content.offsetHeight - container.clientHeight });
|
|
140
174
|
};
|
|
141
175
|
useEffect(() => () => window.clearTimeout(settleTimer.current), []);
|
|
142
|
-
const classes = [
|
|
176
|
+
const classes = [
|
|
177
|
+
baseClass,
|
|
178
|
+
bottomUp ? `${baseClass}--bottom-up` : "",
|
|
179
|
+
scrolling ? `${baseClass}--scrolling` : "",
|
|
180
|
+
className
|
|
181
|
+
].filter(Boolean).join(" ");
|
|
143
182
|
return /* @__PURE__ */ jsxs(
|
|
144
183
|
"div",
|
|
145
184
|
{
|
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
list-style: none;
|
|
187
187
|
max-height: 280px;
|
|
188
188
|
overflow-y: auto;
|
|
189
|
-
z-index:
|
|
189
|
+
z-index: var(--layer-dropdown);
|
|
190
190
|
box-shadow: var(--shadow-floating);
|
|
191
191
|
animation: ds-combobox-appear var(--motion-duration-fast) var(--motion-ease-entrance);
|
|
192
192
|
}
|
|
@@ -480,3 +480,70 @@
|
|
|
480
480
|
transform: translateX(100%);
|
|
481
481
|
}
|
|
482
482
|
}
|
|
483
|
+
|
|
484
|
+
/* ============================================
|
|
485
|
+
KEPT — the record of a choice
|
|
486
|
+
A row that stays on screen after use keeps
|
|
487
|
+
the choice in view with QuestionCard's own
|
|
488
|
+
treatment: the taken suggestion outlined
|
|
489
|
+
solid in the strongest ink, doubled by an
|
|
490
|
+
inset ring so it does not grow, and the rest
|
|
491
|
+
faded behind a dashed line. No check: a chip
|
|
492
|
+
is a line of text, and it keeps its shape.
|
|
493
|
+
Nothing in the row answers the pointer.
|
|
494
|
+
============================================ */
|
|
495
|
+
|
|
496
|
+
.ds-prompt-suggestions--kept .ds-prompt-suggestions__item:not(.ds-prompt-suggestions__item--kept) {
|
|
497
|
+
opacity: 0.4;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
.ds-prompt-suggestions--kept .ds-chip,
|
|
501
|
+
.ds-prompt-suggestions--kept .ds-prompt-suggestions__tile,
|
|
502
|
+
.ds-prompt-suggestions--kept .ds-prompt-suggestions__card {
|
|
503
|
+
border-style: dashed;
|
|
504
|
+
border-color: var(--color-text-tertiary);
|
|
505
|
+
/* A record carries no fill, like QuestionCard's rows once answered: the
|
|
506
|
+
outline alone says which way the conversation went. */
|
|
507
|
+
background-color: transparent;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
.ds-prompt-suggestions__item--kept .ds-chip,
|
|
511
|
+
.ds-prompt-suggestions__item--kept .ds-prompt-suggestions__tile,
|
|
512
|
+
.ds-prompt-suggestions__item--kept .ds-prompt-suggestions__card,
|
|
513
|
+
.ds-prompt-suggestions--kept .ds-prompt-suggestions__item--kept .ds-prompt-suggestions__tile:hover {
|
|
514
|
+
border-style: solid;
|
|
515
|
+
border-color: var(--color-text-primary);
|
|
516
|
+
box-shadow: inset 0 0 0 var(--border-025) var(--color-text-primary);
|
|
517
|
+
color: var(--color-text-primary);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.ds-prompt-suggestions--kept .ds-prompt-suggestions__tile,
|
|
521
|
+
.ds-prompt-suggestions--kept .ds-prompt-suggestions__card {
|
|
522
|
+
cursor: default;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
.ds-prompt-suggestions--kept .ds-prompt-suggestions__tile:hover {
|
|
526
|
+
background-color: var(--color-bg-container-primary-semi);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.ds-prompt-suggestions--kept .ds-prompt-suggestions__card:hover {
|
|
530
|
+
transform: none;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
.ds-prompt-suggestions--kept
|
|
534
|
+
.ds-prompt-suggestions__item:not(.ds-prompt-suggestions__item--kept)
|
|
535
|
+
.ds-prompt-suggestions__card:hover {
|
|
536
|
+
box-shadow: none;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.ds-prompt-suggestions__sr-only {
|
|
540
|
+
position: absolute;
|
|
541
|
+
width: 1px;
|
|
542
|
+
height: 1px;
|
|
543
|
+
padding: 0;
|
|
544
|
+
margin: -1px;
|
|
545
|
+
overflow: hidden;
|
|
546
|
+
clip: rect(0, 0, 0, 0);
|
|
547
|
+
white-space: nowrap;
|
|
548
|
+
border: 0;
|
|
549
|
+
}
|
|
@@ -57,6 +57,14 @@ type PromptSuggestionsOwnProps = {
|
|
|
57
57
|
* the quieter row for placements alongside a live conversation.
|
|
58
58
|
*/
|
|
59
59
|
size?: 'default' | 'compact';
|
|
60
|
+
/**
|
|
61
|
+
* The `id` of the suggestion already taken. Set, the row becomes the
|
|
62
|
+
* record of that choice: the taken suggestion outlined solid in the
|
|
63
|
+
* strongest ink, the rest faded behind a dashed line, and none of them
|
|
64
|
+
* tappable any more. The same treatment QuestionCard gives a pick. For a row that stays
|
|
65
|
+
* on screen after use, such as the follow-ups under an earlier answer.
|
|
66
|
+
*/
|
|
67
|
+
value?: string;
|
|
60
68
|
/** Accessible name for the list. */
|
|
61
69
|
ariaLabel?: string;
|
|
62
70
|
/** Additional CSS classes */
|
|
@@ -15,6 +15,7 @@ const PromptSuggestions = React.forwardRef(
|
|
|
15
15
|
pendingCount = 3,
|
|
16
16
|
entrance = true,
|
|
17
17
|
size = "default",
|
|
18
|
+
value,
|
|
18
19
|
ariaLabel = "Suggested prompts",
|
|
19
20
|
className = "",
|
|
20
21
|
...rest
|
|
@@ -28,8 +29,9 @@ const PromptSuggestions = React.forwardRef(
|
|
|
28
29
|
},
|
|
29
30
|
[]
|
|
30
31
|
);
|
|
32
|
+
const kept = value !== void 0;
|
|
31
33
|
const choose = (id) => {
|
|
32
|
-
if (chosenId || chooseTimer.current) return;
|
|
34
|
+
if (kept || chosenId || chooseTimer.current) return;
|
|
33
35
|
setChosenId(id);
|
|
34
36
|
chooseTimer.current = window.setTimeout(() => {
|
|
35
37
|
chooseTimer.current = null;
|
|
@@ -45,6 +47,7 @@ const PromptSuggestions = React.forwardRef(
|
|
|
45
47
|
`${baseClass}--${size}`,
|
|
46
48
|
`${baseClass}--${arrangement}`,
|
|
47
49
|
chosenId ? `${baseClass}--choosing` : "",
|
|
50
|
+
kept ? `${baseClass}--kept` : "",
|
|
48
51
|
entrance ? "" : `${baseClass}--still`,
|
|
49
52
|
className
|
|
50
53
|
].filter(Boolean).join(" ");
|
|
@@ -64,39 +67,44 @@ const PromptSuggestions = React.forwardRef(
|
|
|
64
67
|
block === "card" && /* @__PURE__ */ jsx("span", { className: `${baseClass}__cover` }),
|
|
65
68
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__skeleton-bar` })
|
|
66
69
|
] })
|
|
67
|
-
) : /* @__PURE__ */ jsx("span", { className: `${baseClass}__skeleton`, children: /* @__PURE__ */ jsx("span", { className: `${baseClass}__skeleton-bar` }) }) }, index)) : suggestions.map((suggestion) => /* @__PURE__ */
|
|
70
|
+
) : /* @__PURE__ */ jsx("span", { className: `${baseClass}__skeleton`, children: /* @__PURE__ */ jsx("span", { className: `${baseClass}__skeleton-bar` }) }) }, index)) : suggestions.map((suggestion) => /* @__PURE__ */ jsxs(
|
|
68
71
|
"div",
|
|
69
72
|
{
|
|
70
73
|
role: "listitem",
|
|
71
|
-
className: `${baseClass}__item${chosenId === suggestion.id ? ` ${baseClass}__item--chosen` : ""}`,
|
|
74
|
+
className: `${baseClass}__item${chosenId === suggestion.id ? ` ${baseClass}__item--chosen` : ""}${value === suggestion.id ? ` ${baseClass}__item--kept` : ""}`,
|
|
72
75
|
onAnimationEnd: (event) => {
|
|
73
76
|
if (event.animationName === "ds-prompt-suggestions-choose") {
|
|
74
77
|
setChosenId(null);
|
|
75
78
|
}
|
|
76
79
|
},
|
|
77
|
-
children:
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
/* @__PURE__ */ jsx("span", { className: `${baseClass}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
80
|
+
children: [
|
|
81
|
+
block ? /* @__PURE__ */ jsxs(
|
|
82
|
+
"button",
|
|
83
|
+
{
|
|
84
|
+
type: "button",
|
|
85
|
+
className: `${baseClass}__${block}`,
|
|
86
|
+
disabled: kept,
|
|
87
|
+
onClick: () => choose(suggestion.id),
|
|
88
|
+
children: [
|
|
89
|
+
block === "card" ? /* @__PURE__ */ jsx("span", { className: `${baseClass}__cover`, children: suggestion.icon != null && renderIcon(suggestion.icon) }) : suggestion.icon != null && renderIcon(suggestion.icon),
|
|
90
|
+
/* @__PURE__ */ jsxs("span", { className: `${baseClass}__text`, children: [
|
|
91
|
+
/* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: suggestion.label }),
|
|
92
|
+
suggestion.description && /* @__PURE__ */ jsx("span", { className: `${baseClass}__description`, children: suggestion.description })
|
|
93
|
+
] }),
|
|
94
|
+
value === suggestion.id && /* @__PURE__ */ jsx("span", { className: `${baseClass}__sr-only`, children: " (chosen)" })
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
) : /* @__PURE__ */ jsx(
|
|
98
|
+
Chip,
|
|
99
|
+
{
|
|
100
|
+
label: suggestion.label,
|
|
101
|
+
icon: suggestion.icon,
|
|
102
|
+
size: chipSize,
|
|
103
|
+
onClick: kept ? void 0 : () => choose(suggestion.id)
|
|
104
|
+
}
|
|
105
|
+
),
|
|
106
|
+
!block && value === suggestion.id && /* @__PURE__ */ jsx("span", { className: `${baseClass}__sr-only`, children: " (chosen)" })
|
|
107
|
+
]
|
|
100
108
|
},
|
|
101
109
|
suggestion.id
|
|
102
110
|
))
|