@corbits/react-ui 0.1.0 → 0.2.0

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 (170) hide show
  1. package/LICENSE +174 -499
  2. package/README.md +228 -85
  3. package/dist/blocks/login/auth-layout.d.ts +1 -1
  4. package/dist/blocks/login/auth-layout.js +3 -33
  5. package/dist/blocks/login/login-form.js +6 -119
  6. package/dist/hooks/use-command-palette-navigation.js +18 -17
  7. package/dist/hooks/use-controllable-state.d.ts +2 -2
  8. package/dist/hooks/use-controllable-state.js +23 -15
  9. package/dist/hooks/use-delayed-autofocus.js +10 -11
  10. package/dist/hooks/use-dismissable-popover.d.ts +2 -2
  11. package/dist/hooks/use-dismissable-popover.js +21 -29
  12. package/dist/hooks/use-list-selection.js +54 -85
  13. package/dist/hooks/use-prefers-reduced-motion.js +8 -4
  14. package/dist/hooks/use-scroll-current-into-view.js +5 -7
  15. package/dist/index.d.ts +0 -11
  16. package/dist/index.js +10 -19
  17. package/dist/lib/artifact.js +16 -35
  18. package/dist/lib/chart-geometry.js +33 -20
  19. package/dist/lib/chart-palette.js +17 -31
  20. package/dist/lib/chat-message.js +32 -13
  21. package/dist/lib/chat-parts.js +2 -1
  22. package/dist/lib/csv.js +42 -26
  23. package/dist/lib/metrics.js +30 -48
  24. package/dist/lib/now-item.js +26 -25
  25. package/dist/lib/relative-time.js +14 -29
  26. package/dist/lib/theme.js +32 -30
  27. package/dist/lib/url.js +9 -8
  28. package/dist/lib/workflow-display-flow.js +37 -33
  29. package/dist/lib/workflow-registry.d.ts +0 -41
  30. package/dist/lib/workflow-registry.js +13 -23
  31. package/dist/lib/workflow-run-error.js +16 -20
  32. package/dist/lib/workflow-run-progress.js +94 -52
  33. package/dist/lib/workflow-run.js +17 -13
  34. package/dist/styles.css +11 -11
  35. package/dist/test/render-hook.js +11 -12
  36. package/dist/theme.css +51 -14
  37. package/dist/ui/agent-turn.d.ts +1 -1
  38. package/dist/ui/agent-turn.js +4 -37
  39. package/dist/ui/animated-number.js +15 -28
  40. package/dist/ui/approval-card.js +5 -90
  41. package/dist/ui/artifact-body.js +47 -125
  42. package/dist/ui/artifact-notice.d.ts +1 -1
  43. package/dist/ui/artifact-notice.js +9 -16
  44. package/dist/ui/avatar.d.ts +1 -1
  45. package/dist/ui/avatar.js +11 -48
  46. package/dist/ui/badge.js +4 -12
  47. package/dist/ui/bar-chart.d.ts +1 -1
  48. package/dist/ui/bar-chart.js +22 -74
  49. package/dist/ui/block-card.js +7 -45
  50. package/dist/ui/boot-screen.d.ts +1 -1
  51. package/dist/ui/boot-screen.js +4 -33
  52. package/dist/ui/bulk-action-bar.d.ts +1 -1
  53. package/dist/ui/bulk-action-bar.js +14 -33
  54. package/dist/ui/button.js +10 -24
  55. package/dist/ui/card.js +5 -25
  56. package/dist/ui/category-bars.js +14 -59
  57. package/dist/ui/chart-frame.d.ts +2 -2
  58. package/dist/ui/chart-frame.js +6 -85
  59. package/dist/ui/chat-composer.js +4 -16
  60. package/dist/ui/chat-dock-timing.js +7 -3
  61. package/dist/ui/chat-input.js +20 -100
  62. package/dist/ui/chat-panel.d.ts +1 -1
  63. package/dist/ui/chat-panel.js +7 -41
  64. package/dist/ui/chat-thread.js +13 -31
  65. package/dist/ui/checkbox.js +10 -52
  66. package/dist/ui/command-palette.js +71 -246
  67. package/dist/ui/compare-body.d.ts +1 -1
  68. package/dist/ui/compare-body.js +28 -98
  69. package/dist/ui/confirm-button.js +8 -15
  70. package/dist/ui/corbits-mark.js +7 -16
  71. package/dist/ui/csv-table.d.ts +1 -1
  72. package/dist/ui/csv-table.js +8 -50
  73. package/dist/ui/dialog.d.ts +1 -1
  74. package/dist/ui/dialog.js +32 -62
  75. package/dist/ui/dictation-status-line.js +7 -25
  76. package/dist/ui/dither-canvas.d.ts +1 -1
  77. package/dist/ui/dither-canvas.js +31 -56
  78. package/dist/ui/embed-body.d.ts +1 -1
  79. package/dist/ui/embed-body.js +7 -56
  80. package/dist/ui/empty-state.d.ts +1 -1
  81. package/dist/ui/empty-state.js +3 -26
  82. package/dist/ui/file-input.js +17 -37
  83. package/dist/ui/filter-bar.d.ts +1 -1
  84. package/dist/ui/filter-bar.js +11 -71
  85. package/dist/ui/filter-chip.d.ts +1 -1
  86. package/dist/ui/filter-chip.js +7 -15
  87. package/dist/ui/gate-block.d.ts +2 -1
  88. package/dist/ui/gate-block.js +4 -29
  89. package/dist/ui/horizontal-stepper.d.ts +1 -1
  90. package/dist/ui/horizontal-stepper.js +18 -45
  91. package/dist/ui/input.js +1 -6
  92. package/dist/ui/inspector-shell.d.ts +5 -5
  93. package/dist/ui/inspector-shell.js +14 -81
  94. package/dist/ui/intake-form.d.ts +1 -1
  95. package/dist/ui/intake-form.js +21 -97
  96. package/dist/ui/kind-card-grid.js +9 -31
  97. package/dist/ui/library-page-header.js +4 -32
  98. package/dist/ui/list-detail.js +5 -35
  99. package/dist/ui/live-run-banner.d.ts +1 -1
  100. package/dist/ui/live-run-banner.js +5 -15
  101. package/dist/ui/live-status-line.js +6 -24
  102. package/dist/ui/menu.js +7 -24
  103. package/dist/ui/message-bubble.d.ts +3 -3
  104. package/dist/ui/message-bubble.js +5 -44
  105. package/dist/ui/mic-button.d.ts +1 -1
  106. package/dist/ui/mic-button.js +15 -21
  107. package/dist/ui/mic-permission-dialog.js +5 -41
  108. package/dist/ui/notifications-bell.js +9 -43
  109. package/dist/ui/now-cards.d.ts +2 -2
  110. package/dist/ui/now-cards.js +16 -94
  111. package/dist/ui/page-panel.js +11 -11
  112. package/dist/ui/page-shell.js +4 -11
  113. package/dist/ui/parts-renderer.js +51 -149
  114. package/dist/ui/profile-card.js +7 -111
  115. package/dist/ui/progress-checklist.js +11 -49
  116. package/dist/ui/provider-mark.d.ts +2 -2
  117. package/dist/ui/provider-mark.js +9 -16
  118. package/dist/ui/quick-reply-chips.js +6 -14
  119. package/dist/ui/quote-card.js +12 -32
  120. package/dist/ui/reasoning-block.d.ts +1 -1
  121. package/dist/ui/reasoning-block.js +14 -33
  122. package/dist/ui/research-body.js +32 -213
  123. package/dist/ui/rich-empty-state.js +6 -48
  124. package/dist/ui/run-now-button.js +14 -15
  125. package/dist/ui/section.d.ts +1 -1
  126. package/dist/ui/section.js +4 -40
  127. package/dist/ui/select.js +1 -15
  128. package/dist/ui/selection-checkbox.d.ts +1 -1
  129. package/dist/ui/selection-checkbox.js +11 -29
  130. package/dist/ui/settings-panel.js +7 -50
  131. package/dist/ui/shimmer-text.js +3 -6
  132. package/dist/ui/sidebar-item-row.d.ts +1 -1
  133. package/dist/ui/sidebar-item-row.js +9 -39
  134. package/dist/ui/sidebar-panel.js +15 -40
  135. package/dist/ui/sidebar.js +15 -76
  136. package/dist/ui/skeleton.js +3 -7
  137. package/dist/ui/sortable-table.js +29 -72
  138. package/dist/ui/sparkline.js +14 -38
  139. package/dist/ui/stat-grid.js +17 -52
  140. package/dist/ui/status-dot.d.ts +1 -1
  141. package/dist/ui/status-dot.js +8 -20
  142. package/dist/ui/step-list.d.ts +1 -0
  143. package/dist/ui/step-list.js +11 -50
  144. package/dist/ui/switch.js +4 -16
  145. package/dist/ui/table.js +7 -32
  146. package/dist/ui/tabs.js +39 -54
  147. package/dist/ui/textarea.js +10 -19
  148. package/dist/ui/theme-provider.js +54 -78
  149. package/dist/ui/theme-toggle.js +13 -16
  150. package/dist/ui/thinking-indicator.js +3 -15
  151. package/dist/ui/thinking-label.js +16 -35
  152. package/dist/ui/thinking-mark.d.ts +1 -1
  153. package/dist/ui/thinking-mark.js +4 -145
  154. package/dist/ui/time-series-chart.js +43 -174
  155. package/dist/ui/toast.js +12 -20
  156. package/dist/ui/token-mosaic.js +5 -43
  157. package/dist/ui/tool-block.js +18 -70
  158. package/dist/ui/tool-narrative.d.ts +1 -1
  159. package/dist/ui/tool-narrative.js +10 -57
  160. package/dist/ui/tool-picker.js +57 -145
  161. package/dist/ui/tooltip.d.ts +1 -1
  162. package/dist/ui/tooltip.js +4 -33
  163. package/dist/ui/top-bar.js +14 -72
  164. package/dist/ui/trace-waterfall.d.ts +1 -1
  165. package/dist/ui/trace-waterfall.js +21 -93
  166. package/dist/ui/typing-indicator.d.ts +1 -1
  167. package/dist/ui/typing-indicator.js +4 -18
  168. package/dist/ui/view-toggle.js +10 -29
  169. package/dist/ui/voice-waveform.js +3 -11
  170. package/package.json +94 -535
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { useState } from "react";
3
4
  import { cn } from "../lib/utils.js";
