@corbits/react-ui 0.1.0 → 0.3.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 +257 -19
  35. package/dist/test/render-hook.js +11 -12
  36. package/dist/theme.css +92 -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 +21 -4
  45. package/dist/ui/avatar.js +40 -49
  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 +85 -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 +96 -535
@@ -1,11 +1,23 @@
1
1
  import type { ReactNode } from "react";
2
2
  export type AvatarTone = "neutral" | "agent" | "agent2" | "agent3";
3
+ export type AvatarShape = "circle" | "square";
4
+ export type AvatarSize = "xs" | "sm" | "md" | "lg" | "xl";
5
+ export type AvatarStatus = "working" | "ready" | "idle";
3
6
  export type AvatarProps = {
4
7
  /** One or two characters shown when no image is provided. */
5
8
  readonly initials: string;
6
9
  readonly label: string;
7
10
  readonly tone?: AvatarTone;
8
- readonly size?: "sm" | "md" | "lg";
11
+ readonly size?: AvatarSize;
12
+ /**
13
+ * `circle` is fully round; `square` rounds by `--avatar-radius` (defaults to
14
+ * `--radius`). Omitted keeps the unrounded default.
15
+ */
16
+ readonly shape?: AvatarShape;
17
+ /** Corner dot marking state; the label gains the state for assistive tech. */
18
+ readonly status?: AvatarStatus;
19
+ /** Orange arc circling the avatar. Static under reduced motion. */
20
+ readonly orbit?: boolean;
9
21
  /** Tenant monogram badge overlaid on the corner. */
10
22
  readonly tenantMonogram?: string;
11
23
  readonly className?: string;
@@ -15,23 +27,28 @@ export type AvatarProps = {
15
27
  * intentionally unsupported here: identity headers should not flash or
16
28
  * depend on third-party avatar hosts.
17
29
  */
18
- export declare function Avatar({ initials, label, tone, size, tenantMonogram, className, }: AvatarProps): import("react").JSX.Element;
30
+ export declare function Avatar({ initials, label, tone, size, shape, status, orbit, tenantMonogram, className, }: AvatarProps): import("react").JSX.Element;
19
31
  export type AvatarStackItem = {
20
32
  readonly id: string;
21
33
  readonly initials: string;
22
34
  readonly label: string;
23
35
  readonly tone?: AvatarTone;
36
+ readonly shape?: AvatarShape;
37
+ readonly status?: AvatarStatus;
38
+ readonly orbit?: boolean;
24
39
  readonly tenantMonogram?: string;
25
40
  };
26
41
  export type AvatarStackProps = {
27
42
  readonly items: readonly AvatarStackItem[];
28
43
  /** Cap visible avatars; remainder becomes a +N chip. */
29
44
  readonly max?: number;
30
- readonly size?: "sm" | "md";
45
+ readonly size?: AvatarSize;
46
+ /** Default shape for every item; an item's own `shape` wins. */
47
+ readonly shape?: AvatarShape;
31
48
  readonly className?: string;
32
49
  };
33
50
  /**
34
51
  * Overlapping avatar stack for thread participants and channel members.
35
52
  */
36
- export declare function AvatarStack({ items, max, size, className }: AvatarStackProps): import("react").JSX.Element;
53
+ export declare function AvatarStack({ items, max, size, shape, className, }: AvatarStackProps): import("react").JSX.Element;
37
54
  export type AvatarStackSlot = ReactNode;
package/dist/ui/avatar.js CHANGED
@@ -1,73 +1,64 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { cn } from "../lib/utils.js";
3
3
  const SIZE_CLASS = {
4
+ xs: "size-5 text-[8px]",
4
5
  sm: "size-6 text-[10px]",
5
6
  md: "size-8 text-xs",
6
- lg: "size-10 text-sm"
7
+ lg: "size-10 text-sm",
8
+ xl: "size-14 text-lg",
9
+ };
10
+ const SHAPE_CLASS = {
11
+ circle: "rounded-full",
12
+ square: "rounded-[var(--avatar-radius,var(--radius))]",
13
+ };
14
+ const STATUS_CLASS = {
15
+ working: "bg-primary-emphasis",
16
+ ready: "bg-ok",
17
+ idle: "bg-muted-foreground",
18
+ };
19
+ const DOT_SIZE = {
20
+ xs: "size-1.5",
21
+ sm: "size-2",
22
+ md: "size-2.5",
23
+ lg: "size-3",
24
+ xl: "size-3.5",
7
25
  };
8
26
  const TONE_CLASS = {
9
- neutral: "bg-muted text-muted-foreground",
27
+ neutral: "bg-muted text-muted-foreground dark:bg-[color-mix(in_srgb,var(--foreground)_14%,var(--muted))]",
10
28
  agent: "bg-primary text-primary-foreground",
11
29
  agent2: "bg-accent text-accent-foreground",
12
- agent3: "bg-success text-success-foreground"
30
+ agent3: "bg-success text-success-foreground",
13
31
  };
14
32
  const BADGE_SIZE = {
33
+ xs: "size-2.5 text-[6px]",
15
34
  sm: "size-3 text-[7px]",
16
35
  md: "size-3.5 text-[8px]",
17
- lg: "size-4 text-[9px]"
36
+ lg: "size-4 text-[9px]",
37
+ xl: "size-5 text-[10px]",
18
38
  };
19
39
  /**
20
40
  * Initials avatar with optional tenant monogram badge. Images are
21
41
  * intentionally unsupported here: identity headers should not flash or
22
42
  * 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
- });
43
+ */
44
+ export function Avatar({ initials, label, tone = "neutral", size = "md", shape, status, orbit = false, tenantMonogram, className, }) {
45
+ return (_jsxs("span", { role: "img", "aria-label": status === undefined ? label : `${label}, ${status}`, className: cn("relative inline-flex shrink-0 items-center justify-center font-bold uppercase", SIZE_CLASS[size], TONE_CLASS[tone], "dark:shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--foreground)_14%,transparent)]", shape !== undefined && SHAPE_CLASS[shape], className), children: [orbit ? (_jsx("span", { "aria-hidden": true, className: "corbits-avatar-orbit", style: {
46
+ borderRadius: shape === "circle"
47
+ ? "9999px"
48
+ : shape === "square"
49
+ ? "calc(var(--avatar-radius, var(--radius)) + 4px)"
50
+ : "0",
51
+ } })) : null, _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) })), status === undefined ? null : (_jsx("span", { "aria-hidden": true, className: cn("absolute -right-0.5 -bottom-0.5 rounded-full ring-2 ring-background", DOT_SIZE[size], STATUS_CLASS[status], tenantMonogram !== undefined && "right-auto -left-0.5") }))] }));
40
52
  }
