@handled-ai/design-system 0.18.11 → 0.18.12
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/account-contacts-popover.d.ts +5 -1
- package/dist/components/account-contacts-popover.js +25 -4
- package/dist/components/account-contacts-popover.js.map +1 -1
- package/dist/components/data-table-condition-filter.d.ts +2 -1
- package/dist/components/data-table-condition-filter.js +23 -41
- package/dist/components/data-table-condition-filter.js.map +1 -1
- package/dist/components/data-table-filter.js +8 -9
- package/dist/components/data-table-filter.js.map +1 -1
- package/dist/components/entity-panel.d.ts +2 -1
- package/dist/components/entity-panel.js +52 -45
- package/dist/components/entity-panel.js.map +1 -1
- package/dist/components/score-why-chips.d.ts +1 -1
- package/dist/components/signal-priority-popover.d.ts +1 -1
- package/dist/components/signal-priority-popover.js +4 -4
- package/dist/components/signal-priority-popover.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/prototype/index.d.ts +1 -1
- package/dist/prototype/prototype-accounts-view.d.ts +1 -1
- package/dist/prototype/prototype-admin-view.d.ts +1 -1
- package/dist/prototype/prototype-config.d.ts +1 -1
- package/dist/prototype/prototype-inbox-view.d.ts +5 -3
- package/dist/prototype/prototype-inbox-view.js +11 -5
- package/dist/prototype/prototype-inbox-view.js.map +1 -1
- package/dist/prototype/prototype-insights-view.d.ts +1 -1
- package/dist/prototype/prototype-shell.d.ts +1 -1
- package/dist/{signal-priority-popover-BT6CPYNs.d.ts → signal-priority-popover-BEDoPsNE.d.ts} +6 -0
- package/package.json +1 -2
- package/src/components/__tests__/account-contacts-popover.test.tsx +79 -0
- package/src/components/__tests__/data-table-condition-filter.test.tsx +96 -0
- package/src/components/__tests__/data-table-filter.test.tsx +45 -0
- package/src/components/__tests__/entity-panel-header.test.tsx +44 -0
- package/src/components/__tests__/signal-priority-popover.test.tsx +30 -0
- package/src/components/account-contacts-popover.tsx +29 -1
- package/src/components/data-table-condition-filter.tsx +32 -47
- package/src/components/data-table-filter.tsx +7 -10
- package/src/components/entity-panel.tsx +56 -40
- package/src/components/signal-priority-popover.tsx +15 -4
- package/src/prototype/__tests__/detail-view-title-slots.test.tsx +15 -0
- package/src/prototype/prototype-config.ts +2 -0
- package/src/prototype/prototype-inbox-view.tsx +17 -5
|
@@ -135,14 +135,16 @@ export function EntityPanelHeader({
|
|
|
135
135
|
icon,
|
|
136
136
|
title,
|
|
137
137
|
badgeLabel,
|
|
138
|
-
subtitle
|
|
138
|
+
subtitle,
|
|
139
139
|
headerAction,
|
|
140
|
+
headerSecondaryAction,
|
|
140
141
|
}: {
|
|
141
142
|
icon?: React.ReactNode
|
|
142
143
|
title: string
|
|
143
144
|
badgeLabel?: string
|
|
144
145
|
subtitle?: string
|
|
145
146
|
headerAction?: React.ReactNode
|
|
147
|
+
headerSecondaryAction?: React.ReactNode
|
|
146
148
|
}) {
|
|
147
149
|
const { panelMode, cyclePanelMode, onClose } = useEntityPanel()
|
|
148
150
|
|
|
@@ -150,49 +152,63 @@ export function EntityPanelHeader({
|
|
|
150
152
|
panelMode === 'default' ? 'Wide' : panelMode === 'wide' ? 'Fullscreen' : 'Exit fullscreen'
|
|
151
153
|
|
|
152
154
|
return (
|
|
153
|
-
<div className="
|
|
154
|
-
<div className="flex items-center
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
155
|
+
<div className="mb-3 space-y-2">
|
|
156
|
+
<div className="flex items-center justify-between">
|
|
157
|
+
<div className="flex items-center gap-2 min-w-0">
|
|
158
|
+
{icon ?? <CalendarDays className="w-5 h-5 text-muted-foreground shrink-0" />}
|
|
159
|
+
<h2 className="text-[16px] font-semibold text-foreground truncate">{title}</h2>
|
|
160
|
+
{badgeLabel && (
|
|
161
|
+
<Badge
|
|
162
|
+
variant="outline"
|
|
163
|
+
className="text-blue-600 border-blue-300 dark:border-blue-700 dark:text-blue-400 shadow-none px-2 py-0.5 text-[11px] font-medium shrink-0"
|
|
164
|
+
>
|
|
165
|
+
{badgeLabel}
|
|
166
|
+
</Badge>
|
|
167
|
+
)}
|
|
168
|
+
</div>
|
|
169
|
+
<div className="flex items-center gap-1 shrink-0 ml-4 text-muted-foreground">
|
|
170
|
+
{headerAction}
|
|
171
|
+
<button
|
|
172
|
+
type="button"
|
|
173
|
+
className="p-1.5 rounded-md hover:bg-secondary transition-colors"
|
|
174
|
+
title="Copy Link"
|
|
175
|
+
>
|
|
176
|
+
<LinkIcon className="w-4 h-4" />
|
|
177
|
+
</button>
|
|
178
|
+
<button
|
|
179
|
+
type="button"
|
|
180
|
+
onClick={cyclePanelMode}
|
|
181
|
+
className="p-1.5 rounded-md hover:bg-secondary transition-colors"
|
|
182
|
+
title={sizeButtonTitle}
|
|
161
183
|
>
|
|
162
|
-
{
|
|
163
|
-
|
|
164
|
-
|
|
184
|
+
{panelMode === 'fullscreen' ? (
|
|
185
|
+
<Minimize2 className="w-4 h-4" />
|
|
186
|
+
) : (
|
|
187
|
+
<Maximize2 className="w-4 h-4" />
|
|
188
|
+
)}
|
|
189
|
+
</button>
|
|
190
|
+
<button
|
|
191
|
+
type="button"
|
|
192
|
+
onClick={onClose}
|
|
193
|
+
className="p-1.5 rounded-md hover:bg-secondary transition-colors"
|
|
194
|
+
title="Close"
|
|
195
|
+
>
|
|
196
|
+
<X className="w-4 h-4" />
|
|
197
|
+
</button>
|
|
198
|
+
</div>
|
|
165
199
|
</div>
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
className="p-1.5 rounded-md hover:bg-secondary transition-colors"
|
|
171
|
-
title="Copy Link"
|
|
172
|
-
>
|
|
173
|
-
<LinkIcon className="w-4 h-4" />
|
|
174
|
-
</button>
|
|
175
|
-
<button
|
|
176
|
-
type="button"
|
|
177
|
-
onClick={cyclePanelMode}
|
|
178
|
-
className="p-1.5 rounded-md hover:bg-secondary transition-colors"
|
|
179
|
-
title={sizeButtonTitle}
|
|
180
|
-
>
|
|
181
|
-
{panelMode === 'fullscreen' ? (
|
|
182
|
-
<Minimize2 className="w-4 h-4" />
|
|
200
|
+
{(subtitle || headerSecondaryAction) && (
|
|
201
|
+
<div className="flex flex-wrap items-center justify-between gap-x-3 gap-y-2">
|
|
202
|
+
{subtitle ? (
|
|
203
|
+
<p className="min-w-0 flex-1 text-xs text-muted-foreground">{subtitle}</p>
|
|
183
204
|
) : (
|
|
184
|
-
<
|
|
205
|
+
<div className="min-w-0 flex-1" />
|
|
185
206
|
)}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
title="Close"
|
|
192
|
-
>
|
|
193
|
-
<X className="w-4 h-4" />
|
|
194
|
-
</button>
|
|
195
|
-
</div>
|
|
207
|
+
{headerSecondaryAction ? (
|
|
208
|
+
<div className="flex shrink-0 items-center gap-2">{headerSecondaryAction}</div>
|
|
209
|
+
) : null}
|
|
210
|
+
</div>
|
|
211
|
+
)}
|
|
196
212
|
</div>
|
|
197
213
|
)
|
|
198
214
|
}
|
|
@@ -40,8 +40,12 @@ export interface PriorityFactor {
|
|
|
40
40
|
tone: "alert" | "warn" | "info"
|
|
41
41
|
/** Explicit semantic label - NOT inferred from score+weight. */
|
|
42
42
|
direction: "raises" | "lowers" | "neutral"
|
|
43
|
+
/** Optional display label for the direction text. Keeps semantic direction icon/color unchanged. */
|
|
44
|
+
directionLabel?: string
|
|
43
45
|
/** 0-100 */
|
|
44
46
|
score: number
|
|
47
|
+
/** Optional display label rendered instead of the numeric score cell. */
|
|
48
|
+
displayValueLabel?: string
|
|
45
49
|
/** Evidence text (e.g. "$3.4M moved in 8h - current treasury balance $0.00"). */
|
|
46
50
|
rationale: string
|
|
47
51
|
}
|
|
@@ -168,12 +172,13 @@ function PriorityFactorRow({ factor, initialFeedback, onFactorFeedback }: Priori
|
|
|
168
172
|
const IconComponent = FACTOR_ICONS[factor.icon] ?? Activity
|
|
169
173
|
const toneClasses = TONE_ICON_CLASSES[factor.tone]
|
|
170
174
|
const directionClasses = DIRECTION_CLASSES[factor.direction]
|
|
171
|
-
const directionLabel =
|
|
175
|
+
const directionLabel = factor.directionLabel ?? (
|
|
172
176
|
factor.direction === "raises"
|
|
173
177
|
? "Raises"
|
|
174
178
|
: factor.direction === "lowers"
|
|
175
179
|
? "Lowers"
|
|
176
180
|
: "Neutral"
|
|
181
|
+
)
|
|
177
182
|
|
|
178
183
|
return (
|
|
179
184
|
<div
|
|
@@ -206,10 +211,16 @@ function PriorityFactorRow({ factor, initialFeedback, onFactorFeedback }: Priori
|
|
|
206
211
|
</span>
|
|
207
212
|
</div>
|
|
208
213
|
|
|
209
|
-
{/* Score number */}
|
|
214
|
+
{/* Score number / display label */}
|
|
210
215
|
<div className="flex items-center text-right">
|
|
211
|
-
|
|
212
|
-
|
|
216
|
+
{factor.displayValueLabel ? (
|
|
217
|
+
<span className="text-xs font-semibold text-foreground">{factor.displayValueLabel}</span>
|
|
218
|
+
) : (
|
|
219
|
+
<>
|
|
220
|
+
<span className="text-sm font-bold tabular-nums">{factor.score}</span>
|
|
221
|
+
<span className="text-xs font-normal text-muted-foreground">/100</span>
|
|
222
|
+
</>
|
|
223
|
+
)}
|
|
213
224
|
</div>
|
|
214
225
|
|
|
215
226
|
{/* empty grid cell under icon column */}
|
|
@@ -62,4 +62,19 @@ describe("DetailView title slots", () => {
|
|
|
62
62
|
|
|
63
63
|
expect(screen.getByRole("button", { name: "Quick action" })).toBeTruthy()
|
|
64
64
|
})
|
|
65
|
+
it("renders a full-width title action row without replacing title extra or metadata", () => {
|
|
66
|
+
renderDetailView({
|
|
67
|
+
renderTitleExtra: () => <span data-testid="title-extra">Compact extra</span>,
|
|
68
|
+
renderTitleActionRow: () => (
|
|
69
|
+
<button type="button">Full-width quick action</button>
|
|
70
|
+
),
|
|
71
|
+
renderMetadataExtra: () => <span data-testid="metadata-extra">Owner: Lee</span>,
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
expect(screen.getByTestId("title-extra").textContent).toBe("Compact extra")
|
|
75
|
+
expect(screen.getByRole("button", { name: "Full-width quick action" })).toBeTruthy()
|
|
76
|
+
expect(screen.getByTestId("metadata-extra").textContent).toBe("Owner: Lee")
|
|
77
|
+
expect(screen.getByTestId("priority-popover-trigger")).toBeTruthy()
|
|
78
|
+
})
|
|
79
|
+
|
|
65
80
|
})
|
|
@@ -229,6 +229,8 @@ export interface InboxViewConfig {
|
|
|
229
229
|
attentionCount?: number
|
|
230
230
|
/** Render extra content inline with the detail title. */
|
|
231
231
|
renderTitleExtra?: (item: QueueItem) => React.ReactNode
|
|
232
|
+
/** Render a full-width action row below the detail title row. */
|
|
233
|
+
renderTitleActionRow?: (item: QueueItem) => React.ReactNode
|
|
232
234
|
/** Render supporting content below the detail title. */
|
|
233
235
|
renderTitleSubtext?: (item: QueueItem) => React.ReactNode
|
|
234
236
|
/** Sort options for the inbox. When provided, a sort dropdown is rendered in the split view toolbar. */
|
|
@@ -141,6 +141,8 @@ export interface DetailViewProps {
|
|
|
141
141
|
lastActivityTime?: string
|
|
142
142
|
/** Render extra content inline with the detail title. */
|
|
143
143
|
renderTitleExtra?: (item: QueueItem) => React.ReactNode
|
|
144
|
+
/** Render a full-width action row below the detail title row. */
|
|
145
|
+
renderTitleActionRow?: (item: QueueItem) => React.ReactNode
|
|
144
146
|
/** Render supporting content below the detail title. */
|
|
145
147
|
renderTitleSubtext?: (item: QueueItem) => React.ReactNode
|
|
146
148
|
/** Render extra metadata chips (e.g. assignee) inside the chips row below the title. */
|
|
@@ -321,6 +323,7 @@ export function DetailView({
|
|
|
321
323
|
renderAfterScore,
|
|
322
324
|
lastActivityTime,
|
|
323
325
|
renderTitleExtra,
|
|
326
|
+
renderTitleActionRow,
|
|
324
327
|
renderTitleSubtext,
|
|
325
328
|
renderMetadataExtra,
|
|
326
329
|
onOpenSignalBucket,
|
|
@@ -468,12 +471,19 @@ export function DetailView({
|
|
|
468
471
|
<span className="text-xs text-muted-foreground">{item.company}</span>
|
|
469
472
|
</div>
|
|
470
473
|
|
|
471
|
-
<div className="mb-3
|
|
472
|
-
<div className="
|
|
473
|
-
<
|
|
474
|
-
|
|
474
|
+
<div className="mb-3 space-y-3">
|
|
475
|
+
<div className="flex flex-wrap items-start gap-x-3 gap-y-2">
|
|
476
|
+
<div className="min-w-0 flex-1">
|
|
477
|
+
<h1 className="text-2xl font-bold tracking-tight text-foreground">{item.title}</h1>
|
|
478
|
+
{renderTitleSubtext?.(item)}
|
|
479
|
+
</div>
|
|
480
|
+
{renderTitleExtra?.(item)}
|
|
475
481
|
</div>
|
|
476
|
-
{
|
|
482
|
+
{renderTitleActionRow ? (
|
|
483
|
+
<div className="flex w-full flex-wrap items-center gap-2">
|
|
484
|
+
{renderTitleActionRow(item)}
|
|
485
|
+
</div>
|
|
486
|
+
) : null}
|
|
477
487
|
</div>
|
|
478
488
|
|
|
479
489
|
<div className="mb-6 flex flex-wrap items-center gap-2">
|
|
@@ -649,6 +659,7 @@ export function PrototypeInboxView({
|
|
|
649
659
|
timelineSystemEventsConfig,
|
|
650
660
|
attentionCount,
|
|
651
661
|
renderTitleExtra,
|
|
662
|
+
renderTitleActionRow,
|
|
652
663
|
renderTitleSubtext,
|
|
653
664
|
sortOptions,
|
|
654
665
|
activeSortId,
|
|
@@ -891,6 +902,7 @@ export function PrototypeInboxView({
|
|
|
891
902
|
timelineSystemEventsConfig,
|
|
892
903
|
attentionCount,
|
|
893
904
|
renderTitleExtra,
|
|
905
|
+
renderTitleActionRow,
|
|
894
906
|
renderTitleSubtext,
|
|
895
907
|
onOpenSignalBucket,
|
|
896
908
|
}
|