@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
|
@@ -1,193 +1,104 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "../contextual-quick-action-launcher";
|
|
9
|
-
|
|
10
|
-
vi.mock("../dropdown-menu", async () => {
|
|
11
|
-
const ReactMod = await import("react");
|
|
12
|
-
|
|
13
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
14
|
-
const DropdownMenu = ({ children, open, defaultOpen, onOpenChange }: any) => {
|
|
15
|
-
const [internalOpen, setInternalOpen] = ReactMod.useState(defaultOpen ?? false);
|
|
16
|
-
const isControlled = open !== undefined;
|
|
17
|
-
const currentOpen = isControlled ? open : internalOpen;
|
|
18
|
-
const setOpen = (nextOpen: boolean) => {
|
|
19
|
-
if (!isControlled) setInternalOpen(nextOpen);
|
|
20
|
-
onOpenChange?.(nextOpen);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
return ReactMod.createElement(
|
|
24
|
-
"div",
|
|
25
|
-
{
|
|
26
|
-
"data-slot": "dropdown-menu",
|
|
27
|
-
"data-open": currentOpen ? "true" : "false",
|
|
28
|
-
},
|
|
29
|
-
ReactMod.Children.map(children, (child: any) => {
|
|
30
|
-
if (!ReactMod.isValidElement(child)) return child;
|
|
31
|
-
return ReactMod.cloneElement(child, { __open: currentOpen, __setOpen: setOpen } as any);
|
|
32
|
-
})
|
|
33
|
-
);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const DropdownMenuTrigger = ({ children, asChild, __open, __setOpen, ...props }: any) => {
|
|
37
|
-
const childProps = {
|
|
38
|
-
"data-slot": "dropdown-menu-trigger",
|
|
39
|
-
"aria-expanded": __open ? "true" : "false",
|
|
40
|
-
onClick: () => __setOpen?.(!__open),
|
|
41
|
-
...props,
|
|
42
|
-
};
|
|
43
|
-
if (asChild && ReactMod.isValidElement(children)) {
|
|
44
|
-
return ReactMod.cloneElement(children, childProps);
|
|
45
|
-
}
|
|
46
|
-
return ReactMod.createElement("button", childProps, children);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const DropdownMenuContent = ({
|
|
50
|
-
children,
|
|
51
|
-
__open,
|
|
52
|
-
__setOpen: _setOpen,
|
|
53
|
-
className,
|
|
54
|
-
align: _align,
|
|
55
|
-
side: _side,
|
|
56
|
-
sideOffset: _sideOffset,
|
|
57
|
-
...props
|
|
58
|
-
}: any) => {
|
|
59
|
-
if (!__open) return null;
|
|
60
|
-
return ReactMod.createElement(
|
|
61
|
-
"div",
|
|
62
|
-
{ "data-slot": "dropdown-menu-content", role: "menu", className, ...props },
|
|
63
|
-
children
|
|
64
|
-
);
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const DropdownMenuItem = ({ children, onSelect, disabled, className, ...props }: any) =>
|
|
68
|
-
ReactMod.createElement(
|
|
69
|
-
"button",
|
|
70
|
-
{
|
|
71
|
-
"data-slot": "dropdown-menu-item",
|
|
72
|
-
role: "menuitem",
|
|
73
|
-
type: "button",
|
|
74
|
-
disabled,
|
|
75
|
-
className,
|
|
76
|
-
onClick: (event: any) => onSelect?.(event),
|
|
77
|
-
...props,
|
|
78
|
-
},
|
|
79
|
-
children
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
const DropdownMenuSeparator = ({ className, ...props }: any) =>
|
|
83
|
-
ReactMod.createElement("div", { "data-slot": "dropdown-menu-separator", className, ...props });
|
|
84
|
-
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
DropdownMenu,
|
|
88
|
-
DropdownMenuTrigger,
|
|
89
|
-
DropdownMenuContent,
|
|
90
|
-
DropdownMenuItem,
|
|
91
|
-
DropdownMenuSeparator,
|
|
92
|
-
};
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
const items: ContextualQuickActionItem[] = [
|
|
96
|
-
{
|
|
97
|
-
id: "create-opportunity",
|
|
98
|
-
label: "Create an opportunity",
|
|
99
|
-
description: "New sales or expansion deal",
|
|
100
|
-
icon: <span data-testid="salesforce-icon">SF</span>,
|
|
101
|
-
},
|
|
1
|
+
import { fireEvent, render, screen } from "@testing-library/react"
|
|
2
|
+
import { describe, expect, it, vi } from "vitest"
|
|
3
|
+
|
|
4
|
+
import { ContextualQuickActionLauncher } from "../contextual-quick-action-launcher"
|
|
5
|
+
|
|
6
|
+
const items = [
|
|
7
|
+
{ id: "log-feedback", label: "Log feedback", description: "Capture product feedback" },
|
|
102
8
|
{
|
|
103
|
-
id: "
|
|
104
|
-
label: "
|
|
105
|
-
description: "
|
|
9
|
+
id: "support",
|
|
10
|
+
label: "Submit support request",
|
|
11
|
+
description: "Submit a case",
|
|
106
12
|
disabled: true,
|
|
107
|
-
disabledReason: "
|
|
13
|
+
disabledReason: "Coming soon",
|
|
108
14
|
},
|
|
109
|
-
]
|
|
110
|
-
|
|
111
|
-
function renderLauncher(
|
|
112
|
-
props: Partial<React.ComponentProps<typeof ContextualQuickActionLauncher>> = {}
|
|
113
|
-
) {
|
|
114
|
-
return render(
|
|
115
|
-
<ContextualQuickActionLauncher
|
|
116
|
-
contextLabel="Supabase"
|
|
117
|
-
contextSecondary="Account"
|
|
118
|
-
items={items}
|
|
119
|
-
onSelect={() => {}}
|
|
120
|
-
{...props}
|
|
121
|
-
/>
|
|
122
|
-
);
|
|
123
|
-
}
|
|
15
|
+
]
|
|
124
16
|
|
|
125
17
|
describe("ContextualQuickActionLauncher", () => {
|
|
126
|
-
it("renders
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
expect(screen.getByText("Acting on")).
|
|
139
|
-
expect(screen.getByText("
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
18
|
+
it("renders contextual actions with context label when open", () => {
|
|
19
|
+
render(
|
|
20
|
+
<ContextualQuickActionLauncher
|
|
21
|
+
contextLabel="Acme Corp"
|
|
22
|
+
contextSecondary="Account"
|
|
23
|
+
items={items}
|
|
24
|
+
onSelect={() => {}}
|
|
25
|
+
open
|
|
26
|
+
/>,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
expect(screen.getByRole("menu", { name: /quick action/i })).toBeTruthy()
|
|
30
|
+
expect(screen.getByText("Acting on")).toBeTruthy()
|
|
31
|
+
expect(screen.getByText("Acme Corp")).toBeTruthy()
|
|
32
|
+
expect(screen.getByText("Log feedback")).toBeTruthy()
|
|
33
|
+
expect(screen.getByText("Coming soon")).toBeTruthy()
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it("calls onSelect for enabled items and closes the menu", () => {
|
|
37
|
+
const onSelect = vi.fn()
|
|
38
|
+
const onOpenChange = vi.fn()
|
|
39
|
+
|
|
40
|
+
render(
|
|
41
|
+
<ContextualQuickActionLauncher
|
|
42
|
+
contextLabel="Acme Corp"
|
|
43
|
+
items={items}
|
|
44
|
+
onSelect={onSelect}
|
|
45
|
+
onOpenChange={onOpenChange}
|
|
46
|
+
open
|
|
47
|
+
/>,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
fireEvent.click(screen.getByText("Log feedback"))
|
|
51
|
+
|
|
52
|
+
expect(onSelect).toHaveBeenCalledWith(items[0])
|
|
53
|
+
expect(onOpenChange).toHaveBeenCalledWith(false)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it("does not call onSelect for disabled items", () => {
|
|
57
|
+
const onSelect = vi.fn()
|
|
58
|
+
render(
|
|
59
|
+
<ContextualQuickActionLauncher
|
|
60
|
+
contextLabel="Acme Corp"
|
|
61
|
+
items={items}
|
|
62
|
+
onSelect={onSelect}
|
|
63
|
+
open
|
|
64
|
+
/>,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
fireEvent.click(screen.getByText("Submit support request"))
|
|
68
|
+
|
|
69
|
+
expect(onSelect).not.toHaveBeenCalled()
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it("calls Browse all actions callback", () => {
|
|
73
|
+
const onBrowseAll = vi.fn()
|
|
74
|
+
const onOpenChange = vi.fn()
|
|
75
|
+
render(
|
|
76
|
+
<ContextualQuickActionLauncher
|
|
77
|
+
contextLabel="Acme Corp"
|
|
78
|
+
items={items}
|
|
79
|
+
onSelect={() => {}}
|
|
80
|
+
onBrowseAll={onBrowseAll}
|
|
81
|
+
onOpenChange={onOpenChange}
|
|
82
|
+
open
|
|
83
|
+
/>,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
fireEvent.click(screen.getByRole("button", { name: /browse all actions/i }))
|
|
87
|
+
|
|
88
|
+
expect(onBrowseAll).toHaveBeenCalledTimes(1)
|
|
89
|
+
expect(onOpenChange).toHaveBeenCalledWith(false)
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it("renders optional hint outside the menu", () => {
|
|
93
|
+
render(
|
|
94
|
+
<ContextualQuickActionLauncher
|
|
95
|
+
contextLabel="Acme Corp"
|
|
96
|
+
items={items}
|
|
97
|
+
onSelect={() => {}}
|
|
98
|
+
showHint
|
|
99
|
+
/>,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
expect(screen.getByText(/for all actions/i)).toBeTruthy()
|
|
103
|
+
})
|
|
104
|
+
})
|