@@ -17,100 +18,14 @@ const LONG_VALUE = 140;
17
18
  * Every argument the action will run with is shown. A card that hides them
18
19
  * behind "details" is asking for approval of something the user cannot see, so
19
20
  * long values clamp rather than disappear.
20
- */ export function ApprovalCard({ request, onApprove, onReject, onAllowAlways, state = "idle", error = null, className, children }) {
21
+ */
22
+ export function ApprovalCard({ request, onApprove, onReject, onAllowAlways, state = "idle", error = null, className, children, }) {
21
23
  const busy = state !== "idle";
22
24
  const canAllowAlways = onAllowAlways !== undefined && request.actionKey !== undefined;
23
- return /*#__PURE__*/ _jsxs("section", {
24
- "aria-label": `Approval requested: ${request.headline}`,
25
- className: cn("flex flex-col gap-3 rounded-lg border border-primary-emphasis bg-card p-4", className),
26
- children: [
27
- /*#__PURE__*/ _jsxs("div", {
28
- className: "flex flex-wrap items-center gap-2",
29
- children: [
30
- /*#__PURE__*/ _jsx(Badge, {
31
- tone: "accent",
32
- children: "Needs your approval"
33
- }),
34
- /*#__PURE__*/ _jsxs("span", {
35
- className: "text-xs text-muted-foreground",
36
- children: [
37
- "Requested by ",
38
- request.requestedBy
39
- ]
40
- })
41
- ]
42
- }),
43
- /*#__PURE__*/ _jsx("p", {
44
- className: "text-sm font-semibold",
45
- children: request.headline
46
- }),
47
- request.details === undefined || request.details.length === 0 ? null : /*#__PURE__*/ _jsx("dl", {
48
- className: "flex flex-col gap-1.5 rounded-md bg-muted p-3 text-xs",
49
- children: request.details.map((detail)=>/*#__PURE__*/ _jsx(ApprovalDetailRow, {
50
- detail: detail
51
- }, detail.label))
52
- }),
53
- children,
54
- error === null ? null : /*#__PURE__*/ _jsx("p", {
55
- role: "alert",
56
- className: "text-sm text-destructive",
57
- children: error
58
- }),
59
- /*#__PURE__*/ _jsxs("div", {
60
- className: "flex flex-wrap items-center gap-2",
61
- children: [
62
- /*#__PURE__*/ _jsx(Button, {
63
- size: "sm",
64
- onClick: onApprove,
65
- disabled: busy,
66
- children: state === "approving" ? "Approving…" : "Approve"
67
- }),
68
- /*#__PURE__*/ _jsx(Button, {
69
- variant: "outline",
70
- size: "sm",
71
- onClick: onReject,
72
- disabled: busy,
73
- children: state === "rejecting" ? "Rejecting…" : "Reject"
74
- }),
75
- canAllowAlways ? /*#__PURE__*/ _jsx(Button, {
76
- variant: "ghost",
77
- size: "sm",
78
- onClick: ()=>onAllowAlways(request.actionKey),
79
- disabled: busy,
80
- className: "ml-auto",
81
- children: state === "allowing-always" ? "Saving…" : "Always allow this"
82
- }) : null
83
- ]
84
- })
85
- ]
86
- });
25
+ return (_jsxs("section", { "aria-label": `Approval requested: ${request.headline}`, className: cn("flex flex-col gap-3 rounded-lg border border-primary-emphasis bg-card p-4", className), children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Badge, { tone: "accent", children: "Needs your approval" }), _jsxs("span", { className: "text-xs text-muted-foreground", children: ["Requested by ", request.requestedBy] })] }), _jsx("p", { className: "text-sm font-semibold", children: request.headline }), request.details === undefined || request.details.length === 0 ? null : (_jsx("dl", { className: "flex flex-col gap-1.5 rounded-md bg-muted p-3 text-xs", children: request.details.map((detail) => (_jsx(ApprovalDetailRow, { detail: detail }, detail.label))) })), children, error === null ? null : (_jsx("p", { role: "alert", className: "text-sm text-destructive", children: error })), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Button, { size: "sm", onClick: onApprove, disabled: busy, children: state === "approving" ? "Approving…" : "Approve" }), _jsx(Button, { variant: "outline", size: "sm", onClick: onReject, disabled: busy, children: state === "rejecting" ? "Rejecting…" : "Reject" }), canAllowAlways ? (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => onAllowAlways(request.actionKey), disabled: busy, className: "ml-auto", children: state === "allowing-always" ? "Saving…" : "Always allow this" })) : null] })] }));
87
26
  }
