@handled-ai/design-system 0.17.0 → 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/badge.d.ts +1 -1
- package/dist/components/button.d.ts +1 -1
- 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/tabs.d.ts +1 -1
- 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 -328
- package/dist/prototype/prototype-inbox-view.d.ts +8 -3
- package/dist/prototype/prototype-inbox-view.js +24 -13
- 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 -0
- package/src/prototype/prototype-inbox-view.tsx +25 -11
|
@@ -3,8 +3,19 @@
|
|
|
3
3
|
"use client";
|
|
4
4
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import * as React from "react";
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
ChevronDown,
|
|
8
|
+
ChevronUp,
|
|
9
|
+
ChevronRight,
|
|
10
|
+
X,
|
|
11
|
+
TrendingDown,
|
|
12
|
+
ArrowUpRight,
|
|
13
|
+
Radar,
|
|
14
|
+
ArrowDownLeft,
|
|
15
|
+
GitMerge,
|
|
16
|
+
Activity
|
|
17
|
+
} from "lucide-react";
|
|
18
|
+
import { FeedbackFooter } from "./feedback-primitives.js";
|
|
8
19
|
import { cn } from "../lib/utils.js";
|
|
9
20
|
function getSignalScoreUrgencyLabel(score, providedLabel) {
|
|
10
21
|
if (providedLabel) return providedLabel;
|
|
@@ -13,25 +24,6 @@ function getSignalScoreUrgencyLabel(score, providedLabel) {
|
|
|
13
24
|
if (score >= 35) return "Medium";
|
|
14
25
|
return "Low";
|
|
15
26
|
}
|
|
16
|
-
function getUrgencyChipClass(label) {
|
|
17
|
-
switch (label) {
|
|
18
|
-
case "Urgent":
|
|
19
|
-
return "border-red-200 bg-red-50 text-red-700 hover:bg-red-100 dark:border-red-900/50 dark:bg-red-950/30 dark:text-red-300";
|
|
20
|
-
case "High":
|
|
21
|
-
return "border-orange-200 bg-orange-50 text-orange-700 hover:bg-orange-100 dark:border-orange-900/50 dark:bg-orange-950/30 dark:text-orange-300";
|
|
22
|
-
case "Medium":
|
|
23
|
-
return "border-amber-200 bg-amber-50 text-amber-700 hover:bg-amber-100 dark:border-amber-900/50 dark:bg-amber-950/30 dark:text-amber-300";
|
|
24
|
-
case "Low":
|
|
25
|
-
return "border-emerald-200 bg-emerald-50 text-emerald-700 hover:bg-emerald-100 dark:border-emerald-900/50 dark:bg-emerald-950/30 dark:text-emerald-300";
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function classificationForScore(score) {
|
|
29
|
-
if (score == null) return void 0;
|
|
30
|
-
if (score >= 80) return "Urgent";
|
|
31
|
-
if (score >= 60) return "High";
|
|
32
|
-
if (score >= 35) return "Medium";
|
|
33
|
-
return "Low";
|
|
34
|
-
}
|
|
35
27
|
function scoreRangeForUrgency(label) {
|
|
36
28
|
switch (label) {
|
|
37
29
|
case "Urgent":
|
|
@@ -47,18 +39,6 @@ function scoreRangeForUrgency(label) {
|
|
|
47
39
|
function makeDomId(...parts) {
|
|
48
40
|
return parts.filter((part) => Boolean(part)).join("-").replace(/[^A-Za-z0-9_-]+/g, "-");
|
|
49
41
|
}
|
|
50
|
-
function scoreFactorToPriorityBucket(factor) {
|
|
51
|
-
var _a, _b, _c;
|
|
52
|
-
return {
|
|
53
|
-
key: factor.key,
|
|
54
|
-
label: factor.label,
|
|
55
|
-
kind: "factor",
|
|
56
|
-
score: (_a = factor.score) != null ? _a : void 0,
|
|
57
|
-
classification: (_c = factor.risk) != null ? _c : classificationForScore((_b = factor.score) != null ? _b : void 0),
|
|
58
|
-
rationale: factor.why,
|
|
59
|
-
factorKeys: [factor.key]
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
42
|
function bucketHasSignalRows(bucket) {
|
|
63
43
|
var _a, _b, _c, _d;
|
|
64
44
|
return ((_b = (_a = bucket.signals) == null ? void 0 : _a.length) != null ? _b : 0) > 0 || ((_d = (_c = bucket.signalIds) == null ? void 0 : _c.length) != null ? _d : 0) > 0 || Boolean(bucket.primarySignalId);
|
|
@@ -78,119 +58,253 @@ function getBucketSignals(bucket) {
|
|
|
78
58
|
label: `${bucket.label} signal`
|
|
79
59
|
}));
|
|
80
60
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
61
|
+
const SIGNAL_TYPE_ICONS = {
|
|
62
|
+
treasury_liquidation: TrendingDown,
|
|
63
|
+
cumulative_treasury_outflow: ArrowUpRight,
|
|
64
|
+
test_transaction: Radar,
|
|
65
|
+
micro_deposit: ArrowDownLeft,
|
|
66
|
+
combined_signal: GitMerge
|
|
67
|
+
};
|
|
68
|
+
function resolveIcon(iconName) {
|
|
69
|
+
var _a;
|
|
70
|
+
if (!iconName) return Activity;
|
|
71
|
+
return (_a = SIGNAL_TYPE_ICONS[iconName]) != null ? _a : Activity;
|
|
84
72
|
}
|
|
85
|
-
|
|
86
|
-
|
|
73
|
+
const SIGNAL_TONE_CLASSES = {
|
|
74
|
+
alert: "bg-red-50 text-red-600",
|
|
75
|
+
warn: "bg-amber-50 text-amber-600",
|
|
76
|
+
info: "bg-blue-50 text-blue-600"
|
|
77
|
+
};
|
|
78
|
+
const DEFAULT_TONE_CLASS = "bg-muted text-muted-foreground";
|
|
79
|
+
function slotValue(value) {
|
|
80
|
+
return value && value.trim().length > 0 ? value : "";
|
|
87
81
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
82
|
+
const BUCKET_NEGATIVE_CHIPS = [
|
|
83
|
+
{
|
|
84
|
+
label: "Not relevant for this account",
|
|
85
|
+
subPrompt: "Why isn't it relevant?",
|
|
86
|
+
subChips: [
|
|
87
|
+
"Business as usual for this account",
|
|
88
|
+
"Account in maintenance mode",
|
|
89
|
+
"Wrong contact for this signal",
|
|
90
|
+
"Other"
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
{ label: "Bad timing" },
|
|
94
|
+
{
|
|
95
|
+
label: "Inaccurate data",
|
|
96
|
+
subPrompt: "Which field?",
|
|
97
|
+
subChips: ["Balance figures", "Counterparty", "Timestamp", "Other"]
|
|
98
|
+
},
|
|
99
|
+
{ label: "Wrong account" },
|
|
100
|
+
{ label: "Already handled" },
|
|
101
|
+
{ label: "Other" }
|
|
102
|
+
];
|
|
103
|
+
const DEFAULT_VISIBLE_ROWS = 8;
|
|
104
|
+
function WhyPill({ bucket, isSelected, signalCount, panelId, onToggle, onClose }) {
|
|
105
|
+
const IconComponent = resolveIcon(bucket.icon);
|
|
106
|
+
const sharedClasses = cn(
|
|
107
|
+
"inline-flex items-center text-[11px] font-semibold transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
108
|
+
isSelected ? "border-border bg-muted text-foreground" : "border-border bg-background text-muted-foreground hover:bg-muted/60 hover:text-foreground"
|
|
115
109
|
);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
"
|
|
131
|
-
|
|
132
|
-
"
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
/* @__PURE__ */ jsxs("span", { className: "rounded-full bg-background px-2 py-0.5", children: [
|
|
143
|
-
urgencyLabel,
|
|
144
|
-
" range: ",
|
|
145
|
-
scoreRange
|
|
146
|
-
] })
|
|
147
|
-
] })
|
|
148
|
-
] }),
|
|
149
|
-
(whyNowSection || topFactorSection) && /* @__PURE__ */ jsxs("div", { className: "mt-3 grid gap-2 text-xs text-muted-foreground sm:grid-cols-2", children: [
|
|
150
|
-
whyNowSection ? /* @__PURE__ */ jsxs("div", { className: "rounded-md bg-background/80 p-2", children: [
|
|
151
|
-
/* @__PURE__ */ jsx("p", { className: "font-medium text-foreground", children: "Why now" }),
|
|
152
|
-
/* @__PURE__ */ jsx("p", { className: "mt-0.5 leading-relaxed", children: whyNowSection })
|
|
153
|
-
] }) : null,
|
|
154
|
-
topFactorSection ? /* @__PURE__ */ jsxs("div", { className: "rounded-md bg-background/80 p-2", children: [
|
|
155
|
-
/* @__PURE__ */ jsx("p", { className: "font-medium text-foreground", children: "Top factor" }),
|
|
156
|
-
/* @__PURE__ */ jsx("p", { className: "mt-0.5 leading-relaxed", children: topFactorSection })
|
|
157
|
-
] }) : null
|
|
158
|
-
] }),
|
|
159
|
-
signalData.factors.length > 0 ? /* @__PURE__ */ jsx(
|
|
160
|
-
ScoreBreakdown,
|
|
110
|
+
return /* @__PURE__ */ jsxs("div", { className: "inline-flex h-[26px] items-stretch", children: [
|
|
111
|
+
/* @__PURE__ */ jsxs(
|
|
112
|
+
"button",
|
|
113
|
+
{
|
|
114
|
+
type: "button",
|
|
115
|
+
onClick: onToggle,
|
|
116
|
+
"aria-expanded": isSelected,
|
|
117
|
+
"aria-controls": panelId,
|
|
118
|
+
className: cn(
|
|
119
|
+
sharedClasses,
|
|
120
|
+
"gap-1.5 rounded-lg border px-2.5 py-1",
|
|
121
|
+
isSelected && "rounded-b-none rounded-r-none border-r-0"
|
|
122
|
+
),
|
|
123
|
+
children: [
|
|
124
|
+
/* @__PURE__ */ jsx(IconComponent, { className: "h-3 w-3 shrink-0" }),
|
|
125
|
+
bucket.label,
|
|
126
|
+
signalCount > 1 && /* @__PURE__ */ jsxs("span", { className: cn("rounded-full px-1.5 py-0 text-[10px]", isSelected ? "bg-background/60" : "bg-muted"), children: [
|
|
127
|
+
"x",
|
|
128
|
+
signalCount
|
|
129
|
+
] }),
|
|
130
|
+
isSelected ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-3 w-3 shrink-0" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3 shrink-0" })
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
),
|
|
134
|
+
isSelected && /* @__PURE__ */ jsx(
|
|
135
|
+
"button",
|
|
161
136
|
{
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
137
|
+
type: "button",
|
|
138
|
+
"aria-label": `Close ${bucket.label}`,
|
|
139
|
+
onClick: onClose,
|
|
140
|
+
className: cn(
|
|
141
|
+
sharedClasses,
|
|
142
|
+
"rounded-lg rounded-b-none rounded-l-none border border-l-0 border-border px-1.5 py-1 hover:bg-background/60"
|
|
143
|
+
),
|
|
144
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
|
|
166
145
|
}
|
|
167
|
-
)
|
|
146
|
+
)
|
|
168
147
|
] });
|
|
169
148
|
}
|
|
170
|
-
function
|
|
149
|
+
function CombinedSignalMiniChips({ components }) {
|
|
150
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-1", children: components.map((comp, idx) => {
|
|
151
|
+
const CompIcon = resolveIcon(comp.type);
|
|
152
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
153
|
+
idx > 0 && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground/60", children: "+" }),
|
|
154
|
+
/* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-0.5 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground", children: [
|
|
155
|
+
/* @__PURE__ */ jsx(CompIcon, { className: "h-2.5 w-2.5 shrink-0" }),
|
|
156
|
+
comp.type.replace(/_/g, " "),
|
|
157
|
+
" x",
|
|
158
|
+
comp.count
|
|
159
|
+
] })
|
|
160
|
+
] }, comp.type);
|
|
161
|
+
}) });
|
|
162
|
+
}
|
|
163
|
+
function StructuredSignalRow({ item, bucketKey, signal, tone, onOpenSignalBucket }) {
|
|
164
|
+
var _a;
|
|
165
|
+
const IconComponent = resolveIcon(signal.signalTypeName);
|
|
166
|
+
const toneClass = tone ? (_a = SIGNAL_TONE_CLASSES[tone]) != null ? _a : DEFAULT_TONE_CLASS : DEFAULT_TONE_CLASS;
|
|
167
|
+
const isCombined = signal.signalTypeName === "combined_signal" && signal.components && signal.components.length > 0;
|
|
171
168
|
const rowContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
172
|
-
/* @__PURE__ */
|
|
169
|
+
/* @__PURE__ */ jsx("div", { className: cn("flex h-5 w-5 shrink-0 items-center justify-center rounded", toneClass), children: /* @__PURE__ */ jsx(IconComponent, { className: "h-3 w-3" }) }),
|
|
170
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0", children: isCombined ? /* @__PURE__ */ jsx(CombinedSignalMiniChips, { components: signal.components }) : /* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-1.5", children: [
|
|
171
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold tabular-nums text-foreground", children: slotValue(signal.primaryValue) }),
|
|
172
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: slotValue(signal.qualifier) })
|
|
173
|
+
] }) }),
|
|
174
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsx("span", { className: "block truncate text-xs text-muted-foreground", children: slotValue(signal.counterparty) }) }),
|
|
175
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-[11px] text-muted-foreground/70", children: slotValue(signal.time) }),
|
|
176
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 shrink-0 text-muted-foreground/60 transition-transform group-hover:translate-x-0.5 group-hover:text-foreground/50" })
|
|
177
|
+
] });
|
|
178
|
+
if (signal.id && onOpenSignalBucket) {
|
|
179
|
+
return /* @__PURE__ */ jsx(
|
|
180
|
+
"button",
|
|
181
|
+
{
|
|
182
|
+
type: "button",
|
|
183
|
+
className: "group grid w-full cursor-pointer items-center gap-x-3 gap-y-1 rounded-md px-3 py-2 text-left transition-colors hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
184
|
+
style: { gridTemplateColumns: "20px minmax(0,1fr) minmax(0,1fr) auto 16px" },
|
|
185
|
+
onClick: () => onOpenSignalBucket({ item, bucketKey, signalId: signal.id }),
|
|
186
|
+
children: rowContent
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
return /* @__PURE__ */ jsx(
|
|
191
|
+
"div",
|
|
192
|
+
{
|
|
193
|
+
className: "grid w-full items-center gap-x-3 gap-y-1 rounded-md px-3 py-2",
|
|
194
|
+
style: { gridTemplateColumns: "20px minmax(0,1fr) minmax(0,1fr) auto 16px" },
|
|
195
|
+
children: rowContent
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
function LegacySignalRow({ item, bucketKey, signal, onOpenSignalBucket }) {
|
|
200
|
+
const isClickable = !!(signal.id && onOpenSignalBucket);
|
|
201
|
+
const rowContent = /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
202
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
173
203
|
/* @__PURE__ */ jsx("p", { className: "font-medium text-foreground", children: signal.label }),
|
|
174
|
-
signal.
|
|
204
|
+
signal.description ? /* @__PURE__ */ jsx("p", { className: "mt-1 leading-relaxed text-muted-foreground", children: signal.description }) : null,
|
|
205
|
+
(signal.source || signal.metric) && /* @__PURE__ */ jsxs("div", { className: "mt-1.5 flex flex-wrap gap-1.5 text-[11px] text-muted-foreground/80", children: [
|
|
206
|
+
signal.source ? /* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-2 py-0.5", children: signal.source }) : null,
|
|
207
|
+
signal.metric ? /* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-2 py-0.5", children: signal.metric }) : null
|
|
208
|
+
] })
|
|
175
209
|
] }),
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
signal.metric ? /* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-2 py-0.5", children: signal.metric }) : null
|
|
210
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
211
|
+
signal.time ? /* @__PURE__ */ jsx("span", { className: "text-[11px] text-muted-foreground/70", children: signal.time }) : null,
|
|
212
|
+
isClickable && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 text-muted-foreground/60 transition-transform group-hover:translate-x-0.5 group-hover:text-foreground/50" })
|
|
180
213
|
] })
|
|
181
|
-
] });
|
|
182
|
-
if (
|
|
214
|
+
] }) });
|
|
215
|
+
if (isClickable) {
|
|
183
216
|
return /* @__PURE__ */ jsx(
|
|
184
217
|
"button",
|
|
185
218
|
{
|
|
186
219
|
type: "button",
|
|
187
|
-
className: "w-full rounded-md bg-background/80 p-
|
|
220
|
+
className: "group w-full cursor-pointer rounded-md bg-background/80 p-3 text-left text-xs transition-colors hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
188
221
|
onClick: () => onOpenSignalBucket({ item, bucketKey, signalId: signal.id }),
|
|
189
222
|
children: rowContent
|
|
190
223
|
}
|
|
191
224
|
);
|
|
192
225
|
}
|
|
193
|
-
return /* @__PURE__ */ jsx("div", { className: "rounded-md bg-background/80 p-
|
|
226
|
+
return /* @__PURE__ */ jsx("div", { className: "rounded-md bg-background/80 p-3 text-xs", children: rowContent });
|
|
227
|
+
}
|
|
228
|
+
function hasStructuredData(signal) {
|
|
229
|
+
return Boolean(
|
|
230
|
+
signal.primaryValue || signal.qualifier || signal.counterparty || signal.components && signal.components.length > 0
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
function WhyCard({ bucket, signals, item, panelId, onOpenSignalBucket, onBucketFeedback }) {
|
|
234
|
+
var _a;
|
|
235
|
+
const [showAll, setShowAll] = React.useState(false);
|
|
236
|
+
const [bucketFeedback, setBucketFeedback] = React.useState(null);
|
|
237
|
+
const totalCount = (_a = bucket.signalCount) != null ? _a : signals.length;
|
|
238
|
+
const visibleSignals = showAll ? signals : signals.slice(0, DEFAULT_VISIBLE_ROWS);
|
|
239
|
+
const hiddenCount = signals.length - DEFAULT_VISIBLE_ROWS;
|
|
240
|
+
const useStructured = signals.some(hasStructuredData);
|
|
241
|
+
return /* @__PURE__ */ jsxs(
|
|
242
|
+
"div",
|
|
243
|
+
{
|
|
244
|
+
id: panelId,
|
|
245
|
+
className: "rounded-lg rounded-t-none border border-t-0 border-border bg-muted/20 p-3",
|
|
246
|
+
role: "region",
|
|
247
|
+
"aria-label": `${bucket.label} details`,
|
|
248
|
+
children: [
|
|
249
|
+
/* @__PURE__ */ jsx("div", { className: "mb-2 flex items-center justify-between", children: /* @__PURE__ */ jsxs("span", { className: "text-[10px] font-bold uppercase tracking-wider text-muted-foreground", children: [
|
|
250
|
+
totalCount,
|
|
251
|
+
" signal",
|
|
252
|
+
totalCount !== 1 ? "s" : "",
|
|
253
|
+
" \u2013 ",
|
|
254
|
+
bucket.label
|
|
255
|
+
] }) }),
|
|
256
|
+
visibleSignals.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "divide-y divide-border/30", "aria-label": "Matching signals", children: visibleSignals.map((signal, index) => {
|
|
257
|
+
var _a2;
|
|
258
|
+
return /* @__PURE__ */ jsx("li", { children: useStructured ? /* @__PURE__ */ jsx(
|
|
259
|
+
StructuredSignalRow,
|
|
260
|
+
{
|
|
261
|
+
item,
|
|
262
|
+
bucketKey: bucket.key,
|
|
263
|
+
signal,
|
|
264
|
+
tone: bucket.tone,
|
|
265
|
+
onOpenSignalBucket
|
|
266
|
+
}
|
|
267
|
+
) : /* @__PURE__ */ jsx(
|
|
268
|
+
LegacySignalRow,
|
|
269
|
+
{
|
|
270
|
+
item,
|
|
271
|
+
bucketKey: bucket.key,
|
|
272
|
+
signal,
|
|
273
|
+
onOpenSignalBucket
|
|
274
|
+
}
|
|
275
|
+
) }, (_a2 = signal.id) != null ? _a2 : `${bucket.key}-signal-${index}`);
|
|
276
|
+
}) }) : bucket.evidence && bucket.evidence.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "mt-3 space-y-1.5", "aria-label": "Matching signals", children: bucket.evidence.map((evidence, index) => /* @__PURE__ */ jsxs("li", { className: "flex gap-2 text-xs text-muted-foreground", children: [
|
|
277
|
+
/* @__PURE__ */ jsx("span", { className: "mt-1.5 h-1 w-1 shrink-0 rounded-full bg-primary" }),
|
|
278
|
+
/* @__PURE__ */ jsx("span", { className: "leading-relaxed", children: evidence })
|
|
279
|
+
] }, `${bucket.key}-evidence-${index}`)) }) : null,
|
|
280
|
+
!showAll && hiddenCount > 0 && /* @__PURE__ */ jsxs(
|
|
281
|
+
"button",
|
|
282
|
+
{
|
|
283
|
+
type: "button",
|
|
284
|
+
onClick: () => setShowAll(true),
|
|
285
|
+
className: "mt-2 flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground",
|
|
286
|
+
children: [
|
|
287
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3" }),
|
|
288
|
+
"Show ",
|
|
289
|
+
hiddenCount,
|
|
290
|
+
" more"
|
|
291
|
+
]
|
|
292
|
+
}
|
|
293
|
+
),
|
|
294
|
+
onBucketFeedback && /* @__PURE__ */ jsx("div", { className: "mt-3 border-t border-border/40 pt-3", children: /* @__PURE__ */ jsx(
|
|
295
|
+
FeedbackFooter,
|
|
296
|
+
{
|
|
297
|
+
feedback: bucketFeedback,
|
|
298
|
+
onFeedbackChange: setBucketFeedback,
|
|
299
|
+
onSubmit: (data) => onBucketFeedback(bucket.key, data),
|
|
300
|
+
negativeChips: BUCKET_NEGATIVE_CHIPS,
|
|
301
|
+
negativePrompt: "Was this bucket useful?",
|
|
302
|
+
positivePrompt: "Thanks! What was useful about this bucket?"
|
|
303
|
+
}
|
|
304
|
+
) })
|
|
305
|
+
]
|
|
306
|
+
}
|
|
307
|
+
);
|
|
194
308
|
}
|
|
195
309
|
function ScoreWhyChips({
|
|
196
310
|
item,
|
|
@@ -198,7 +312,7 @@ function ScoreWhyChips({
|
|
|
198
312
|
onOpenSignalBucket,
|
|
199
313
|
className
|
|
200
314
|
}) {
|
|
201
|
-
var _a
|
|
315
|
+
var _a;
|
|
202
316
|
const [selectedBucketKey, setSelectedBucketKey] = React.useState(null);
|
|
203
317
|
React.useEffect(() => {
|
|
204
318
|
setSelectedBucketKey(null);
|
|
@@ -213,69 +327,41 @@ function ScoreWhyChips({
|
|
|
213
327
|
return /* @__PURE__ */ jsxs("div", { className: cn("mt-4", className), children: [
|
|
214
328
|
/* @__PURE__ */ jsx("div", { className: "mb-2 flex items-center gap-2", children: /* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold uppercase tracking-wider text-muted-foreground", children: "Why" }) }),
|
|
215
329
|
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: buckets.map((bucket) => {
|
|
330
|
+
var _a2;
|
|
216
331
|
const isSelected = selectedBucketKey === bucket.key;
|
|
217
332
|
const panelId = `${idPrefix}-panel-${makeDomId(bucket.key)}`;
|
|
218
|
-
|
|
219
|
-
|
|
333
|
+
const signals = getBucketSignals(bucket);
|
|
334
|
+
const signalCount = (_a2 = bucket.signalCount) != null ? _a2 : signals.length;
|
|
335
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-col", children: /* @__PURE__ */ jsx(
|
|
336
|
+
WhyPill,
|
|
220
337
|
{
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
children: [
|
|
230
|
-
bucket.label,
|
|
231
|
-
bucket.signalCount && bucket.signalCount > 1 ? /* @__PURE__ */ jsxs("span", { className: cn("rounded-full px-1.5 py-0 text-[10px]", isSelected ? "bg-background/20" : "bg-muted"), children: [
|
|
232
|
-
"\xD7",
|
|
233
|
-
bucket.signalCount
|
|
234
|
-
] }) : null
|
|
235
|
-
]
|
|
236
|
-
},
|
|
237
|
-
bucket.key
|
|
238
|
-
);
|
|
338
|
+
bucket,
|
|
339
|
+
isSelected,
|
|
340
|
+
signalCount,
|
|
341
|
+
panelId,
|
|
342
|
+
onToggle: () => setSelectedBucketKey((prev) => prev === bucket.key ? null : bucket.key),
|
|
343
|
+
onClose: () => setSelectedBucketKey(null)
|
|
344
|
+
}
|
|
345
|
+
) }, bucket.key);
|
|
239
346
|
}) }),
|
|
240
|
-
selectedBucket && /* @__PURE__ */
|
|
241
|
-
|
|
347
|
+
selectedBucket && selectedPanelId && /* @__PURE__ */ jsx(
|
|
348
|
+
WhyCard,
|
|
242
349
|
{
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: selectedBucket.label }),
|
|
250
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 flex flex-wrap gap-1.5 text-[11px] text-muted-foreground", children: /* @__PURE__ */ jsxs("span", { className: "rounded-full bg-background px-2 py-0.5", children: [
|
|
251
|
-
(_b = selectedBucket.signalCount) != null ? _b : selectedBucketSignals.length,
|
|
252
|
-
" signals"
|
|
253
|
-
] }) })
|
|
254
|
-
] }) }),
|
|
255
|
-
selectedBucketSignals.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "mt-3 space-y-2", "aria-label": "Matching signals", children: selectedBucketSignals.map((signal, index) => {
|
|
256
|
-
var _a2;
|
|
257
|
-
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
258
|
-
SignalRow,
|
|
259
|
-
{
|
|
260
|
-
item,
|
|
261
|
-
bucketKey: selectedBucket.key,
|
|
262
|
-
signal,
|
|
263
|
-
onOpenSignalBucket
|
|
264
|
-
}
|
|
265
|
-
) }, (_a2 = signal.id) != null ? _a2 : `${selectedBucket.key}-signal-${index}`);
|
|
266
|
-
}) }) : selectedBucket.evidence && selectedBucket.evidence.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "mt-3 space-y-1.5", "aria-label": "Matching signals", children: selectedBucket.evidence.map((evidence, index) => /* @__PURE__ */ jsxs("li", { className: "flex gap-2 text-xs text-muted-foreground", children: [
|
|
267
|
-
/* @__PURE__ */ jsx("span", { className: "mt-1.5 h-1 w-1 shrink-0 rounded-full bg-primary" }),
|
|
268
|
-
/* @__PURE__ */ jsx("span", { className: "leading-relaxed", children: evidence })
|
|
269
|
-
] }, `${selectedBucket.key}-evidence-${index}`)) }) : null
|
|
270
|
-
]
|
|
350
|
+
bucket: selectedBucket,
|
|
351
|
+
signals: selectedBucketSignals,
|
|
352
|
+
item,
|
|
353
|
+
panelId: selectedPanelId,
|
|
354
|
+
onOpenSignalBucket,
|
|
355
|
+
onBucketFeedback: signalData.onBucketFeedback
|
|
271
356
|
}
|
|
272
357
|
)
|
|
273
358
|
] });
|
|
274
359
|
}
|
|
275
360
|
export {
|
|
361
|
+
DEFAULT_TONE_CLASS,
|
|
362
|
+
SIGNAL_TONE_CLASSES,
|
|
276
363
|
ScoreWhyChips,
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
getSignalScoreUrgencyLabel
|
|
364
|
+
getSignalScoreUrgencyLabel,
|
|
365
|
+
scoreRangeForUrgency
|
|
280
366
|
};
|
|
281
367
|
//# sourceMappingURL=score-why-chips.js.map
|