@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
@@ -16,7 +16,8 @@ const isProduction = typeof process !== "undefined" && process.env?.NODE_ENV ===
16
16
  * logs a `console.error` in non-production builds, mirroring React's own
17
17
  * controlled/uncontrolled `<input>` warning; it does not throw, and the
18
18
  * production build is silent.
19
- */ export function useControllableState(options) {
19
+ */
20
+ export function useControllableState(options) {
20
21
  const { value: controlledValue, defaultValue, onChange, name } = options;
21
22
  const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
22
23
  const isControlled = controlledValue !== undefined;
@@ -25,20 +26,27 @@ const isProduction = typeof process !== "undefined" && process.env?.NODE_ENV ===
25
26
  if (!isProduction && wasControlledRef.current !== isControlled) {
26
27
  const from = wasControlledRef.current ? "controlled" : "uncontrolled";
27
28
  const to = isControlled ? "controlled" : "uncontrolled";
28
- console.error(`${name} is changing from ${from} to ${to}. Components should not switch between controlled ` + "and uncontrolled across their lifetime. Decide between using a controlled or uncontrolled " + `value for the lifetime of the component (i.e. always pass a value to \`${name}\`, or never do).`);
29
+ console.error(`${name} is changing from ${from} to ${to}. Components should not switch between controlled ` +
30
+ "and uncontrolled across their lifetime. Decide between using a controlled or uncontrolled " +
31
+ `value for the lifetime of the component (i.e. always pass a value to \`${name}\`, or never do).`);
29
32
  }
30
33
  wasControlledRef.current = isControlled;
31
- const setValue = useCallback((action)=>{
32
- const resolved = typeof action === "function" ? action(value) : action;
33
- if (!isControlled) setUncontrolledValue(resolved);
34
- onChange?.(resolved);
35
- }, [
36
- isControlled,
37
- value,
38
- onChange
39
- ]);
40
- return [
41
- value,
42
- setValue
43
- ];
34
+ // Mirrors the uncontrolled state synchronously so batched functional updates
35
+ // chain off each other. Resolving inside a React updater instead would call
36
+ // `onChange` from that updater, which StrictMode invokes twice.
37
+ const latestUncontrolledRef = useRef(uncontrolledValue);
38
+ const setValue = useCallback((action) => {
39
+ const previous = isControlled
40
+ ? controlledValue
41
+ : latestUncontrolledRef.current;
42
+ const next = typeof action === "function"
43
+ ? action(previous)
44
+ : action;
45
+ if (!isControlled) {
46
+ latestUncontrolledRef.current = next;
47
+ setUncontrolledValue(next);
48
+ }
49
+ onChange?.(next);
50
+ }, [isControlled, controlledValue, onChange]);
51
+ return [value, setValue];
44
52
  }
@@ -6,15 +6,14 @@ import { CHAT_DOCK_AUTOFOCUS_DELAY_MS } from "../ui/chat-dock-timing.js";
6
6
  * still mid-animation, so the delay is deliberate rather than a magic number.
7
7
  * `delayMs` defaults to `CHAT_DOCK_AUTOFOCUS_DELAY_MS`, which is pinned `>=`
8
8
  * the dock's own entrance duration so focus never lands mid-animation.
9
- */ export function useDelayedAutofocus(ref, active, delayMs = CHAT_DOCK_AUTOFOCUS_DELAY_MS) {
10
- useEffect(()=>{
11
- if (!active) return;
12
- const timer = window.setTimeout(()=>ref.current?.focus(), delayMs);
13
- return ()=>window.clearTimeout(timer);
14
- // `ref` is intentionally excluded: it is a stable container, and including
15
- // it would refocus on every render that happens to produce a new object.
16
- }, [
17
- active,
18
- delayMs
19
- ]);
9
+ */
10
+ export function useDelayedAutofocus(ref, active, delayMs = CHAT_DOCK_AUTOFOCUS_DELAY_MS) {
11
+ useEffect(() => {
12
+ if (!active)
13
+ return;
14
+ const timer = window.setTimeout(() => ref.current?.focus(), delayMs);
15
+ return () => window.clearTimeout(timer);
16
+ // `ref` is intentionally excluded: it is a stable container, and including
17
+ // it would refocus on every render that happens to produce a new object.
18
+ }, [active, delayMs]);
20
19
  }
@@ -2,8 +2,8 @@ import { type RefObject } from "react";
2
2
  import { type ControllableStateAction } from "./use-controllable-state.js";
3
3
  export type UseDismissablePopoverOptions = {
4
4
  /** Controlled open flag. Supply this with `onOpenChange` to lift state to a parent. */
5
- readonly open?: boolean;
6
- readonly onOpenChange?: (open: boolean) => void;
5
+ readonly open?: boolean | undefined;
6
+ readonly onOpenChange?: ((open: boolean) => void) | undefined;
7
7
  /** Seeds the hook's own state when `open` is not supplied. */
8
8
  readonly defaultOpen?: boolean;
9
9
  /** Escape closes the popover and returns focus to the trigger. Default `true`. */
@@ -1,5 +1,5 @@
1
1
  import { useCallback, useEffect, useRef } from "react";
2
- import { useControllableState } from "./use-controllable-state.js";
2
+ import { useControllableState, } from "./use-controllable-state.js";
3
3
  /**
4
4
  * The behavior every dismissable popover trigger shares: an open flag, a
5
5
  * pointer-down outside `rootRef` that closes it, and (by default) Escape that
@@ -16,49 +16,41 @@ import { useControllableState } from "./use-controllable-state.js";
16
16
  * a caller switches between them after mount — is `useControllableState`;
17
17
  * this hook only adds the popover-specific dismissal behavior on top.
18
18
  * `setOpen` takes a value or an updater, same as `useState`.
19
- */ export function useDismissablePopover(options = {}) {
20
- const { open: controlledOpen, onOpenChange, defaultOpen = false, closeOnEscape = true } = options;
19
+ */
20
+ export function useDismissablePopover(options = {}) {
21
+ const { open: controlledOpen, onOpenChange, defaultOpen = false, closeOnEscape = true, } = options;
21
22
  const [open, setOpen] = useControllableState({
22
23
  value: controlledOpen,
23
24
  defaultValue: defaultOpen,
24
25
  onChange: onOpenChange,
25
- name: "useDismissablePopover"
26
+ name: "useDismissablePopover",
26
27
  });
27
28
  const rootRef = useRef(null);
28
29
  const triggerRef = useRef(null);
29
- const close = useCallback(()=>{
30
+ const close = useCallback(() => {
30
31
  setOpen(false);
31
32
  triggerRef.current?.focus();
32
- }, [
33
- setOpen
34
- ]);
35
- useEffect(()=>{
36
- if (!open) return;
37
- const onPointerDown = (event)=>{
38
- if (!(event.target instanceof Node)) return;
39
- if (rootRef.current?.contains(event.target) === false) setOpen(false);
33
+ }, [setOpen]);
34
+ useEffect(() => {
35
+ if (!open)
36
+ return;
37
+ const onPointerDown = (event) => {
38
+ if (!(event.target instanceof Node))
39
+ return;
40
+ if (rootRef.current?.contains(event.target) === false)
41
+ setOpen(false);
40
42
  };
41
- const onKeyDown = (event)=>{
42
- if (!closeOnEscape || event.key !== "Escape") return;
43
+ const onKeyDown = (event) => {
44
+ if (!closeOnEscape || event.key !== "Escape")
45
+ return;
43
46
  close();
44
47
  };
45
48
  document.addEventListener("pointerdown", onPointerDown);
46
49
  document.addEventListener("keydown", onKeyDown);
47
- return ()=>{
50
+ return () => {
48
51
  document.removeEventListener("pointerdown", onPointerDown);
49
52
  document.removeEventListener("keydown", onKeyDown);
50
53
  };
51
- }, [
52
- open,
53
- close,
54
- setOpen,
55
- closeOnEscape
56
- ]);
57
- return {
58
- open,
59
- setOpen,
60
- rootRef,
61
- triggerRef,
62
- close
63
- };
54
+ }, [open, close, setOpen, closeOnEscape]);
55
+ return { open, setOpen, rootRef, triggerRef, close };
64
56
  }
@@ -1,67 +1,47 @@
1
1
  import { useCallback, useMemo, useReducer, useRef } from "react";
2
2
  function reducer(state, action) {
3
- switch(action.type){
3
+ switch (action.type) {
4
4
  case "clear":
5
5
  return {
6
6
  selectedIds: new Set(),
7
7
  anchorId: undefined,
8
- baseSelection: new Set()
8
+ baseSelection: new Set(),
9
9
  };
10
- case "selectAll":
11
- {
12
- const all = new Set(action.ids);
13
- return {
14
- selectedIds: all,
15
- anchorId: state.anchorId,
16
- baseSelection: all
17
- };
18
- }
19
- case "toggle":
20
- {
21
- const { id, shiftKey, ids } = action;
22
- if (shiftKey && state.anchorId !== undefined) {
23
- const anchorIndex = ids.indexOf(state.anchorId);
24
- const targetIndex = ids.indexOf(id);
25
- if (anchorIndex === -1 || targetIndex === -1) {
26
- // The anchor or target scrolled out of the known set — fall back
27
- // to a plain toggle rather than ranging over an index that no
28
- // longer means anything.
29
- const next = toggleOne(state.selectedIds, id);
30
- return {
31
- selectedIds: next,
32
- anchorId: id,
33
- baseSelection: next
34
- };
35
- }
36
- const [start, end] = anchorIndex <= targetIndex ? [
37
- anchorIndex,
38
- targetIndex
39
- ] : [
40
- targetIndex,
41
- anchorIndex
42
- ];
43
- const range = ids.slice(start, end + 1);
44
- const selectedIds = new Set(state.baseSelection);
45
- for (const rangeId of range)selectedIds.add(rangeId);
46
- return {
47
- ...state,
48
- selectedIds
49
- };
10
+ case "selectAll": {
11
+ const all = new Set(action.ids);
12
+ return { selectedIds: all, anchorId: state.anchorId, baseSelection: all };
13
+ }
14
+ case "toggle": {
15
+ const { id, shiftKey, ids } = action;
16
+ if (shiftKey && state.anchorId !== undefined) {
17
+ const anchorIndex = ids.indexOf(state.anchorId);
18
+ const targetIndex = ids.indexOf(id);
19
+ if (anchorIndex === -1 || targetIndex === -1) {
20
+ // The anchor or target scrolled out of the known set — fall back
21
+ // to a plain toggle rather than ranging over an index that no
22
+ // longer means anything.
23
+ const next = toggleOne(state.selectedIds, id);
24
+ return { selectedIds: next, anchorId: id, baseSelection: next };
50
25
  }
51
- const next = toggleOne(state.selectedIds, id);
52
- return {
53
- selectedIds: next,
54
- anchorId: id,
55
- baseSelection: next
56
- };
26
+ const [start, end] = anchorIndex <= targetIndex
27
+ ? [anchorIndex, targetIndex]
28
+ : [targetIndex, anchorIndex];
29
+ const range = ids.slice(start, end + 1);
30
+ const selectedIds = new Set(state.baseSelection);
31
+ for (const rangeId of range)
32
+ selectedIds.add(rangeId);
33
+ return { ...state, selectedIds };
57
34
  }
35
+ const next = toggleOne(state.selectedIds, id);
36
+ return { selectedIds: next, anchorId: id, baseSelection: next };
37
+ }
58
38
  }
59
39
  }
60
40
  function createInitialState() {
61
41
  return {
62
42
  selectedIds: new Set(),
63
43
  anchorId: undefined,
64
- baseSelection: new Set()
44
+ baseSelection: new Set(),
65
45
  };
66
46
  }
67
47
  /**
@@ -92,56 +72,45 @@ function createInitialState() {
92
72
  * array each time (e.g. an inline `rows.map(row => row.id)`) — a memoized
93
73
  * row downstream that depends on `toggle` does not re-render just because
94
74
  * the caller didn't bother memoizing `ids`.
95
- */ export function useListSelection({ ids }) {
96
- const [state, dispatch] = useReducer(reducer, undefined, createInitialState);
75
+ */
76
+ export function useListSelection({ ids, }) {
77
+ const [state, dispatch] = useReducer((reducer), undefined, (createInitialState));
97
78
  // Updated on every render, read only inside event handlers — never during
98
79
  // render — so `toggle`/`selectAll` can stay referentially stable while
99
80
  // still acting on the `ids` most recently passed in.
100
81
  const idsRef = useRef(ids);
101
82
  idsRef.current = ids;
102
- const toggle = useCallback((id, modifiers)=>dispatch({
103
- type: "toggle",
104
- id,
105
- shiftKey: modifiers?.shiftKey ?? false,
106
- ids: idsRef.current
107
- }), []);
108
- const selectAll = useCallback(()=>dispatch({
109
- type: "selectAll",
110
- ids: idsRef.current
111
- }), []);
112
- const clear = useCallback(()=>dispatch({
113
- type: "clear"
114
- }), []);
115
- const selectedIds = useMemo(()=>{
83
+ const toggle = useCallback((id, modifiers) => dispatch({
84
+ type: "toggle",
85
+ id,
86
+ shiftKey: modifiers?.shiftKey ?? false,
87
+ ids: idsRef.current,
88
+ }), []);
89
+ const selectAll = useCallback(() => dispatch({ type: "selectAll", ids: idsRef.current }), []);
90
+ const clear = useCallback(() => dispatch({ type: "clear" }), []);
91
+ const selectedIds = useMemo(() => {
116
92
  const known = new Set(ids);
117
93
  const reconciled = new Set();
118
- for (const id of state.selectedIds)if (known.has(id)) reconciled.add(id);
94
+ for (const id of state.selectedIds)
95
+ if (known.has(id))
96
+ reconciled.add(id);
119
97
  return reconciled;
120
- }, [
121
- state.selectedIds,
122
- ids
123
- ]);
124
- const isSelected = useCallback((id)=>selectedIds.has(id), [
125
- selectedIds
126
- ]);
127
- return useMemo(()=>({
128
- selectedIds,
129
- selectedCount: selectedIds.size,
130
- isSelected,
131
- toggle,
132
- selectAll,
133
- clear
134
- }), [
98
+ }, [state.selectedIds, ids]);
99
+ const isSelected = useCallback((id) => selectedIds.has(id), [selectedIds]);
100
+ return useMemo(() => ({
135
101
  selectedIds,
102
+ selectedCount: selectedIds.size,
136
103
  isSelected,
137
104
  toggle,
138
105
  selectAll,
139
- clear
140
- ]);
106
+ clear,
107
+ }), [selectedIds, isSelected, toggle, selectAll, clear]);
141
108
  }
142
109
  function toggleOne(current, id) {
143
110
  const next = new Set(current);
144
- if (next.has(id)) next.delete(id);
145
- else next.add(id);
111
+ if (next.has(id))
112
+ next.delete(id);
113
+ else
114
+ next.add(id);
146
115
  return next;
147
116
  }
@@ -1,13 +1,16 @@
1
1
  import { useSyncExternalStore } from "react";
2
2
  const QUERY = "(prefers-reduced-motion: reduce)";
3
3
  function subscribe(callback) {
4
- if (typeof window === "undefined") return ()=>{};
4
+ if (typeof window === "undefined")
5
+ return () => { };
5
6
  const query = window.matchMedia(QUERY);
6
7
  query.addEventListener("change", callback);
7
- return ()=>query.removeEventListener("change", callback);
8
+ return () => query.removeEventListener("change", callback);
8
9
  }
9
10
  function getSnapshot() {
10
- return typeof window === "undefined" ? false : window.matchMedia(QUERY).matches;
11
+ return typeof window === "undefined"
12
+ ? false
13
+ : window.matchMedia(QUERY).matches;
11
14
  }
12
15
  function getServerSnapshot() {
13
16
  return false;
@@ -23,6 +26,7 @@ function getServerSnapshot() {
23
26
  * and `use-scroll-current-into-view` each read `matchMedia` by hand before
24
27
  * this shipped; this is the one place that logic lives now, and — unlike
25
28
  * those one-shot reads — it updates if the preference changes while mounted.
26
- */ export function usePrefersReducedMotion() {
29
+ */
30
+ export function usePrefersReducedMotion() {
27
31
  return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
28
32
  }
@@ -16,18 +16,16 @@ import { usePrefersReducedMotion } from "./use-prefers-reduced-motion.js";
16
16
  * The scroll itself is smooth, but `scrollIntoView` isn't covered by the
17
17
  * theme's global reduced-motion block, so a `prefers-reduced-motion: reduce`
18
18
  * check here falls back to an instant jump.
19
- */ export function useScrollCurrentIntoView(currentKey) {
19
+ */
20
+ export function useScrollCurrentIntoView(currentKey) {
20
21
  const currentRef = useRef(null);
21
22
  const prefersReducedMotion = usePrefersReducedMotion();
22
- useEffect(()=>{
23
+ useEffect(() => {
23
24
  currentRef.current?.scrollIntoView({
24
25
  block: "nearest",
25
26
  inline: "center",
26
- behavior: prefersReducedMotion ? "auto" : "smooth"
27
+ behavior: prefersReducedMotion ? "auto" : "smooth",
27
28
  });
28
- }, [
29
- currentKey,
30
- prefersReducedMotion
31
- ]);
29
+ }, [currentKey, prefersReducedMotion]);
32
30
  return currentRef;
33
31
  }
package/dist/index.d.ts CHANGED
@@ -11,15 +11,11 @@ export * from "./lib/artifact.js";
11
11
  export * from "./lib/chart-palette.js";
12
12
  export * from "./lib/chat-message.js";
13
13
  export * from "./lib/chat-parts.js";
14
- export * from "./lib/csv.js";
15
14
  export * from "./lib/metrics.js";
16
15
  export * from "./lib/now-item.js";
17
16
  export * from "./lib/relative-time.js";
18
17
  export * from "./lib/theme.js";
19
- export * from "./lib/url.js";
20
- export * from "./lib/utils.js";
21
18
  export * from "./lib/workflow-display-flow.js";
22
- export * from "./lib/workflow-registry.js";
23
19
  export * from "./lib/workflow-run.js";
24
20
  export * from "./lib/workflow-run-error.js";
25
21
  export * from "./lib/workflow-run-progress.js";
@@ -39,17 +35,14 @@ export * from "./ui/card.js";
39
35
  export * from "./ui/category-bars.js";
40
36
  export * from "./ui/chart-frame.js";
41
37
  export * from "./ui/chat-composer.js";
42
- export * from "./ui/chat-dock-timing.js";
43
38
  export * from "./ui/chat-input.js";
44
39
  export * from "./ui/chat-panel.js";
45
40
  export * from "./ui/chat-thread.js";
46
41
  export * from "./ui/checkbox.js";
47
- export * from "./ui/command-palette.js";
48
42
  export * from "./ui/compare-body.js";
49
43
  export * from "./ui/confirm-button.js";
50
44
  export * from "./ui/corbits-mark.js";
51
45
  export * from "./ui/csv-table.js";
52
- export * from "./ui/dialog.js";
53
46
  export * from "./ui/dictation-status-line.js";
54
47
  export * from "./ui/dither-canvas.js";
55
48
  export * from "./ui/embed-body.js";
@@ -67,10 +60,8 @@ export * from "./ui/library-page-header.js";
67
60
  export * from "./ui/list-detail.js";
68
61
  export * from "./ui/live-run-banner.js";
69
62
  export * from "./ui/live-status-line.js";
70
- export * from "./ui/menu.js";
71
63
  export * from "./ui/message-bubble.js";
72
64
  export * from "./ui/mic-button.js";
73
- export * from "./ui/mic-permission-dialog.js";
74
65
  export * from "./ui/notifications-bell.js";
75
66
  export * from "./ui/now-cards.js";
76
67
  export * from "./ui/page-panel.js";
@@ -109,12 +100,10 @@ export * from "./ui/thinking-indicator.js";
109
100
  export * from "./ui/thinking-label.js";
110
101
  export * from "./ui/thinking-mark.js";
111
102
  export * from "./ui/time-series-chart.js";
112
- export * from "./ui/toast.js";
113
103
  export * from "./ui/token-mosaic.js";
114
104
  export * from "./ui/tool-block.js";
115
105
  export * from "./ui/tool-narrative.js";
116
106
  export * from "./ui/tool-picker.js";
117
- export * from "./ui/tooltip.js";
118
107
  export * from "./ui/top-bar.js";
119
108
  export * from "./ui/trace-waterfall.js";
120
109
  export * from "./ui/typing-indicator.js";
package/dist/index.js CHANGED
@@ -1,12 +1,14 @@
1
- // Generated by scripts/generate-exports.mjs. Do not edit.
1
+ // The public surface. Anything not re-exported here is internal.
2
2
  //
3
- // Re-exports only, and the package is sideEffects-free, so importing from
4
- // the root still tree-shakes down to what you used.
5
- //
6
- // Modules that statically import an optional peer dependency are absent here
7
- // on purpose and must be imported by their subpath. The barrel is a single
8
- // module: anything it re-exports is loaded by any root import, so one such
9
- // re-export would make the optional peer mandatory for everyone.
3
+ // Modules that statically import an optional peer are not re-exported: the
4
+ // barrel is one module, so any root import would load that peer. They have
5
+ // their own entries in the `exports` map instead:
6
+ // @corbits/react-ui/ui/command-palette
7
+ // @corbits/react-ui/ui/dialog
8
+ // @corbits/react-ui/ui/menu
9
+ // @corbits/react-ui/ui/mic-permission-dialog
10
+ // @corbits/react-ui/ui/toast
11
+ // @corbits/react-ui/ui/tooltip
10
12
  export * from "./blocks/login/auth-layout.js";
11
13
  export * from "./blocks/login/login-form.js";
12
14
  export * from "./hooks/use-command-palette-navigation.js";
@@ -20,15 +22,11 @@ export * from "./lib/artifact.js";
20
22
  export * from "./lib/chart-palette.js";
21
23
  export * from "./lib/chat-message.js";
22
24
  export * from "./lib/chat-parts.js";
23
- export * from "./lib/csv.js";
24
25
  export * from "./lib/metrics.js";
25
26
  export * from "./lib/now-item.js";
26
27
  export * from "./lib/relative-time.js";
27
28
  export * from "./lib/theme.js";
28
- export * from "./lib/url.js";
29
- export * from "./lib/utils.js";
30
29
  export * from "./lib/workflow-display-flow.js";
31
- export * from "./lib/workflow-registry.js";
32
30
  export * from "./lib/workflow-run.js";
33
31
  export * from "./lib/workflow-run-error.js";
34
32
  export * from "./lib/workflow-run-progress.js";
@@ -48,17 +46,14 @@ export * from "./ui/card.js";
48
46
  export * from "./ui/category-bars.js";
49
47
  export * from "./ui/chart-frame.js";
50
48
  export * from "./ui/chat-composer.js";
51
- export * from "./ui/chat-dock-timing.js";
52
49
  export * from "./ui/chat-input.js";
53
50
  export * from "./ui/chat-panel.js";
54
51
  export * from "./ui/chat-thread.js";
55
52
  export * from "./ui/checkbox.js";
56
- export * from "./ui/command-palette.js";
57
53
  export * from "./ui/compare-body.js";
58
54
  export * from "./ui/confirm-button.js";
59
55
  export * from "./ui/corbits-mark.js";
60
56
  export * from "./ui/csv-table.js";
61
- export * from "./ui/dialog.js";
62
57
  export * from "./ui/dictation-status-line.js";
63
58
  export * from "./ui/dither-canvas.js";
64
59
  export * from "./ui/embed-body.js";
@@ -76,10 +71,8 @@ export * from "./ui/library-page-header.js";
76
71
  export * from "./ui/list-detail.js";
77
72
  export * from "./ui/live-run-banner.js";
78
73
  export * from "./ui/live-status-line.js";
79
- export * from "./ui/menu.js";
80
74
  export * from "./ui/message-bubble.js";
81
75
  export * from "./ui/mic-button.js";
82
- export * from "./ui/mic-permission-dialog.js";
83
76
  export * from "./ui/notifications-bell.js";
84
77
  export * from "./ui/now-cards.js";
85
78
  export * from "./ui/page-panel.js";
@@ -118,12 +111,10 @@ export * from "./ui/thinking-indicator.js";
118
111
  export * from "./ui/thinking-label.js";
119
112
  export * from "./ui/thinking-mark.js";
120
113
  export * from "./ui/time-series-chart.js";
121
- export * from "./ui/toast.js";
122
114
  export * from "./ui/token-mosaic.js";
123
115
  export * from "./ui/tool-block.js";
124
116
  export * from "./ui/tool-narrative.js";
125
117
  export * from "./ui/tool-picker.js";
126
- export * from "./ui/tooltip.js";
127
118
  export * from "./ui/top-bar.js";
128
119
  export * from "./ui/trace-waterfall.js";
129
120
  export * from "./ui/typing-indicator.js";
@@ -1,36 +1,13 @@
1
- /**
2
- * The shape an artifact surface renders.
3
- *
4
- * Deliberately not a mirror of any producer's row type: the registry has no
5
- * backend, so this is the projection a viewer actually needs — an identity, a
6
- * name, a kind, a payload, and enough provenance to caption a tile. Map your
7
- * own record onto it at the edge of your app and the whole artifacts family
8
- * works unchanged.
9
- */ const FORM_BY_SUFFIX = [
10
- [
11
- /(^|-)csv(-|$)|(^|-)sheet(-|$)|(^|-)table(-|$)/,
12
- "table"
13
- ],
14
- [
15
- /(^|-)comparison(-|$)|(^|-)compare(-|$)|^ab-/,
16
- "comparison"
17
- ],
18
- [
19
- /(^|-)research(-|$)|(^|-)brief(-|$)/,
20
- "research"
21
- ],
1
+ const FORM_BY_SUFFIX = [
2
+ [/(^|-)csv(-|$)|(^|-)sheet(-|$)|(^|-)table(-|$)/, "table"],
3
+ [/(^|-)comparison(-|$)|(^|-)compare(-|$)|^ab-/, "comparison"],
4
+ [/(^|-)research(-|$)|(^|-)brief(-|$)/, "research"],
22
5
  [
23
6
  /(^|-)deck(-|$)|(^|-)presentation(-|$)|(^|-)slides(-|$)|(^|-)embed(-|$)/,
24
- "embed"
7
+ "embed",
25
8
  ],
26
- [
27
- /(^|-)image(-|$)|(^|-)photo(-|$)|(^|-)screenshot(-|$)/,
28
- "image"
29
- ],
30
- [
31
- /(^|-)file(-|$)|(^|-)upload(-|$)|(^|-)binary(-|$)/,
32
- "download"
33
- ]
9
+ [/(^|-)image(-|$)|(^|-)photo(-|$)|(^|-)screenshot(-|$)/, "image"],
10
+ [/(^|-)file(-|$)|(^|-)upload(-|$)|(^|-)binary(-|$)/, "download"],
34
11
  ];
35
12
  /**
36
13
  * Guesses a form from a kind string, defaulting to prose.
@@ -46,10 +23,12 @@
46
23
  * Prose is the default because it is the only form that cannot mislead: text
47
24
  * rendered as text is always honest, whereas a non-tabular payload forced into
48
25
  * a grid silently shifts cells into the wrong columns.
49
- */ export function artifactForm(kind) {
26
+ */
27
+ export function artifactForm(kind) {
50
28
  const normalized = kind.trim().toLowerCase();
51
- for (const [pattern, form] of FORM_BY_SUFFIX){
52
- if (pattern.test(normalized)) return form;
29
+ for (const [pattern, form] of FORM_BY_SUFFIX) {
30
+ if (pattern.test(normalized))
31
+ return form;
53
32
  }
54
33
  return "prose";
55
34
  }
@@ -60,8 +39,10 @@
60
39
  * first time a producer ships a kind nobody told the UI about, and an unlabelled
61
40
  * tile is worse than a mechanically-titled one. Pass your own labels through
62
41
  * the `kindLabel` prop where a surface offers it if you need better copy.
63
- */ export function artifactKindLabel(kind) {
42
+ */
43
+ export function artifactKindLabel(kind) {
64
44
  const words = kind.trim().replace(/[_-]+/g, " ").replace(/\s+/g, " ");
65
- if (words === "") return "Artifact";
45
+ if (words === "")
46
+ return "Artifact";
66
47
  return words.charAt(0).toUpperCase() + words.slice(1);
67
48
  }