88
27
  function ApprovalDetailRow({ detail }) {
89
28
  const [expanded, setExpanded] = useState(false);
90
29
  const long = detail.value.length > LONG_VALUE;
91
- return /*#__PURE__*/ _jsxs("div", {
92
- className: "grid grid-cols-[minmax(0,8rem)_1fr] gap-2",
93
- children: [
94
- /*#__PURE__*/ _jsx("dt", {
95
- className: "truncate text-muted-foreground",
96
- children: detail.label
97
- }),
98
- /*#__PURE__*/ _jsxs("dd", {
99
- className: "min-w-0",
100
- children: [
101
- /*#__PURE__*/ _jsx("span", {
102
- className: cn("block break-words whitespace-pre-wrap", long && !expanded && "line-clamp-2"),
103
- children: detail.value
104
- }),
105
- long ? /*#__PURE__*/ _jsx("button", {
106
- type: "button",
107
- onClick: ()=>setExpanded((value)=>!value),
108
- "aria-expanded": expanded,
109
- className: "mt-0.5 text-primary-emphasis hover:underline",
110
- children: expanded ? "Show less" : "Show more"
111
- }) : null
112
- ]
113
- })
114
- ]
115
- });
30
+ return (_jsxs("div", { className: "grid grid-cols-[minmax(0,8rem)_1fr] gap-2", children: [_jsx("dt", { className: "truncate text-muted-foreground", children: detail.label }), _jsxs("dd", { className: "min-w-0", children: [_jsx("span", { className: cn("block break-words whitespace-pre-wrap", long && !expanded && "line-clamp-2"), children: detail.value }), long ? (_jsx("button", { type: "button", onClick: () => setExpanded((value) => !value), "aria-expanded": expanded, className: "mt-0.5 text-primary-emphasis hover:underline", children: expanded ? "Show less" : "Show more" })) : null] })] }));
116
31
  }
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Download } from "lucide-react";
3
- import { artifactForm } from "../lib/artifact.js";
3
+ import { artifactForm, } from "../lib/artifact.js";
4
4
  import { toSafeHref } from "../lib/url.js";
