@handled-ai/design-system 0.18.58 → 0.19.0-rc.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 (64) hide show
  1. package/dist/components/badge.d.ts +1 -1
  2. package/dist/components/button.d.ts +1 -1
  3. package/dist/components/case-panel-activity-timeline.d.ts +2 -0
  4. package/dist/components/case-panel-activity-timeline.js +22 -1
  5. package/dist/components/case-panel-activity-timeline.js.map +1 -1
  6. package/dist/components/comment-composer.d.ts +29 -0
  7. package/dist/components/comment-composer.js +102 -0
  8. package/dist/components/comment-composer.js.map +1 -0
  9. package/dist/components/conversation-panel.d.ts +95 -0
  10. package/dist/components/conversation-panel.js +636 -0
  11. package/dist/components/conversation-panel.js.map +1 -0
  12. package/dist/components/detail-view.js +1 -1
  13. package/dist/components/detail-view.js.map +1 -1
  14. package/dist/components/owner-chips.d.ts +59 -0
  15. package/dist/components/owner-chips.js +256 -0
  16. package/dist/components/owner-chips.js.map +1 -0
  17. package/dist/components/pill.d.ts +1 -1
  18. package/dist/components/score-why-chips.d.ts +1 -1
  19. package/dist/components/signal-priority-popover.d.ts +1 -1
  20. package/dist/components/signal-priority-popover.js +16 -7
  21. package/dist/components/signal-priority-popover.js.map +1 -1
  22. package/dist/components/tabs.d.ts +1 -1
  23. package/dist/components/timeline-activity.d.ts +7 -0
  24. package/dist/components/timeline-activity.js +22 -1
  25. package/dist/components/timeline-activity.js.map +1 -1
  26. package/dist/components/virtualized-data-table.js +4 -4
  27. package/dist/components/virtualized-data-table.js.map +1 -1
  28. package/dist/index.d.ts +4 -1
  29. package/dist/index.js +3 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/internal/safe-html.d.ts +11 -0
  32. package/dist/internal/safe-html.js +222 -0
  33. package/dist/internal/safe-html.js.map +1 -0
  34. package/dist/prototype/index.d.ts +1 -1
  35. package/dist/prototype/prototype-accounts-view.d.ts +1 -1
  36. package/dist/prototype/prototype-admin-view.d.ts +1 -1
  37. package/dist/prototype/prototype-config.d.ts +1 -1
  38. package/dist/prototype/prototype-inbox-view.d.ts +1 -1
  39. package/dist/prototype/prototype-inbox-view.js +2 -0
  40. package/dist/prototype/prototype-inbox-view.js.map +1 -1
  41. package/dist/prototype/prototype-insights-view.d.ts +1 -1
  42. package/dist/prototype/prototype-shell.d.ts +1 -1
  43. package/dist/{signal-priority-popover-QJngMAj7.d.ts → signal-priority-popover-CZitE9xq.d.ts} +11 -2
  44. package/package.json +1 -1
  45. package/src/components/__tests__/comment-composer.test.tsx +57 -0
  46. package/src/components/__tests__/conversation-panel.test.tsx +157 -0
  47. package/src/components/__tests__/owner-chips.test.tsx +100 -0
  48. package/src/components/__tests__/signal-priority-popover.test.tsx +41 -4
  49. package/src/components/__tests__/timeline-activity.test.tsx +55 -0
  50. package/src/components/__tests__/virtualized-data-table-resize.test.tsx +18 -0
  51. package/src/components/case-panel-activity-timeline.tsx +20 -0
  52. package/src/components/comment-composer.tsx +119 -0
  53. package/src/components/conversation-panel.tsx +790 -0
  54. package/src/components/detail-view.tsx +3 -1
  55. package/src/components/owner-chips.tsx +335 -0
  56. package/src/components/signal-priority-popover.tsx +19 -6
  57. package/src/components/timeline-activity.tsx +37 -3
  58. package/src/components/virtualized-data-table.tsx +4 -4
  59. package/src/index.ts +4 -1
  60. package/src/internal/__tests__/safe-html.test.ts +53 -0
  61. package/src/internal/safe-html.ts +284 -0
  62. package/src/prototype/__tests__/detail-view-score-why.test.tsx +34 -0
  63. package/src/prototype/prototype-config.ts +5 -1
  64. package/src/prototype/prototype-inbox-view.tsx +2 -0