41
53
  /**
42
54
  * Overlapping avatar stack for thread participants and channel members.
43
- */ export function AvatarStack({ items, max = 4, size = "sm", className }) {
55
+ */
56
+ export function AvatarStack({ items, max = 4, size = "sm", shape, className, }) {
44
57
  const visible = items.slice(0, max);
45
58
  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
- });
59
+ 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.shape === undefined && shape === undefined
60
+ ? {}
61
+ : { shape: item.shape ?? shape }), ...(item.status === undefined ? {} : { status: item.status }), ...(item.orbit === undefined ? {} : { orbit: item.orbit }), ...(item.tenantMonogram === undefined
62
+ ? {}
63
+ : { 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", shape !== undefined && SHAPE_CLASS[shape], SIZE_CLASS[size], visible.length > 0 && "-ml-1.5"), "aria-label": `${overflow} more`, children: ["+", overflow] }))] }));
73
64
  }
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
  }
@@ -8,59 +8,21 @@ import { cn } from "../lib/utils.js";
8
8
  * can tell "the agent made this" at a glance. Lifted out of a consumer app
9
9
  * unchanged; see `RiskBadge` below for the tone it pairs with inside
10
10
  * `children`.
11
- */ export function BlockCard({ title, children, className }) {
12
- return /*#__PURE__*/ _jsxs("div", {
13
- "data-slot": "block-card",
14
- className: cn("overflow-hidden rounded-none border border-border bg-card", className),
15
- children: [
16
- /*#__PURE__*/ _jsxs("div", {
17
- "data-slot": "block-card-header",
18
- className: "flex items-center gap-2 border-b border-border px-3.5 py-2.5 text-xs font-bold tracking-[0.02em] text-primary-emphasis",
19
- children: [
20
- /*#__PURE__*/ _jsx("span", {
21
- "aria-hidden": true,
22
- className: "size-1.5 shrink-0 rounded-none bg-current [animation:corbits-block-pulse_1.6s_ease_infinite]"
23
- }),
24
- /*#__PURE__*/ _jsx("span", {
25
- "data-slot": "block-card-title",
26
- children: title
27
- })
28
- ]
29
- }),
30
- /*#__PURE__*/ _jsx("div", {
31
- "data-slot": "block-card-body",
32
- className: "p-4",
33
- children: children
34
- })
35
- ]
36
- });
11
+ */
12
+ export function BlockCard({ title, children, className }) {
13
+ return (_jsxs("div", { "data-slot": "block-card", className: cn("overflow-hidden rounded-none border border-border bg-card", className), children: [_jsxs("div", { "data-slot": "block-card-header", className: "flex items-center gap-2 border-b border-border px-3.5 py-2.5 text-xs font-bold tracking-[0.02em] text-primary-emphasis", children: [_jsx("span", { "aria-hidden": true, className: "size-1.5 shrink-0 rounded-none bg-current [animation:corbits-block-pulse_1.6s_ease_infinite]" }), _jsx("span", { "data-slot": "block-card-title", children: title })] }), _jsx("div", { "data-slot": "block-card-body", className: "p-4", children: children })] }));
37
14
  }
38
15
  const RISK_TONE_CLASS = {
39
16
  low: "text-muted-foreground",
40
17
  medium: "text-warn",
41
- high: "text-destructive"
18
+ high: "text-destructive",
42
19
  };
43
20
  /**
44
21
  * A risk callout for a block whose action carries consequence — approve this
45
22
  * order cancellation, run this migration. `level` drives colour only; the
46
23
  * `label` is what actually says what the risk is, so the badge is never a
47
24
  * bare colour dot.
48
- */ export function RiskBadge({ level, label, note, className }) {
49
- return /*#__PURE__*/ _jsxs("span", {
50
- "data-slot": "risk-badge",
51
- "data-risk": level,
52
- className: cn("inline-flex items-center gap-1.5 text-xs font-bold [&_svg]:size-3.5", RISK_TONE_CLASS[level], className),
53
- children: [
54
- /*#__PURE__*/ _jsx(TriangleAlert, {
55
- "aria-hidden": true
56
- }),
57
- /*#__PURE__*/ _jsx("span", {
58
- children: label
59
- }),
60
- note === undefined ? null : /*#__PURE__*/ _jsx("span", {
61
- className: "font-medium text-muted-foreground",
62
- children: note
63
- })
64
- ]
65
- });
25
+ */
26
+ export function RiskBadge({ level, label, note, className }) {
27
+ return (_jsxs("span", { "data-slot": "risk-badge", "data-risk": level, className: cn("inline-flex items-center gap-1.5 text-xs font-bold [&_svg]:size-3.5", RISK_TONE_CLASS[level], className), children: [_jsx(TriangleAlert, { "aria-hidden": true }), _jsx("span", { children: label }), note === undefined ? null : (_jsx("span", { className: "font-medium text-muted-foreground", children: note }))] }));
66
28
  }
@@ -20,4 +20,4 @@ export type BootScreenProps = {
20
20
  * to a still frame under the theme's reduced-motion rule with nothing to do
21
21
  * here.
22
22
  */
23
- export declare function BootScreen({ message, brand, footer, className }: BootScreenProps): import("react").JSX.Element;
23
+ export declare function BootScreen({ message, brand, footer, className, }: BootScreenProps): import("react").JSX.Element;
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { useId } from "react";
3
4
  import { cn } from "../lib/utils.js";
@@ -12,38 +13,8 @@ import { cn } from "../lib/utils.js";
12
13
  * No spinner: the pulsing bar is decorative and `aria-hidden`, and it collapses
13
14
  * to a still frame under the theme's reduced-motion rule with nothing to do
14
15
  * here.
15
- */ export function BootScreen({ message, brand, footer, className }) {
16
+ */
17
+ export function BootScreen({ message, brand, footer, className, }) {
16
18
  const messageId = useId();
17
- return /*#__PURE__*/ _jsxs("div", {
18
- role: "status",
19
- "aria-labelledby": messageId,
20
- className: cn("absolute inset-0 overflow-hidden bg-background text-foreground", className),
21
- children: [
22
- brand === undefined ? null : /*#__PURE__*/ _jsx("div", {
23
- className: "absolute top-6 left-7",
24
- children: brand
25
- }),
26
- /*#__PURE__*/ _jsxs("div", {
27
- className: "absolute inset-0 flex flex-col items-center justify-center gap-4 p-6",
28
- children: [
29
- /*#__PURE__*/ _jsx("span", {
30
- "aria-hidden": true,
31
- className: "h-0.5 w-24 overflow-hidden rounded-full bg-muted",
32
- children: /*#__PURE__*/ _jsx("span", {
33
- className: "block h-full w-1/3 rounded-full bg-primary [animation:corbits-boot-sweep_1.4s_ease-in-out_infinite]"
34
- })
35
- }),
36
- /*#__PURE__*/ _jsx("p", {
37
- id: messageId,
38
- className: "max-w-[32ch] text-center text-xs leading-relaxed text-muted-foreground",
39
- children: message
40
- })
41
- ]
42
- }),
43
- footer === undefined ? null : /*#__PURE__*/ _jsx("div", {
44
- className: "absolute bottom-6 left-7 font-mono text-[11px] text-muted-foreground",
45
- children: footer
46
- })
47
- ]
48
- });
19
+ return (_jsxs("div", { role: "status", "aria-labelledby": messageId, className: cn("absolute inset-0 overflow-hidden bg-background text-foreground", className), children: [brand === undefined ? null : (_jsx("div", { className: "absolute top-6 left-7", children: brand })), _jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center gap-4 p-6", children: [_jsx("span", { "aria-hidden": true, className: "h-0.5 w-24 overflow-hidden rounded-full bg-muted", children: _jsx("span", { className: "block h-full w-1/3 rounded-full bg-primary [animation:corbits-boot-sweep_1.4s_ease-in-out_infinite]" }) }), _jsx("p", { id: messageId, className: "max-w-[32ch] text-center text-xs leading-relaxed text-muted-foreground", children: message })] }), footer === undefined ? null : (_jsx("div", { className: "absolute bottom-6 left-7 font-mono text-[11px] text-muted-foreground", children: footer }))] }));
49
20
  }
@@ -34,4 +34,4 @@ export type BulkActionBarProps = {
34
34
  * already handled its own Escape wins instead of also clearing the
35
35
  * selection underneath it.
36
36
  */
37
- export declare function BulkActionBar({ count, onClear, children, label, className }: BulkActionBarProps): import("react").JSX.Element | null;
37
+ export declare function BulkActionBar({ count, onClear, children, label, className, }: BulkActionBarProps): import("react").JSX.Element | null;
@@ -1,4 +1,5 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ "use client";
2
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
3
  import { useEffect } from "react";
3
4
  import { cn } from "../lib/utils.js";
4
5
  /**
@@ -26,39 +27,19 @@ import { cn } from "../lib/utils.js";
26
27
  * `event.defaultPrevented`, so a dialog or input stacked above the bar that
27
28
  * already handled its own Escape wins instead of also clearing the
28
29
  * selection underneath it.
29
- */ export function BulkActionBar({ count, onClear, children, label = "Bulk actions", className }) {
30
- useEffect(()=>{
31
- if (count === 0) return;
30
+ */
31
+ export function BulkActionBar({ count, onClear, children, label = "Bulk actions", className, }) {
32
+ useEffect(() => {
33
+ if (count === 0)
34
+ return;
32
35
  function onKeyDown(event) {
33
- if (event.key === "Escape" && !event.defaultPrevented) onClear();
36
+ if (event.key === "Escape" && !event.defaultPrevented)
37
+ onClear();
34
38
  }
35
39
  window.addEventListener("keydown", onKeyDown);
36
- return ()=>window.removeEventListener("keydown", onKeyDown);
37
- }, [
38
- count,
39
- onClear
40
- ]);
41
- if (count === 0) return null;
42
- return /*#__PURE__*/ _jsx("div", {
43
- className: cn("fixed bottom-6 left-1/2 z-40 -translate-x-1/2", className),
44
- children: /*#__PURE__*/ _jsxs("div", {
45
- role: "group",
46
- "aria-label": label,
47
- className: cn("flex items-center gap-3 rounded-full border border-border bg-card px-4 py-2 shadow-lg", "motion-safe:[animation:corbits-bulk-action-bar-in_220ms_var(--ease-out)_both]"),
48
- children: [
49
- /*#__PURE__*/ _jsxs("span", {
50
- "aria-live": "polite",
51
- className: "text-sm font-medium whitespace-nowrap",
52
- children: [
53
- count,
54
- " selected"
55
- ]
56
- }),
57
- /*#__PURE__*/ _jsx("div", {
58
- className: "flex items-center gap-2",
59
- children: children
60
- })
61
- ]
62
- })
63
- });
40
+ return () => window.removeEventListener("keydown", onKeyDown);
41
+ }, [count, onClear]);
42
+ if (count === 0)
43
+ return null;
44
+ return (_jsx("div", { className: cn("fixed bottom-6 left-1/2 z-40 -translate-x-1/2", className), children: _jsxs("div", { role: "group", "aria-label": label, className: cn("flex items-center gap-3 rounded-full border border-border bg-card px-4 py-2 shadow-lg", "motion-safe:[animation:corbits-bulk-action-bar-in_220ms_var(--ease-out)_both]"), children: [_jsxs("span", { "aria-live": "polite", className: "text-sm font-medium whitespace-nowrap", children: [count, " selected"] }), _jsx("div", { className: "flex items-center gap-2", children: children })] }) }));
64
45
  }
package/dist/ui/button.js CHANGED
@@ -10,7 +10,8 @@ import { cn } from "../lib/utils.js";
10
10
  // orange primary. That measures 2.69:1, a hard AA failure. `text-primary-
11
11
  // foreground` resolves to ink in light (5.53:1) and black in dark (5.34:1),
12
12
  // which is correct. DESIGN.md is wrong; do not "fix" this back.
13
- const buttonVariantsBase = cva(// active:brightness-95 is the press state for every variant: it darkens the
13
+ const buttonVariantsBase = cva(
14
+ // active:brightness-95 is the press state for every variant: it darkens the
14
15
  // rendered fill whatever that fill is, so it needs no per-variant pressed
15
16
  // token. Deliberately outside `transition-colors` — a press should land on
16
17
  // the frame the pointer goes down, not ease in. The scale feedback gets its
@@ -24,33 +25,25 @@ const buttonVariantsBase = cva(// active:brightness-95 is the press state for ev
24
25
  outline: "border border-input bg-transparent hover:bg-muted",
25
26
  ghost: "hover:bg-muted",
26
27
  link: "text-primary-emphasis underline-offset-4 hover:underline",
27
- destructive: "bg-destructive text-destructive-foreground hover:opacity-90"
28
+ destructive: "bg-destructive text-destructive-foreground hover:opacity-90",
28
29
  },
29
30
  size: {
30
31
  sm: "h-8 px-3",
31
32
  md: "h-9 px-4",
32
33
  lg: "h-10 px-6",
33
- icon: "size-9"
34
- }
34
+ icon: "size-9",
35
+ },
35
36
  },
36
37
  // link reads as inline text, not a control — it opts out of every size's
37
38
  // fixed height/padding rather than getting a box of its own.
38
39
  compoundVariants: [
39
40
  {
40
41
  variant: "link",
41
- size: [
42
- "sm",
43
- "md",
44
- "lg",
45
- "icon"
46
- ],
47
- class: "h-auto px-0"
48
- }
42
+ size: ["sm", "md", "lg", "icon"],
43
+ class: "h-auto px-0",
44
+ },
49
45
  ],
50
- defaultVariants: {
51
- variant: "primary",
52
- size: "md"
53
- }
46
+ defaultVariants: { variant: "primary", size: "md" },
54
47
  });
55
48
  // cva concatenates variant, size, and compound-variant classes as plain
56
49
  // strings with no dedup, so the compound override above only wins once
@@ -61,13 +54,6 @@ function buttonVariants(props) {
61
54
  }
62
55
  export function Button({ className, variant, size, asChild = false, ...props }) {
63
56
  const Comp = asChild ? Slot : "button";
64
- return /*#__PURE__*/ _jsx(Comp, {
65
- "data-slot": "button",
66
- className: cn(buttonVariants({
67
- variant,
68
- size
69
- }), className),
70
- ...props
71
- });
57
+ return (_jsx(Comp, { "data-slot": "button", className: cn(buttonVariants({ variant, size }), className), ...props }));
72
58
  }
73
59
  export { buttonVariants };
package/dist/ui/card.js CHANGED
@@ -1,37 +1,17 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cn } from "../lib/utils.js";
3
3
  export function Card({ className, ...props }) {
4
- return /*#__PURE__*/ _jsx("div", {
5
- "data-slot": "card",
6
- className: cn("flex flex-col gap-4 rounded-lg border border-border bg-card p-6 text-card-foreground", className),
7
- ...props
8
- });
4
+ return (_jsx("div", { "data-slot": "card", className: cn("flex flex-col gap-4 rounded-lg border border-border bg-card p-6 text-card-foreground", className), ...props }));
9
5
  }
10
6
  export function CardHeader({ className, ...props }) {
11
- return /*#__PURE__*/ _jsx("div", {
12
- "data-slot": "card-header",
13
- className: cn("flex flex-col gap-1", className),
14
- ...props
15
- });
7
+ return (_jsx("div", { "data-slot": "card-header", className: cn("flex flex-col gap-1", className), ...props }));
16
8
  }
17
9
  export function CardTitle({ className, ...props }) {
18
- return /*#__PURE__*/ _jsx("h3", {
19
- "data-slot": "card-title",
20
- className: cn("text-base leading-none font-semibold", className),
21
- ...props
22
- });
10
+ return (_jsx("h3", { "data-slot": "card-title", className: cn("text-base leading-none font-semibold", className), ...props }));
23
11
  }
24
12
  export function CardDescription({ className, ...props }) {
25
- return /*#__PURE__*/ _jsx("p", {
26
- "data-slot": "card-description",
27
- className: cn("text-sm text-muted-foreground", className),
28
- ...props
29
- });
13
+ return (_jsx("p", { "data-slot": "card-description", className: cn("text-sm text-muted-foreground", className), ...props }));
30
14
  }
31
15
  export function CardFooter({ className, ...props }) {
32
- return /*#__PURE__*/ _jsx("div", {
33
- "data-slot": "card-footer",
34
- className: cn("flex items-center gap-2", className),
35
- ...props
36
- });
16
+ return (_jsx("div", { "data-slot": "card-footer", className: cn("flex items-center gap-2", className), ...props }));
37
17
  }