@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.
Files changed (51) hide show
  1. package/dist/components/badge.d.ts +1 -1
  2. package/dist/components/button.d.ts +1 -1
  3. package/dist/components/feedback-primitives.d.ts +66 -0
  4. package/dist/components/feedback-primitives.js +295 -0
  5. package/dist/components/feedback-primitives.js.map +1 -0
  6. package/dist/components/score-why-chips.d.ts +8 -17
  7. package/dist/components/score-why-chips.js +266 -180
  8. package/dist/components/score-why-chips.js.map +1 -1
  9. package/dist/components/signal-priority-popover.d.ts +17 -0
  10. package/dist/components/signal-priority-popover.js +247 -0
  11. package/dist/components/signal-priority-popover.js.map +1 -0
  12. package/dist/components/tabs.d.ts +1 -1
  13. package/dist/components/user-display.d.ts +22 -0
  14. package/dist/components/user-display.js +138 -0
  15. package/dist/components/user-display.js.map +1 -0
  16. package/dist/components/user-pill.d.ts +3 -0
  17. package/dist/components/user-pill.js +5 -0
  18. package/dist/components/user-pill.js.map +1 -0
  19. package/dist/index.d.ts +6 -3
  20. package/dist/index.js +12 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/lib/user-display.d.ts +31 -0
  23. package/dist/lib/user-display.js +57 -0
  24. package/dist/lib/user-display.js.map +1 -0
  25. package/dist/prototype/index.d.ts +2 -1
  26. package/dist/prototype/prototype-accounts-view.d.ts +2 -1
  27. package/dist/prototype/prototype-admin-view.d.ts +2 -1
  28. package/dist/prototype/prototype-config.d.ts +15 -328
  29. package/dist/prototype/prototype-inbox-view.d.ts +8 -3
  30. package/dist/prototype/prototype-inbox-view.js +24 -13
  31. package/dist/prototype/prototype-inbox-view.js.map +1 -1
  32. package/dist/prototype/prototype-insights-view.d.ts +2 -1
  33. package/dist/prototype/prototype-shell.d.ts +2 -1
  34. package/dist/signal-priority-popover-DQ_VuHac.d.ts +390 -0
  35. package/package.json +1 -1
  36. package/src/components/__tests__/contextual-quick-action-launcher.test.tsx +99 -188
  37. package/src/components/__tests__/feedback-primitives.test.tsx +509 -0
  38. package/src/components/__tests__/score-why-chips.test.tsx +540 -0
  39. package/src/components/__tests__/signal-priority-popover.test.tsx +312 -0
  40. package/src/components/feedback-primitives.tsx +424 -0
  41. package/src/components/score-why-chips.tsx +413 -203
  42. package/src/components/signal-priority-popover.tsx +359 -0
  43. package/src/components/user-display.tsx +96 -0
  44. package/src/components/user-pill.tsx +1 -0
  45. package/src/index.ts +6 -0
  46. package/src/lib/__tests__/user-display.test.ts +43 -0
  47. package/src/lib/user-display.ts +88 -0
  48. package/src/prototype/__tests__/detail-view-score-why.test.tsx +33 -29
  49. package/src/prototype/__tests__/detail-view-title-slots.test.tsx +65 -0
  50. package/src/prototype/prototype-config.ts +28 -0
  51. package/src/prototype/prototype-inbox-view.tsx +25 -11