@@ -0,0 +1,222 @@
1
+ const DANGEROUS_BLOCK_TAGS = /* @__PURE__ */ new Set([
2
+ "script",
3
+ "style",
4
+ "iframe",
5
+ "object",
6
+ "embed",
7
+ "svg",
8
+ "math",
9
+ "template",
10
+ "noscript",
11
+ "textarea",
12
+ "select"
13
+ ]);
14
+ const ALLOWED_TAGS = /* @__PURE__ */ new Set([
15
+ "a",
16
+ "b",
17
+ "blockquote",
18
+ "br",
19
+ "code",
20
+ "del",
21
+ "div",
22
+ "em",
23
+ "hr",
24
+ "i",
25
+ "img",
26
+ "li",
27
+ "ol",
28
+ "p",
29
+ "pre",
30
+ "s",
31
+ "span",
32
+ "strong",
33
+ "table",
34
+ "tbody",
35
+ "td",
36
+ "th",
37
+ "thead",
38
+ "tr",
39
+ "u",
40
+ "ul"
41
+ ]);
42
+ const VOID_TAGS = /* @__PURE__ */ new Set(["br", "hr", "img"]);
43
+ const SAFE_GLOBAL_ATTRS = /* @__PURE__ */ new Set(["aria-label", "role", "title"]);
44
+ const SAFE_URL_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]);
45
+ function escapeHtml(value) {
46
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
47
+ }
48
+ function escapeAttribute(value) {
49
+ return escapeHtml(value).replace(/"/g, "&quot;");
50
+ }
51
+ function safeCodePoint(value) {
52
+ return Number.isInteger(value) && value >= 0 && value <= 1114111 ? String.fromCodePoint(value) : "";
53
+ }
54
+ function decodeHtmlEntities(value) {
55
+ const namedEntities = {
56
+ amp: "&",
57
+ apos: "'",
58
+ colon: ":",
59
+ gt: ">",
60
+ lt: "<",
61
+ newline: "\n",
62
+ quot: '"',
63
+ tab: " "
64
+ };
65
+ let decoded = value;
66
+ for (let i = 0; i < 4; i += 1) {
67
+ const next = decoded.replace(/&#x([0-9a-f]+);?/gi, (_match, hex) => {
68
+ const codePoint = Number.parseInt(hex, 16);
69
+ return safeCodePoint(codePoint);
70
+ }).replace(/&#(\d+);?/g, (_match, decimal) => {
71
+ const codePoint = Number.parseInt(decimal, 10);
72
+ return safeCodePoint(codePoint);
73
+ }).replace(/&([a-z]+);/gi, (match, name) => {
74
+ var _a;
75
+ return (_a = namedEntities[name.toLowerCase()]) != null ? _a : match;
76
+ });
77
+ if (next === decoded) return decoded;
78
+ decoded = next;
79
+ }
80
+ return decoded;
81
+ }
82
+ function isSafeUrl(value) {
83
+ const decoded = decodeHtmlEntities(value).replace(/[\u0000-\u001f\u007f\s]+/g, "").trim();
84
+ if (!decoded) return false;
85
+ if (decoded.startsWith("//")) return false;
86
+ if (decoded.startsWith("#") || decoded.startsWith("/") || decoded.startsWith("./") || decoded.startsWith("../")) {
87
+ return true;
88
+ }
89
+ try {
90
+ return SAFE_URL_PROTOCOLS.has(new URL(decoded, "https://handled.local").protocol);
91
+ } catch (e) {
92
+ return false;
93
+ }
94
+ }
95
+ function sanitizeClassName(value) {
96
+ const safeTokens = value.split(/\s+/).map((token) => token.trim()).filter((token) => /^[A-Za-z0-9_-]+$/.test(token));
97
+ return safeTokens.length ? safeTokens.join(" ") : null;
98
+ }
99
+ function sanitizeAttribute(tagName, name, value) {
100
+ const attr = name.toLowerCase();
101
+ if (attr.startsWith("on") || attr === "style" || attr === "srcdoc" || attr === "formaction" || attr === "xlink:href" || attr === "xmlns") {
102
+ return null;
103
+ }
104
+ if (attr === "class") {
105
+ const safeClassName = sanitizeClassName(value);
106
+ return safeClassName ? `class="${escapeAttribute(safeClassName)}"` : null;
107
+ }
108
+ if (SAFE_GLOBAL_ATTRS.has(attr) || attr.startsWith("aria-")) {
109
+ return `${attr}="${escapeAttribute(value)}"`;
110
+ }
111
+ if (tagName === "a" && attr === "href" && isSafeUrl(value)) {
112
+ return `href="${escapeAttribute(value)}"`;
113
+ }
114
+ if (tagName === "img" && attr === "src" && isSafeUrl(value)) {
115
+ return `src="${escapeAttribute(value)}"`;
116
+ }
117
+ if (tagName === "img" && (attr === "alt" || attr === "width" || attr === "height")) {
118
+ return `${attr}="${escapeAttribute(value)}"`;
119
+ }
120
+ if ((tagName === "td" || tagName === "th") && (attr === "colspan" || attr === "rowspan")) {
121
+ return `${attr}="${escapeAttribute(value)}"`;
122
+ }
123
+ return null;
124
+ }
125
+ function sanitizeAttributes(tagName, rawAttributes = "") {
126
+ var _a, _b;
127
+ const attributes = [];
128
+ const attrPattern = /([A-Za-z_:][-A-Za-z0-9_:.]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
129
+ let match;
130
+ while ((match = attrPattern.exec(rawAttributes)) !== null) {
131
+ const [, name, doubleQuotedValue, singleQuotedValue, unquotedValue] = match;
132
+ const value = (_b = (_a = doubleQuotedValue != null ? doubleQuotedValue : singleQuotedValue) != null ? _a : unquotedValue) != null ? _b : "";
133
+ const safeAttribute = sanitizeAttribute(tagName, name, value);
134
+ if (safeAttribute) attributes.push(safeAttribute);
135
+ }
136
+ if (tagName === "a" && attributes.some((attr) => attr.startsWith("href="))) {
137
+ attributes.push('target="_blank"', 'rel="noopener noreferrer"');
138
+ }
139
+ return attributes.length ? ` ${attributes.join(" ")}` : "";
140
+ }
141
+ function findTagEnd(html, startIndex) {
142
+ let quote = null;
143
+ for (let i = startIndex + 1; i < html.length; i += 1) {
144
+ const char = html[i];
145
+ if (quote) {
146
+ if (char === quote) quote = null;
147
+ continue;
148
+ }
149
+ if (char === '"' || char === "'") {
150
+ quote = char;
151
+ continue;
152
+ }
153
+ if (char === ">") return i;
154
+ }
155
+ return -1;
156
+ }
157
+ function parseTag(rawTag) {
158
+ var _a;
159
+ const match = rawTag.match(/^<\s*(\/)?\s*([A-Za-z][A-Za-z0-9:-]*)\b([\s\S]*?)\/?>$/);
160
+ if (!match) return null;
161
+ return {
162
+ closing: !!match[1],
163
+ name: match[2].toLowerCase(),
164
+ attributes: (_a = match[3]) != null ? _a : ""
165
+ };
166
+ }
167
+ function findDangerousClose(html, tagName, fromIndex) {
168
+ const closePattern = new RegExp(`</\\s*${tagName}\\s*>`, "ig");
169
+ closePattern.lastIndex = fromIndex;
170
+ const match = closePattern.exec(html);
171
+ return match ? closePattern.lastIndex : -1;
172
+ }
173
+ function sanitizeHtml(html) {
174
+ let output = "";
175
+ let cursor = 0;
176
+ while (cursor < html.length) {
177
+ const tagStart = html.indexOf("<", cursor);
178
+ if (tagStart === -1) {
179
+ output += html.slice(cursor);
180
+ break;
181
+ }
182
+ output += html.slice(cursor, tagStart);
183
+ if (html.startsWith("<!--", tagStart)) {
184
+ const commentEnd = html.indexOf("-->", tagStart + 4);
185
+ cursor = commentEnd === -1 ? html.length : commentEnd + 3;
186
+ continue;
187
+ }
188
+ const tagEnd = findTagEnd(html, tagStart);
189
+ if (tagEnd === -1) {
190
+ output += escapeHtml(html.slice(tagStart));
191
+ break;
192
+ }
193
+ const rawTag = html.slice(tagStart, tagEnd + 1);
194
+ const parsed = parseTag(rawTag);
195
+ if (!parsed) {
196
+ cursor = tagEnd + 1;
197
+ continue;
198
+ }
199
+ if (DANGEROUS_BLOCK_TAGS.has(parsed.name)) {
200
+ const closeEnd = parsed.closing ? -1 : findDangerousClose(html, parsed.name, tagEnd + 1);
201
+ cursor = closeEnd === -1 ? tagEnd + 1 : closeEnd;
202
+ continue;
203
+ }
204
+ if (ALLOWED_TAGS.has(parsed.name)) {
205
+ if (parsed.closing) {
206
+ if (!VOID_TAGS.has(parsed.name)) output += `</${parsed.name}>`;
207
+ } else {
208
+ output += `<${parsed.name}${sanitizeAttributes(parsed.name, parsed.attributes)}>`;
209
+ }
210
+ }
211
+ cursor = tagEnd + 1;
212
+ }
213
+ return output;
214
+ }
215
+ function htmlToTextSnippet(html, maxLength = 140) {
216
+ return sanitizeHtml(html).replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim().slice(0, maxLength);
217
+ }
218
+ export {
219
+ htmlToTextSnippet,
220
+ sanitizeHtml
221
+ };
222
+ //# sourceMappingURL=safe-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/internal/safe-html.ts"],"sourcesContent":["const DANGEROUS_BLOCK_TAGS = new Set([\n \"script\",\n \"style\",\n \"iframe\",\n \"object\",\n \"embed\",\n \"svg\",\n \"math\",\n \"template\",\n \"noscript\",\n \"textarea\",\n \"select\",\n])\n\nconst ALLOWED_TAGS = new Set([\n \"a\",\n \"b\",\n \"blockquote\",\n \"br\",\n \"code\",\n \"del\",\n \"div\",\n \"em\",\n \"hr\",\n \"i\",\n \"img\",\n \"li\",\n \"ol\",\n \"p\",\n \"pre\",\n \"s\",\n \"span\",\n \"strong\",\n \"table\",\n \"tbody\",\n \"td\",\n \"th\",\n \"thead\",\n \"tr\",\n \"u\",\n \"ul\",\n])\n\nconst VOID_TAGS = new Set([\"br\", \"hr\", \"img\"])\nconst SAFE_GLOBAL_ATTRS = new Set([\"aria-label\", \"role\", \"title\"])\nconst SAFE_URL_PROTOCOLS = new Set([\"http:\", \"https:\", \"mailto:\", \"tel:\"])\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n}\n\nfunction escapeAttribute(value: string): string {\n return escapeHtml(value).replace(/\"/g, \"&quot;\")\n}\n\nfunction safeCodePoint(value: number): string {\n return Number.isInteger(value) && value >= 0 && value <= 0x10ffff ? String.fromCodePoint(value) : \"\"\n}\n\nfunction decodeHtmlEntities(value: string): string {\n const namedEntities: Record<string, string> = {\n amp: \"&\",\n apos: \"'\",\n colon: \":\",\n gt: \">\",\n lt: \"<\",\n newline: \"\\n\",\n quot: '\"',\n tab: \"\\t\",\n }\n\n let decoded = value\n for (let i = 0; i < 4; i += 1) {\n const next = decoded\n .replace(/&#x([0-9a-f]+);?/gi, (_match, hex: string) => {\n const codePoint = Number.parseInt(hex, 16)\n return safeCodePoint(codePoint)\n })\n .replace(/&#(\\d+);?/g, (_match, decimal: string) => {\n const codePoint = Number.parseInt(decimal, 10)\n return safeCodePoint(codePoint)\n })\n .replace(/&([a-z]+);/gi, (match, name: string) => namedEntities[name.toLowerCase()] ?? match)\n\n if (next === decoded) return decoded\n decoded = next\n }\n\n return decoded\n}\n\nfunction isSafeUrl(value: string): boolean {\n const decoded = decodeHtmlEntities(value).replace(/[\\u0000-\\u001f\\u007f\\s]+/g, \"\").trim()\n if (!decoded) return false\n if (decoded.startsWith(\"//\")) return false\n if (decoded.startsWith(\"#\") || decoded.startsWith(\"/\") || decoded.startsWith(\"./\") || decoded.startsWith(\"../\")) {\n return true\n }\n\n try {\n return SAFE_URL_PROTOCOLS.has(new URL(decoded, \"https://handled.local\").protocol)\n } catch {\n return false\n }\n}\n\nfunction sanitizeClassName(value: string): string | null {\n const safeTokens = value\n .split(/\\s+/)\n .map((token) => token.trim())\n .filter((token) => /^[A-Za-z0-9_-]+$/.test(token))\n\n return safeTokens.length ? safeTokens.join(\" \") : null\n}\n\nfunction sanitizeAttribute(tagName: string, name: string, value: string): string | null {\n const attr = name.toLowerCase()\n\n if (\n attr.startsWith(\"on\") ||\n attr === \"style\" ||\n attr === \"srcdoc\" ||\n attr === \"formaction\" ||\n attr === \"xlink:href\" ||\n attr === \"xmlns\"\n ) {\n return null\n }\n\n if (attr === \"class\") {\n const safeClassName = sanitizeClassName(value)\n return safeClassName ? `class=\"${escapeAttribute(safeClassName)}\"` : null\n }\n\n if (SAFE_GLOBAL_ATTRS.has(attr) || attr.startsWith(\"aria-\")) {\n return `${attr}=\"${escapeAttribute(value)}\"`\n }\n\n if (tagName === \"a\" && attr === \"href\" && isSafeUrl(value)) {\n return `href=\"${escapeAttribute(value)}\"`\n }\n\n if (tagName === \"img\" && attr === \"src\" && isSafeUrl(value)) {\n return `src=\"${escapeAttribute(value)}\"`\n }\n\n if (tagName === \"img\" && (attr === \"alt\" || attr === \"width\" || attr === \"height\")) {\n return `${attr}=\"${escapeAttribute(value)}\"`\n }\n\n if ((tagName === \"td\" || tagName === \"th\") && (attr === \"colspan\" || attr === \"rowspan\")) {\n return `${attr}=\"${escapeAttribute(value)}\"`\n }\n\n return null\n}\n\nfunction sanitizeAttributes(tagName: string, rawAttributes = \"\"): string {\n const attributes: string[] = []\n const attrPattern = /([A-Za-z_:][-A-Za-z0-9_:.]*)(?:\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'=<>`]+)))?/g\n let match: RegExpExecArray | null\n\n while ((match = attrPattern.exec(rawAttributes)) !== null) {\n const [, name, doubleQuotedValue, singleQuotedValue, unquotedValue] = match\n const value = doubleQuotedValue ?? singleQuotedValue ?? unquotedValue ?? \"\"\n const safeAttribute = sanitizeAttribute(tagName, name, value)\n if (safeAttribute) attributes.push(safeAttribute)\n }\n\n if (tagName === \"a\" && attributes.some((attr) => attr.startsWith(\"href=\"))) {\n attributes.push('target=\"_blank\"', 'rel=\"noopener noreferrer\"')\n }\n\n return attributes.length ? ` ${attributes.join(\" \")}` : \"\"\n}\n\nfunction findTagEnd(html: string, startIndex: number): number {\n let quote: '\"' | \"'\" | null = null\n\n for (let i = startIndex + 1; i < html.length; i += 1) {\n const char = html[i]\n if (quote) {\n if (char === quote) quote = null\n continue\n }\n\n if (char === '\"' || char === \"'\") {\n quote = char\n continue\n }\n\n if (char === \">\") return i\n }\n\n return -1\n}\n\nfunction parseTag(rawTag: string): { closing: boolean; name: string; attributes: string } | null {\n const match = rawTag.match(/^<\\s*(\\/)?\\s*([A-Za-z][A-Za-z0-9:-]*)\\b([\\s\\S]*?)\\/?>$/)\n if (!match) return null\n\n return {\n closing: !!match[1],\n name: match[2].toLowerCase(),\n attributes: match[3] ?? \"\",\n }\n}\n\nfunction findDangerousClose(html: string, tagName: string, fromIndex: number): number {\n const closePattern = new RegExp(`</\\\\s*${tagName}\\\\s*>`, \"ig\")\n closePattern.lastIndex = fromIndex\n const match = closePattern.exec(html)\n return match ? closePattern.lastIndex : -1\n}\n\n/**\n * Conservative, deterministic sanitizer for user/email supplied HTML rendered by\n * design-system components. It keeps common email formatting tags while removing\n * executable tags, event handlers, inline styles, and unsafe URLs. This stays\n * dependency-free for the shared package and intentionally favors stripping\n * ambiguous email content over preserving every possible HTML feature.\n */\nexport function sanitizeHtml(html: string): string {\n let output = \"\"\n let cursor = 0\n\n while (cursor < html.length) {\n const tagStart = html.indexOf(\"<\", cursor)\n if (tagStart === -1) {\n output += html.slice(cursor)\n break\n }\n\n output += html.slice(cursor, tagStart)\n\n if (html.startsWith(\"<!--\", tagStart)) {\n const commentEnd = html.indexOf(\"-->\", tagStart + 4)\n cursor = commentEnd === -1 ? html.length : commentEnd + 3\n continue\n }\n\n const tagEnd = findTagEnd(html, tagStart)\n if (tagEnd === -1) {\n output += escapeHtml(html.slice(tagStart))\n break\n }\n\n const rawTag = html.slice(tagStart, tagEnd + 1)\n const parsed = parseTag(rawTag)\n if (!parsed) {\n cursor = tagEnd + 1\n continue\n }\n\n if (DANGEROUS_BLOCK_TAGS.has(parsed.name)) {\n const closeEnd = parsed.closing ? -1 : findDangerousClose(html, parsed.name, tagEnd + 1)\n cursor = closeEnd === -1 ? tagEnd + 1 : closeEnd\n continue\n }\n\n if (ALLOWED_TAGS.has(parsed.name)) {\n if (parsed.closing) {\n if (!VOID_TAGS.has(parsed.name)) output += `</${parsed.name}>`\n } else {\n output += `<${parsed.name}${sanitizeAttributes(parsed.name, parsed.attributes)}>`\n }\n }\n\n cursor = tagEnd + 1\n }\n\n return output\n}\n\nexport function htmlToTextSnippet(html: string, maxLength = 140): string {\n return sanitizeHtml(html)\n .replace(/<[^>]+>/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, maxLength)\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,4 @@
1
- export { A as AccountFilterTab, a as AccountsViewConfig, b as AdminTab, c as AdminViewConfig, B as BriefStyleVariant, E as EntityPanelConfig, d as EntityPanelSection, I as InboxDetailSections, e as InboxSortOption, f as InboxViewConfig, g as InsightsCustomTab, h as InsightsViewConfig, i as PrototypeBrandConfig, j as PrototypeConfig, Q as QueueItem, l as SignalScoreData, m as SignalScoreExplanationBucket, n as SignalScoreExplanationSignal, o as SignalScoreUrgencyLabel, T as TimelineSystemEventsConfig, W as WorkQueueViewConfig } from '../signal-priority-popover-QJngMAj7.js';
1
+ export { A as AccountFilterTab, a as AccountsViewConfig, b as AdminTab, c as AdminViewConfig, B as BriefStyleVariant, E as EntityPanelConfig, d as EntityPanelSection, I as InboxDetailSections, e as InboxSortOption, f as InboxViewConfig, g as InsightsCustomTab, h as InsightsViewConfig, i as PrototypeBrandConfig, j as PrototypeConfig, Q as QueueItem, m as SignalScoreData, n as SignalScoreExplanationBucket, o as SignalScoreExplanationSignal, p as SignalScoreUrgencyLabel, T as TimelineSystemEventsConfig, W as WorkQueueViewConfig } from '../signal-priority-popover-CZitE9xq.js';
2
2
  export { PrototypeShell, PrototypeShellProps } from './prototype-shell.js';
3
3
  export { DetailView, DetailViewProps, PrototypeInboxView, PrototypeInboxViewProps } from './prototype-inbox-view.js';
4
4
  export { PrototypeInsightsView, PrototypeInsightsViewProps } from './prototype-insights-view.js';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { a as AccountsViewConfig } from '../signal-priority-popover-QJngMAj7.js';
2
+ import { a as AccountsViewConfig } from '../signal-priority-popover-CZitE9xq.js';
3
3
  import { DataRow } from '../components/data-table.js';
4
4
  import '../components/feedback-primitives.js';
5
5
  import '../components/quick-action-sidebar-nav.js';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { c as AdminViewConfig } from '../signal-priority-popover-QJngMAj7.js';
2
+ import { c as AdminViewConfig } from '../signal-priority-popover-CZitE9xq.js';
3
3
  import '../components/feedback-primitives.js';
4
4
  import '../components/quick-action-sidebar-nav.js';
5
5
  import '../components/quick-action-modal.js';
@@ -11,7 +11,7 @@ import '../charts/pipeline-overview.js';
11
11
  import '../components/timeline-activity.js';
12
12
  import '../components/signal-feedback-inline.js';
13
13
  import 'lucide-react';
14
- export { A as AccountFilterTab, a as AccountsViewConfig, b as AdminTab, c as AdminViewConfig, B as BriefStyleVariant, E as EntityPanelConfig, d as EntityPanelSection, I as InboxDetailSections, e as InboxSortOption, f as InboxViewConfig, g as InsightsCustomTab, h as InsightsViewConfig, i as PrototypeBrandConfig, j as PrototypeConfig, Q as QueueItem, l as SignalScoreData, m as SignalScoreExplanationBucket, n as SignalScoreExplanationSignal, o as SignalScoreUrgencyLabel, T as TimelineSystemEventsConfig, W as WorkQueueViewConfig } from '../signal-priority-popover-QJngMAj7.js';
14
+ export { A as AccountFilterTab, a as AccountsViewConfig, b as AdminTab, c as AdminViewConfig, B as BriefStyleVariant, E as EntityPanelConfig, d as EntityPanelSection, I as InboxDetailSections, e as InboxSortOption, f as InboxViewConfig, g as InsightsCustomTab, h as InsightsViewConfig, i as PrototypeBrandConfig, j as PrototypeConfig, Q as QueueItem, m as SignalScoreData, n as SignalScoreExplanationBucket, o as SignalScoreExplanationSignal, p as SignalScoreUrgencyLabel, T as TimelineSystemEventsConfig, W as WorkQueueViewConfig } from '../signal-priority-popover-CZitE9xq.js';
15
15
  import '../components/feedback-primitives.js';
16
16
  import '../components/quick-action-modal.js';
17
17
  import '../components/score-semantics.js';
@@ -3,7 +3,7 @@ import { OpportunityDraft, ApprovalState, OpportunityPreview } from '../componen
3
3
  import { SourceDef } from '../components/detail-view.js';
4
4
  import { SuggestedAction, SuggestedContact } from '../components/suggested-actions.js';
5
5
  import { TimelineEvent } from '../components/timeline-activity.js';
6
- import { Q as QueueItem, I as InboxDetailSections, l as SignalScoreData, f as InboxViewConfig, B as BriefStyleVariant, T as TimelineSystemEventsConfig } from '../signal-priority-popover-QJngMAj7.js';
6
+ import { Q as QueueItem, I as InboxDetailSections, m as SignalScoreData, f as InboxViewConfig, B as BriefStyleVariant, T as TimelineSystemEventsConfig } from '../signal-priority-popover-CZitE9xq.js';
7
7
  import '../components/feedback-primitives.js';
8
8
  import '../components/quick-action-sidebar-nav.js';
9
9
  import '../components/quick-action-modal.js';
@@ -362,6 +362,8 @@ function DetailView({
362
362
  score: signalData.score,
363
363
  urgencyLabel: signalData.urgencyLabel,
364
364
  urgencyExplanation: (_b = signalData.urgencyExplanation) != null ? _b : signalData.signalBrief,
365
+ scoreDisplay: signalData.priorityScoreDisplay,
366
+ formulaLabel: signalData.priorityFormulaLabel,
365
367
  factors: (_c = signalData.priorityFactors) != null ? _c : [],
366
368
  metaText: void 0,
367
369
  feedbackChips: signalData.priorityFeedbackChips,