5
5
  import { cn } from "../lib/utils.js";
6
6
  import { ArtifactNotice } from "./artifact-notice.js";
@@ -22,133 +22,57 @@ import { ResearchBody, parseResearchArtifact } from "./research-body.js";
22
22
  * "empty" is a real state here — artifacts are frequently rendered while they
23
23
  * are still being written — and each form's own empty rendering (a table with
24
24
  * no rows, a frame with no src) reads as a fault rather than as progress.
25
- */ export function ArtifactBody({ artifact, form, className }) {
25
+ */
26
+ export function ArtifactBody({ artifact, form, className }) {
26
27
  const resolved = form ?? artifactForm(artifact.kind);
27
28
  const content = artifact.content;
28
29
  const blank = content.trim() === "";
29
- return /*#__PURE__*/ _jsx("div", {
30
- className: cn("w-full", className),
31
- children: body()
32
- });
30
+ return _jsx("div", { className: cn("w-full", className), children: body() });
33
31
  function body() {
34
- switch(resolved){
35
- case "image":
36
- {
37
- // The thumbnail URL, not the content: an image artifact's bytes live
38
- // behind a route, and `content` for one is either empty or a caption.
39
- const src = toSafeHref(artifact.thumbnailUrl ?? artifact.downloadUrl);
40
- if (src === undefined) return /*#__PURE__*/ _jsx(ArtifactNotice, {
41
- pending: artifact.pending
42
- });
43
- return /*#__PURE__*/ _jsxs("figure", {
44
- className: "flex flex-col gap-3",
45
- children: [
46
- /*#__PURE__*/ _jsx("img", {
47
- src: src,
48
- alt: artifact.title,
49
- className: "max-h-[480px] max-w-full rounded-lg border border-border"
50
- }),
51
- blank ? null : /*#__PURE__*/ _jsx("figcaption", {
52
- className: "text-xs text-muted-foreground",
53
- children: content
54
- })
55
- ]
56
- });
57
- }
58
- case "download":
59
- {
60
- const downloadUrl = toSafeHref(artifact.downloadUrl);
61
- if (downloadUrl === undefined) {
62
- return /*#__PURE__*/ _jsx(ArtifactNotice, {
63
- message: "This file has no download location, so it cannot be retrieved."
64
- });
65
- }
66
- return /*#__PURE__*/ _jsxs("a", {
67
- href: downloadUrl,
68
- download: true,
69
- className: buttonVariants({
70
- variant: "outline",
71
- size: "sm"
72
- }),
73
- children: [
74
- /*#__PURE__*/ _jsx(Download, {
75
- "aria-hidden": true
76
- }),
77
- "Download ",
78
- artifact.title
79
- ]
80
- });
32
+ switch (resolved) {
33
+ case "image": {
34
+ // The thumbnail URL, not the content: an image artifact's bytes live
35
+ // behind a route, and `content` for one is either empty or a caption.
36
+ const src = toSafeHref(artifact.thumbnailUrl ?? artifact.downloadUrl);
37
+ if (src === undefined)
38
+ return _jsx(ArtifactNotice, { pending: artifact.pending });
39
+ return (_jsxs("figure", { className: "flex flex-col gap-3", children: [_jsx("img", { src: src, alt: artifact.title, className: "max-h-[480px] max-w-full rounded-lg border border-border" }), blank ? null : (_jsx("figcaption", { className: "text-xs text-muted-foreground", children: content }))] }));
40
+ }
41
+ case "download": {
42
+ const downloadUrl = toSafeHref(artifact.downloadUrl);
43
+ if (downloadUrl === undefined) {
44
+ return (_jsx(ArtifactNotice, { message: "This file has no download location, so it cannot be retrieved." }));
81
45
  }
46
+ return (_jsxs("a", { href: downloadUrl, download: true, className: buttonVariants({ variant: "outline", size: "sm" }), children: [_jsx(Download, { "aria-hidden": true }), "Download ", artifact.title] }));
47
+ }
82
48
  case "embed":
83
- return /*#__PURE__*/ _jsx(EmbedBody, {
84
- url: content.trim(),
85
- title: artifact.title,
86
- ...artifact.downloadUrl === undefined ? {} : {
87
- downloadUrl: artifact.downloadUrl
88
- }
89
- });
90
- case "table":
91
- {
92
- if (blank) return /*#__PURE__*/ _jsx(ArtifactNotice, {
93
- pending: artifact.pending
94
- });
95
- const downloadUrl = toSafeHref(artifact.downloadUrl);
96
- return /*#__PURE__*/ _jsxs("div", {
97
- className: "flex flex-col gap-3",
98
- children: [
99
- downloadUrl === undefined ? null : /*#__PURE__*/ _jsxs("a", {
100
- href: downloadUrl,
101
- download: true,
102
- className: cn(buttonVariants({
103
- variant: "outline",
104
- size: "sm"
105
- }), "self-start"),
106
- children: [
107
- /*#__PURE__*/ _jsx(Download, {
108
- "aria-hidden": true
109
- }),
110
- "Download"
111
- ]
112
- }),
113
- /*#__PURE__*/ _jsx(CsvTable, {
114
- text: content,
115
- caption: artifact.title
116
- })
117
- ]
118
- });
119
- }
49
+ return (_jsx(EmbedBody, { url: content.trim(), title: artifact.title, ...(artifact.downloadUrl === undefined
50
+ ? {}
51
+ : { downloadUrl: artifact.downloadUrl }) }));
52
+ case "table": {
53
+ if (blank)
54
+ return _jsx(ArtifactNotice, { pending: artifact.pending });
55
+ const downloadUrl = toSafeHref(artifact.downloadUrl);
56
+ return (_jsxs("div", { className: "flex flex-col gap-3", children: [downloadUrl === undefined ? null : (_jsxs("a", { href: downloadUrl, download: true, className: cn(buttonVariants({ variant: "outline", size: "sm" }), "self-start"), children: [_jsx(Download, { "aria-hidden": true }), "Download"] })), _jsx(CsvTable, { text: content, caption: artifact.title })] }));
57
+ }
120
58
  case "comparison":
121
- return /*#__PURE__*/ _jsx(CompareBodyFromJson, {
122
- content: content,
123
- ...artifact.pending === undefined ? {} : {
124
- pending: artifact.pending
125
- }
126
- });
127
- case "research":
128
- {
129
- if (blank) return /*#__PURE__*/ _jsx(ArtifactNotice, {
130
- pending: artifact.pending
131
- });
132
- const parsed = parseResearchArtifact(content);
133
- // Unparseable is not a failure worth an error card — the payload is
134
- // still the artifact, so fall through to prose and let it be read.
135
- if (parsed === null) return /*#__PURE__*/ _jsx(Prose, {
136
- text: content
137
- });
138
- return /*#__PURE__*/ _jsx(ResearchBody, {
139
- brief: parsed.brief,
140
- ...parsed.body === undefined ? {} : {
141
- body: parsed.body
142
- }
143
- });
144
- }
59
+ return (_jsx(CompareBodyFromJson, { content: content, ...(artifact.pending === undefined
60
+ ? {}
61
+ : { pending: artifact.pending }) }));
62
+ case "research": {
63
+ if (blank)
64
+ return _jsx(ArtifactNotice, { pending: artifact.pending });
65
+ const parsed = parseResearchArtifact(content);
66
+ // Unparseable is not a failure worth an error card — the payload is
67
+ // still the artifact, so fall through to prose and let it be read.
68
+ if (parsed === null)
69
+ return _jsx(Prose, { text: content });
70
+ return (_jsx(ResearchBody, { brief: parsed.brief, ...(parsed.body === undefined ? {} : { body: parsed.body }) }));
71
+ }
145
72
  case "prose":
146
- if (blank) return /*#__PURE__*/ _jsx(ArtifactNotice, {
147
- pending: artifact.pending
148
- });
149
- return /*#__PURE__*/ _jsx(Prose, {
150
- text: content
151
- });
73
+ if (blank)
74
+ return _jsx(ArtifactNotice, { pending: artifact.pending });
75
+ return _jsx(Prose, { text: content });
152
76
  }
153
77
  }
154
78
  }
@@ -162,9 +86,7 @@ import { ResearchBody, parseResearchArtifact } from "./research-body.js";
162
86
  *
163
87
  * `max-w-prose` caps the measure at roughly 65 characters. Full-bleed body text
164
88
  * on a wide screen is unreadable regardless of how good the type is.
165
- */ function Prose({ text }) {
166
- return /*#__PURE__*/ _jsx("div", {
167
- className: "max-w-prose text-sm leading-relaxed whitespace-pre-wrap",
168
- children: text
169
- });
89
+ */
90
+ function Prose({ text }) {
91
+ return (_jsx("div", { className: "max-w-prose text-sm leading-relaxed whitespace-pre-wrap", children: text }));
170
92
  }
@@ -16,6 +16,6 @@ export declare function ArtifactNotice({
16
16
  pending,
17
17
  /** Overrides the pending/empty wording — use for a specific failure. */
18
18
  message, }: {
19
- readonly pending?: boolean;
19
+ readonly pending?: boolean | undefined;
20
20
  readonly message?: string;
21
21
  }): import("react").JSX.Element;
@@ -13,24 +13,17 @@ import { EmptyState } from "./empty-state.js";
13
13
  * artifact means the producer has not finished writing; an empty payload on a
14
14
  * settled one means there is genuinely nothing. Same markup, opposite message,
15
15
  * and getting it backwards makes a working system look broken.
16
- */ export function ArtifactNotice({ /** The producer is still writing. Changes the message, not the layout. */ pending = false, /** Overrides the pending/empty wording — use for a specific failure. */ message }) {
16
+ */
17
+ export function ArtifactNotice({
18
+ /** The producer is still writing. Changes the message, not the layout. */
19
+ pending = false,
20
+ /** Overrides the pending/empty wording — use for a specific failure. */
21
+ message, }) {
17
22
  if (message !== undefined) {
18
- return /*#__PURE__*/ _jsx(EmptyState, {
19
- icon: /*#__PURE__*/ _jsx(FileWarning, {}),
20
- title: "Nothing to preview",
21
- description: message
22
- });
23
+ return (_jsx(EmptyState, { icon: _jsx(FileWarning, {}), title: "Nothing to preview", description: message }));
23
24
  }
24
25
  if (pending) {
25
- return /*#__PURE__*/ _jsx(EmptyState, {
26
- icon: /*#__PURE__*/ _jsx(Loader2, {}),
27
- title: "Still being produced",
28
- description: "This artifact has no content yet — check back shortly."
29
- });
26
+ return (_jsx(EmptyState, { icon: _jsx(Loader2, {}), title: "Still being produced", description: "This artifact has no content yet \u2014 check back shortly." }));
30
27
  }
31
- return /*#__PURE__*/ _jsx(EmptyState, {
32
- icon: /*#__PURE__*/ _jsx(FileWarning, {}),
33
- title: "No content",
34
- description: "This artifact is empty."
35
- });
28
+ return (_jsx(EmptyState, { icon: _jsx(FileWarning, {}), title: "No content", description: "This artifact is empty." }));
36
29
  }
@@ -33,5 +33,5 @@ export type AvatarStackProps = {
33
33
  /**
34
34
  * Overlapping avatar stack for thread participants and channel members.
35
35
  */
36
- export declare function AvatarStack({ items, max, size, className }: AvatarStackProps): import("react").JSX.Element;
36
+ export declare function AvatarStack({ items, max, size, className, }: AvatarStackProps): import("react").JSX.Element;
37
37
  export type AvatarStackSlot = ReactNode;
package/dist/ui/avatar.js CHANGED
@@ -3,71 +3,34 @@ import { cn } from "../lib/utils.js";
3
3
  const SIZE_CLASS = {
4
4
  sm: "size-6 text-[10px]",
5
5
  md: "size-8 text-xs",
6
- lg: "size-10 text-sm"
6
+ lg: "size-10 text-sm",
7
7
  };
8
8
  const TONE_CLASS = {
9
9
  neutral: "bg-muted text-muted-foreground",
10
10
  agent: "bg-primary text-primary-foreground",
11
11
  agent2: "bg-accent text-accent-foreground",
12
- agent3: "bg-success text-success-foreground"
12
+ agent3: "bg-success text-success-foreground",
13
13
  };
14
14
  const BADGE_SIZE = {
15
15
  sm: "size-3 text-[7px]",
16
16
  md: "size-3.5 text-[8px]",
17
- lg: "size-4 text-[9px]"
17
+ lg: "size-4 text-[9px]",
18
18
  };
19
19
  /**
20
20
  * Initials avatar with optional tenant monogram badge. Images are
21
21
  * intentionally unsupported here: identity headers should not flash or
22
22
  * depend on third-party avatar hosts.
23
- */ export function Avatar({ initials, label, tone = "neutral", size = "md", tenantMonogram, className }) {
24
- return /*#__PURE__*/ _jsxs("span", {
25
- role: "img",
26
- "aria-label": label,
27
- className: cn("relative inline-flex shrink-0 items-center justify-center font-bold uppercase", SIZE_CLASS[size], TONE_CLASS[tone], className),
28
- children: [
29
- /*#__PURE__*/ _jsx("span", {
30
- "aria-hidden": true,
31
- children: initials.slice(0, 2)
32
- }),
33
- tenantMonogram === undefined ? null : /*#__PURE__*/ _jsx("span", {
34
- "aria-hidden": true,
35
- className: cn("absolute -right-0.5 -bottom-0.5 inline-flex items-center justify-center border border-background bg-muted font-bold uppercase text-muted-foreground", BADGE_SIZE[size]),
36
- children: tenantMonogram.slice(0, 1)
37
- })
38
- ]
39
- });
23
+ */
24
+ export function Avatar({ initials, label, tone = "neutral", size = "md", tenantMonogram, className, }) {
25
+ return (_jsxs("span", { role: "img", "aria-label": label, className: cn("relative inline-flex shrink-0 items-center justify-center font-bold uppercase", SIZE_CLASS[size], TONE_CLASS[tone], className), children: [_jsx("span", { "aria-hidden": true, children: initials.slice(0, 2) }), tenantMonogram === undefined ? null : (_jsx("span", { "aria-hidden": true, className: cn("absolute -right-0.5 -bottom-0.5 inline-flex items-center justify-center border border-background bg-muted font-bold uppercase text-muted-foreground", BADGE_SIZE[size]), children: tenantMonogram.slice(0, 1) }))] }));
40
26
  }
41
27
  /**
42
28
  * Overlapping avatar stack for thread participants and channel members.
43
- */ export function AvatarStack({ items, max = 4, size = "sm", className }) {
29
+ */
30
+ export function AvatarStack({ items, max = 4, size = "sm", className, }) {
44
31
  const visible = items.slice(0, max);
45
32
  const overflow = items.length - visible.length;
46
- return /*#__PURE__*/ _jsxs("span", {
47
- className: cn("inline-flex items-center", className),
48
- role: "group",
49
- "aria-label": "Participants",
50
- children: [
51
- visible.map((item, index)=>/*#__PURE__*/ _jsx(Avatar, {
52
- initials: item.initials,
53
- label: item.label,
54
- ...item.tone === undefined ? {} : {
55
- tone: item.tone
56
- },
57
- ...item.tenantMonogram === undefined ? {} : {
58
- tenantMonogram: item.tenantMonogram
59
- },
60
- size: size,
61
- className: cn("ring-1 ring-background", index > 0 && "-ml-1.5")
62
- }, item.id)),
63
- overflow <= 0 ? null : /*#__PURE__*/ _jsxs("span", {
64
- className: cn("inline-flex items-center justify-center bg-muted font-mono font-semibold text-muted-foreground ring-1 ring-background", SIZE_CLASS[size], visible.length > 0 && "-ml-1.5"),
65
- "aria-label": `${overflow} more`,
66
- children: [
67
- "+",
68
- overflow
69
- ]
70
- })
71
- ]
72
- });
33
+ return (_jsxs("span", { className: cn("inline-flex items-center", className), role: "group", "aria-label": "Participants", children: [visible.map((item, index) => (_jsx(Avatar, { initials: item.initials, label: item.label, ...(item.tone === undefined ? {} : { tone: item.tone }), ...(item.tenantMonogram === undefined
34
+ ? {}
35
+ : { tenantMonogram: item.tenantMonogram }), size: size, className: cn("ring-1 ring-background", index > 0 && "-ml-1.5") }, item.id))), overflow <= 0 ? null : (_jsxs("span", { className: cn("inline-flex items-center justify-center bg-muted font-mono font-semibold text-muted-foreground ring-1 ring-background", SIZE_CLASS[size], visible.length > 0 && "-ml-1.5"), "aria-label": `${overflow} more`, children: ["+", overflow] }))] }));
73
36
  }
package/dist/ui/badge.js CHANGED
@@ -16,20 +16,12 @@ const badgeVariants = cva("inline-flex items-center gap-1 rounded-sm border px-1
16
16
  warning: "border-primary-emphasis/40 bg-primary/10 text-primary-emphasis",
17
17
  danger: "border-destructive bg-destructive text-destructive-foreground",
18
18
  shared: "border-accent bg-accent text-accent-foreground",
19
- access: "border-primary-emphasis/40 bg-primary/10 text-primary-emphasis"
20
- }
19
+ access: "border-primary-emphasis/40 bg-primary/10 text-primary-emphasis",
20
+ },
21
21
  },
22
- defaultVariants: {
23
- tone: "neutral"
24
- }
22
+ defaultVariants: { tone: "neutral" },
25
23
  });
26
24
  export function Badge({ className, tone, ...props }) {
27
- return /*#__PURE__*/ _jsx("span", {
28
- "data-slot": "badge",
29
- className: cn(badgeVariants({
30
- tone
31
- }), className),
32
- ...props
33
- });
25
+ return (_jsx("span", { "data-slot": "badge", className: cn(badgeVariants({ tone }), className), ...props }));
34
26
  }
35
27
  export { badgeVariants };
@@ -35,4 +35,4 @@ export type BarChartProps = {
35
35
  * the exact values — which is what anyone reading non-visually wants — are in
36
36
  * the table, in order, with headers.
37
37
  */
38
- export declare function BarChart({ title, description, data, valueLabel, format, className }: BarChartProps): import("react").JSX.Element;
38
+ export declare function BarChart({ title, description, data, valueLabel, format, className, }: BarChartProps): import("react").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { formatCompact, niceTicks, scaleLinear } from "../lib/chart-geometry.js";
2
+ import { formatCompact, niceTicks, scaleLinear, } from "../lib/chart-geometry.js";
3
3
  import { seriesColor } from "../lib/chart-palette.js";
4
4
  import { cn } from "../lib/utils.js";
5
5
  import { ChartFrame } from "./chart-frame.js";
@@ -30,89 +30,37 @@ const RADIUS = 4;
30
30
  * numbers. An SVG full of `<rect>` elements announced individually is noise, and
31
31
  * the exact values — which is what anyone reading non-visually wants — are in
32
32
  * the table, in order, with headers.
33
- */ export function BarChart({ title, description, data, valueLabel = "Value", format = formatCompact, className }) {
34
- const max = Math.max(0, ...data.map((datum)=>datum.value));
33
+ */
34
+ export function BarChart({ title, description, data, valueLabel = "Value", format = formatCompact, className, }) {
35
+ const max = Math.max(0, ...data.map((datum) => datum.value));
35
36
  const ticks = niceTicks(max);
36
37
  const axisMax = ticks[ticks.length - 1] ?? 1;
37
38
  const plotWidth = 320;
38
39
  const height = data.length * ROW_HEIGHT;
39
40
  const width = LABEL_WIDTH + plotWidth + VALUE_WIDTH;
40
- return /*#__PURE__*/ _jsxs(ChartFrame, {
41
- title: title,
42
- ...description === undefined ? {} : {
43
- description
44
- },
45
- table: {
46
- columns: [
47
- "Category",
48
- valueLabel
49
- ],
50
- rows: data.map((datum)=>[
51
- datum.label,
52
- format(datum.value)
53
- ])
54
- },
55
- className: className,
56
- children: [
57
- /*#__PURE__*/ _jsxs("svg", {
58
- viewBox: `0 0 ${width} ${height}`,
41
+ return (_jsxs(ChartFrame, { title: title, ...(description === undefined ? {} : { description }), table: {
42
+ columns: ["Category", valueLabel],
43
+ rows: data.map((datum) => [datum.label, format(datum.value)]),
44
+ }, className: className, children: [_jsxs("svg", { viewBox: `0 0 ${width} ${height}`,
59
45
  // Scales to the container's width; the row rhythm is what must stay
60
46
  // fixed, and it is expressed in the viewBox.
61
- className: "h-auto w-full",
62
- "aria-hidden": true,
63
- focusable: "false",
64
- children: [
65
- ticks.map((tick)=>{
47
+ className: "h-auto w-full", "aria-hidden": true, focusable: "false", children: [ticks.map((tick) => {
66
48
  const x = LABEL_WIDTH + scaleLinear(tick, axisMax, plotWidth);
67
- return(// Hairline, solid, one step off the surface: present enough to
49
+ return (
50
+ // Hairline, solid, one step off the surface: present enough to
68
51
  // measure against, quiet enough that the bars stay the loud thing.
69
- /*#__PURE__*/ _jsx("line", {
70
- x1: x,
71
- y1: 0,
72
- x2: x,
73
- y2: height,
74
- stroke: "var(--border)",
75
- strokeWidth: 1
76
- }, tick));
77
- }),
78
- data.map((datum, index)=>{
52
+ _jsx("line", { x1: x, y1: 0, x2: x, y2: height, stroke: "var(--border)", strokeWidth: 1 }, tick));
53
+ }), data.map((datum, index) => {
79
54
  const y = index * ROW_HEIGHT + (ROW_HEIGHT - BAR_HEIGHT) / 2;
80
55
  const length = scaleLinear(datum.value, axisMax, plotWidth);
81
56
  const radius = Math.min(RADIUS, length / 2);
82
- return /*#__PURE__*/ _jsxs("g", {
83
- children: [
84
- /*#__PURE__*/ _jsx("text", {
85
- x: LABEL_WIDTH - 8,
86
- y: index * ROW_HEIGHT + ROW_HEIGHT / 2,
87
- textAnchor: "end",
88
- dominantBaseline: "middle",
89
- className: "fill-muted-foreground text-[11px]",
90
- children: datum.label
91
- }),
92
- /*#__PURE__*/ _jsx("path", {
93
- d: length <= 0 ? "" : `M${LABEL_WIDTH} ${y}` + `H${LABEL_WIDTH + length - radius}` + `a${radius} ${radius} 0 0 1 ${radius} ${radius}` + `V${y + BAR_HEIGHT - radius}` + `a${radius} ${radius} 0 0 1 ${-radius} ${radius}` + `H${LABEL_WIDTH}Z`,
94
- fill: seriesColor(0)
95
- }),
96
- /*#__PURE__*/ _jsx("text", {
97
- x: LABEL_WIDTH + length + 8,
98
- y: index * ROW_HEIGHT + ROW_HEIGHT / 2,
99
- dominantBaseline: "middle",
100
- className: "fill-foreground text-[11px] tabular-nums",
101
- children: format(datum.value)
102
- })
103
- ]
104
- }, datum.label);
105
- })
106
- ]
107
- }),
108
- /*#__PURE__*/ _jsxs("p", {
109
- className: cn("text-xs text-muted-foreground"),
110
- children: [
111
- "Axis to ",
112
- format(axisMax),
113
- ", from zero."
114
- ]
115
- })
116
- ]
117
- });
57
+ return (_jsxs("g", { children: [_jsx("text", { x: LABEL_WIDTH - 8, y: index * ROW_HEIGHT + ROW_HEIGHT / 2, textAnchor: "end", dominantBaseline: "middle", className: "fill-muted-foreground text-[11px]", children: datum.label }), _jsx("path", { d: length <= 0
58
+ ? ""
59
+ : `M${LABEL_WIDTH} ${y}` +
60
+ `H${LABEL_WIDTH + length - radius}` +
61
+ `a${radius} ${radius} 0 0 1 ${radius} ${radius}` +
62
+ `V${y + BAR_HEIGHT - radius}` +
63
+ `a${radius} ${radius} 0 0 1 ${-radius} ${radius}` +
64
+ `H${LABEL_WIDTH}Z`, fill: seriesColor(0) }), _jsx("text", { x: LABEL_WIDTH + length + 8, y: index * ROW_HEIGHT + ROW_HEIGHT / 2, dominantBaseline: "middle", className: "fill-foreground text-[11px] tabular-nums", children: format(datum.value) })] }, datum.label));
65
+ })] }), _jsxs("p", { className: cn("text-xs text-muted-foreground"), children: ["Axis to ", format(axisMax), ", from zero."] })] }));
118
66
  }