@handled-ai/design-system 0.17.1 → 0.18.1

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 (101) hide show
  1. package/dist/charts/empty-chart-state.d.ts +11 -0
  2. package/dist/charts/empty-chart-state.js +70 -0
  3. package/dist/charts/empty-chart-state.js.map +1 -0
  4. package/dist/charts/index.d.ts +1 -0
  5. package/dist/charts/index.js +1 -0
  6. package/dist/charts/index.js.map +1 -1
  7. package/dist/charts/pipeline-overview.d.ts +2 -1
  8. package/dist/charts/pipeline-overview.js +29 -1
  9. package/dist/charts/pipeline-overview.js.map +1 -1
  10. package/dist/components/actor-byline.d.ts +3 -0
  11. package/dist/components/actor-byline.js +5 -0
  12. package/dist/components/actor-byline.js.map +1 -0
  13. package/dist/components/days-open-cell.d.ts +16 -0
  14. package/dist/components/days-open-cell.js +73 -0
  15. package/dist/components/days-open-cell.js.map +1 -0
  16. package/dist/components/detail-drawer.d.ts +16 -0
  17. package/dist/components/detail-drawer.js +45 -0
  18. package/dist/components/detail-drawer.js.map +1 -0
  19. package/dist/components/feedback-primitives.d.ts +66 -0
  20. package/dist/components/feedback-primitives.js +295 -0
  21. package/dist/components/feedback-primitives.js.map +1 -0
  22. package/dist/components/insights-filter-bar.d.ts +2 -1
  23. package/dist/components/insights-filter-bar.js +13 -5
  24. package/dist/components/insights-filter-bar.js.map +1 -1
  25. package/dist/components/linked-entity-cell.d.ts +14 -0
  26. package/dist/components/linked-entity-cell.js +96 -0
  27. package/dist/components/linked-entity-cell.js.map +1 -0
  28. package/dist/components/metric-card.d.ts +14 -1
  29. package/dist/components/metric-card.js +86 -0
  30. package/dist/components/metric-card.js.map +1 -1
  31. package/dist/components/performance-metrics-table.d.ts +2 -1
  32. package/dist/components/performance-metrics-table.js +78 -46
  33. package/dist/components/performance-metrics-table.js.map +1 -1
  34. package/dist/components/pill.d.ts +26 -0
  35. package/dist/components/pill.js +77 -0
  36. package/dist/components/pill.js.map +1 -0
  37. package/dist/components/quick-segment.d.ts +13 -0
  38. package/dist/components/quick-segment.js +96 -0
  39. package/dist/components/quick-segment.js.map +1 -0
  40. package/dist/components/score-why-chips.d.ts +8 -17
  41. package/dist/components/score-why-chips.js +266 -180
  42. package/dist/components/score-why-chips.js.map +1 -1
  43. package/dist/components/signal-priority-popover.d.ts +17 -0
  44. package/dist/components/signal-priority-popover.js +247 -0
  45. package/dist/components/signal-priority-popover.js.map +1 -0
  46. package/dist/components/user-display.d.ts +22 -0
  47. package/dist/components/user-display.js +138 -0
  48. package/dist/components/user-display.js.map +1 -0
  49. package/dist/components/user-pill.d.ts +3 -0
  50. package/dist/components/user-pill.js +5 -0
  51. package/dist/components/user-pill.js.map +1 -0
  52. package/dist/index.d.ts +13 -4
  53. package/dist/index.js +17 -0
  54. package/dist/index.js.map +1 -1
  55. package/dist/lib/user-display.d.ts +31 -0
  56. package/dist/lib/user-display.js +57 -0
  57. package/dist/lib/user-display.js.map +1 -0
  58. package/dist/prototype/index.d.ts +2 -1
  59. package/dist/prototype/prototype-accounts-view.d.ts +2 -1
  60. package/dist/prototype/prototype-admin-view.d.ts +2 -1
  61. package/dist/prototype/prototype-config.d.ts +15 -332
  62. package/dist/prototype/prototype-inbox-view.d.ts +2 -1
  63. package/dist/prototype/prototype-inbox-view.js +11 -12
  64. package/dist/prototype/prototype-inbox-view.js.map +1 -1
  65. package/dist/prototype/prototype-insights-view.d.ts +2 -1
  66. package/dist/prototype/prototype-shell.d.ts +2 -1
  67. package/dist/signal-priority-popover-DQ_VuHac.d.ts +390 -0
  68. package/package.json +1 -1
  69. package/src/charts/__tests__/insights-charts.test.tsx +62 -0
  70. package/src/charts/empty-chart-state.tsx +44 -0
  71. package/src/charts/index.ts +1 -0
  72. package/src/charts/pipeline-overview.tsx +38 -1
  73. package/src/components/__tests__/contextual-quick-action-launcher.test.tsx +99 -188
  74. package/src/components/__tests__/feedback-primitives.test.tsx +509 -0
  75. package/src/components/__tests__/insights-primitives.test.tsx +117 -0
  76. package/src/components/__tests__/performance-metrics-table.test.tsx +54 -0
  77. package/src/components/__tests__/score-why-chips.test.tsx +540 -0
  78. package/src/components/__tests__/signal-priority-popover.test.tsx +312 -0
  79. package/src/components/__tests__/user-display.test.tsx +75 -0
  80. package/src/components/actor-byline.tsx +1 -0
  81. package/src/components/days-open-cell.tsx +50 -0
  82. package/src/components/detail-drawer.tsx +60 -0
  83. package/src/components/feedback-primitives.tsx +424 -0
  84. package/src/components/insights-filter-bar.tsx +13 -4
  85. package/src/components/linked-entity-cell.tsx +74 -0
  86. package/src/components/metric-card.tsx +82 -0
  87. package/src/components/performance-metrics-table.tsx +99 -63
  88. package/src/components/pill.tsx +67 -0
  89. package/src/components/quick-segment.tsx +68 -0
  90. package/src/components/score-why-chips.tsx +413 -203
  91. package/src/components/signal-priority-popover.tsx +359 -0
  92. package/src/components/user-display.tsx +96 -0
  93. package/src/components/user-pill.tsx +1 -0
  94. package/src/index.ts +11 -0
  95. package/src/lib/__tests__/user-display.test.ts +85 -0
  96. package/src/lib/user-display.ts +88 -0
  97. package/src/prototype/__tests__/detail-view-score-why.test.tsx +33 -29
  98. package/src/prototype/__tests__/detail-view-title-slots.test.tsx +65 -0
  99. package/src/prototype/prototype-config.ts +28 -4
  100. package/src/prototype/prototype-inbox-view.tsx +8 -10
  101. package/src/prototype/__tests__/detail-view-title-subtext.test.tsx +0 -72
