@handled-ai/design-system 0.17.1 → 0.17.2
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/components/feedback-primitives.d.ts +66 -0
- package/dist/components/feedback-primitives.js +295 -0
- package/dist/components/feedback-primitives.js.map +1 -0
- package/dist/components/score-why-chips.d.ts +8 -17
- package/dist/components/score-why-chips.js +266 -180
- package/dist/components/score-why-chips.js.map +1 -1
- package/dist/components/signal-priority-popover.d.ts +17 -0
- package/dist/components/signal-priority-popover.js +247 -0
- package/dist/components/signal-priority-popover.js.map +1 -0
- package/dist/components/user-display.d.ts +22 -0
- package/dist/components/user-display.js +138 -0
- package/dist/components/user-display.js.map +1 -0
- package/dist/components/user-pill.d.ts +3 -0
- package/dist/components/user-pill.js +5 -0
- package/dist/components/user-pill.js.map +1 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/user-display.d.ts +31 -0
- package/dist/lib/user-display.js +57 -0
- package/dist/lib/user-display.js.map +1 -0
- package/dist/prototype/index.d.ts +2 -1
- package/dist/prototype/prototype-accounts-view.d.ts +2 -1
- package/dist/prototype/prototype-admin-view.d.ts +2 -1
- package/dist/prototype/prototype-config.d.ts +15 -332
- package/dist/prototype/prototype-inbox-view.d.ts +2 -1
- package/dist/prototype/prototype-inbox-view.js +11 -12
- package/dist/prototype/prototype-inbox-view.js.map +1 -1
- package/dist/prototype/prototype-insights-view.d.ts +2 -1
- package/dist/prototype/prototype-shell.d.ts +2 -1
- package/dist/signal-priority-popover-DQ_VuHac.d.ts +390 -0
- package/package.json +1 -1
- package/src/components/__tests__/contextual-quick-action-launcher.test.tsx +99 -188
- package/src/components/__tests__/feedback-primitives.test.tsx +509 -0
- package/src/components/__tests__/score-why-chips.test.tsx +540 -0
- package/src/components/__tests__/signal-priority-popover.test.tsx +312 -0
- package/src/components/feedback-primitives.tsx +424 -0
- package/src/components/score-why-chips.tsx +413 -203
- package/src/components/signal-priority-popover.tsx +359 -0
- package/src/components/user-display.tsx +96 -0
- package/src/components/user-pill.tsx +1 -0
- package/src/index.ts +6 -0
- package/src/lib/__tests__/user-display.test.ts +43 -0
- package/src/lib/user-display.ts +88 -0
- package/src/prototype/__tests__/detail-view-score-why.test.tsx +33 -29
- package/src/prototype/__tests__/detail-view-title-slots.test.tsx +65 -0
- package/src/prototype/prototype-config.ts +28 -4
- package/src/prototype/prototype-inbox-view.tsx +8 -10
- package/src/prototype/__tests__/detail-view-title-subtext.test.tsx +0 -72
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Structured feedback data shape.
|
|
5
|
+
*
|
|
6
|
+
* Preserves the tree structure for DB persistence:
|
|
7
|
+
* reasonTop -> tier-1 chip label (maps to case_feedback.reason_top)
|
|
8
|
+
* reasonSub -> tier-2 sub-chip label (maps to case_feedback.reason_sub)
|
|
9
|
+
* pills -> any additional selected chips (maps to case_feedback.pills)
|
|
10
|
+
* detail -> free-text input (maps to case_feedback.free_text)
|
|
11
|
+
*/
|
|
12
|
+
interface FeedbackSubmitData {
|
|
13
|
+
sentiment: "positive" | "negative";
|
|
14
|
+
reasonTop?: string;
|
|
15
|
+
reasonSub?: string;
|
|
16
|
+
pills: string[];
|
|
17
|
+
detail: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Defines a tier-1 chip that may have tier-2 sub-chips.
|
|
21
|
+
*/
|
|
22
|
+
interface FeedbackChipTree {
|
|
23
|
+
label: string;
|
|
24
|
+
subPrompt?: string;
|
|
25
|
+
subChips?: string[];
|
|
26
|
+
}
|
|
27
|
+
interface FeedbackChipGroupProps {
|
|
28
|
+
chips: string[];
|
|
29
|
+
selected: string[];
|
|
30
|
+
onToggle: (chip: string) => void;
|
|
31
|
+
flavor: "positive" | "negative";
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
declare function FeedbackChipGroup({ chips, selected, onToggle, flavor, className, }: FeedbackChipGroupProps): React.JSX.Element;
|
|
35
|
+
interface FeedbackInputProps {
|
|
36
|
+
placeholder?: string;
|
|
37
|
+
value: string;
|
|
38
|
+
onChange: (value: string) => void;
|
|
39
|
+
onSubmit?: () => void;
|
|
40
|
+
className?: string;
|
|
41
|
+
}
|
|
42
|
+
declare function FeedbackInput({ placeholder, value, onChange, onSubmit, className, }: FeedbackInputProps): React.JSX.Element;
|
|
43
|
+
interface FeedbackActionsProps {
|
|
44
|
+
onSubmit: () => void;
|
|
45
|
+
onCancel: () => void;
|
|
46
|
+
submitDisabled?: boolean;
|
|
47
|
+
submitLabel?: string;
|
|
48
|
+
cancelLabel?: string;
|
|
49
|
+
hint?: string;
|
|
50
|
+
className?: string;
|
|
51
|
+
}
|
|
52
|
+
declare function FeedbackActions({ onSubmit, onCancel, submitDisabled, submitLabel, cancelLabel, hint, className, }: FeedbackActionsProps): React.JSX.Element;
|
|
53
|
+
interface FeedbackFooterProps {
|
|
54
|
+
feedback: "positive" | "negative" | null;
|
|
55
|
+
onFeedbackChange: (value: "positive" | "negative" | null) => void;
|
|
56
|
+
onSubmit: (data: FeedbackSubmitData) => void;
|
|
57
|
+
metaText?: string;
|
|
58
|
+
positivePrompt?: string;
|
|
59
|
+
negativePrompt?: string;
|
|
60
|
+
negativeChips?: FeedbackChipTree[];
|
|
61
|
+
positiveChips?: string[];
|
|
62
|
+
className?: string;
|
|
63
|
+
}
|
|
64
|
+
declare function FeedbackFooter({ feedback, onFeedbackChange, onSubmit, metaText, positivePrompt, negativePrompt, negativeChips, positiveChips, className, }: FeedbackFooterProps): React.JSX.Element;
|
|
65
|
+
|
|
66
|
+
export { FeedbackActions, type FeedbackActionsProps, FeedbackChipGroup, type FeedbackChipGroupProps, type FeedbackChipTree, FeedbackFooter, type FeedbackFooterProps, FeedbackInput, type FeedbackInputProps, type FeedbackSubmitData };
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
"use client";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { ThumbsUp, ThumbsDown } from "lucide-react";
|
|
7
|
+
import { cn } from "../lib/utils.js";
|
|
8
|
+
const CHIP_SELECTED_CLASSES = {
|
|
9
|
+
negative: "bg-red-50 text-red-700 border-red-200",
|
|
10
|
+
positive: "bg-muted text-foreground border-border"
|
|
11
|
+
};
|
|
12
|
+
const CHIP_IDLE_CLASS = "bg-background text-muted-foreground border-border hover:bg-muted/50";
|
|
13
|
+
function FeedbackChipGroup({
|
|
14
|
+
chips,
|
|
15
|
+
selected,
|
|
16
|
+
onToggle,
|
|
17
|
+
flavor,
|
|
18
|
+
className
|
|
19
|
+
}) {
|
|
20
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap gap-1.5", className), children: chips.map((chip) => {
|
|
21
|
+
const isSelected = selected.includes(chip);
|
|
22
|
+
return /* @__PURE__ */ jsx(
|
|
23
|
+
"button",
|
|
24
|
+
{
|
|
25
|
+
type: "button",
|
|
26
|
+
onClick: () => onToggle(chip),
|
|
27
|
+
className: cn(
|
|
28
|
+
"rounded-md px-2.5 py-1 text-[11px] font-medium border transition-colors",
|
|
29
|
+
isSelected ? CHIP_SELECTED_CLASSES[flavor] : CHIP_IDLE_CLASS
|
|
30
|
+
),
|
|
31
|
+
children: chip
|
|
32
|
+
},
|
|
33
|
+
chip
|
|
34
|
+
);
|
|
35
|
+
}) });
|
|
36
|
+
}
|
|
37
|
+
function FeedbackInput({
|
|
38
|
+
placeholder,
|
|
39
|
+
value,
|
|
40
|
+
onChange,
|
|
41
|
+
onSubmit,
|
|
42
|
+
className
|
|
43
|
+
}) {
|
|
44
|
+
return /* @__PURE__ */ jsx(
|
|
45
|
+
"input",
|
|
46
|
+
{
|
|
47
|
+
type: "text",
|
|
48
|
+
value,
|
|
49
|
+
onChange: (e) => onChange(e.target.value),
|
|
50
|
+
onKeyDown: (e) => {
|
|
51
|
+
if (e.key === "Enter" && onSubmit) {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
onSubmit();
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
placeholder,
|
|
57
|
+
className: cn(
|
|
58
|
+
"w-full text-xs bg-background border border-border rounded-md px-2.5 py-2 text-foreground placeholder:text-muted-foreground/50 focus:outline-none focus:ring-1 focus:ring-ring",
|
|
59
|
+
className
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
function FeedbackActions({
|
|
65
|
+
onSubmit,
|
|
66
|
+
onCancel,
|
|
67
|
+
submitDisabled = false,
|
|
68
|
+
submitLabel = "Submit",
|
|
69
|
+
cancelLabel = "Cancel",
|
|
70
|
+
hint,
|
|
71
|
+
className
|
|
72
|
+
}) {
|
|
73
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
|
|
74
|
+
/* @__PURE__ */ jsx(
|
|
75
|
+
"button",
|
|
76
|
+
{
|
|
77
|
+
type: "button",
|
|
78
|
+
onClick: onSubmit,
|
|
79
|
+
disabled: submitDisabled,
|
|
80
|
+
className: "bg-foreground text-background rounded-md px-3 py-1.5 text-xs font-semibold disabled:opacity-50",
|
|
81
|
+
children: submitLabel
|
|
82
|
+
}
|
|
83
|
+
),
|
|
84
|
+
/* @__PURE__ */ jsx(
|
|
85
|
+
"button",
|
|
86
|
+
{
|
|
87
|
+
type: "button",
|
|
88
|
+
onClick: onCancel,
|
|
89
|
+
className: "border border-border rounded-md px-3 py-1.5 text-xs font-medium",
|
|
90
|
+
children: cancelLabel
|
|
91
|
+
}
|
|
92
|
+
),
|
|
93
|
+
hint && /* @__PURE__ */ jsx("span", { className: "ml-auto text-[11px] text-muted-foreground", children: hint })
|
|
94
|
+
] });
|
|
95
|
+
}
|
|
96
|
+
const SENTIMENT_BUTTON_ACTIVE = {
|
|
97
|
+
negative: "text-red-600 bg-red-50 border-red-200",
|
|
98
|
+
positive: "text-foreground bg-muted border-border"
|
|
99
|
+
};
|
|
100
|
+
const SENTIMENT_BUTTON_IDLE = "text-muted-foreground hover:text-foreground";
|
|
101
|
+
function FeedbackFooter({
|
|
102
|
+
feedback,
|
|
103
|
+
onFeedbackChange,
|
|
104
|
+
onSubmit,
|
|
105
|
+
metaText,
|
|
106
|
+
positivePrompt = "Thanks! Anything to keep about this score?",
|
|
107
|
+
negativePrompt = "What's the issue?",
|
|
108
|
+
negativeChips = [],
|
|
109
|
+
positiveChips = [],
|
|
110
|
+
className
|
|
111
|
+
}) {
|
|
112
|
+
const [expanded, setExpanded] = React.useState(false);
|
|
113
|
+
const [selectedTier1, setSelectedTier1] = React.useState(null);
|
|
114
|
+
const [selectedTier2, setSelectedTier2] = React.useState(null);
|
|
115
|
+
const [additionalPills, setAdditionalPills] = React.useState([]);
|
|
116
|
+
const [detailText, setDetailText] = React.useState("");
|
|
117
|
+
const [activeTreeIndex, setActiveTreeIndex] = React.useState(
|
|
118
|
+
null
|
|
119
|
+
);
|
|
120
|
+
const resetState = React.useCallback(() => {
|
|
121
|
+
setExpanded(false);
|
|
122
|
+
setSelectedTier1(null);
|
|
123
|
+
setSelectedTier2(null);
|
|
124
|
+
setAdditionalPills([]);
|
|
125
|
+
setDetailText("");
|
|
126
|
+
setActiveTreeIndex(null);
|
|
127
|
+
}, []);
|
|
128
|
+
const handleSentimentClick = React.useCallback(
|
|
129
|
+
(sentiment) => {
|
|
130
|
+
onFeedbackChange(sentiment);
|
|
131
|
+
resetState();
|
|
132
|
+
setExpanded(true);
|
|
133
|
+
},
|
|
134
|
+
[onFeedbackChange, resetState]
|
|
135
|
+
);
|
|
136
|
+
const handleTier1Toggle = React.useCallback(
|
|
137
|
+
(chipLabel) => {
|
|
138
|
+
if (selectedTier1 === chipLabel) {
|
|
139
|
+
setSelectedTier1(null);
|
|
140
|
+
setSelectedTier2(null);
|
|
141
|
+
setActiveTreeIndex(null);
|
|
142
|
+
} else if (selectedTier1 === null) {
|
|
143
|
+
setSelectedTier1(chipLabel);
|
|
144
|
+
setSelectedTier2(null);
|
|
145
|
+
const idx = negativeChips.findIndex((c) => c.label === chipLabel);
|
|
146
|
+
if (idx !== -1 && negativeChips[idx].subChips) {
|
|
147
|
+
setActiveTreeIndex(idx);
|
|
148
|
+
} else {
|
|
149
|
+
setActiveTreeIndex(null);
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
setAdditionalPills(
|
|
153
|
+
(prev) => prev.includes(chipLabel) ? prev.filter((p) => p !== chipLabel) : [...prev, chipLabel]
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
[selectedTier1, negativeChips]
|
|
158
|
+
);
|
|
159
|
+
const handleTier2Toggle = React.useCallback((subChip) => {
|
|
160
|
+
setSelectedTier2((prev) => prev === subChip ? null : subChip);
|
|
161
|
+
}, []);
|
|
162
|
+
const handlePositiveChipToggle = React.useCallback(
|
|
163
|
+
(chip) => {
|
|
164
|
+
if (selectedTier1 === chip) {
|
|
165
|
+
setSelectedTier1(null);
|
|
166
|
+
} else if (selectedTier1 === null) {
|
|
167
|
+
setSelectedTier1(chip);
|
|
168
|
+
} else {
|
|
169
|
+
setAdditionalPills(
|
|
170
|
+
(prev) => prev.includes(chip) ? prev.filter((p) => p !== chip) : [...prev, chip]
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
[selectedTier1]
|
|
175
|
+
);
|
|
176
|
+
const handleSubmit = React.useCallback(() => {
|
|
177
|
+
if (!feedback) return;
|
|
178
|
+
onSubmit({
|
|
179
|
+
sentiment: feedback,
|
|
180
|
+
reasonTop: selectedTier1 != null ? selectedTier1 : void 0,
|
|
181
|
+
reasonSub: selectedTier2 != null ? selectedTier2 : void 0,
|
|
182
|
+
pills: additionalPills,
|
|
183
|
+
detail: detailText
|
|
184
|
+
});
|
|
185
|
+
resetState();
|
|
186
|
+
}, [
|
|
187
|
+
feedback,
|
|
188
|
+
selectedTier1,
|
|
189
|
+
selectedTier2,
|
|
190
|
+
additionalPills,
|
|
191
|
+
detailText,
|
|
192
|
+
onSubmit,
|
|
193
|
+
resetState
|
|
194
|
+
]);
|
|
195
|
+
const handleCancel = React.useCallback(() => {
|
|
196
|
+
resetState();
|
|
197
|
+
onFeedbackChange(null);
|
|
198
|
+
}, [resetState, onFeedbackChange]);
|
|
199
|
+
const allSelectedChips = React.useMemo(() => {
|
|
200
|
+
const result = [];
|
|
201
|
+
if (selectedTier1) result.push(selectedTier1);
|
|
202
|
+
result.push(...additionalPills);
|
|
203
|
+
return result;
|
|
204
|
+
}, [selectedTier1, additionalPills]);
|
|
205
|
+
const activeTree = activeTreeIndex !== null ? negativeChips[activeTreeIndex] : null;
|
|
206
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-3", className), children: [
|
|
207
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
208
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
209
|
+
/* @__PURE__ */ jsxs(
|
|
210
|
+
"button",
|
|
211
|
+
{
|
|
212
|
+
type: "button",
|
|
213
|
+
onClick: () => handleSentimentClick("positive"),
|
|
214
|
+
className: cn(
|
|
215
|
+
"flex gap-1 items-center text-[11px] font-medium rounded-md px-2 py-1 transition-colors",
|
|
216
|
+
feedback === "positive" ? SENTIMENT_BUTTON_ACTIVE.positive : SENTIMENT_BUTTON_IDLE
|
|
217
|
+
),
|
|
218
|
+
children: [
|
|
219
|
+
/* @__PURE__ */ jsx(ThumbsUp, { className: "h-[11px] w-[11px]" }),
|
|
220
|
+
"Helpful"
|
|
221
|
+
]
|
|
222
|
+
}
|
|
223
|
+
),
|
|
224
|
+
/* @__PURE__ */ jsxs(
|
|
225
|
+
"button",
|
|
226
|
+
{
|
|
227
|
+
type: "button",
|
|
228
|
+
onClick: () => handleSentimentClick("negative"),
|
|
229
|
+
className: cn(
|
|
230
|
+
"flex gap-1 items-center text-[11px] font-medium rounded-md px-2 py-1 transition-colors",
|
|
231
|
+
feedback === "negative" ? SENTIMENT_BUTTON_ACTIVE.negative : SENTIMENT_BUTTON_IDLE
|
|
232
|
+
),
|
|
233
|
+
children: [
|
|
234
|
+
/* @__PURE__ */ jsx(ThumbsDown, { className: "h-[11px] w-[11px]" }),
|
|
235
|
+
"Not helpful"
|
|
236
|
+
]
|
|
237
|
+
}
|
|
238
|
+
)
|
|
239
|
+
] }),
|
|
240
|
+
metaText && /* @__PURE__ */ jsx("span", { className: "text-[11px] text-muted-foreground", children: metaText })
|
|
241
|
+
] }),
|
|
242
|
+
expanded && feedback && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
243
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: feedback === "negative" ? negativePrompt : positivePrompt }),
|
|
244
|
+
feedback === "negative" && negativeChips.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
245
|
+
/* @__PURE__ */ jsx(
|
|
246
|
+
FeedbackChipGroup,
|
|
247
|
+
{
|
|
248
|
+
chips: negativeChips.map((c) => c.label),
|
|
249
|
+
selected: allSelectedChips,
|
|
250
|
+
onToggle: handleTier1Toggle,
|
|
251
|
+
flavor: "negative"
|
|
252
|
+
}
|
|
253
|
+
),
|
|
254
|
+
activeTree && activeTree.subChips && /* @__PURE__ */ jsxs("div", { className: "pl-3 space-y-1.5", children: [
|
|
255
|
+
activeTree.subPrompt && /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: activeTree.subPrompt }),
|
|
256
|
+
/* @__PURE__ */ jsx(
|
|
257
|
+
FeedbackChipGroup,
|
|
258
|
+
{
|
|
259
|
+
chips: activeTree.subChips,
|
|
260
|
+
selected: selectedTier2 ? [selectedTier2] : [],
|
|
261
|
+
onToggle: handleTier2Toggle,
|
|
262
|
+
flavor: "negative"
|
|
263
|
+
}
|
|
264
|
+
)
|
|
265
|
+
] })
|
|
266
|
+
] }),
|
|
267
|
+
feedback === "positive" && positiveChips.length > 0 && /* @__PURE__ */ jsx(
|
|
268
|
+
FeedbackChipGroup,
|
|
269
|
+
{
|
|
270
|
+
chips: positiveChips,
|
|
271
|
+
selected: allSelectedChips,
|
|
272
|
+
onToggle: handlePositiveChipToggle,
|
|
273
|
+
flavor: "positive"
|
|
274
|
+
}
|
|
275
|
+
),
|
|
276
|
+
/* @__PURE__ */ jsx(
|
|
277
|
+
FeedbackInput,
|
|
278
|
+
{
|
|
279
|
+
placeholder: "Add optional detail\u2026",
|
|
280
|
+
value: detailText,
|
|
281
|
+
onChange: setDetailText,
|
|
282
|
+
onSubmit: handleSubmit
|
|
283
|
+
}
|
|
284
|
+
),
|
|
285
|
+
/* @__PURE__ */ jsx(FeedbackActions, { onSubmit: handleSubmit, onCancel: handleCancel })
|
|
286
|
+
] })
|
|
287
|
+
] });
|
|
288
|
+
}
|
|
289
|
+
export {
|
|
290
|
+
FeedbackActions,
|
|
291
|
+
FeedbackChipGroup,
|
|
292
|
+
FeedbackFooter,
|
|
293
|
+
FeedbackInput
|
|
294
|
+
};
|
|
295
|
+
//# sourceMappingURL=feedback-primitives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/feedback-primitives.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { ThumbsUp, ThumbsDown } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Structured feedback data shape.\n *\n * Preserves the tree structure for DB persistence:\n * reasonTop -> tier-1 chip label (maps to case_feedback.reason_top)\n * reasonSub -> tier-2 sub-chip label (maps to case_feedback.reason_sub)\n * pills -> any additional selected chips (maps to case_feedback.pills)\n * detail -> free-text input (maps to case_feedback.free_text)\n */\nexport interface FeedbackSubmitData {\n sentiment: \"positive\" | \"negative\"\n reasonTop?: string\n reasonSub?: string\n pills: string[]\n detail: string\n}\n\n/**\n * Defines a tier-1 chip that may have tier-2 sub-chips.\n */\nexport interface FeedbackChipTree {\n label: string\n subPrompt?: string\n subChips?: string[]\n}\n\n// ---------------------------------------------------------------------------\n// FeedbackChipGroup\n// ---------------------------------------------------------------------------\n\nexport interface FeedbackChipGroupProps {\n chips: string[]\n selected: string[]\n onToggle: (chip: string) => void\n flavor: \"positive\" | \"negative\"\n className?: string\n}\n\nconst CHIP_SELECTED_CLASSES: Record<\"positive\" | \"negative\", string> = {\n negative: \"bg-red-50 text-red-700 border-red-200\",\n positive: \"bg-muted text-foreground border-border\",\n}\n\nconst CHIP_IDLE_CLASS =\n \"bg-background text-muted-foreground border-border hover:bg-muted/50\"\n\nexport function FeedbackChipGroup({\n chips,\n selected,\n onToggle,\n flavor,\n className,\n}: FeedbackChipGroupProps) {\n return (\n <div className={cn(\"flex flex-wrap gap-1.5\", className)}>\n {chips.map((chip) => {\n const isSelected = selected.includes(chip)\n return (\n <button\n key={chip}\n type=\"button\"\n onClick={() => onToggle(chip)}\n className={cn(\n \"rounded-md px-2.5 py-1 text-[11px] font-medium border transition-colors\",\n isSelected ? CHIP_SELECTED_CLASSES[flavor] : CHIP_IDLE_CLASS,\n )}\n >\n {chip}\n </button>\n )\n })}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// FeedbackInput\n// ---------------------------------------------------------------------------\n\nexport interface FeedbackInputProps {\n placeholder?: string\n value: string\n onChange: (value: string) => void\n onSubmit?: () => void\n className?: string\n}\n\nexport function FeedbackInput({\n placeholder,\n value,\n onChange,\n onSubmit,\n className,\n}: FeedbackInputProps) {\n return (\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && onSubmit) {\n e.preventDefault()\n onSubmit()\n }\n }}\n placeholder={placeholder}\n className={cn(\n \"w-full text-xs bg-background border border-border rounded-md px-2.5 py-2 text-foreground placeholder:text-muted-foreground/50 focus:outline-none focus:ring-1 focus:ring-ring\",\n className,\n )}\n />\n )\n}\n\n// ---------------------------------------------------------------------------\n// FeedbackActions\n// ---------------------------------------------------------------------------\n\nexport interface FeedbackActionsProps {\n onSubmit: () => void\n onCancel: () => void\n submitDisabled?: boolean\n submitLabel?: string\n cancelLabel?: string\n hint?: string\n className?: string\n}\n\nexport function FeedbackActions({\n onSubmit,\n onCancel,\n submitDisabled = false,\n submitLabel = \"Submit\",\n cancelLabel = \"Cancel\",\n hint,\n className,\n}: FeedbackActionsProps) {\n return (\n <div className={cn(\"flex items-center gap-2\", className)}>\n <button\n type=\"button\"\n onClick={onSubmit}\n disabled={submitDisabled}\n className=\"bg-foreground text-background rounded-md px-3 py-1.5 text-xs font-semibold disabled:opacity-50\"\n >\n {submitLabel}\n </button>\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"border border-border rounded-md px-3 py-1.5 text-xs font-medium\"\n >\n {cancelLabel}\n </button>\n {hint && (\n <span className=\"ml-auto text-[11px] text-muted-foreground\">\n {hint}\n </span>\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// FeedbackFooter\n// ---------------------------------------------------------------------------\n\nexport interface FeedbackFooterProps {\n feedback: \"positive\" | \"negative\" | null\n onFeedbackChange: (value: \"positive\" | \"negative\" | null) => void\n onSubmit: (data: FeedbackSubmitData) => void\n metaText?: string\n positivePrompt?: string\n negativePrompt?: string\n negativeChips?: FeedbackChipTree[]\n positiveChips?: string[]\n className?: string\n}\n\nconst SENTIMENT_BUTTON_ACTIVE: Record<\"positive\" | \"negative\", string> = {\n negative: \"text-red-600 bg-red-50 border-red-200\",\n positive: \"text-foreground bg-muted border-border\",\n}\n\nconst SENTIMENT_BUTTON_IDLE =\n \"text-muted-foreground hover:text-foreground\"\n\nexport function FeedbackFooter({\n feedback,\n onFeedbackChange,\n onSubmit,\n metaText,\n positivePrompt = \"Thanks! Anything to keep about this score?\",\n negativePrompt = \"What's the issue?\",\n negativeChips = [],\n positiveChips = [],\n className,\n}: FeedbackFooterProps) {\n const [expanded, setExpanded] = React.useState(false)\n const [selectedTier1, setSelectedTier1] = React.useState<string | null>(null)\n const [selectedTier2, setSelectedTier2] = React.useState<string | null>(null)\n const [additionalPills, setAdditionalPills] = React.useState<string[]>([])\n const [detailText, setDetailText] = React.useState(\"\")\n const [activeTreeIndex, setActiveTreeIndex] = React.useState<number | null>(\n null,\n )\n\n // Reset state when feedback collapses\n const resetState = React.useCallback(() => {\n setExpanded(false)\n setSelectedTier1(null)\n setSelectedTier2(null)\n setAdditionalPills([])\n setDetailText(\"\")\n setActiveTreeIndex(null)\n }, [])\n\n const handleSentimentClick = React.useCallback(\n (sentiment: \"positive\" | \"negative\") => {\n onFeedbackChange(sentiment)\n // Reset chip state when switching sentiment, then expand\n resetState()\n setExpanded(true)\n },\n [onFeedbackChange, resetState],\n )\n\n const handleTier1Toggle = React.useCallback(\n (chipLabel: string) => {\n if (selectedTier1 === chipLabel) {\n // Deselect the tier-1 chip\n setSelectedTier1(null)\n setSelectedTier2(null)\n setActiveTreeIndex(null)\n } else if (selectedTier1 === null) {\n // First selection becomes the primary reasonTop\n setSelectedTier1(chipLabel)\n setSelectedTier2(null)\n // Find the chip's tree index to show sub-chips\n const idx = negativeChips.findIndex((c) => c.label === chipLabel)\n if (idx !== -1 && negativeChips[idx].subChips) {\n setActiveTreeIndex(idx)\n } else {\n setActiveTreeIndex(null)\n }\n } else {\n // Additional selections become pills\n setAdditionalPills((prev) =>\n prev.includes(chipLabel)\n ? prev.filter((p) => p !== chipLabel)\n : [...prev, chipLabel],\n )\n }\n },\n [selectedTier1, negativeChips],\n )\n\n const handleTier2Toggle = React.useCallback((subChip: string) => {\n setSelectedTier2((prev) => (prev === subChip ? null : subChip))\n }, [])\n\n const handlePositiveChipToggle = React.useCallback(\n (chip: string) => {\n if (selectedTier1 === chip) {\n setSelectedTier1(null)\n } else if (selectedTier1 === null) {\n setSelectedTier1(chip)\n } else {\n setAdditionalPills((prev) =>\n prev.includes(chip)\n ? prev.filter((p) => p !== chip)\n : [...prev, chip],\n )\n }\n },\n [selectedTier1],\n )\n\n const handleSubmit = React.useCallback(() => {\n if (!feedback) return\n onSubmit({\n sentiment: feedback,\n reasonTop: selectedTier1 ?? undefined,\n reasonSub: selectedTier2 ?? undefined,\n pills: additionalPills,\n detail: detailText,\n })\n resetState()\n }, [\n feedback,\n selectedTier1,\n selectedTier2,\n additionalPills,\n detailText,\n onSubmit,\n resetState,\n ])\n\n const handleCancel = React.useCallback(() => {\n resetState()\n onFeedbackChange(null)\n }, [resetState, onFeedbackChange])\n\n // Determine which chips are selected (combining tier1 + additionalPills)\n const allSelectedChips = React.useMemo(() => {\n const result: string[] = []\n if (selectedTier1) result.push(selectedTier1)\n result.push(...additionalPills)\n return result\n }, [selectedTier1, additionalPills])\n\n // Active tier-1 chip tree (for showing sub-chips)\n const activeTree =\n activeTreeIndex !== null ? negativeChips[activeTreeIndex] : null\n\n return (\n <div className={cn(\"space-y-3\", className)}>\n {/* Sentiment buttons + meta text bar */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => handleSentimentClick(\"positive\")}\n className={cn(\n \"flex gap-1 items-center text-[11px] font-medium rounded-md px-2 py-1 transition-colors\",\n feedback === \"positive\"\n ? SENTIMENT_BUTTON_ACTIVE.positive\n : SENTIMENT_BUTTON_IDLE,\n )}\n >\n <ThumbsUp className=\"h-[11px] w-[11px]\" />\n Helpful\n </button>\n <button\n type=\"button\"\n onClick={() => handleSentimentClick(\"negative\")}\n className={cn(\n \"flex gap-1 items-center text-[11px] font-medium rounded-md px-2 py-1 transition-colors\",\n feedback === \"negative\"\n ? SENTIMENT_BUTTON_ACTIVE.negative\n : SENTIMENT_BUTTON_IDLE,\n )}\n >\n <ThumbsDown className=\"h-[11px] w-[11px]\" />\n Not helpful\n </button>\n </div>\n {metaText && (\n <span className=\"text-[11px] text-muted-foreground\">{metaText}</span>\n )}\n </div>\n\n {/* Expanded feedback area */}\n {expanded && feedback && (\n <div className=\"space-y-3\">\n {/* Prompt text */}\n <p className=\"text-xs text-muted-foreground\">\n {feedback === \"negative\" ? negativePrompt : positivePrompt}\n </p>\n\n {/* Chip area */}\n {feedback === \"negative\" && negativeChips.length > 0 && (\n <div className=\"space-y-2\">\n {/* Tier-1 chips */}\n <FeedbackChipGroup\n chips={negativeChips.map((c) => c.label)}\n selected={allSelectedChips}\n onToggle={handleTier1Toggle}\n flavor=\"negative\"\n />\n\n {/* Tier-2 sub-chips (shown when a tier-1 with sub-chips is active) */}\n {activeTree && activeTree.subChips && (\n <div className=\"pl-3 space-y-1.5\">\n {activeTree.subPrompt && (\n <p className=\"text-[11px] text-muted-foreground\">\n {activeTree.subPrompt}\n </p>\n )}\n <FeedbackChipGroup\n chips={activeTree.subChips}\n selected={selectedTier2 ? [selectedTier2] : []}\n onToggle={handleTier2Toggle}\n flavor=\"negative\"\n />\n </div>\n )}\n </div>\n )}\n\n {feedback === \"positive\" && positiveChips.length > 0 && (\n <FeedbackChipGroup\n chips={positiveChips}\n selected={allSelectedChips}\n onToggle={handlePositiveChipToggle}\n flavor=\"positive\"\n />\n )}\n\n {/* Detail text input */}\n <FeedbackInput\n placeholder=\"Add optional detail…\"\n value={detailText}\n onChange={setDetailText}\n onSubmit={handleSubmit}\n />\n\n {/* Action buttons */}\n <FeedbackActions onSubmit={handleSubmit} onCancel={handleCancel} />\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { QueueItem, SignalScoreData, SignalScoreUrgencyLabel } from '../
|
|
2
|
+
import { Q as QueueItem, l as SignalScoreData, o as SignalScoreUrgencyLabel } from '../signal-priority-popover-DQ_VuHac.js';
|
|
3
|
+
import './feedback-primitives.js';
|
|
3
4
|
import './quick-action-sidebar-nav.js';
|
|
4
5
|
import './quick-action-modal.js';
|
|
5
6
|
import './score-breakdown.js';
|
|
@@ -16,21 +17,11 @@ import './signal-feedback-inline.js';
|
|
|
16
17
|
import 'lucide-react';
|
|
17
18
|
|
|
18
19
|
declare function getSignalScoreUrgencyLabel(score: number, providedLabel?: SignalScoreUrgencyLabel): SignalScoreUrgencyLabel;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
onClick?: () => void;
|
|
25
|
-
className?: string;
|
|
26
|
-
}
|
|
27
|
-
declare function SignalPriorityChip({ score, urgencyLabel: providedLabel, isOpen, controlsId, onClick, className, }: SignalPriorityChipProps): React.JSX.Element;
|
|
28
|
-
interface SignalPriorityPanelProps {
|
|
29
|
-
signalData: SignalScoreData;
|
|
30
|
-
className?: string;
|
|
31
|
-
id?: string;
|
|
32
|
-
}
|
|
33
|
-
declare function SignalPriorityPanel({ signalData, className, id }: SignalPriorityPanelProps): React.JSX.Element;
|
|
20
|
+
declare function scoreRangeForUrgency(label: SignalScoreUrgencyLabel): string;
|
|
21
|
+
/** Shared tone-to-class map. Re-exported for signal-priority-popover. */
|
|
22
|
+
declare const SIGNAL_TONE_CLASSES: Record<string, string>;
|
|
23
|
+
/** Default tone for missing/unknown tone values */
|
|
24
|
+
declare const DEFAULT_TONE_CLASS = "bg-muted text-muted-foreground";
|
|
34
25
|
interface ScoreWhyChipsProps {
|
|
35
26
|
item: QueueItem;
|
|
36
27
|
signalData: SignalScoreData;
|
|
@@ -43,4 +34,4 @@ interface ScoreWhyChipsProps {
|
|
|
43
34
|
}
|
|
44
35
|
declare function ScoreWhyChips({ item, signalData, onOpenSignalBucket, className, }: ScoreWhyChipsProps): React.JSX.Element | null;
|
|
45
36
|
|
|
46
|
-
export {
|
|
37
|
+
export { DEFAULT_TONE_CLASS, SIGNAL_TONE_CLASSES, ScoreWhyChips, type ScoreWhyChipsProps, getSignalScoreUrgencyLabel, scoreRangeForUrgency };
|