@@ -0,0 +1,390 @@
1
+ import * as React from 'react';
2
+ import { FeedbackChipTree, FeedbackSubmitData } from './components/feedback-primitives.js';
3
+ import { SidebarNavSection } from './components/quick-action-sidebar-nav.js';
4
+ import { ScoreFactor } from './components/score-breakdown.js';
5
+ import { SuggestedContact, SuggestedAction } from './components/suggested-actions.js';
6
+ import { SourceDef } from './components/detail-view.js';
7
+ import { InboxFilterCategory } from './components/inbox-toolbar.js';
8
+ import { DataTableFilterCategory } from './components/data-table-filter.js';
9
+ import { DataRow } from './components/data-table.js';
10
+ import { MetricCardProps } from './components/metric-card.js';
11
+ import { PipelineStage, PipelineStageMetrics, PipelineStageTiming } from './charts/pipeline-overview.js';
12
+ import { TimelineEvent } from './components/timeline-activity.js';
13
+ import { ApprovalState } from './components/signal-feedback-inline.js';
14
+ import { LucideIcon } from 'lucide-react';
15
+
16
+ interface PrototypeBrandConfig {
17
+ name: string;
18
+ logo?: string;
19
+ assistantName?: string;
20
+ }
21
+ interface QueueItem {
22
+ id: string;
23
+ title: string;
24
+ details: string;
25
+ statusColor: string;
26
+ time: string;
27
+ company: string;
28
+ tag1: string;
29
+ }
30
+ type SignalScoreUrgencyLabel = "Low" | "Medium" | "High" | "Urgent";
31
+ interface SignalScoreExplanationSignal {
32
+ id?: string;
33
+ label: string;
34
+ description?: string;
35
+ source?: string;
36
+ time?: string;
37
+ metric?: string;
38
+ /** Signal type name (e.g., "treasury_liquidation"). Used for combined signal component identification. */
39
+ signalTypeName?: string;
40
+ /** Primary display value (e.g., "-$1,724,310.11"). */
41
+ primaryValue?: string;
42
+ /** Qualifier text (e.g., "100% of balance"). */
43
+ qualifier?: string;
44
+ /** Counterparty / destination (e.g., "-> JPMorgan Chase --6042"). */
45
+ counterparty?: string;
46
+ /** Component breakdown for combined signals. */
47
+ components?: Array<{
48
+ type: string;
49
+ count: number;
50
+ }>;
51
+ }
52
+ interface SignalScoreExplanationBucket {
53
+ key: string;
54
+ label: string;
55
+ kind: "signal" | "factor" | "merged";
56
+ score?: number;
57
+ classification?: string;
58
+ rationale?: string;
59
+ evidence?: string[];
60
+ signals?: SignalScoreExplanationSignal[];
61
+ primaryMetricLabel?: string;
62
+ primaryMetricValue?: string;
63
+ signalCount?: number;
64
+ signalIds?: string[];
65
+ primarySignalId?: string;
66
+ factorKeys?: string[];
67
+ /** Lucide icon name for the bucket type (e.g., "trending-down"). */
68
+ icon?: string;
69
+ /** Tonal styling hint for the bucket. */
70
+ tone?: "alert" | "warn" | "info";
71
+ }
72
+ interface SignalScoreData {
73
+ score: number;
74
+ factors: ScoreFactor[];
75
+ whyNow: string;
76
+ evidence: string[];
77
+ confidence: number;
78
+ urgencyLabel?: SignalScoreUrgencyLabel;
79
+ urgencyExplanation?: string;
80
+ explanationBuckets?: SignalScoreExplanationBucket[];
81
+ onFactorFeedback?: (factorKey: string, type: "up" | "down" | null, detail?: string) => void;
82
+ /** @deprecated The compact score UX no longer renders score-level thumbs by default. */
83
+ onScoreFeedback?: (type: "up" | "down", pills: string[], detail: string) => void;
84
+ onApproveFeedback?: (reasons: string[], detail: string) => void;
85
+ onDismissFeedback?: (reasons: string[], detail: string, subReason?: string) => void;
86
+ /** @deprecated The compact score UX no longer renders score-level thumbs by default. */
87
+ initialScoreFeedback?: {
88
+ type: "up" | "down";
89
+ pills: string[];
90
+ detail: string;
91
+ } | null;
92
+ initialFactorFeedback?: Record<string, {
93
+ type: "up" | "down";
94
+ detail: string;
95
+ }>;
96
+ /** Priority factors for the popover breakdown. */
97
+ priorityFactors?: PriorityFactor[];
98
+ /** Negative feedback chip tree for the priority popover. */
99
+ priorityFeedbackChips?: FeedbackChipTree[];
100
+ /** Callback when user submits priority-level feedback. */
101
+ onPriorityFeedback?: (data: FeedbackSubmitData) => void;
102
+ /** Callback when user submits bucket-level feedback. */
103
+ onBucketFeedback?: (bucketKey: string, data: FeedbackSubmitData) => void;
104
+ /** AI-generated signal brief text. When present, rendered in a dedicated section. */
105
+ signalBrief?: string;
106
+ /** Compact label for time-remaining chip (e.g., "13 days left"). */
107
+ timeChipLabel?: string;
108
+ /** Expanded detail for time chip popover (e.g., "Day 2 of 14 · Event detected on May 1"). */
109
+ timeChipDetail?: string;
110
+ }
111
+ interface InboxSortOption {
112
+ id: string;
113
+ label: string;
114
+ }
115
+ /** Controls the visual prominence of the signal brief section. */
116
+ type BriefStyleVariant = "default" | "prominent";
117
+ interface InboxDetailSections {
118
+ signalBrief?: boolean;
119
+ suggestedActions?: boolean;
120
+ timeline?: boolean;
121
+ }
122
+ interface InboxViewConfig {
123
+ items: QueueItem[];
124
+ filterCategories?: InboxFilterCategory[];
125
+ detailSections?: InboxDetailSections;
126
+ accountContacts?: SuggestedContact[];
127
+ buildAccountContacts?: (item: QueueItem) => SuggestedContact[];
128
+ emailSignature?: string | React.ReactNode;
129
+ buildSuggestedActions?: (item: QueueItem) => SuggestedAction[];
130
+ buildSourceItems?: (item: QueueItem) => SourceDef[];
131
+ getSignalScore?: (company: string, item?: QueueItem) => SignalScoreData;
132
+ getTimelineEvents?: (item: QueueItem) => TimelineEvent[];
133
+ iconMap?: Record<string, string>;
134
+ hideToolbarActions?: boolean;
135
+ hideHoverActions?: boolean;
136
+ onSuggestedActionFeedback?: (actionId: number | string, feedback: string, actionTitle?: string) => void;
137
+ /** @deprecated The compact score UX no longer renders score-level thumbs by default. */
138
+ onScoreFeedback?: (type: "up" | "down", pills: string[], detail: string) => void;
139
+ onOpenSignalBucket?: (args: {
140
+ item: QueueItem;
141
+ bucketKey: string;
142
+ signalId: string;
143
+ }) => void;
144
+ buildEntityChips?: (item: QueueItem) => Array<{
145
+ id: string;
146
+ label: string;
147
+ avatarLetter: string;
148
+ onClick?: () => void;
149
+ }>;
150
+ quickFilterTabs?: Array<{
151
+ id: string;
152
+ label: string;
153
+ matchValue?: string;
154
+ count?: number;
155
+ }>;
156
+ hideAccountsButton?: boolean;
157
+ accountDetailsLabel?: string;
158
+ onSignalApprove?: (item: QueueItem) => void | Promise<boolean>;
159
+ getSignalApprovalState?: (item: QueueItem) => ApprovalState | undefined;
160
+ signalLabels?: {
161
+ approveButton?: string;
162
+ dismissButton?: string;
163
+ approvedStatus?: string;
164
+ dismissedStatus?: string;
165
+ opportunityCreated?: string;
166
+ confirmPrompt?: string;
167
+ creatingStatus?: string;
168
+ };
169
+ /** When true, the approve/create-opportunity button is hidden but the dismiss button remains. */
170
+ hideApproveButton?: boolean;
171
+ /**
172
+ * Override the copy used in the detail panel "Signal brief" section.
173
+ * Useful when the prototype represents an internal ops inbox rather than
174
+ * an outbound sales signal — the default heading and intro line are
175
+ * written for the latter.
176
+ */
177
+ signalBriefCopy?: {
178
+ /** Section heading (default: "Signal brief"). Pass an empty string to hide. */
179
+ heading?: string;
180
+ /**
181
+ * Introductory line rendered above the per-item `whyNow` text.
182
+ * Receives the `QueueItem` so the caller can interpolate the company
183
+ * name or other fields. Pass `null` (or a function returning `null`)
184
+ * to suppress the intro line entirely.
185
+ */
186
+ intro?: string | ((item: QueueItem) => string | null) | null;
187
+ };
188
+ /** Controls the visual prominence of the signal brief section.
189
+ * - "default": current styling (muted intro, text-foreground/90 brief)
190
+ * - "prominent": standard foreground color, text-base size for the brief
191
+ */
192
+ briefStyleVariant?: BriefStyleVariant;
193
+ /** Render extra content at the end of the detail view, below the suggested actions section. */
194
+ renderDetailExtra?: (item: QueueItem) => React.ReactNode;
195
+ /** Render content between the signal brief text and the signal score bar (e.g. "Signals on Case" chips). */
196
+ renderBeforeScore?: (item: QueueItem) => React.ReactNode;
197
+ /** Render content between the signal score section and the activity timeline (e.g. OpportunityPanel). */
198
+ renderAfterScore?: (item: QueueItem) => React.ReactNode;
199
+ /** Formatted string for "Last activity X ago" in the collapsed timeline header. If omitted, falls back to the first event's time. */
200
+ lastActivityTime?: string;
201
+ /** Render extra content inline with the detail title. */
202
+ renderTitleExtra?: (item: QueueItem) => React.ReactNode;
203
+ /** Render supporting content below the detail title. */
204
+ renderTitleSubtext?: (item: QueueItem) => React.ReactNode;
205
+ /** Sort options for the inbox. When provided, a sort dropdown is rendered in the split view toolbar. */
206
+ sortOptions?: InboxSortOption[];
207
+ /** Currently active sort option id. */
208
+ activeSortId?: string;
209
+ /** Callback when the user changes the sort option. */
210
+ onSortChange?: (sortId: string) => void;
211
+ }
212
+ interface InsightsCustomTab {
213
+ id: string;
214
+ label: string;
215
+ icon?: React.ComponentType<{
216
+ className?: string;
217
+ }>;
218
+ content: React.ReactNode;
219
+ }
220
+ interface InsightsViewConfig {
221
+ customTabs?: InsightsCustomTab[];
222
+ tabs?: {
223
+ overview?: boolean;
224
+ analytics?: boolean;
225
+ };
226
+ coaching?: {
227
+ enabled?: boolean;
228
+ message?: string;
229
+ };
230
+ metrics?: MetricCardProps[];
231
+ expandedMetrics?: MetricCardProps[];
232
+ dashboardCards?: {
233
+ topTasks?: boolean;
234
+ upcomingMeetings?: boolean;
235
+ recentlyCompleted?: boolean;
236
+ checkIns?: boolean;
237
+ };
238
+ analytics?: {
239
+ pipeline?: {
240
+ stages: PipelineStage[];
241
+ stageMetrics: Record<string, PipelineStageMetrics>;
242
+ stageTimings: (PipelineStageTiming | null)[];
243
+ filterBreakdowns?: Record<string, Record<string, Record<string, number>>>;
244
+ };
245
+ volumeChart?: {
246
+ data: Record<string, unknown>[];
247
+ dataKeys: Array<{
248
+ key: string;
249
+ color: string;
250
+ }>;
251
+ filterOptions?: Array<{
252
+ label: string;
253
+ value: string;
254
+ }>;
255
+ };
256
+ donutChart?: {
257
+ data: Array<{
258
+ name: string;
259
+ value: number;
260
+ color: string;
261
+ }>;
262
+ centerLabel?: number;
263
+ };
264
+ trendChart?: {
265
+ data: Record<string, unknown>[];
266
+ series: Array<{
267
+ dataKey: string;
268
+ color: string;
269
+ }>;
270
+ xAxisKey?: string;
271
+ height?: number;
272
+ toggleOptions?: string[];
273
+ };
274
+ barChart?: {
275
+ data: Record<string, unknown>[];
276
+ bars: Array<{
277
+ dataKey: string;
278
+ color: string;
279
+ name: string;
280
+ icon?: LucideIcon;
281
+ }>;
282
+ };
283
+ barList?: {
284
+ data: Array<{
285
+ name: string;
286
+ value: number;
287
+ }>;
288
+ valueFormatter?: (v: number) => string;
289
+ };
290
+ };
291
+ }
292
+ interface AccountFilterTab {
293
+ label: string;
294
+ count?: number;
295
+ variant?: "default" | "attention" | "ghost";
296
+ }
297
+ interface AccountsViewConfig {
298
+ filterTabs?: AccountFilterTab[];
299
+ rows?: DataRow[];
300
+ filterCategories?: DataTableFilterCategory[];
301
+ quickViews?: string[];
302
+ moreQuickViews?: string[];
303
+ quickViewFilters?: Record<string, (row: DataRow) => boolean>;
304
+ iconMap?: {
305
+ salesforce?: string;
306
+ };
307
+ entityUrlBuilder?: (row: DataRow) => string;
308
+ onScoreFactorFeedback?: (account: string, scoreType: string, factorKey: string, type: "up" | "down" | null, detail?: string) => void;
309
+ onScoreApproveFeedback?: (account: string, scoreType: string, reasons: string[], detail: string) => void;
310
+ onScoreDismissFeedback?: (account: string, scoreType: string, reasons: string[], detail: string) => void;
311
+ }
312
+ interface WorkQueueViewConfig {
313
+ [key: string]: unknown;
314
+ }
315
+ interface AdminTab {
316
+ id: string;
317
+ label: string;
318
+ icon?: React.ComponentType<{
319
+ className?: string;
320
+ }>;
321
+ content: React.ReactNode;
322
+ }
323
+ interface AdminViewConfig {
324
+ /** View title displayed in the header. Defaults to "Admin". */
325
+ title?: string;
326
+ /** Icon displayed next to the title. */
327
+ icon?: React.ComponentType<{
328
+ className?: string;
329
+ }>;
330
+ tabs: AdminTab[];
331
+ /** Which tab is active initially. Defaults to first tab's id. */
332
+ defaultTab?: string;
333
+ }
334
+ interface EntityPanelSection {
335
+ type: "details" | "contacts" | "recentActivity" | "connectedApps" | "systemActivity";
336
+ props?: Record<string, unknown>;
337
+ }
338
+ interface EntityPanelConfig {
339
+ sections?: EntityPanelSection[];
340
+ icons?: Record<string, string>;
341
+ }
342
+ interface PrototypeConfig {
343
+ brand?: PrototypeBrandConfig;
344
+ sidebar: SidebarNavSection[];
345
+ views: {
346
+ inbox?: InboxViewConfig;
347
+ insights?: InsightsViewConfig;
348
+ accounts?: AccountsViewConfig;
349
+ workQueue?: WorkQueueViewConfig;
350
+ admin?: AdminViewConfig;
351
+ };
352
+ defaultView: string;
353
+ entityPanel?: EntityPanelConfig;
354
+ /** Sidebar item IDs that trigger view navigation. Defaults to keys of `views`. */
355
+ navigableViews?: string[];
356
+ }
357
+
358
+ /**
359
+ * A single contributing factor in the priority popover.
360
+ */
361
+ interface PriorityFactor {
362
+ key: string;
363
+ label: string;
364
+ /** Lucide icon name (e.g. "radar", "wallet", "link-2", "message-square"). */
365
+ icon: string;
366
+ /** Drives icon background tint. */
367
+ tone: "alert" | "warn" | "info";
368
+ /** Explicit semantic label - NOT inferred from score+weight. */
369
+ direction: "raises" | "lowers" | "neutral";
370
+ /** 0-100 */
371
+ score: number;
372
+ /** Evidence text (e.g. "$3.4M moved in 8h - current treasury balance $0.00"). */
373
+ rationale: string;
374
+ }
375
+ interface SignalPriorityPopoverProps {
376
+ score: number;
377
+ urgencyLabel?: SignalScoreUrgencyLabel;
378
+ /** Synthesis sentence displayed in the popover head. */
379
+ urgencyExplanation?: string;
380
+ factors: PriorityFactor[];
381
+ /** e.g. "Updated 4m ago - model v3.2" */
382
+ metaText?: string;
383
+ /** Negative feedback issue tree. */
384
+ feedbackChips?: FeedbackChipTree[];
385
+ onFeedbackSubmit?: (data: FeedbackSubmitData) => void;
386
+ className?: string;
387
+ }
388
+ declare function SignalPriorityPopover({ score, urgencyLabel: providedLabel, urgencyExplanation, factors, metaText, feedbackChips, onFeedbackSubmit, className, }: SignalPriorityPopoverProps): React.JSX.Element;
389
+
390
+ export { type AccountFilterTab as A, type BriefStyleVariant as B, type EntityPanelConfig as E, type InboxDetailSections as I, type PriorityFactor as P, type QueueItem as Q, SignalPriorityPopover as S, type WorkQueueViewConfig as W, type AccountsViewConfig as a, type AdminTab as b, type AdminViewConfig as c, type EntityPanelSection as d, type InboxSortOption as e, type InboxViewConfig as f, type InsightsCustomTab as g, type InsightsViewConfig as h, type PrototypeBrandConfig as i, type PrototypeConfig as j, type SignalPriorityPopoverProps as k, type SignalScoreData as l, type SignalScoreExplanationBucket as m, type SignalScoreExplanationSignal as n, type SignalScoreUrgencyLabel as o };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@handled-ai/design-system",
3
- "version": "0.17.0",
3
+ "version": "0.17.2",
4
4
  "description": "Handled UI component library (shadcn-style, New York)",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@9.12.0",