@@ -1,193 +1,104 @@
1
- import { describe, it, expect, vi } from "vitest";
2
- import React from "react";
3
- import { fireEvent, render, screen } from "@testing-library/react";
4
-
5
- import {
6
- ContextualQuickActionLauncher,
7
- type ContextualQuickActionItem,
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: "update-opportunity",
104
- label: "Update an opportunity",
105
- description: "Edit stage, close date, or details",
9
+ id: "support",
10
+ label: "Submit support request",
11
+ description: "Submit a case",
106
12
  disabled: true,
107
- disabledReason: "No opportunity",
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 the accessible trigger name", () => {
127
- renderLauncher();
128
-
129
- expect(screen.getByRole("button", { name: /quick action/i })).not.toBeNull();
130
- });
131
-
132
- it("opens and closes in uncontrolled mode", () => {
133
- renderLauncher();
134
-
135
- expect(screen.queryByText("Acting on")).toBeNull();
136
-
137
- fireEvent.click(screen.getByRole("button", { name: /quick action/i }));
138
- expect(screen.getByText("Acting on")).not.toBeNull();
139
- expect(screen.getByText("Supabase")).not.toBeNull();
140
-
141
- fireEvent.click(screen.getByRole("button", { name: /quick action/i }));
142
- expect(screen.queryByText("Acting on")).toBeNull();
143
- });
144
-
145
- it("selects enabled items and closes the menu", () => {
146
- const onSelect = vi.fn();
147
- renderLauncher({ onSelect });
148
-
149
- fireEvent.click(screen.getByRole("button", { name: /quick action/i }));
150
- fireEvent.click(screen.getByRole("menuitem", { name: /create an opportunity/i }));
151
-
152
- expect(onSelect).toHaveBeenCalledTimes(1);
153
- expect(onSelect).toHaveBeenCalledWith(items[0]);
154
- expect(screen.queryByText("Acting on")).toBeNull();
155
- });
156
-
157
- it("does not select disabled items", () => {
158
- const onSelect = vi.fn();
159
- renderLauncher({ onSelect });
160
-
161
- fireEvent.click(screen.getByRole("button", { name: /quick action/i }));
162
- fireEvent.click(screen.getByRole("menuitem", { name: /update an opportunity/i }));
163
-
164
- expect(onSelect).not.toHaveBeenCalled();
165
- expect(screen.getByText("No opportunity")).not.toBeNull();
166
- });
167
-
168
- it("calls browse all and closes the menu", () => {
169
- const onBrowseAll = vi.fn();
170
- renderLauncher({ onBrowseAll });
171
-
172
- fireEvent.click(screen.getByRole("button", { name: /quick action/i }));
173
- fireEvent.click(screen.getByRole("button", { name: /browse all actions/i }));
174
-
175
- expect(onBrowseAll).toHaveBeenCalledTimes(1);
176
- expect(screen.queryByText("Acting on")).toBeNull();
177
- });
178
-
179
- it("renders optional hint text", () => {
180
- renderLauncher({ showHint: true });
181
-
182
- expect(screen.getByText(/or press/i)).not.toBeNull();
183
- expect(screen.getByText("⌘K")).not.toBeNull();
184
- expect(screen.getByText(/for all actions/i)).not.toBeNull();
185
- });
186
-
187
- it("uses pointer-events-auto on portalled content", () => {
188
- renderLauncher({ defaultOpen: true });
189
-
190
- const content = document.querySelector('[data-slot="dropdown-menu-content"]');
191
- expect(content?.className).toContain("pointer-events-auto");
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
+ })