@corbits/react-ui 0.1.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.
- package/LICENSE +501 -0
- package/README.md +125 -0
- package/dist/blocks/login/auth-layout.d.ts +38 -0
- package/dist/blocks/login/auth-layout.js +52 -0
- package/dist/blocks/login/login-form.d.ts +60 -0
- package/dist/blocks/login/login-form.js +151 -0
- package/dist/hooks/use-command-palette-navigation.d.ts +25 -0
- package/dist/hooks/use-command-palette-navigation.js +52 -0
- package/dist/hooks/use-controllable-state.d.ts +28 -0
- package/dist/hooks/use-controllable-state.js +44 -0
- package/dist/hooks/use-delayed-autofocus.d.ts +9 -0
- package/dist/hooks/use-delayed-autofocus.js +20 -0
- package/dist/hooks/use-dismissable-popover.d.ts +37 -0
- package/dist/hooks/use-dismissable-popover.js +64 -0
- package/dist/hooks/use-list-selection.d.ts +66 -0
- package/dist/hooks/use-list-selection.js +147 -0
- package/dist/hooks/use-prefers-reduced-motion.d.ts +13 -0
- package/dist/hooks/use-prefers-reduced-motion.js +28 -0
- package/dist/hooks/use-scroll-current-into-view.d.ts +19 -0
- package/dist/hooks/use-scroll-current-into-view.js +33 -0
- package/dist/index.d.ts +122 -0
- package/dist/index.js +131 -0
- package/dist/lib/artifact.d.ts +72 -0
- package/dist/lib/artifact.js +67 -0
- package/dist/lib/chart-geometry.d.ts +62 -0
- package/dist/lib/chart-geometry.js +86 -0
- package/dist/lib/chart-palette.d.ts +76 -0
- package/dist/lib/chart-palette.js +92 -0
- package/dist/lib/chat-message.d.ts +115 -0
- package/dist/lib/chat-message.js +41 -0
- package/dist/lib/chat-parts.d.ts +64 -0
- package/dist/lib/chat-parts.js +16 -0
- package/dist/lib/csv.d.ts +60 -0
- package/dist/lib/csv.js +108 -0
- package/dist/lib/metrics.d.ts +70 -0
- package/dist/lib/metrics.js +101 -0
- package/dist/lib/now-item.d.ts +65 -0
- package/dist/lib/now-item.js +59 -0
- package/dist/lib/relative-time.d.ts +9 -0
- package/dist/lib/relative-time.js +47 -0
- package/dist/lib/theme.d.ts +30 -0
- package/dist/lib/theme.js +77 -0
- package/dist/lib/url.d.ts +26 -0
- package/dist/lib/url.js +37 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +5 -0
- package/dist/lib/workflow-display-flow.d.ts +83 -0
- package/dist/lib/workflow-display-flow.js +104 -0
- package/dist/lib/workflow-registry.d.ts +90 -0
- package/dist/lib/workflow-registry.js +56 -0
- package/dist/lib/workflow-run-error.d.ts +31 -0
- package/dist/lib/workflow-run-error.js +105 -0
- package/dist/lib/workflow-run-progress.d.ts +97 -0
- package/dist/lib/workflow-run-progress.js +135 -0
- package/dist/lib/workflow-run.d.ts +43 -0
- package/dist/lib/workflow-run.js +56 -0
- package/dist/styles.css +3080 -0
- package/dist/test/render-hook.d.ts +14 -0
- package/dist/test/render-hook.js +38 -0
- package/dist/theme.css +628 -0
- package/dist/ui/agent-turn.d.ts +26 -0
- package/dist/ui/agent-turn.js +60 -0
- package/dist/ui/animated-number.d.ts +25 -0
- package/dist/ui/animated-number.js +63 -0
- package/dist/ui/approval-card.d.ts +46 -0
- package/dist/ui/approval-card.js +116 -0
- package/dist/ui/artifact-body.d.ts +26 -0
- package/dist/ui/artifact-body.js +170 -0
- package/dist/ui/artifact-notice.d.ts +21 -0
- package/dist/ui/artifact-notice.js +36 -0
- package/dist/ui/avatar.d.ts +37 -0
- package/dist/ui/avatar.js +73 -0
- package/dist/ui/badge.d.ts +10 -0
- package/dist/ui/badge.js +35 -0
- package/dist/ui/bar-chart.d.ts +38 -0
- package/dist/ui/bar-chart.js +118 -0
- package/dist/ui/block-card.d.ts +29 -0
- package/dist/ui/block-card.js +66 -0
- package/dist/ui/boot-screen.d.ts +23 -0
- package/dist/ui/boot-screen.js +49 -0
- package/dist/ui/bulk-action-bar.d.ts +37 -0
- package/dist/ui/bulk-action-bar.js +64 -0
- package/dist/ui/button.d.ts +12 -0
- package/dist/ui/button.js +73 -0
- package/dist/ui/card.d.ts +6 -0
- package/dist/ui/card.js +37 -0
- package/dist/ui/category-bars.d.ts +20 -0
- package/dist/ui/category-bars.js +69 -0
- package/dist/ui/chart-frame.d.ts +54 -0
- package/dist/ui/chart-frame.js +108 -0
- package/dist/ui/chat-composer.d.ts +24 -0
- package/dist/ui/chat-composer.js +32 -0
- package/dist/ui/chat-dock-timing.d.ts +15 -0
- package/dist/ui/chat-dock-timing.js +11 -0
- package/dist/ui/chat-input.d.ts +38 -0
- package/dist/ui/chat-input.js +138 -0
- package/dist/ui/chat-panel.d.ts +20 -0
- package/dist/ui/chat-panel.js +56 -0
- package/dist/ui/chat-thread.d.ts +28 -0
- package/dist/ui/chat-thread.js +61 -0
- package/dist/ui/checkbox.d.ts +25 -0
- package/dist/ui/checkbox.js +63 -0
- package/dist/ui/command-palette.d.ts +100 -0
- package/dist/ui/command-palette.js +341 -0
- package/dist/ui/compare-body.d.ts +52 -0
- package/dist/ui/compare-body.js +140 -0
- package/dist/ui/confirm-button.d.ts +29 -0
- package/dist/ui/confirm-button.js +41 -0
- package/dist/ui/corbits-mark.d.ts +29 -0
- package/dist/ui/corbits-mark.js +33 -0
- package/dist/ui/csv-table.d.ts +22 -0
- package/dist/ui/csv-table.js +85 -0
- package/dist/ui/dialog.d.ts +37 -0
- package/dist/ui/dialog.js +105 -0
- package/dist/ui/dictation-status-line.d.ts +20 -0
- package/dist/ui/dictation-status-line.js +38 -0
- package/dist/ui/dither-canvas.d.ts +31 -0
- package/dist/ui/dither-canvas.js +169 -0
- package/dist/ui/embed-body.d.ts +30 -0
- package/dist/ui/embed-body.js +92 -0
- package/dist/ui/empty-state.d.ts +26 -0
- package/dist/ui/empty-state.js +42 -0
- package/dist/ui/file-input.d.ts +25 -0
- package/dist/ui/file-input.js +66 -0
- package/dist/ui/filter-bar.d.ts +42 -0
- package/dist/ui/filter-bar.js +95 -0
- package/dist/ui/filter-chip.d.ts +14 -0
- package/dist/ui/filter-chip.js +23 -0
- package/dist/ui/gate-block.d.ts +16 -0
- package/dist/ui/gate-block.js +37 -0
- package/dist/ui/horizontal-stepper.d.ts +13 -0
- package/dist/ui/horizontal-stepper.js +65 -0
- package/dist/ui/input.d.ts +2 -0
- package/dist/ui/input.js +14 -0
- package/dist/ui/inspector-shell.d.ts +47 -0
- package/dist/ui/inspector-shell.js +98 -0
- package/dist/ui/intake-form.d.ts +39 -0
- package/dist/ui/intake-form.js +119 -0
- package/dist/ui/kind-card-grid.d.ts +23 -0
- package/dist/ui/kind-card-grid.js +43 -0
- package/dist/ui/library-page-header.d.ts +20 -0
- package/dist/ui/library-page-header.js +43 -0
- package/dist/ui/list-detail.d.ts +28 -0
- package/dist/ui/list-detail.js +55 -0
- package/dist/ui/live-run-banner.d.ts +13 -0
- package/dist/ui/live-run-banner.js +23 -0
- package/dist/ui/live-status-line.d.ts +22 -0
- package/dist/ui/live-status-line.js +37 -0
- package/dist/ui/menu.d.ts +18 -0
- package/dist/ui/menu.js +45 -0
- package/dist/ui/message-bubble.d.ts +24 -0
- package/dist/ui/message-bubble.js +64 -0
- package/dist/ui/mic-button.d.ts +35 -0
- package/dist/ui/mic-button.js +61 -0
- package/dist/ui/mic-permission-dialog.d.ts +20 -0
- package/dist/ui/mic-permission-dialog.js +50 -0
- package/dist/ui/notifications-bell.d.ts +28 -0
- package/dist/ui/notifications-bell.js +69 -0
- package/dist/ui/now-cards.d.ts +37 -0
- package/dist/ui/now-cards.js +116 -0
- package/dist/ui/page-panel.d.ts +37 -0
- package/dist/ui/page-panel.js +23 -0
- package/dist/ui/page-shell.d.ts +21 -0
- package/dist/ui/page-shell.js +26 -0
- package/dist/ui/parts-renderer.d.ts +22 -0
- package/dist/ui/parts-renderer.js +234 -0
- package/dist/ui/profile-card.d.ts +39 -0
- package/dist/ui/profile-card.js +124 -0
- package/dist/ui/progress-checklist.d.ts +25 -0
- package/dist/ui/progress-checklist.js +70 -0
- package/dist/ui/provider-mark.d.ts +32 -0
- package/dist/ui/provider-mark.js +31 -0
- package/dist/ui/quick-reply-chips.d.ts +14 -0
- package/dist/ui/quick-reply-chips.js +24 -0
- package/dist/ui/quote-card.d.ts +39 -0
- package/dist/ui/quote-card.js +66 -0
- package/dist/ui/reasoning-block.d.ts +35 -0
- package/dist/ui/reasoning-block.js +60 -0
- package/dist/ui/research-body.d.ts +70 -0
- package/dist/ui/research-body.js +270 -0
- package/dist/ui/rich-empty-state.d.ts +35 -0
- package/dist/ui/rich-empty-state.js +65 -0
- package/dist/ui/run-now-button.d.ts +23 -0
- package/dist/ui/run-now-button.js +42 -0
- package/dist/ui/section.d.ts +20 -0
- package/dist/ui/section.js +48 -0
- package/dist/ui/select.d.ts +2 -0
- package/dist/ui/select.js +22 -0
- package/dist/ui/selection-checkbox.d.ts +42 -0
- package/dist/ui/selection-checkbox.js +54 -0
- package/dist/ui/settings-panel.d.ts +35 -0
- package/dist/ui/settings-panel.js +68 -0
- package/dist/ui/shimmer-text.d.ts +19 -0
- package/dist/ui/shimmer-text.js +20 -0
- package/dist/ui/sidebar-item-row.d.ts +40 -0
- package/dist/ui/sidebar-item-row.js +64 -0
- package/dist/ui/sidebar-panel.d.ts +25 -0
- package/dist/ui/sidebar-panel.js +56 -0
- package/dist/ui/sidebar.d.ts +46 -0
- package/dist/ui/sidebar.js +111 -0
- package/dist/ui/skeleton.d.ts +13 -0
- package/dist/ui/skeleton.js +20 -0
- package/dist/ui/sortable-table.d.ts +43 -0
- package/dist/ui/sortable-table.js +103 -0
- package/dist/ui/sparkline.d.ts +27 -0
- package/dist/ui/sparkline.js +68 -0
- package/dist/ui/stat-grid.d.ts +55 -0
- package/dist/ui/stat-grid.js +87 -0
- package/dist/ui/status-dot.d.ts +13 -0
- package/dist/ui/status-dot.js +51 -0
- package/dist/ui/step-list.d.ts +21 -0
- package/dist/ui/step-list.js +77 -0
- package/dist/ui/switch.d.ts +23 -0
- package/dist/ui/switch.js +29 -0
- package/dist/ui/table.d.ts +8 -0
- package/dist/ui/table.js +48 -0
- package/dist/ui/tabs.d.ts +44 -0
- package/dist/ui/tabs.js +101 -0
- package/dist/ui/textarea.d.ts +8 -0
- package/dist/ui/textarea.js +32 -0
- package/dist/ui/theme-provider.d.ts +36 -0
- package/dist/ui/theme-provider.js +126 -0
- package/dist/ui/theme-toggle.d.ts +11 -0
- package/dist/ui/theme-toggle.js +32 -0
- package/dist/ui/thinking-indicator.d.ts +7 -0
- package/dist/ui/thinking-indicator.js +19 -0
- package/dist/ui/thinking-label.d.ts +19 -0
- package/dist/ui/thinking-label.js +54 -0
- package/dist/ui/thinking-mark.d.ts +10 -0
- package/dist/ui/thinking-mark.js +153 -0
- package/dist/ui/time-series-chart.d.ts +55 -0
- package/dist/ui/time-series-chart.js +249 -0
- package/dist/ui/toast.d.ts +16 -0
- package/dist/ui/toast.js +41 -0
- package/dist/ui/token-mosaic.d.ts +22 -0
- package/dist/ui/token-mosaic.js +65 -0
- package/dist/ui/tool-block.d.ts +54 -0
- package/dist/ui/tool-block.js +170 -0
- package/dist/ui/tool-narrative.d.ts +22 -0
- package/dist/ui/tool-narrative.js +77 -0
- package/dist/ui/tool-picker.d.ts +44 -0
- package/dist/ui/tool-picker.js +200 -0
- package/dist/ui/tooltip.d.ts +21 -0
- package/dist/ui/tooltip.js +48 -0
- package/dist/ui/top-bar.d.ts +53 -0
- package/dist/ui/top-bar.js +98 -0
- package/dist/ui/trace-waterfall.d.ts +38 -0
- package/dist/ui/trace-waterfall.js +121 -0
- package/dist/ui/typing-indicator.d.ts +9 -0
- package/dist/ui/typing-indicator.js +25 -0
- package/dist/ui/view-toggle.d.ts +17 -0
- package/dist/ui/view-toggle.js +46 -0
- package/dist/ui/voice-waveform.d.ts +16 -0
- package/dist/ui/voice-waveform.js +23 -0
- package/package.json +583 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { useCallback, useMemo, useReducer, useRef } from "react";
|
|
2
|
+
function reducer(state, action) {
|
|
3
|
+
switch(action.type){
|
|
4
|
+
case "clear":
|
|
5
|
+
return {
|
|
6
|
+
selectedIds: new Set(),
|
|
7
|
+
anchorId: undefined,
|
|
8
|
+
baseSelection: new Set()
|
|
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
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const next = toggleOne(state.selectedIds, id);
|
|
52
|
+
return {
|
|
53
|
+
selectedIds: next,
|
|
54
|
+
anchorId: id,
|
|
55
|
+
baseSelection: next
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function createInitialState() {
|
|
61
|
+
return {
|
|
62
|
+
selectedIds: new Set(),
|
|
63
|
+
anchorId: undefined,
|
|
64
|
+
baseSelection: new Set()
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Headless selection state for a list/table: toggle-by-id, shift-click range
|
|
69
|
+
* selection anchored on the last row toggled outside a range, and
|
|
70
|
+
* select-all/clear. Renders nothing and owns no DOM — `SelectionCheckbox` and
|
|
71
|
+
* `BulkActionBar` are the rendered halves of this.
|
|
72
|
+
*
|
|
73
|
+
* The anchor is the last id passed to `toggle` *without* `shiftKey` — the
|
|
74
|
+
* same row a Finder/Sheets shift-click ranges from. A shift-click does not
|
|
75
|
+
* move the anchor, so a person can shift-click several times in a row (even
|
|
76
|
+
* in different directions) and each click re-ranges from the same start
|
|
77
|
+
* rather than from wherever they last landed.
|
|
78
|
+
*
|
|
79
|
+
* **Stale-id reconciliation.** The hook keeps whatever was selected even
|
|
80
|
+
* after a row drops out of `ids` (a refetch, a filter change) rather than
|
|
81
|
+
* pruning it immediately — pruning on every `ids` change would need an
|
|
82
|
+
* effect, and an extra render on top of whatever caused `ids` to change in
|
|
83
|
+
* the first place. Instead `selectedIds`/`selectedCount`/`isSelected` are
|
|
84
|
+
* reconciled against the current `ids` on every read, so a stale id can
|
|
85
|
+
* never inflate the count or reach the caller; it simply stops counting
|
|
86
|
+
* once its row is gone, and starts counting again if the same id reappears
|
|
87
|
+
* (e.g. a filter that got cleared) with no action needed from the caller.
|
|
88
|
+
*
|
|
89
|
+
* **Stable callbacks.** `toggle`/`selectAll`/`clear` read `ids` through a
|
|
90
|
+
* ref rather than closing over the `ids` array directly, so their identity
|
|
91
|
+
* stays stable across renders even when a caller passes a freshly allocated
|
|
92
|
+
* array each time (e.g. an inline `rows.map(row => row.id)`) — a memoized
|
|
93
|
+
* row downstream that depends on `toggle` does not re-render just because
|
|
94
|
+
* the caller didn't bother memoizing `ids`.
|
|
95
|
+
*/ export function useListSelection({ ids }) {
|
|
96
|
+
const [state, dispatch] = useReducer(reducer, undefined, createInitialState);
|
|
97
|
+
// Updated on every render, read only inside event handlers — never during
|
|
98
|
+
// render — so `toggle`/`selectAll` can stay referentially stable while
|
|
99
|
+
// still acting on the `ids` most recently passed in.
|
|
100
|
+
const idsRef = useRef(ids);
|
|
101
|
+
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(()=>{
|
|
116
|
+
const known = new Set(ids);
|
|
117
|
+
const reconciled = new Set();
|
|
118
|
+
for (const id of state.selectedIds)if (known.has(id)) reconciled.add(id);
|
|
119
|
+
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
|
+
}), [
|
|
135
|
+
selectedIds,
|
|
136
|
+
isSelected,
|
|
137
|
+
toggle,
|
|
138
|
+
selectAll,
|
|
139
|
+
clear
|
|
140
|
+
]);
|
|
141
|
+
}
|
|
142
|
+
function toggleOne(current, id) {
|
|
143
|
+
const next = new Set(current);
|
|
144
|
+
if (next.has(id)) next.delete(id);
|
|
145
|
+
else next.add(id);
|
|
146
|
+
return next;
|
|
147
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The OS-level "reduce motion" preference, read once and kept live.
|
|
3
|
+
*
|
|
4
|
+
* `theme.css` collapses every CSS transition/animation duration to near-zero
|
|
5
|
+
* under this same query, so most components need nothing here — that global
|
|
6
|
+
* rule is the default. This hook exists for the handful that animate outside
|
|
7
|
+
* CSS (a `requestAnimationFrame` loop, an imperative scroll), where the
|
|
8
|
+
* stylesheet has no duration to collapse. `animated-number`, `dither-canvas`
|
|
9
|
+
* and `use-scroll-current-into-view` each read `matchMedia` by hand before
|
|
10
|
+
* this shipped; this is the one place that logic lives now, and — unlike
|
|
11
|
+
* those one-shot reads — it updates if the preference changes while mounted.
|
|
12
|
+
*/
|
|
13
|
+
export declare function usePrefersReducedMotion(): boolean;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useSyncExternalStore } from "react";
|
|
2
|
+
const QUERY = "(prefers-reduced-motion: reduce)";
|
|
3
|
+
function subscribe(callback) {
|
|
4
|
+
if (typeof window === "undefined") return ()=>{};
|
|
5
|
+
const query = window.matchMedia(QUERY);
|
|
6
|
+
query.addEventListener("change", callback);
|
|
7
|
+
return ()=>query.removeEventListener("change", callback);
|
|
8
|
+
}
|
|
9
|
+
function getSnapshot() {
|
|
10
|
+
return typeof window === "undefined" ? false : window.matchMedia(QUERY).matches;
|
|
11
|
+
}
|
|
12
|
+
function getServerSnapshot() {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The OS-level "reduce motion" preference, read once and kept live.
|
|
17
|
+
*
|
|
18
|
+
* `theme.css` collapses every CSS transition/animation duration to near-zero
|
|
19
|
+
* under this same query, so most components need nothing here — that global
|
|
20
|
+
* rule is the default. This hook exists for the handful that animate outside
|
|
21
|
+
* CSS (a `requestAnimationFrame` loop, an imperative scroll), where the
|
|
22
|
+
* stylesheet has no duration to collapse. `animated-number`, `dither-canvas`
|
|
23
|
+
* and `use-scroll-current-into-view` each read `matchMedia` by hand before
|
|
24
|
+
* this shipped; this is the one place that logic lives now, and — unlike
|
|
25
|
+
* those one-shot reads — it updates if the preference changes while mounted.
|
|
26
|
+
*/ export function usePrefersReducedMotion() {
|
|
27
|
+
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
28
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Keeps "the current item" visible inside a scrollable rail: attach the
|
|
4
|
+
* returned ref to whichever element is current, and it is scrolled into view
|
|
5
|
+
* whenever `currentKey` changes. Headless — no markup, no styling — so a
|
|
6
|
+
* stepper, a tab strip or a timeline can all share the one behaviour.
|
|
7
|
+
*
|
|
8
|
+
* `currentKey` takes a single primitive (a step number, a tab id) rather than
|
|
9
|
+
* a dependency array, so there is nothing to spread and no way for a new
|
|
10
|
+
* array identity to re-fire the scroll on every unrelated parent render.
|
|
11
|
+
*
|
|
12
|
+
* `block: "nearest"` keeps the page itself from jumping; only the rail's own
|
|
13
|
+
* scroll position moves.
|
|
14
|
+
*
|
|
15
|
+
* The scroll itself is smooth, but `scrollIntoView` isn't covered by the
|
|
16
|
+
* theme's global reduced-motion block, so a `prefers-reduced-motion: reduce`
|
|
17
|
+
* check here falls back to an instant jump.
|
|
18
|
+
*/
|
|
19
|
+
export declare function useScrollCurrentIntoView<T extends HTMLElement>(currentKey: string | number): RefObject<T | null>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
import { usePrefersReducedMotion } from "./use-prefers-reduced-motion.js";
|
|
3
|
+
/**
|
|
4
|
+
* Keeps "the current item" visible inside a scrollable rail: attach the
|
|
5
|
+
* returned ref to whichever element is current, and it is scrolled into view
|
|
6
|
+
* whenever `currentKey` changes. Headless — no markup, no styling — so a
|
|
7
|
+
* stepper, a tab strip or a timeline can all share the one behaviour.
|
|
8
|
+
*
|
|
9
|
+
* `currentKey` takes a single primitive (a step number, a tab id) rather than
|
|
10
|
+
* a dependency array, so there is nothing to spread and no way for a new
|
|
11
|
+
* array identity to re-fire the scroll on every unrelated parent render.
|
|
12
|
+
*
|
|
13
|
+
* `block: "nearest"` keeps the page itself from jumping; only the rail's own
|
|
14
|
+
* scroll position moves.
|
|
15
|
+
*
|
|
16
|
+
* The scroll itself is smooth, but `scrollIntoView` isn't covered by the
|
|
17
|
+
* theme's global reduced-motion block, so a `prefers-reduced-motion: reduce`
|
|
18
|
+
* check here falls back to an instant jump.
|
|
19
|
+
*/ export function useScrollCurrentIntoView(currentKey) {
|
|
20
|
+
const currentRef = useRef(null);
|
|
21
|
+
const prefersReducedMotion = usePrefersReducedMotion();
|
|
22
|
+
useEffect(()=>{
|
|
23
|
+
currentRef.current?.scrollIntoView({
|
|
24
|
+
block: "nearest",
|
|
25
|
+
inline: "center",
|
|
26
|
+
behavior: prefersReducedMotion ? "auto" : "smooth"
|
|
27
|
+
});
|
|
28
|
+
}, [
|
|
29
|
+
currentKey,
|
|
30
|
+
prefersReducedMotion
|
|
31
|
+
]);
|
|
32
|
+
return currentRef;
|
|
33
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
export * from "./blocks/login/auth-layout.js";
|
|
2
|
+
export * from "./blocks/login/login-form.js";
|
|
3
|
+
export * from "./hooks/use-command-palette-navigation.js";
|
|
4
|
+
export * from "./hooks/use-controllable-state.js";
|
|
5
|
+
export * from "./hooks/use-delayed-autofocus.js";
|
|
6
|
+
export * from "./hooks/use-dismissable-popover.js";
|
|
7
|
+
export * from "./hooks/use-list-selection.js";
|
|
8
|
+
export * from "./hooks/use-prefers-reduced-motion.js";
|
|
9
|
+
export * from "./hooks/use-scroll-current-into-view.js";
|
|
10
|
+
export * from "./lib/artifact.js";
|
|
11
|
+
export * from "./lib/chart-palette.js";
|
|
12
|
+
export * from "./lib/chat-message.js";
|
|
13
|
+
export * from "./lib/chat-parts.js";
|
|
14
|
+
export * from "./lib/csv.js";
|
|
15
|
+
export * from "./lib/metrics.js";
|
|
16
|
+
export * from "./lib/now-item.js";
|
|
17
|
+
export * from "./lib/relative-time.js";
|
|
18
|
+
export * from "./lib/theme.js";
|
|
19
|
+
export * from "./lib/url.js";
|
|
20
|
+
export * from "./lib/utils.js";
|
|
21
|
+
export * from "./lib/workflow-display-flow.js";
|
|
22
|
+
export * from "./lib/workflow-registry.js";
|
|
23
|
+
export * from "./lib/workflow-run.js";
|
|
24
|
+
export * from "./lib/workflow-run-error.js";
|
|
25
|
+
export * from "./lib/workflow-run-progress.js";
|
|
26
|
+
export * from "./ui/agent-turn.js";
|
|
27
|
+
export * from "./ui/animated-number.js";
|
|
28
|
+
export * from "./ui/approval-card.js";
|
|
29
|
+
export * from "./ui/artifact-body.js";
|
|
30
|
+
export * from "./ui/artifact-notice.js";
|
|
31
|
+
export * from "./ui/avatar.js";
|
|
32
|
+
export * from "./ui/badge.js";
|
|
33
|
+
export * from "./ui/bar-chart.js";
|
|
34
|
+
export * from "./ui/block-card.js";
|
|
35
|
+
export * from "./ui/boot-screen.js";
|
|
36
|
+
export * from "./ui/bulk-action-bar.js";
|
|
37
|
+
export * from "./ui/button.js";
|
|
38
|
+
export * from "./ui/card.js";
|
|
39
|
+
export * from "./ui/category-bars.js";
|
|
40
|
+
export * from "./ui/chart-frame.js";
|
|
41
|
+
export * from "./ui/chat-composer.js";
|
|
42
|
+
export * from "./ui/chat-dock-timing.js";
|
|
43
|
+
export * from "./ui/chat-input.js";
|
|
44
|
+
export * from "./ui/chat-panel.js";
|
|
45
|
+
export * from "./ui/chat-thread.js";
|
|
46
|
+
export * from "./ui/checkbox.js";
|
|
47
|
+
export * from "./ui/command-palette.js";
|
|
48
|
+
export * from "./ui/compare-body.js";
|
|
49
|
+
export * from "./ui/confirm-button.js";
|
|
50
|
+
export * from "./ui/corbits-mark.js";
|
|
51
|
+
export * from "./ui/csv-table.js";
|
|
52
|
+
export * from "./ui/dialog.js";
|
|
53
|
+
export * from "./ui/dictation-status-line.js";
|
|
54
|
+
export * from "./ui/dither-canvas.js";
|
|
55
|
+
export * from "./ui/embed-body.js";
|
|
56
|
+
export * from "./ui/empty-state.js";
|
|
57
|
+
export * from "./ui/file-input.js";
|
|
58
|
+
export * from "./ui/filter-bar.js";
|
|
59
|
+
export * from "./ui/filter-chip.js";
|
|
60
|
+
export * from "./ui/gate-block.js";
|
|
61
|
+
export * from "./ui/horizontal-stepper.js";
|
|
62
|
+
export * from "./ui/input.js";
|
|
63
|
+
export * from "./ui/inspector-shell.js";
|
|
64
|
+
export * from "./ui/intake-form.js";
|
|
65
|
+
export * from "./ui/kind-card-grid.js";
|
|
66
|
+
export * from "./ui/library-page-header.js";
|
|
67
|
+
export * from "./ui/list-detail.js";
|
|
68
|
+
export * from "./ui/live-run-banner.js";
|
|
69
|
+
export * from "./ui/live-status-line.js";
|
|
70
|
+
export * from "./ui/menu.js";
|
|
71
|
+
export * from "./ui/message-bubble.js";
|
|
72
|
+
export * from "./ui/mic-button.js";
|
|
73
|
+
export * from "./ui/mic-permission-dialog.js";
|
|
74
|
+
export * from "./ui/notifications-bell.js";
|
|
75
|
+
export * from "./ui/now-cards.js";
|
|
76
|
+
export * from "./ui/page-panel.js";
|
|
77
|
+
export * from "./ui/page-shell.js";
|
|
78
|
+
export * from "./ui/parts-renderer.js";
|
|
79
|
+
export * from "./ui/profile-card.js";
|
|
80
|
+
export * from "./ui/progress-checklist.js";
|
|
81
|
+
export * from "./ui/provider-mark.js";
|
|
82
|
+
export * from "./ui/quick-reply-chips.js";
|
|
83
|
+
export * from "./ui/quote-card.js";
|
|
84
|
+
export * from "./ui/reasoning-block.js";
|
|
85
|
+
export * from "./ui/research-body.js";
|
|
86
|
+
export * from "./ui/rich-empty-state.js";
|
|
87
|
+
export * from "./ui/run-now-button.js";
|
|
88
|
+
export * from "./ui/section.js";
|
|
89
|
+
export * from "./ui/select.js";
|
|
90
|
+
export * from "./ui/selection-checkbox.js";
|
|
91
|
+
export * from "./ui/settings-panel.js";
|
|
92
|
+
export * from "./ui/shimmer-text.js";
|
|
93
|
+
export * from "./ui/sidebar.js";
|
|
94
|
+
export * from "./ui/sidebar-item-row.js";
|
|
95
|
+
export * from "./ui/sidebar-panel.js";
|
|
96
|
+
export * from "./ui/skeleton.js";
|
|
97
|
+
export * from "./ui/sortable-table.js";
|
|
98
|
+
export * from "./ui/sparkline.js";
|
|
99
|
+
export * from "./ui/stat-grid.js";
|
|
100
|
+
export * from "./ui/status-dot.js";
|
|
101
|
+
export * from "./ui/step-list.js";
|
|
102
|
+
export * from "./ui/switch.js";
|
|
103
|
+
export * from "./ui/table.js";
|
|
104
|
+
export * from "./ui/tabs.js";
|
|
105
|
+
export * from "./ui/textarea.js";
|
|
106
|
+
export * from "./ui/theme-provider.js";
|
|
107
|
+
export * from "./ui/theme-toggle.js";
|
|
108
|
+
export * from "./ui/thinking-indicator.js";
|
|
109
|
+
export * from "./ui/thinking-label.js";
|
|
110
|
+
export * from "./ui/thinking-mark.js";
|
|
111
|
+
export * from "./ui/time-series-chart.js";
|
|
112
|
+
export * from "./ui/toast.js";
|
|
113
|
+
export * from "./ui/token-mosaic.js";
|
|
114
|
+
export * from "./ui/tool-block.js";
|
|
115
|
+
export * from "./ui/tool-narrative.js";
|
|
116
|
+
export * from "./ui/tool-picker.js";
|
|
117
|
+
export * from "./ui/tooltip.js";
|
|
118
|
+
export * from "./ui/top-bar.js";
|
|
119
|
+
export * from "./ui/trace-waterfall.js";
|
|
120
|
+
export * from "./ui/typing-indicator.js";
|
|
121
|
+
export * from "./ui/view-toggle.js";
|
|
122
|
+
export * from "./ui/voice-waveform.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// Generated by scripts/generate-exports.mjs. Do not edit.
|
|
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.
|
|
10
|
+
export * from "./blocks/login/auth-layout.js";
|
|
11
|
+
export * from "./blocks/login/login-form.js";
|
|
12
|
+
export * from "./hooks/use-command-palette-navigation.js";
|
|
13
|
+
export * from "./hooks/use-controllable-state.js";
|
|
14
|
+
export * from "./hooks/use-delayed-autofocus.js";
|
|
15
|
+
export * from "./hooks/use-dismissable-popover.js";
|
|
16
|
+
export * from "./hooks/use-list-selection.js";
|
|
17
|
+
export * from "./hooks/use-prefers-reduced-motion.js";
|
|
18
|
+
export * from "./hooks/use-scroll-current-into-view.js";
|
|
19
|
+
export * from "./lib/artifact.js";
|
|
20
|
+
export * from "./lib/chart-palette.js";
|
|
21
|
+
export * from "./lib/chat-message.js";
|
|
22
|
+
export * from "./lib/chat-parts.js";
|
|
23
|
+
export * from "./lib/csv.js";
|
|
24
|
+
export * from "./lib/metrics.js";
|
|
25
|
+
export * from "./lib/now-item.js";
|
|
26
|
+
export * from "./lib/relative-time.js";
|
|
27
|
+
export * from "./lib/theme.js";
|
|
28
|
+
export * from "./lib/url.js";
|
|
29
|
+
export * from "./lib/utils.js";
|
|
30
|
+
export * from "./lib/workflow-display-flow.js";
|
|
31
|
+
export * from "./lib/workflow-registry.js";
|
|
32
|
+
export * from "./lib/workflow-run.js";
|
|
33
|
+
export * from "./lib/workflow-run-error.js";
|
|
34
|
+
export * from "./lib/workflow-run-progress.js";
|
|
35
|
+
export * from "./ui/agent-turn.js";
|
|
36
|
+
export * from "./ui/animated-number.js";
|
|
37
|
+
export * from "./ui/approval-card.js";
|
|
38
|
+
export * from "./ui/artifact-body.js";
|
|
39
|
+
export * from "./ui/artifact-notice.js";
|
|
40
|
+
export * from "./ui/avatar.js";
|
|
41
|
+
export * from "./ui/badge.js";
|
|
42
|
+
export * from "./ui/bar-chart.js";
|
|
43
|
+
export * from "./ui/block-card.js";
|
|
44
|
+
export * from "./ui/boot-screen.js";
|
|
45
|
+
export * from "./ui/bulk-action-bar.js";
|
|
46
|
+
export * from "./ui/button.js";
|
|
47
|
+
export * from "./ui/card.js";
|
|
48
|
+
export * from "./ui/category-bars.js";
|
|
49
|
+
export * from "./ui/chart-frame.js";
|
|
50
|
+
export * from "./ui/chat-composer.js";
|
|
51
|
+
export * from "./ui/chat-dock-timing.js";
|
|
52
|
+
export * from "./ui/chat-input.js";
|
|
53
|
+
export * from "./ui/chat-panel.js";
|
|
54
|
+
export * from "./ui/chat-thread.js";
|
|
55
|
+
export * from "./ui/checkbox.js";
|
|
56
|
+
export * from "./ui/command-palette.js";
|
|
57
|
+
export * from "./ui/compare-body.js";
|
|
58
|
+
export * from "./ui/confirm-button.js";
|
|
59
|
+
export * from "./ui/corbits-mark.js";
|
|
60
|
+
export * from "./ui/csv-table.js";
|
|
61
|
+
export * from "./ui/dialog.js";
|
|
62
|
+
export * from "./ui/dictation-status-line.js";
|
|
63
|
+
export * from "./ui/dither-canvas.js";
|
|
64
|
+
export * from "./ui/embed-body.js";
|
|
65
|
+
export * from "./ui/empty-state.js";
|
|
66
|
+
export * from "./ui/file-input.js";
|
|
67
|
+
export * from "./ui/filter-bar.js";
|
|
68
|
+
export * from "./ui/filter-chip.js";
|
|
69
|
+
export * from "./ui/gate-block.js";
|
|
70
|
+
export * from "./ui/horizontal-stepper.js";
|
|
71
|
+
export * from "./ui/input.js";
|
|
72
|
+
export * from "./ui/inspector-shell.js";
|
|
73
|
+
export * from "./ui/intake-form.js";
|
|
74
|
+
export * from "./ui/kind-card-grid.js";
|
|
75
|
+
export * from "./ui/library-page-header.js";
|
|
76
|
+
export * from "./ui/list-detail.js";
|
|
77
|
+
export * from "./ui/live-run-banner.js";
|
|
78
|
+
export * from "./ui/live-status-line.js";
|
|
79
|
+
export * from "./ui/menu.js";
|
|
80
|
+
export * from "./ui/message-bubble.js";
|
|
81
|
+
export * from "./ui/mic-button.js";
|
|
82
|
+
export * from "./ui/mic-permission-dialog.js";
|
|
83
|
+
export * from "./ui/notifications-bell.js";
|
|
84
|
+
export * from "./ui/now-cards.js";
|
|
85
|
+
export * from "./ui/page-panel.js";
|
|
86
|
+
export * from "./ui/page-shell.js";
|
|
87
|
+
export * from "./ui/parts-renderer.js";
|
|
88
|
+
export * from "./ui/profile-card.js";
|
|
89
|
+
export * from "./ui/progress-checklist.js";
|
|
90
|
+
export * from "./ui/provider-mark.js";
|
|
91
|
+
export * from "./ui/quick-reply-chips.js";
|
|
92
|
+
export * from "./ui/quote-card.js";
|
|
93
|
+
export * from "./ui/reasoning-block.js";
|
|
94
|
+
export * from "./ui/research-body.js";
|
|
95
|
+
export * from "./ui/rich-empty-state.js";
|
|
96
|
+
export * from "./ui/run-now-button.js";
|
|
97
|
+
export * from "./ui/section.js";
|
|
98
|
+
export * from "./ui/select.js";
|
|
99
|
+
export * from "./ui/selection-checkbox.js";
|
|
100
|
+
export * from "./ui/settings-panel.js";
|
|
101
|
+
export * from "./ui/shimmer-text.js";
|
|
102
|
+
export * from "./ui/sidebar.js";
|
|
103
|
+
export * from "./ui/sidebar-item-row.js";
|
|
104
|
+
export * from "./ui/sidebar-panel.js";
|
|
105
|
+
export * from "./ui/skeleton.js";
|
|
106
|
+
export * from "./ui/sortable-table.js";
|
|
107
|
+
export * from "./ui/sparkline.js";
|
|
108
|
+
export * from "./ui/stat-grid.js";
|
|
109
|
+
export * from "./ui/status-dot.js";
|
|
110
|
+
export * from "./ui/step-list.js";
|
|
111
|
+
export * from "./ui/switch.js";
|
|
112
|
+
export * from "./ui/table.js";
|
|
113
|
+
export * from "./ui/tabs.js";
|
|
114
|
+
export * from "./ui/textarea.js";
|
|
115
|
+
export * from "./ui/theme-provider.js";
|
|
116
|
+
export * from "./ui/theme-toggle.js";
|
|
117
|
+
export * from "./ui/thinking-indicator.js";
|
|
118
|
+
export * from "./ui/thinking-label.js";
|
|
119
|
+
export * from "./ui/thinking-mark.js";
|
|
120
|
+
export * from "./ui/time-series-chart.js";
|
|
121
|
+
export * from "./ui/toast.js";
|
|
122
|
+
export * from "./ui/token-mosaic.js";
|
|
123
|
+
export * from "./ui/tool-block.js";
|
|
124
|
+
export * from "./ui/tool-narrative.js";
|
|
125
|
+
export * from "./ui/tool-picker.js";
|
|
126
|
+
export * from "./ui/tooltip.js";
|
|
127
|
+
export * from "./ui/top-bar.js";
|
|
128
|
+
export * from "./ui/trace-waterfall.js";
|
|
129
|
+
export * from "./ui/typing-indicator.js";
|
|
130
|
+
export * from "./ui/view-toggle.js";
|
|
131
|
+
export * from "./ui/voice-waveform.js";
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
*/
|
|
10
|
+
export type Artifact = {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly title: string;
|
|
13
|
+
/**
|
|
14
|
+
* Open vocabulary, owned by whatever produced the artifact — "one-pager",
|
|
15
|
+
* "csv-export", "deck". It is a plain string rather than a union because the
|
|
16
|
+
* registry cannot know your kinds, and a union here would force every
|
|
17
|
+
* consumer to fork this file on their first new kind.
|
|
18
|
+
*/
|
|
19
|
+
readonly kind: string;
|
|
20
|
+
/**
|
|
21
|
+
* The payload. Prose kinds carry text, embed kinds carry a URL, structured
|
|
22
|
+
* kinds carry JSON. Empty is a legitimate value — see `pending`.
|
|
23
|
+
*/
|
|
24
|
+
readonly content: string;
|
|
25
|
+
readonly createdAt: string;
|
|
26
|
+
readonly updatedAt?: string;
|
|
27
|
+
readonly ownerName?: string;
|
|
28
|
+
/**
|
|
29
|
+
* The producer is still writing this one. An empty `content` means "not
|
|
30
|
+
* written yet" rather than "broken", and the viewer must say which — an
|
|
31
|
+
* artifact that reads as damaged while it is merely mid-generation is the
|
|
32
|
+
* single most common false alarm on this surface.
|
|
33
|
+
*/
|
|
34
|
+
readonly pending?: boolean;
|
|
35
|
+
/** A preview image the host can serve, when it has one. */
|
|
36
|
+
readonly thumbnailUrl?: string;
|
|
37
|
+
/** The original bytes, when the host exposes a download route. */
|
|
38
|
+
readonly downloadUrl?: string;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* How an artifact should be *drawn*, as opposed to what it is called.
|
|
42
|
+
*
|
|
43
|
+
* A closed union, unlike `kind`: there are only so many ways to present a
|
|
44
|
+
* payload, and every one of them is a component in this registry. Kinds
|
|
45
|
+
* multiply; forms do not.
|
|
46
|
+
*/
|
|
47
|
+
export type ArtifactForm = "prose" | "table" | "comparison" | "research" | "embed" | "image" | "download";
|
|
48
|
+
/**
|
|
49
|
+
* Guesses a form from a kind string, defaulting to prose.
|
|
50
|
+
*
|
|
51
|
+
* **This is the function you edit.** It is a plain lookup, not a plugin
|
|
52
|
+
* registry, precisely because you own this file once `shadcn add` copies it —
|
|
53
|
+
* adding a kind should be one line here, readable at a glance, not a
|
|
54
|
+
* registration call into machinery you have to go read. The regexes cover the
|
|
55
|
+
* naming conventions kinds usually arrive with; replace them with an explicit
|
|
56
|
+
* `Record<string, ArtifactForm>` the moment your vocabulary is closed enough to
|
|
57
|
+
* enumerate, which is strictly better than pattern-matching once you can.
|
|
58
|
+
*
|
|
59
|
+
* Prose is the default because it is the only form that cannot mislead: text
|
|
60
|
+
* rendered as text is always honest, whereas a non-tabular payload forced into
|
|
61
|
+
* a grid silently shifts cells into the wrong columns.
|
|
62
|
+
*/
|
|
63
|
+
export declare function artifactForm(kind: string): ArtifactForm;
|
|
64
|
+
/**
|
|
65
|
+
* "sales-one-pager" → "Sales one pager".
|
|
66
|
+
*
|
|
67
|
+
* Derived rather than looked up: a hand-maintained label map goes stale the
|
|
68
|
+
* first time a producer ships a kind nobody told the UI about, and an unlabelled
|
|
69
|
+
* tile is worse than a mechanically-titled one. Pass your own labels through
|
|
70
|
+
* the `kindLabel` prop where a surface offers it if you need better copy.
|
|
71
|
+
*/
|
|
72
|
+
export declare function artifactKindLabel(kind: string): string;
|
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
],
|
|
22
|
+
[
|
|
23
|
+
/(^|-)deck(-|$)|(^|-)presentation(-|$)|(^|-)slides(-|$)|(^|-)embed(-|$)/,
|
|
24
|
+
"embed"
|
|
25
|
+
],
|
|
26
|
+
[
|
|
27
|
+
/(^|-)image(-|$)|(^|-)photo(-|$)|(^|-)screenshot(-|$)/,
|
|
28
|
+
"image"
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
/(^|-)file(-|$)|(^|-)upload(-|$)|(^|-)binary(-|$)/,
|
|
32
|
+
"download"
|
|
33
|
+
]
|
|
34
|
+
];
|
|
35
|
+
/**
|
|
36
|
+
* Guesses a form from a kind string, defaulting to prose.
|
|
37
|
+
*
|
|
38
|
+
* **This is the function you edit.** It is a plain lookup, not a plugin
|
|
39
|
+
* registry, precisely because you own this file once `shadcn add` copies it —
|
|
40
|
+
* adding a kind should be one line here, readable at a glance, not a
|
|
41
|
+
* registration call into machinery you have to go read. The regexes cover the
|
|
42
|
+
* naming conventions kinds usually arrive with; replace them with an explicit
|
|
43
|
+
* `Record<string, ArtifactForm>` the moment your vocabulary is closed enough to
|
|
44
|
+
* enumerate, which is strictly better than pattern-matching once you can.
|
|
45
|
+
*
|
|
46
|
+
* Prose is the default because it is the only form that cannot mislead: text
|
|
47
|
+
* rendered as text is always honest, whereas a non-tabular payload forced into
|
|
48
|
+
* a grid silently shifts cells into the wrong columns.
|
|
49
|
+
*/ export function artifactForm(kind) {
|
|
50
|
+
const normalized = kind.trim().toLowerCase();
|
|
51
|
+
for (const [pattern, form] of FORM_BY_SUFFIX){
|
|
52
|
+
if (pattern.test(normalized)) return form;
|
|
53
|
+
}
|
|
54
|
+
return "prose";
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* "sales-one-pager" → "Sales one pager".
|
|
58
|
+
*
|
|
59
|
+
* Derived rather than looked up: a hand-maintained label map goes stale the
|
|
60
|
+
* first time a producer ships a kind nobody told the UI about, and an unlabelled
|
|
61
|
+
* tile is worse than a mechanically-titled one. Pass your own labels through
|
|
62
|
+
* the `kindLabel` prop where a surface offers it if you need better copy.
|
|
63
|
+
*/ export function artifactKindLabel(kind) {
|
|
64
|
+
const words = kind.trim().replace(/[_-]+/g, " ").replace(/\s+/g, " ");
|
|
65
|
+
if (words === "") return "Artifact";
|
|
66
|
+
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
67
|
+
}
|