@columenlabs/lumen-ui 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +12 -0
  3. package/README.md +4 -2
  4. package/dist/add-column.d.ts +23 -0
  5. package/dist/add-column.js +62 -0
  6. package/dist/api-fetch.d.ts +9 -0
  7. package/dist/api-fetch.js +60 -0
  8. package/dist/app-switcher.d.ts +21 -0
  9. package/dist/app-switcher.js +12 -0
  10. package/dist/app-views.d.ts +18 -0
  11. package/dist/app-views.js +41 -0
  12. package/dist/assistant-context.d.ts +72 -0
  13. package/dist/assistant-context.js +30 -0
  14. package/dist/assistant-panel.d.ts +58 -0
  15. package/dist/assistant-panel.js +244 -0
  16. package/dist/assistant-screen.d.ts +124 -0
  17. package/dist/assistant-screen.js +252 -0
  18. package/dist/card-switch.d.ts +16 -0
  19. package/dist/card-switch.js +16 -0
  20. package/dist/color-dot.d.ts +14 -0
  21. package/dist/color-dot.js +19 -0
  22. package/dist/confirm.d.ts +18 -0
  23. package/dist/confirm.js +5 -0
  24. package/dist/connections.d.ts +45 -0
  25. package/dist/connections.js +275 -0
  26. package/dist/coverage-calendar-map.d.ts +27 -0
  27. package/dist/coverage-calendar-map.js +84 -0
  28. package/dist/coverage-cells.d.ts +55 -0
  29. package/dist/coverage-cells.js +85 -0
  30. package/dist/coverage-map.d.ts +112 -0
  31. package/dist/coverage-map.js +428 -0
  32. package/dist/details-table.d.ts +20 -0
  33. package/dist/details-table.js +13 -0
  34. package/dist/drawer-section.d.ts +27 -0
  35. package/dist/drawer-section.js +23 -0
  36. package/dist/floating-head.d.ts +2 -0
  37. package/dist/floating-head.js +57 -0
  38. package/dist/fold.d.ts +16 -0
  39. package/dist/fold.js +70 -0
  40. package/dist/form-issues.d.ts +32 -0
  41. package/dist/form-issues.js +60 -0
  42. package/dist/formula-input.d.ts +17 -0
  43. package/dist/formula-input.js +104 -0
  44. package/dist/frame-script.d.ts +7 -0
  45. package/dist/frame-script.js +103 -0
  46. package/dist/freshness.d.ts +24 -0
  47. package/dist/freshness.js +99 -0
  48. package/dist/group-button.d.ts +33 -0
  49. package/dist/group-button.js +67 -0
  50. package/dist/growth-chart.d.ts +77 -0
  51. package/dist/growth-chart.js +195 -0
  52. package/dist/hooks/use-keyboard-fit.d.ts +15 -0
  53. package/dist/hooks/use-keyboard-fit.js +29 -0
  54. package/dist/hooks/use-mobile.d.ts +1 -0
  55. package/dist/hooks/use-mobile.js +15 -0
  56. package/dist/icon-button.d.ts +21 -0
  57. package/dist/icon-button.js +22 -0
  58. package/dist/icon-picker.d.ts +14 -0
  59. package/dist/icon-picker.js +36 -0
  60. package/dist/index.d.ts +83 -0
  61. package/dist/index.js +90 -0
  62. package/dist/integrations.d.ts +57 -0
  63. package/dist/integrations.js +73 -0
  64. package/dist/joins.d.ts +128 -0
  65. package/dist/joins.js +767 -0
  66. package/dist/kit-config.d.ts +13 -0
  67. package/dist/kit-config.js +15 -0
  68. package/dist/lib/utils.d.ts +2 -0
  69. package/dist/lib/utils.js +5 -0
  70. package/dist/lumen-boundary.d.ts +7 -0
  71. package/dist/lumen-boundary.js +10 -0
  72. package/dist/lumen-code-editor-impl.d.ts +2 -0
  73. package/dist/lumen-code-editor-impl.js +16 -0
  74. package/dist/lumen-code-editor.d.ts +11 -0
  75. package/dist/lumen-code-editor.js +11 -0
  76. package/dist/lumen-code.d.ts +22 -0
  77. package/dist/lumen-code.js +75 -0
  78. package/dist/lumen-drawer.d.ts +30 -0
  79. package/dist/lumen-drawer.js +27 -0
  80. package/dist/lumen-echart.d.ts +58 -0
  81. package/dist/lumen-echart.js +129 -0
  82. package/dist/lumen-filter.d.ts +75 -0
  83. package/dist/lumen-filter.js +546 -0
  84. package/dist/lumen-finder.d.ts +62 -0
  85. package/dist/lumen-finder.js +275 -0
  86. package/dist/lumen-form.d.ts +34 -0
  87. package/dist/lumen-form.js +81 -0
  88. package/dist/lumen-geo-map.d.ts +9 -0
  89. package/dist/lumen-geo-map.js +135 -0
  90. package/dist/lumen-grid.d.ts +49 -0
  91. package/dist/lumen-grid.js +203 -0
  92. package/dist/lumen-layout.d.ts +150 -0
  93. package/dist/lumen-layout.js +658 -0
  94. package/dist/lumen-links.d.ts +96 -0
  95. package/dist/lumen-links.js +213 -0
  96. package/dist/lumen-page-state.d.ts +20 -0
  97. package/dist/lumen-page-state.js +15 -0
  98. package/dist/lumen-selector.d.ts +139 -0
  99. package/dist/lumen-selector.js +308 -0
  100. package/dist/lumen-source.d.ts +137 -0
  101. package/dist/lumen-source.js +327 -0
  102. package/dist/lumen-tab-drawer.d.ts +27 -0
  103. package/dist/lumen-tab-drawer.js +26 -0
  104. package/dist/lumen-tabs.d.ts +21 -0
  105. package/dist/lumen-tabs.js +6 -0
  106. package/dist/lumen-toast.d.ts +11 -0
  107. package/dist/lumen-toast.js +16 -0
  108. package/dist/lumen-trend.d.ts +18 -0
  109. package/dist/lumen-trend.js +157 -0
  110. package/dist/lumen-view-card.d.ts +35 -0
  111. package/dist/lumen-view-card.js +50 -0
  112. package/dist/lumen-view.d.ts +172 -0
  113. package/dist/lumen-view.js +645 -0
  114. package/dist/lumen-widget-charts.d.ts +57 -0
  115. package/dist/lumen-widget-charts.js +69 -0
  116. package/dist/lumen-widget.d.ts +614 -0
  117. package/dist/lumen-widget.js +594 -0
  118. package/dist/market/compare-chart.d.ts +34 -0
  119. package/dist/market/compare-chart.js +292 -0
  120. package/dist/market/indicator-picker.d.ts +29 -0
  121. package/dist/market/indicator-picker.js +125 -0
  122. package/dist/market/indicators.d.ts +63 -0
  123. package/dist/market/indicators.js +314 -0
  124. package/dist/market/live.d.ts +120 -0
  125. package/dist/market/live.js +444 -0
  126. package/dist/market/lumen-chart.d.ts +88 -0
  127. package/dist/market/lumen-chart.js +645 -0
  128. package/dist/market/market-widget.d.ts +45 -0
  129. package/dist/market/market-widget.js +346 -0
  130. package/dist/market/option-chain.d.ts +19 -0
  131. package/dist/market/option-chain.js +53 -0
  132. package/dist/market/price-chart.d.ts +128 -0
  133. package/dist/market/price-chart.js +619 -0
  134. package/dist/mcp-settings.d.ts +20 -0
  135. package/dist/mcp-settings.js +65 -0
  136. package/dist/nav.d.ts +77 -0
  137. package/dist/nav.js +73 -0
  138. package/dist/note-line.d.ts +13 -0
  139. package/dist/note-line.js +5 -0
  140. package/dist/notifications.d.ts +9 -0
  141. package/dist/notifications.js +166 -0
  142. package/dist/origin-legend.d.ts +14 -0
  143. package/dist/origin-legend.js +38 -0
  144. package/dist/overview.d.ts +84 -0
  145. package/dist/overview.js +105 -0
  146. package/dist/page-inputs.d.ts +14 -0
  147. package/dist/page-inputs.js +16 -0
  148. package/dist/page.d.ts +32 -0
  149. package/dist/page.js +45 -0
  150. package/dist/pager.d.ts +10 -0
  151. package/dist/pager.js +14 -0
  152. package/dist/prefs.d.ts +71 -0
  153. package/dist/prefs.js +126 -0
  154. package/dist/query-client.d.ts +7 -0
  155. package/dist/query-client.js +19 -0
  156. package/dist/refresh.d.ts +4 -0
  157. package/dist/refresh.js +19 -0
  158. package/dist/rename-field.d.ts +11 -0
  159. package/dist/rename-field.js +26 -0
  160. package/dist/reset-button.d.ts +9 -0
  161. package/dist/reset-button.js +10 -0
  162. package/dist/route-error.d.ts +42 -0
  163. package/dist/route-error.js +229 -0
  164. package/dist/schedules.d.ts +88 -0
  165. package/dist/schedules.js +221 -0
  166. package/dist/settings.d.ts +51 -0
  167. package/dist/settings.js +181 -0
  168. package/dist/shell.d.ts +99 -0
  169. package/dist/shell.js +137 -0
  170. package/dist/source-health.d.ts +12 -0
  171. package/dist/source-health.js +58 -0
  172. package/dist/spotlight.d.ts +23 -0
  173. package/dist/spotlight.js +138 -0
  174. package/dist/status-health.d.ts +16 -0
  175. package/dist/status-health.js +41 -0
  176. package/dist/status.d.ts +9 -0
  177. package/dist/status.js +12 -0
  178. package/dist/summary-cards.d.ts +56 -0
  179. package/dist/summary-cards.js +270 -0
  180. package/dist/symbol-sheet-context.d.ts +4 -0
  181. package/dist/symbol-sheet-context.js +5 -0
  182. package/dist/symbol-sheet.d.ts +9 -0
  183. package/dist/symbol-sheet.js +24 -0
  184. package/dist/tasks.d.ts +29 -0
  185. package/dist/tasks.js +278 -0
  186. package/dist/theme.css +606 -0
  187. package/dist/tile.d.ts +37 -0
  188. package/dist/tile.js +23 -0
  189. package/dist/ui/alert-dialog.d.ts +18 -0
  190. package/dist/ui/alert-dialog.js +41 -0
  191. package/dist/ui/alert.d.ts +10 -0
  192. package/dist/ui/alert.js +27 -0
  193. package/dist/ui/avatar.d.ts +11 -0
  194. package/dist/ui/avatar.js +22 -0
  195. package/dist/ui/badge.d.ts +9 -0
  196. package/dist/ui/badge.js +27 -0
  197. package/dist/ui/breadcrumb.d.ts +11 -0
  198. package/dist/ui/breadcrumb.js +27 -0
  199. package/dist/ui/button-group.d.ts +11 -0
  200. package/dist/ui/button-group.js +27 -0
  201. package/dist/ui/button.d.ts +10 -0
  202. package/dist/ui/button.js +38 -0
  203. package/dist/ui/card.d.ts +11 -0
  204. package/dist/ui/card.js +24 -0
  205. package/dist/ui/chart.d.ts +44 -0
  206. package/dist/ui/chart.js +117 -0
  207. package/dist/ui/checkbox.d.ts +4 -0
  208. package/dist/ui/checkbox.js +8 -0
  209. package/dist/ui/collapsible.d.ts +5 -0
  210. package/dist/ui/collapsible.js +12 -0
  211. package/dist/ui/combobox.d.ts +24 -0
  212. package/dist/ui/combobox.js +60 -0
  213. package/dist/ui/command.d.ts +18 -0
  214. package/dist/ui/command.js +34 -0
  215. package/dist/ui/dialog.d.ts +23 -0
  216. package/dist/ui/dialog.js +50 -0
  217. package/dist/ui/dropdown-menu.d.ts +29 -0
  218. package/dist/ui/dropdown-menu.js +50 -0
  219. package/dist/ui/emoji-picker.d.ts +6 -0
  220. package/dist/ui/emoji-picker.js +28 -0
  221. package/dist/ui/empty.d.ts +11 -0
  222. package/dist/ui/empty.js +33 -0
  223. package/dist/ui/field.d.ts +24 -0
  224. package/dist/ui/field.js +65 -0
  225. package/dist/ui/hover-card.d.ts +6 -0
  226. package/dist/ui/hover-card.js +13 -0
  227. package/dist/ui/input-group.d.ts +16 -0
  228. package/dist/ui/input-group.js +56 -0
  229. package/dist/ui/input.d.ts +3 -0
  230. package/dist/ui/input.js +6 -0
  231. package/dist/ui/item.d.ts +23 -0
  232. package/dist/ui/item.js +67 -0
  233. package/dist/ui/kbd.d.ts +3 -0
  234. package/dist/ui/kbd.js +9 -0
  235. package/dist/ui/label.d.ts +4 -0
  236. package/dist/ui/label.js +7 -0
  237. package/dist/ui/popover.d.ts +10 -0
  238. package/dist/ui/popover.js +25 -0
  239. package/dist/ui/progress.d.ts +4 -0
  240. package/dist/ui/progress.js +9 -0
  241. package/dist/ui/resizable.d.ts +7 -0
  242. package/dist/ui/resizable.js +13 -0
  243. package/dist/ui/scroll-area.d.ts +5 -0
  244. package/dist/ui/scroll-area.js +10 -0
  245. package/dist/ui/select.d.ts +15 -0
  246. package/dist/ui/select.js +36 -0
  247. package/dist/ui/separator.d.ts +4 -0
  248. package/dist/ui/separator.js +7 -0
  249. package/dist/ui/sheet.d.ts +14 -0
  250. package/dist/ui/sheet.js +54 -0
  251. package/dist/ui/sidebar.d.ts +69 -0
  252. package/dist/ui/sidebar.js +206 -0
  253. package/dist/ui/skeleton.d.ts +2 -0
  254. package/dist/ui/skeleton.js +6 -0
  255. package/dist/ui/slider.d.ts +4 -0
  256. package/dist/ui/slider.js +9 -0
  257. package/dist/ui/sonner.d.ts +3 -0
  258. package/dist/ui/sonner.js +24 -0
  259. package/dist/ui/spinner.d.ts +2 -0
  260. package/dist/ui/spinner.js +7 -0
  261. package/dist/ui/switch.d.ts +6 -0
  262. package/dist/ui/switch.js +7 -0
  263. package/dist/ui/table.d.ts +10 -0
  264. package/dist/ui/table.js +31 -0
  265. package/dist/ui/tabs.d.ts +7 -0
  266. package/dist/ui/tabs.js +22 -0
  267. package/dist/ui/textarea.d.ts +3 -0
  268. package/dist/ui/textarea.js +6 -0
  269. package/dist/ui/toggle-group.d.ts +10 -0
  270. package/dist/ui/toggle-group.js +22 -0
  271. package/dist/ui/toggle.d.ts +9 -0
  272. package/dist/ui/toggle.js +25 -0
  273. package/dist/ui/tooltip.d.ts +7 -0
  274. package/dist/ui/tooltip.js +16 -0
  275. package/dist/view-edit-cell.d.ts +49 -0
  276. package/dist/view-edit-cell.js +198 -0
  277. package/dist/view-editor.d.ts +52 -0
  278. package/dist/view-editor.js +940 -0
  279. package/dist/view-formulas.d.ts +61 -0
  280. package/dist/view-formulas.js +247 -0
  281. package/dist/view-icons.d.ts +20 -0
  282. package/dist/view-icons.js +70 -0
  283. package/dist/view-model.d.ts +390 -0
  284. package/dist/view-model.js +316 -0
  285. package/dist/whats-new.d.ts +3 -0
  286. package/dist/whats-new.js +53 -0
  287. package/dist/widget-controls.d.ts +9 -0
  288. package/dist/widget-controls.js +26 -0
  289. package/dist/widget-settings.d.ts +436 -0
  290. package/dist/widget-settings.js +290 -0
  291. package/dist/widget-thumbs.d.ts +3 -0
  292. package/dist/widget-thumbs.js +29 -0
  293. package/dist/workspace-keys.d.ts +12 -0
  294. package/dist/workspace-keys.js +13 -0
  295. package/dist/workspaces.d.ts +57 -0
  296. package/dist/workspaces.js +473 -0
  297. package/package.json +82 -4
@@ -0,0 +1,198 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // An editable text cell: click the value, pick one already in use or type a
3
+ // new one, or clear it. Saves at once through the field's `edit`. Clicks stay off the row, which
4
+ // opens its details.
5
+ import { PencilLineIcon, PlusIcon, XIcon } from 'lucide-react';
6
+ import { useEffect, useRef, useState } from 'react';
7
+ import { ColorChip, colorIcon } from './color-dot.js';
8
+ import { cn } from './lib/utils.js';
9
+ import { LumenSelector } from './lumen-selector.js';
10
+ import { Input } from './ui/input.js';
11
+ const CLEAR = '\u0000clear';
12
+ export function EditCell({ label, value, options, unused = [], chip, note, colorOf, fixed = false, edited = false, onSave, }) {
13
+ const [open, setOpen] = useState(false);
14
+ const [error, setError] = useState(null);
15
+ const [saving, setSaving] = useState(false);
16
+ // A pick keeps the list open until the save lands, so a failure shows in it.
17
+ const picking = useRef(false);
18
+ const stop = (e) => e.stopPropagation();
19
+ const save = async (v) => {
20
+ if (saving)
21
+ return;
22
+ setSaving(true);
23
+ setError(null);
24
+ try {
25
+ await onSave(v);
26
+ setOpen(false);
27
+ }
28
+ catch (e) {
29
+ setError(e instanceof Error ? e.message : String(e));
30
+ }
31
+ finally {
32
+ picking.current = false;
33
+ setSaving(false);
34
+ }
35
+ };
36
+ const row = (o) => {
37
+ const c = colorOf?.(o);
38
+ return { value: o, label: o, ...(c ? { icon: colorIcon(c) } : {}) };
39
+ };
40
+ const groups = [
41
+ { label: 'In use', options: options.map(row) },
42
+ { label: 'Unused', options: unused.map(row) },
43
+ ...(value !== null
44
+ ? [
45
+ {
46
+ label: '',
47
+ options: [{ value: CLEAR, label: `Clear ${label.toLowerCase()}`, icon: XIcon }],
48
+ },
49
+ ]
50
+ : []),
51
+ ];
52
+ return (_jsxs("span", { className: edited ? 'inline-flex items-center gap-1' : 'contents', onClick: stop, onKeyDown: stop, children: [_jsx(LumenSelector, { trigger: value === null ? 'icon' : chip ? 'chip' : 'field', icon: value === null ? PlusIcon : undefined, size: "sm", label: value === null ? `Set ${label}` : `${label}: ${value}`, className: value === null
53
+ ? '-ml-1 size-6 text-muted-foreground'
54
+ : chip
55
+ ? 'h-6 border-0 bg-secondary px-2 text-xs font-normal text-secondary-foreground dark:bg-secondary'
56
+ : '-ml-1.5 h-6 border-0 bg-transparent px-1.5 font-normal text-sm dark:bg-transparent', groups: groups, value: value, empty: fixed ? 'No match.' : `Type a ${label.toLowerCase()} name.`, create: fixed ? undefined : (q) => q.trim() || null, createLabel: fixed ? undefined : (q) => `Set “${q.trim()}”`, open: open, onOpenChange: (o) => {
57
+ if (!o && picking.current)
58
+ return;
59
+ setOpen(o);
60
+ if (!o)
61
+ setError(null);
62
+ }, onChange: (v) => {
63
+ picking.current = true;
64
+ void save(v === CLEAR ? null : v);
65
+ }, header: (note || error) && (_jsx("p", { role: error ? 'alert' : undefined, className: cn('border-b px-3 py-2 text-xs', error ? 'text-destructive' : 'text-muted-foreground'), children: error ?? note })) }), edited && (_jsx(PencilLineIcon, { "aria-label": "Edited by hand", className: "size-3 shrink-0 text-muted-foreground/70" }))] }));
66
+ }
67
+ /**
68
+ * A cell of several values (labels): each shows as a chip with its colour;
69
+ * a tap opens a picker that ticks any number and takes a typed name, and closing it saves them all
70
+ * at once. Clicks stay off the row, which opens its details.
71
+ */
72
+ export function EditManyCell({ label, values, options, unused = [], note, colorOf, onSave, }) {
73
+ const [open, setOpen] = useState(false);
74
+ const [draft, setDraft] = useState(values);
75
+ const [error, setError] = useState(null);
76
+ const [saving, setSaving] = useState(false);
77
+ const stop = (e) => e.stopPropagation();
78
+ const start = () => {
79
+ setDraft(values);
80
+ setError(null);
81
+ setOpen(true);
82
+ };
83
+ const close = async () => {
84
+ const same = draft.length === values.length && draft.every((v) => values.includes(v));
85
+ if (same)
86
+ return setOpen(false);
87
+ setSaving(true);
88
+ try {
89
+ await onSave(draft);
90
+ setOpen(false);
91
+ }
92
+ catch (e) {
93
+ // The list stays open with why, so the picks are not lost.
94
+ setError(e instanceof Error ? e.message : String(e));
95
+ }
96
+ finally {
97
+ setSaving(false);
98
+ }
99
+ };
100
+ const row = (o) => {
101
+ const c = colorOf?.(o);
102
+ return { value: o, label: o, ...(c ? { icon: colorIcon(c) } : {}) };
103
+ };
104
+ const all = [...options, ...unused];
105
+ const picked = draft.filter((v) => !all.includes(v));
106
+ const groups = [
107
+ { label: 'In use', options: [...options, ...picked].map(row) },
108
+ { label: 'Unused', options: unused.map(row) },
109
+ ];
110
+ return (_jsxs("span", { className: "inline-flex min-w-0 items-center gap-1", onClick: stop, onKeyDown: stop, children: [values.length > 0 && (_jsx("button", { type: "button", "aria-label": `${label}: ${values.join(', ')}`, className: "flex min-w-0 flex-wrap items-center gap-1 rounded text-left", onClick: start, children: values.map((v) => (_jsx(ColorChip, { color: colorOf?.(v), children: v }, v))) })), _jsx(LumenSelector, { multiple: true, trigger: "icon", icon: values.length ? PencilLineIcon : PlusIcon, size: "sm", label: values.length ? `Change ${label.toLowerCase()}` : `Add ${label.toLowerCase()}`, className: cn('size-6 text-muted-foreground', values.length
111
+ ? 'opacity-0 group-hover/row:opacity-100 focus-visible:opacity-100 max-md:opacity-100'
112
+ : '-ml-1'), groups: groups, value: draft, disabled: saving, empty: `Type a ${label.toLowerCase()} name.`, create: (q) => q.trim() || null, createLabel: (q) => `Add “${q.trim()}”`, open: open, onOpenChange: (o) => {
113
+ if (o)
114
+ start();
115
+ else
116
+ void close();
117
+ }, onChange: setDraft, header: (note || error) && (_jsx("p", { role: error ? 'alert' : undefined, className: cn('border-b px-3 py-2 text-xs', error ? 'text-destructive' : 'text-muted-foreground'), children: error ?? note })) })] }));
118
+ }
119
+ /**
120
+ * A cell typed in place (Edits in place), as in a sheet: a click or tap turns
121
+ * the value into a box, Enter saves, Esc leaves it, Tab saves and moves to the next editable cell
122
+ * on the row, and so does clicking away. A cell the person typed carries a small ✎.
123
+ */
124
+ export function EditInputCell({ label, value, type, edited = false, children, onSave, }) {
125
+ const [open, setOpen] = useState(false);
126
+ const [text, setText] = useState('');
127
+ const [error, setError] = useState(null);
128
+ const [saving, setSaving] = useState(false);
129
+ const box = useRef(null);
130
+ const stop = (e) => e.stopPropagation();
131
+ const start = () => {
132
+ setText(value === null ? '' : String(value));
133
+ setError(null);
134
+ setOpen(true);
135
+ };
136
+ useEffect(() => {
137
+ if (open)
138
+ box.current?.select();
139
+ }, [open]);
140
+ const save = async (then) => {
141
+ const next = text.trim() === '' ? null : text.trim();
142
+ const same = (next ?? '') === (value === null ? '' : String(value));
143
+ if (same || saving) {
144
+ setOpen(false);
145
+ if (then)
146
+ moveRight(box.current);
147
+ return;
148
+ }
149
+ setSaving(true);
150
+ try {
151
+ await onSave(next);
152
+ setOpen(false);
153
+ if (then)
154
+ moveRight(box.current);
155
+ }
156
+ catch (e) {
157
+ setError(e instanceof Error ? e.message : String(e));
158
+ box.current?.focus();
159
+ }
160
+ finally {
161
+ setSaving(false);
162
+ }
163
+ };
164
+ if (!open)
165
+ return (_jsxs("button", { type: "button", "data-edit-cell": true, "aria-label": `Edit ${label}`, className: cn('group/cell inline-flex min-h-6 min-w-8 cursor-text items-center gap-1 rounded px-1 -mx-1 text-left hover:bg-muted/60 focus-visible:bg-muted/60 focus-visible:outline-none', value === null && 'text-muted-foreground/60'), onClick: (e) => {
166
+ stop(e);
167
+ start();
168
+ }, onKeyDown: (e) => {
169
+ stop(e);
170
+ if (e.key === 'Enter' || e.key === 'F2')
171
+ start();
172
+ }, children: [_jsx("span", { className: "min-w-0", children: value === null ? '—' : children }), edited && (_jsx(PencilLineIcon, { "aria-label": "Edited by hand", className: "size-3 shrink-0 text-muted-foreground/70" }))] }));
173
+ return (_jsx("span", { className: "contents", onClick: stop, onKeyDown: stop, children: _jsx(Input, { ref: box, "data-edit-cell": true, "aria-label": label, "aria-invalid": error ? true : undefined, title: error ?? undefined, inputMode: type === 'number' ? 'decimal' : 'text', value: text, disabled: saving, onChange: (e) => setText(e.target.value), onBlur: () => void save(), onKeyDown: (e) => {
174
+ if (e.key === 'Enter') {
175
+ e.preventDefault();
176
+ void save();
177
+ }
178
+ else if (e.key === 'Escape') {
179
+ e.preventDefault();
180
+ setOpen(false);
181
+ }
182
+ else if (e.key === 'Tab') {
183
+ e.preventDefault();
184
+ void save('next');
185
+ }
186
+ }, className: cn('h-6 w-24 min-w-16 max-w-48 px-1.5 -mx-1 font-[inherit] text-sm', type === 'number' && 'num text-right', error && 'border-destructive') }) }));
187
+ }
188
+ /** Focuses the next editable cell after `from` on its row, else the first on the row below. */
189
+ function moveRight(from) {
190
+ const row = from?.closest('tr');
191
+ if (!row)
192
+ return;
193
+ const cells = [...row.querySelectorAll('[data-edit-cell]')];
194
+ const i = cells.indexOf(from);
195
+ const next = cells[i + 1] ?? row.nextElementSibling?.querySelector('[data-edit-cell]');
196
+ // The box unmounts on save; its button takes its place on the next frame.
197
+ requestAnimationFrame(() => (next?.isConnected ? next : null)?.focus());
198
+ }
@@ -0,0 +1,52 @@
1
+ import { type CustomViewConfig, type ViewTile, type ViewWidget } from '@columenlabs/lumen-ui-types/views';
2
+ import { type LucideIcon } from 'lucide-react';
3
+ import { type ReactNode } from 'react';
4
+ import { type ConnectedDomain } from './connections.js';
5
+ import { type FilterField, type FilterToken } from './lumen-filter.js';
6
+ import { type ViewDomain } from './view-model.js';
7
+ /** An app's own section in the dialog (an explorer view's columns). */
8
+ export interface ViewEditorSection {
9
+ title: string;
10
+ icon: LucideIcon;
11
+ description?: string;
12
+ content: ReactNode;
13
+ }
14
+ export interface ViewEditDialogProps<T> {
15
+ open: boolean;
16
+ onOpenChange: (open: boolean) => void;
17
+ domain: ViewDomain<T>;
18
+ /** The view: its own table's layout, and the formulas every widget on it shares. */
19
+ config: CustomViewConfig;
20
+ /** The rows the page shows now (after its filters), for the previews. */
21
+ rows: T[];
22
+ /** The filter tokens on the page now, offered as the new defaults. */
23
+ current: FilterToken[];
24
+ /** Saves the view's own table (left out when `card` is edited). */
25
+ onSave?: (config: CustomViewConfig) => void;
26
+ /**
27
+ * Any other widget on the page (one editor for every widget): a second
28
+ * table, a number, a chart. Left out, the editor edits the view's own table.
29
+ */
30
+ card?: ViewWidget;
31
+ /** Saves `card` as edited (its type may have changed) with the view's formulas and links. */
32
+ onSaveCard?: (card: ViewWidget, view: Pick<CustomViewConfig, 'formulas' | 'connections' | 'frames'>) => void;
33
+ /** What each linked or linkable domain read (the app's `useJoins`), for Link in the tree. */
34
+ read?: Record<string, ConnectedDomain>;
35
+ /** The fields a widget's own filter reads. */
36
+ fields?: FilterField<T>[];
37
+ /** The view's own Summary cards, which a Summary without its own starts from. */
38
+ viewTiles?: ViewTile[];
39
+ viewId?: string;
40
+ editor?: ViewEditorSection;
41
+ onDuplicate?: () => void;
42
+ onDelete?: () => void;
43
+ }
44
+ /**
45
+ * Edit widget (one editor for every widget). The same two panes for every
46
+ * widget: on the left Widget (type, name, width, link colour), Fields (a table's columns, any other
47
+ * widget's slots), Settings (the type's own options), Rows, Formulas, Controls; on the right the
48
+ * field tree, which ticks a table's columns or fills a widget's slot. Picking another type swaps
49
+ * only Fields and Settings; a type tried and left comes back as it was. The view's own table stays
50
+ * a table.
51
+ */
52
+ export declare function ViewEditDialog<T>({ open, onOpenChange, domain: joined, config, rows, current, onSave, card, onSaveCard, fields: filterFields, viewTiles, read, viewId, editor, onDuplicate, onDelete, }: ViewEditDialogProps<T>): import("react").JSX.Element;