@ultimat3/ui 29.4.0 → 30.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.
Files changed (168) hide show
  1. package/CATALOG.md +491 -24
  2. package/CLAUDE.md +23 -16
  3. package/README.md +338 -33
  4. package/package.json +16 -5
  5. package/src/components/AppShell.module.scss +23 -7
  6. package/src/components/AppShell.tsx +9 -0
  7. package/src/components/BarChart.module.scss +26 -0
  8. package/src/components/BarChart.tsx +242 -93
  9. package/src/components/Board.module.scss +30 -0
  10. package/src/components/Board.tsx +47 -0
  11. package/src/components/BottomNav.module.scss +49 -0
  12. package/src/components/BottomNav.tsx +57 -0
  13. package/src/components/Calendar.module.scss +118 -0
  14. package/src/components/Calendar.tsx +246 -0
  15. package/src/components/ChartFrame.module.scss +40 -3
  16. package/src/components/ChartFrame.tsx +84 -28
  17. package/src/components/CodeBlock.module.scss +101 -0
  18. package/src/components/CodeBlock.tsx +76 -0
  19. package/src/components/CommandPalette.module.scss +25 -0
  20. package/src/components/CommandPalette.tsx +50 -22
  21. package/src/components/ConfirmDialog.module.scss +36 -0
  22. package/src/components/ConfirmDialog.tsx +188 -0
  23. package/src/components/DataTable.tsx +92 -33
  24. package/src/components/DatePicker.module.scss +37 -0
  25. package/src/components/DatePicker.tsx +134 -0
  26. package/src/components/DateRangePicker.module.scss +54 -0
  27. package/src/components/DateRangePicker.tsx +156 -0
  28. package/src/components/DescriptionList.module.scss +46 -0
  29. package/src/components/DescriptionList.tsx +38 -0
  30. package/src/components/DiffView.module.scss +124 -0
  31. package/src/components/DiffView.tsx +169 -0
  32. package/src/components/DonutChart.tsx +13 -4
  33. package/src/components/Drawer.module.scss +40 -0
  34. package/src/components/Drawer.tsx +56 -0
  35. package/src/components/Gauge.module.scss +8 -0
  36. package/src/components/Gauge.tsx +40 -13
  37. package/src/components/HeatStrip.module.scss +133 -0
  38. package/src/components/HeatStrip.tsx +64 -0
  39. package/src/components/JsonView.module.scss +64 -0
  40. package/src/components/JsonView.tsx +68 -0
  41. package/src/components/LineChart.tsx +45 -18
  42. package/src/components/LiveIndicator.module.scss +44 -0
  43. package/src/components/LiveIndicator.tsx +45 -0
  44. package/src/components/LogViewer.module.scss +102 -0
  45. package/src/components/LogViewer.tsx +123 -0
  46. package/src/components/Markdown.module.scss +87 -0
  47. package/src/components/Markdown.tsx +84 -0
  48. package/src/components/Meter.module.scss +7 -0
  49. package/src/components/Meter.tsx +16 -0
  50. package/src/components/NavList.module.scss +66 -0
  51. package/src/components/NavList.tsx +95 -0
  52. package/src/components/Pagination.module.scss +6 -2
  53. package/src/components/Pagination.tsx +57 -13
  54. package/src/components/Popover.tsx +12 -2
  55. package/src/components/PullToRefresh.module.scss +41 -0
  56. package/src/components/PullToRefresh.tsx +108 -0
  57. package/src/components/Radio.module.scss +51 -0
  58. package/src/components/Radio.tsx +12 -1
  59. package/src/components/SearchableSelect.module.scss +216 -0
  60. package/src/components/SearchableSelect.tsx +331 -0
  61. package/src/components/SearchableSelectChips.tsx +41 -0
  62. package/src/components/SearchableSelectNative.tsx +89 -0
  63. package/src/components/ShortcutSheet.module.scss +33 -0
  64. package/src/components/ShortcutSheet.tsx +67 -0
  65. package/src/components/Slider.module.scss +50 -0
  66. package/src/components/Slider.tsx +68 -0
  67. package/src/components/SortableList.module.scss +72 -0
  68. package/src/components/SortableList.tsx +42 -0
  69. package/src/components/Sparkline.module.scss +10 -2
  70. package/src/components/Sparkline.tsx +27 -10
  71. package/src/components/SplitPane.module.scss +39 -0
  72. package/src/components/SplitPane.tsx +96 -0
  73. package/src/components/StatTile.module.scss +29 -3
  74. package/src/components/StatTile.tsx +75 -16
  75. package/src/components/Stepper.module.scss +78 -0
  76. package/src/components/Stepper.tsx +73 -0
  77. package/src/components/Tabs.module.scss +13 -1
  78. package/src/components/Tabs.tsx +77 -1
  79. package/src/components/TerminalView.module.scss +68 -0
  80. package/src/components/TerminalView.tsx +97 -0
  81. package/src/components/TimeRangePicker.module.scss +85 -0
  82. package/src/components/TimeRangePicker.tsx +91 -0
  83. package/src/components/Timeline.module.scss +74 -0
  84. package/src/components/Timeline.tsx +60 -0
  85. package/src/components/Tree.module.scss +98 -0
  86. package/src/components/Tree.tsx +185 -0
  87. package/src/components/VirtualList.module.scss +60 -0
  88. package/src/components/VirtualList.tsx +251 -0
  89. package/src/components/app-shell-view.ts +4 -1
  90. package/src/components/bar-chart-view.ts +121 -39
  91. package/src/components/board-view.ts +25 -0
  92. package/src/components/bottom-nav-view.ts +18 -0
  93. package/src/components/calendar-view.ts +226 -0
  94. package/src/components/chart-checks.ts +59 -0
  95. package/src/components/chart-frame-view.ts +33 -2
  96. package/src/components/chart-reference-view.ts +41 -0
  97. package/src/components/command-palette-view.ts +47 -6
  98. package/src/components/confirm-dialog-view.ts +47 -0
  99. package/src/components/data-table-rows.ts +93 -0
  100. package/src/components/date-picker-view.ts +38 -0
  101. package/src/components/date-range-view.ts +46 -0
  102. package/src/components/diff-view-view.ts +85 -0
  103. package/src/components/drawer-gesture-view.ts +33 -0
  104. package/src/components/gauge-view.ts +29 -0
  105. package/src/components/heat-strip-view.ts +68 -0
  106. package/src/components/json-view-view.ts +54 -0
  107. package/src/components/line-chart-view.ts +87 -25
  108. package/src/components/log-viewer-view.ts +51 -0
  109. package/src/components/markdown-nodes.tsx +150 -0
  110. package/src/components/nav-list-view.ts +37 -0
  111. package/src/components/pull-refresh-view.ts +93 -0
  112. package/src/components/rank-options.ts +61 -0
  113. package/src/components/searchable-select-keys.ts +118 -0
  114. package/src/components/searchable-select-view.ts +187 -0
  115. package/src/components/slider-view.ts +47 -0
  116. package/src/components/sort-pointer.ts +141 -0
  117. package/src/components/sort-surface.tsx +231 -0
  118. package/src/components/sparkline-view.ts +74 -14
  119. package/src/components/split-pane-view.ts +69 -0
  120. package/src/components/stat-delta.ts +54 -11
  121. package/src/components/stepper-view.ts +38 -0
  122. package/src/components/thunk.ts +9 -0
  123. package/src/components/timeline-view.ts +29 -0
  124. package/src/components/tree-node.tsx +133 -0
  125. package/src/components/tree-view.ts +185 -0
  126. package/src/components/use-command-palette.ts +153 -0
  127. package/src/components/virtual-list-anchor.ts +35 -0
  128. package/src/components/virtual-list-observer.ts +58 -0
  129. package/src/components/virtual-list-view.ts +145 -0
  130. package/src/content/ansi.ts +144 -0
  131. package/src/content/heading-slug.ts +32 -0
  132. package/src/content/highlight.ts +129 -0
  133. package/src/content/languages/all.ts +21 -0
  134. package/src/content/languages/diff.ts +14 -0
  135. package/src/content/languages/html.ts +16 -0
  136. package/src/content/languages/json.ts +15 -0
  137. package/src/content/languages/shell.ts +20 -0
  138. package/src/content/languages/sql.ts +27 -0
  139. package/src/content/languages/ts.ts +26 -0
  140. package/src/content/languages/yaml.ts +18 -0
  141. package/src/content/line-diff.ts +191 -0
  142. package/src/content/markdown-inline.ts +368 -0
  143. package/src/content/markdown-parse.ts +267 -0
  144. package/src/content/markdown-tree.ts +58 -0
  145. package/src/content/unified-patch.ts +53 -0
  146. package/src/drag/pointer-drag.ts +185 -0
  147. package/src/drag/sort-controller.ts +196 -0
  148. package/src/drag/sort-view.ts +201 -0
  149. package/src/errors.ts +1 -1
  150. package/src/form/field-path.ts +7 -33
  151. package/src/form/form-binding.ts +5 -8
  152. package/src/form/form-issue.ts +30 -36
  153. package/src/form/form-values.ts +3 -2
  154. package/src/hotkeys-view.ts +150 -0
  155. package/src/i18n-keys.ts +7 -50
  156. package/src/index.ts +214 -15
  157. package/src/list-url.ts +123 -0
  158. package/src/live-window.ts +23 -0
  159. package/src/roving.ts +2 -0
  160. package/src/theme/inert-runtime.ts +4 -0
  161. package/src/theme/runtime-slot.ts +2 -2
  162. package/src/theme/solid-adapter.ts +11 -5
  163. package/src/time-range-url.ts +200 -0
  164. package/src/tokens/_mixins.scss +1 -1
  165. package/src/tokens/_touch.scss +30 -1
  166. package/src/tokens/contrast-pairs.ts +12 -0
  167. package/src/ui-keys.ts +126 -0
  168. package/src/use-hotkeys.ts +145 -0
package/src/index.ts CHANGED
@@ -60,28 +60,61 @@ export {
60
60
  } from './components/async-branch';
61
61
  export type { BadgeProps } from './components/Badge';
62
62
  export { Badge } from './components/Badge';
63
- export type { BarChartProps } from './components/BarChart';
63
+ export type {
64
+ BarChartPointsProps,
65
+ BarChartProps,
66
+ BarChartSeriesProps,
67
+ } from './components/BarChart';
64
68
  export { BarChart } from './components/BarChart';
69
+ export type { BoardColumn, BoardProps } from './components/Board';
70
+ export { Board } from './components/Board';
71
+ export type { BottomNavItem, BottomNavProps } from './components/BottomNav';
72
+ export { BottomNav } from './components/BottomNav';
65
73
  export type { BreadcrumbItem, BreadcrumbProps } from './components/Breadcrumb';
66
74
  export { Breadcrumb } from './components/Breadcrumb';
67
75
  export type { ButtonProps } from './components/Button';
68
76
  export { Button } from './components/Button';
69
- export type { BarRect, ChartPoint } from './components/bar-chart-view';
77
+ export type { BarExtent, BarRect, ChartPoint } from './components/bar-chart-view';
70
78
  export { barRects } from './components/bar-chart-view';
79
+ export { BOTTOM_NAV_MAX, bottomNavItems } from './components/bottom-nav-view';
80
+ export type {
81
+ CalendarLinkProps,
82
+ CalendarProps,
83
+ CalendarSelectProps,
84
+ } from './components/Calendar';
85
+ export { Calendar } from './components/Calendar';
71
86
  export type { CardProps, Elevation } from './components/Card';
72
87
  export { Card } from './components/Card';
73
88
  export type { ChartFrameProps, ChartLegendItem } from './components/ChartFrame';
74
89
  export { ChartFrame } from './components/ChartFrame';
75
90
  export type { CheckboxProps } from './components/Checkbox';
76
91
  export { Checkbox } from './components/Checkbox';
92
+ export type { CodeBlockProps } from './components/CodeBlock';
93
+ export { CodeBlock } from './components/CodeBlock';
77
94
  export type { ComboboxProps } from './components/Combobox';
78
95
  export { Combobox } from './components/Combobox';
79
96
  export type { CommandPaletteLabels, CommandPaletteProps } from './components/CommandPalette';
80
97
  export { CommandPalette } from './components/CommandPalette';
98
+ export type {
99
+ ConfirmDialogIslandProps,
100
+ ConfirmDialogPostProps,
101
+ ConfirmDialogProps,
102
+ } from './components/ConfirmDialog';
103
+ export { ConfirmDialog } from './components/ConfirmDialog';
81
104
  export type { ContainerProps, ContainerSize } from './components/Container';
82
105
  export { Container } from './components/Container';
83
106
  export type { CopyButtonProps } from './components/CopyButton';
84
107
  export { COPIED_MS, CopyButton } from './components/CopyButton';
108
+ export type { CalendarBounds, CalendarDay, StepOptions, Weekday } from './components/calendar-view';
109
+ export {
110
+ dayLabel,
111
+ monthGrid,
112
+ monthLabel,
113
+ rovingDay,
114
+ stepDay,
115
+ weekdayLabels,
116
+ weekStartOf,
117
+ } from './components/calendar-view';
85
118
  export type {
86
119
  ChartSeries,
87
120
  ChartTable,
@@ -91,17 +124,25 @@ export type {
91
124
  SeriesStyle,
92
125
  } from './components/chart-frame-view';
93
126
  export { CHART_SERIES_SLOTS, chartTable, seriesStyle } from './components/chart-frame-view';
127
+ export type { ChartReference } from './components/chart-reference-view';
94
128
  export type { NiceScale, NiceTicksOptions } from './components/chart-ticks-view';
95
129
  export { niceTicks } from './components/chart-ticks-view';
96
130
  export type { ComboboxOption } from './components/combobox-filter';
97
131
  export { filterOptions, normalizeQuery } from './components/combobox-filter';
98
- export type { CommandPaletteItem, PaletteKeyAction } from './components/command-palette-view';
132
+ export type {
133
+ CommandPaletteGroup,
134
+ CommandPaletteItem,
135
+ PaletteKeyAction,
136
+ } from './components/command-palette-view';
99
137
  export {
100
138
  filterItems,
139
+ groupItems,
101
140
  keyAction,
102
141
  settleActive,
103
142
  stepActive,
104
143
  } from './components/command-palette-view';
144
+ export type { ConfirmEvent, ConfirmState } from './components/confirm-dialog-view';
145
+ export { CONFIRM_IDLE, confirmLabelOf, confirmStep } from './components/confirm-dialog-view';
105
146
  export type {
106
147
  Column,
107
148
  DataTableCallbackProps,
@@ -110,10 +151,18 @@ export type {
110
151
  DataTableProps,
111
152
  } from './components/DataTable';
112
153
  export { DataTable } from './components/DataTable';
154
+ export type { DatePickerProps } from './components/DatePicker';
155
+ export { DatePicker } from './components/DatePicker';
156
+ export type { DateRangePickerProps } from './components/DateRangePicker';
157
+ export { DateRangePicker } from './components/DateRangePicker';
113
158
  export type { DateTimeProps } from './components/DateTime';
114
159
  export { DateTime } from './components/DateTime';
160
+ export type { DescriptionItem, DescriptionListProps } from './components/DescriptionList';
161
+ export { DescriptionList } from './components/DescriptionList';
115
162
  export type { DialogProps } from './components/Dialog';
116
163
  export { Dialog } from './components/Dialog';
164
+ export type { DiffViewPatchProps, DiffViewProps, DiffViewTextProps } from './components/DiffView';
165
+ export { DiffView } from './components/DiffView';
117
166
  export type { DividerProps } from './components/Divider';
118
167
  export { Divider } from './components/Divider';
119
168
  export type { DonutChartProps, DonutSegment } from './components/DonutChart';
@@ -123,6 +172,8 @@ export { Drawer } from './components/Drawer';
123
172
  export type { DropzoneProps } from './components/Dropzone';
124
173
  export { Dropzone } from './components/Dropzone';
125
174
  export type { ColumnPriority } from './components/data-table-view';
175
+ export type { DateRange, SpanPosition } from './components/date-range-view';
176
+ export { orderedRange, pickRange, spanPosition } from './components/date-range-view';
126
177
  export type {
127
178
  DateStyle,
128
179
  DateTimeFormatter,
@@ -131,6 +182,8 @@ export type {
131
182
  TimeInput,
132
183
  } from './components/date-time-view';
133
184
  export { dateTimeView, toDate, toInstant, toIsoInstant } from './components/date-time-view';
185
+ export type { DrawerRelease, DrawerSnap } from './components/drawer-gesture-view';
186
+ export { dragOffset, releaseSnap } from './components/drawer-gesture-view';
134
187
  export type { EmptyStateProps } from './components/EmptyState';
135
188
  export { EmptyState } from './components/EmptyState';
136
189
  export type { ErrorStateProps } from './components/ErrorState';
@@ -157,8 +210,12 @@ export type { GaugeProps } from './components/Gauge';
157
210
  export { Gauge } from './components/Gauge';
158
211
  export type { GridProps } from './components/Grid';
159
212
  export { Grid } from './components/Grid';
213
+ export type { GaugeThreshold } from './components/gauge-view';
214
+ export type { HeatStripProps } from './components/HeatStrip';
215
+ export { HeatStrip } from './components/HeatStrip';
160
216
  export type { HeadingLevel, HeadingTag } from './components/heading-level';
161
217
  export { HEADING_LEVELS, headingTag, nextHeadingLevel } from './components/heading-level';
218
+ export type { HeatCell, HeatRow, HeatShape } from './components/heat-strip-view';
162
219
  export type { IconProps } from './components/Icon';
163
220
  // --- icons: the glyphs themselves are per-icon modules, `@ultimat3/ui/icons/<name>` ---------
164
221
  export { Icon } from './components/Icon';
@@ -184,15 +241,25 @@ export type {
184
241
  } from './components/image-source';
185
242
  export { boxFor, reservedRatio, sourceSetsFor, variantSrcset } from './components/image-source';
186
243
  export type { LoadMoreInput, LoadMoreState } from './components/infinite-scroll-view';
244
+ export type { JsonViewProps } from './components/JsonView';
245
+ export { JsonView } from './components/JsonView';
187
246
  export type { KbdProps } from './components/Kbd';
188
247
  export { Kbd } from './components/Kbd';
189
248
  export type { AreaChartProps, LineChartProps } from './components/LineChart';
190
249
  export { AreaChart, LineChart } from './components/LineChart';
191
250
  export type { ButtonLinkProps, LinkProps, TextLinkProps } from './components/Link';
192
251
  export { Link } from './components/Link';
252
+ export type { LiveIndicatorProps, LiveIndicatorState } from './components/LiveIndicator';
253
+ export { LIVE_INDICATOR_STATES, LiveIndicator } from './components/LiveIndicator';
193
254
  export type { LocaleSwitcherProps } from './components/LocaleSwitcher';
194
255
  export { LocaleSwitcher, localeLabel } from './components/LocaleSwitcher';
256
+ export type { LogViewerProps } from './components/LogViewer';
257
+ export { LogViewer } from './components/LogViewer';
195
258
  export type { LinkTarget } from './components/link-target';
259
+ export type { LogLine, LogViewerLevel } from './components/log-viewer-view';
260
+ export { LOG_VIEWER_LEVELS } from './components/log-viewer-view';
261
+ export type { MarkdownProps, ResolvedImage } from './components/Markdown';
262
+ export { Markdown } from './components/Markdown';
196
263
  export type { MenuItem, MenuProps } from './components/Menu';
197
264
  export { Menu } from './components/Menu';
198
265
  export type { MeterProps } from './components/Meter';
@@ -202,6 +269,14 @@ export { Money } from './components/Money';
202
269
  export type { MoneyFormatter, MoneyInput, MoneyViewOptions } from './components/money-view';
203
270
  // --- formatting cores (pure, renderer-free) ----------------------------------
204
271
  export { moneyText, toMoney } from './components/money-view';
272
+ export type {
273
+ NavListEntry,
274
+ NavListGroup,
275
+ NavListLink,
276
+ NavListProps,
277
+ } from './components/NavList';
278
+ export { NavList } from './components/NavList';
279
+ export { currentOf } from './components/nav-list-view';
205
280
  export type { PageHeaderProps } from './components/PageHeader';
206
281
  export { PageHeader } from './components/PageHeader';
207
282
  export type {
@@ -212,6 +287,17 @@ export type {
212
287
  export { Pagination } from './components/Pagination';
213
288
  export type { Placement, PopoverProps } from './components/Popover';
214
289
  export { Popover } from './components/Popover';
290
+ export type { PullToRefreshProps } from './components/PullToRefresh';
291
+ export { PullToRefresh } from './components/PullToRefresh';
292
+ export type { PullController, PullEvent, PullState } from './components/pull-refresh-view';
293
+ export {
294
+ PULL_IDLE,
295
+ PULL_MAX,
296
+ PULL_THRESHOLD,
297
+ pullController,
298
+ pullDistance,
299
+ pullStep,
300
+ } from './components/pull-refresh-view';
215
301
  export type { QrCodeProps } from './components/QrCode';
216
302
  export { QrCode } from './components/QrCode';
217
303
  export type { QrMatrix } from './components/qr-matrix';
@@ -220,38 +306,78 @@ export type { RadioOption, RadioProps } from './components/Radio';
220
306
  export { Radio } from './components/Radio';
221
307
  export type { RelativeTimeProps } from './components/RelativeTime';
222
308
  export { RelativeTime } from './components/RelativeTime';
309
+ export type { RankableOption, RankedOptions } from './components/rank-options';
310
+ export { rankOptions } from './components/rank-options';
223
311
  export type { RelativeTimeOptions } from './components/relative-time-view';
312
+ export type {
313
+ SearchableSelectManyProps,
314
+ SearchableSelectOneProps,
315
+ SearchableSelectProps,
316
+ } from './components/SearchableSelect';
317
+ export { SearchableSelect } from './components/SearchableSelect';
224
318
  export type { SectionProps } from './components/Section';
225
319
  export { Section } from './components/Section';
226
320
  export type { SelectOption, SelectProps } from './components/Select';
227
321
  export { Select } from './components/Select';
322
+ export type { ShortcutSheetProps } from './components/ShortcutSheet';
323
+ export { ShortcutSheet } from './components/ShortcutSheet';
228
324
  export type { SkeletonProps } from './components/Skeleton';
229
325
  export { Skeleton } from './components/Skeleton';
326
+ export type { SliderProps } from './components/Slider';
327
+ export { Slider } from './components/Slider';
328
+ export type { SortableListProps } from './components/SortableList';
329
+ export { SortableList } from './components/SortableList';
230
330
  export type { SparklineProps } from './components/Sparkline';
231
331
  export { Sparkline } from './components/Sparkline';
232
332
  export type { SpinnerProps } from './components/Spinner';
233
333
  export { Spinner } from './components/Spinner';
334
+ export type { SplitPaneProps } from './components/SplitPane';
335
+ export { SplitPane } from './components/SplitPane';
234
336
  export type { StackProps } from './components/Stack';
235
337
  export { Stack } from './components/Stack';
236
338
  export type { StatTileProps } from './components/StatTile';
237
339
  export { StatTile } from './components/StatTile';
340
+ export type { StepperProps } from './components/Stepper';
341
+ export { Stepper } from './components/Stepper';
238
342
  export type { SwitchProps } from './components/Switch';
239
343
  export { Switch } from './components/Switch';
344
+ export type { SearchableOption } from './components/searchable-select-view';
240
345
  export type { SortDirection, SortState } from './components/sort-state';
241
- export type { SparkPoint } from './components/sparkline-view';
346
+ export type { SortFields } from './components/sort-surface';
347
+ export type { SparklinePoint, SparkPoint } from './components/sparkline-view';
242
348
  export { sparklinePath } from './components/sparkline-view';
243
- export type { StatDelta, StatTrend } from './components/stat-delta';
244
- export { deltaOf } from './components/stat-delta';
349
+ export type {
350
+ DeltaOptions,
351
+ StatDelta,
352
+ StatGoodWhen,
353
+ StatMood,
354
+ StatTrend,
355
+ } from './components/stat-delta';
356
+ export { deltaMood, deltaOf } from './components/stat-delta';
357
+ export type { StepperModel, StepperStep, StepState } from './components/stepper-view';
358
+ export { stepperModel } from './components/stepper-view';
245
359
  export type { TableProps } from './components/Table';
246
360
  export { Table } from './components/Table';
247
- export type { TabItem, TabsProps } from './components/Tabs';
361
+ export type {
362
+ TabItem,
363
+ TabLinkItem,
364
+ TabsButtonProps,
365
+ TabsLinkProps,
366
+ TabsProps,
367
+ } from './components/Tabs';
248
368
  export { Tabs } from './components/Tabs';
369
+ export type { TerminalViewProps } from './components/TerminalView';
370
+ export { TerminalView } from './components/TerminalView';
249
371
  export type { TextProps, TextSize, TextTone, TextWeight } from './components/Text';
250
372
  export { TEXT_TONES, Text } from './components/Text';
251
373
  export type { TextareaProps } from './components/Textarea';
252
374
  export { Textarea } from './components/Textarea';
253
375
  export type { ThemeChoice, ThemeToggleProps } from './components/ThemeToggle';
254
376
  export { ThemeToggle } from './components/ThemeToggle';
377
+ export type { TimelineItem, TimelineProps } from './components/Timeline';
378
+ export { Timeline } from './components/Timeline';
379
+ export type { TimeRangePickerProps } from './components/TimeRangePicker';
380
+ export { TimeRangePicker } from './components/TimeRangePicker';
255
381
  export type { ToastPlacement, ToastProps, ToastRegionProps } from './components/Toast';
256
382
  export { Toast, ToastRegion } from './components/Toast';
257
383
  export type { ToasterProps } from './components/Toaster';
@@ -260,14 +386,63 @@ export type { ToolbarProps } from './components/Toolbar';
260
386
  export { Toolbar } from './components/Toolbar';
261
387
  export type { TooltipProps } from './components/Tooltip';
262
388
  export { Tooltip } from './components/Tooltip';
389
+ export type { TreeLinkProps, TreeProps, TreeSelectProps } from './components/Tree';
390
+ export { Tree } from './components/Tree';
391
+ export type { TimelineGroup } from './components/timeline-view';
392
+ export { timelineGroups } from './components/timeline-view';
393
+ export type { FlatTreeNode, TreeMove, TreeNode } from './components/tree-view';
394
+ export {
395
+ flattenTree,
396
+ treeAncestors,
397
+ treeMove,
398
+ treeTypeahead,
399
+ visibleTreeIds,
400
+ } from './components/tree-view';
401
+ export type {
402
+ CommandPaletteController,
403
+ CommandPaletteState,
404
+ UseCommandPaletteOptions,
405
+ } from './components/use-command-palette';
406
+ export { useCommandPalette } from './components/use-command-palette';
407
+ export type { VirtualListProps } from './components/VirtualList';
408
+ export { VirtualList } from './components/VirtualList';
263
409
  export type { Align, ButtonVariant, Size, SpaceStep, Tone } from './components/variants';
264
410
  // --- variants ----------------------------------------------------------------
265
411
  export { BUTTON_VARIANTS, SIZES, TONES } from './components/variants';
412
+ export type { ScrollAnchor, VisibleRange } from './components/virtual-list-view';
413
+ export {
414
+ anchorAt,
415
+ anchoredScrollTop,
416
+ rowOffsets,
417
+ VIRTUAL_LIST_ESTIMATE,
418
+ VIRTUAL_LIST_OVERSCAN,
419
+ visibleRange,
420
+ } from './components/virtual-list-view';
421
+ export { headingIds, headingSlug } from './content/heading-slug';
422
+ export type { Language, Token, TokenKind, TokenRule } from './content/highlight';
423
+ export { defineLanguage, highlight, TOKEN_KINDS } from './content/highlight';
424
+ export { allLanguages } from './content/languages/all';
425
+ export { diffLanguage } from './content/languages/diff';
426
+ export { htmlLanguage } from './content/languages/html';
427
+ export { jsonLanguage } from './content/languages/json';
428
+ export { shellLanguage } from './content/languages/shell';
429
+ export { sqlLanguage } from './content/languages/sql';
430
+ export { tsLanguage } from './content/languages/ts';
431
+ export { yamlLanguage } from './content/languages/yaml';
432
+ export { parseMarkdown } from './content/markdown-parse';
433
+ export type {
434
+ MarkdownBlock,
435
+ MarkdownInline,
436
+ MarkdownListItem,
437
+ TableAlign,
438
+ } from './content/markdown-tree';
439
+ export { MARKDOWN_MAX_CHARS } from './content/markdown-tree';
266
440
  export type { ClassValue } from './cx';
267
441
  // --- helpers -----------------------------------------------------------------
268
442
  export { cx } from './cx';
269
443
  export type { Debounced } from './debounce';
270
444
  export { DEBOUNCE_DEFAULT_MS, debounce } from './debounce';
445
+ export type { CanDrop, SortMove } from './drag/sort-view';
271
446
  export type { UiErrorCode } from './errors';
272
447
  export {
273
448
  conflictingFieldNameError,
@@ -285,16 +460,11 @@ export {
285
460
  unknownTokenError,
286
461
  } from './errors';
287
462
  // --- forms: the binding between an action's input schema and Field's error slot ---------------
288
- export type { FieldPathSegment, IssuePathSegment } from './form/field-path';
289
- export { fieldSelector, formatFieldPath, MAX_FIELD_INDEX, parseFieldPath } from './form/field-path';
463
+ export type { FieldPathSegment } from './form/field-path';
464
+ export { fieldSelector, MAX_FIELD_INDEX, parseFieldPath } from './form/field-path';
290
465
  export type { FormBinding, FormBindingOptions } from './form/form-binding';
291
466
  export { formBinding } from './form/form-binding';
292
- export type {
293
- FormIssue,
294
- FormSchema,
295
- FormValidationIssue,
296
- FormValidationResult,
297
- } from './form/form-issue';
467
+ export type { FormIssue } from './form/form-issue';
298
468
  export { issuesFromRejection, issuesFromValidation } from './form/form-issue';
299
469
  export type { FormErrors, FormState, FormStatus } from './form/form-state';
300
470
  export {
@@ -312,13 +482,33 @@ export {
312
482
  } from './form/form-touch';
313
483
  export { valuesOfForm } from './form/form-values';
314
484
  export { useForm } from './form/use-form';
485
+ export type {
486
+ CompiledHotkeys,
487
+ HotkeyAnswer,
488
+ HotkeyKeyEvent,
489
+ HotkeyRow,
490
+ HotkeyState,
491
+ HotkeyTable,
492
+ } from './hotkeys-view';
493
+ export {
494
+ CHORD_WINDOW_MS,
495
+ compileHotkeys,
496
+ hotkeyAction,
497
+ hotkeyKeycaps,
498
+ IDLE_HOTKEY_STATE,
499
+ } from './hotkeys-view';
315
500
  export type { UiKey } from './i18n-keys';
316
501
  export { UI_KEYS } from './i18n-keys';
502
+ export type { ListChange, ListLimit, ListUrl, ListUrlOptions } from './list-url';
503
+ export { listUrl } from './list-url';
504
+ export type { LiveWindowOptions } from './live-window';
505
+ export { liveWindow } from './live-window';
317
506
  export type { ArrowKeyElement, RovingItem } from './roving';
318
507
  export {
319
508
  handlesOwnArrowKeys,
320
509
  MENU_ITEM_SELECTOR,
321
510
  TAB_SELECTOR,
511
+ TREE_ITEM_SELECTOR,
322
512
  tabStopIndex,
323
513
  } from './roving';
324
514
  export { ambientUiContext } from './theme/ambient';
@@ -363,6 +553,13 @@ export {
363
553
  toggleTheme,
364
554
  watchOsTheme,
365
555
  } from './theme/theme';
556
+ export type {
557
+ TimeRangeChange,
558
+ TimeRangePreset,
559
+ TimeRangeUrl,
560
+ TimeRangeUrlOptions,
561
+ } from './time-range-url';
562
+ export { fromLocalDateTime, timeRangeUrl, toLocalDateTime } from './time-range-url';
366
563
  export type {
367
564
  ToastAction,
368
565
  ToastDwell,
@@ -423,3 +620,5 @@ export {
423
620
  zTokens,
424
621
  } from './tokens/tokens';
425
622
  export { uiCatalog } from './ui-catalog';
623
+ export type { HotkeyHost } from './use-hotkeys';
624
+ export { EDITABLE_SELECTOR, registerHotkeys, useHotkeyRows, useHotkeys } from './use-hotkeys';
@@ -0,0 +1,123 @@
1
+ // A list's state in its URL — sort, cursor, limit, search — read leniently and written as hrefs, so
2
+ // a server-rendered `DataTable` sorts and pages with no island and an island reads the same URL.
3
+ // Pure: no DOM, no router. Beside `sort-state.ts`, whose `SortState` it speaks.
4
+
5
+ import type { SortDirection, SortState } from './components/sort-state';
6
+
7
+ /** The page size a URL may ask for: `default` when absent or unreadable, never above `max`. */
8
+ export interface ListLimit {
9
+ readonly default: number;
10
+ readonly max: number;
11
+ }
12
+
13
+ export interface ListUrlOptions<S extends string> {
14
+ /** The column keys the list can sort by. Any other `sort` in the URL is no sort. */
15
+ readonly sorts: readonly S[];
16
+ /**
17
+ * Prefixes every parameter (`runs.after`), for two lists on one page. With it, any change but a
18
+ * cursor drops EVERY cursor on the page: a cursor is bound to the filter and sort it was minted
19
+ * under, and the server refuses a stale one (`X_CURSOR_INVALID`).
20
+ */
21
+ readonly ns?: string | undefined;
22
+ readonly limit?: ListLimit | undefined;
23
+ }
24
+
25
+ /** What `href` changes. A key present with `undefined` removes that parameter. */
26
+ export interface ListChange {
27
+ readonly sort?: SortState | undefined;
28
+ readonly q?: string | undefined;
29
+ readonly limit?: number | undefined;
30
+ }
31
+
32
+ export interface ListUrl<S extends string> {
33
+ readonly sort: (SortState & { readonly key: S }) | undefined;
34
+ /** The opaque cursor to read after; `undefined` on the first page. */
35
+ readonly cursor: string | undefined;
36
+ readonly limit: number;
37
+ /** The search text, trimmed; `undefined` when empty. */
38
+ readonly q: string | undefined;
39
+ /** The list under `change`, every other parameter kept, its cursor dropped. */
40
+ href(change: ListChange): string;
41
+ /** `DataTable`/`Pagination`'s `hrefFor`: the same list at `cursor`, everything else kept. */
42
+ hrefFor(cursor: string, direction: 'next' | 'prev'): string;
43
+ /** `DataTable`'s `sortHrefFor`: the list under the next sort state; `undefined` is unsorted. */
44
+ sortHrefFor(sort: SortState | undefined): string;
45
+ /** The first page — the list without its cursor. `undefined` when already there. */
46
+ readonly firstHref: string | undefined;
47
+ }
48
+
49
+ const DEFAULT_LIMIT: ListLimit = { default: 50, max: 100 };
50
+
51
+ /** A relative URL needs a base to parse; it never reaches an href, which is path and query only. */
52
+ const BASE = 'http://list.invalid';
53
+
54
+ const CURSOR = 'after';
55
+
56
+ const isCursorParam = (name: string): boolean => name === CURSOR || name.endsWith(`.${CURSOR}`);
57
+
58
+ const direction = (raw: string | null): SortDirection => (raw === 'desc' ? 'desc' : 'asc');
59
+
60
+ const readLimit = (raw: string | null, bounds: ListLimit): number => {
61
+ if (raw === null || !/^\d+$/.test(raw)) return bounds.default;
62
+ const value = Number(raw);
63
+ return value >= 1 && value <= bounds.max ? value : bounds.default;
64
+ };
65
+
66
+ const present = (raw: string | null): string | undefined => {
67
+ const value = raw?.trim();
68
+ return value === undefined || value === '' ? undefined : value;
69
+ };
70
+
71
+ export function listUrl<S extends string>(
72
+ url: URL | string,
73
+ options: ListUrlOptions<S>,
74
+ ): ListUrl<S> {
75
+ const parsed = new URL(url, BASE);
76
+ const name = (param: string): string =>
77
+ options.ns === undefined ? param : `${options.ns}.${param}`;
78
+ const params = parsed.searchParams;
79
+
80
+ const rawSort = params.get(name('sort'));
81
+ const key = options.sorts.find((candidate) => candidate === rawSort);
82
+ const sort =
83
+ key === undefined ? undefined : { key, direction: direction(params.get(name('dir'))) };
84
+ const cursor = present(params.get(name(CURSOR)));
85
+
86
+ const write = (edit: (next: URLSearchParams) => void): string => {
87
+ const next = new URLSearchParams(params);
88
+ edit(next);
89
+ const search = next.toString();
90
+ return search === '' ? parsed.pathname : `${parsed.pathname}?${search}`;
91
+ };
92
+ const put = (next: URLSearchParams, param: string, value: string | undefined): void => {
93
+ if (value === undefined) next.delete(name(param));
94
+ else next.set(name(param), value);
95
+ };
96
+ /** Without `ns` the list owns one cursor; with it, a filter change resets every list. */
97
+ const dropCursors = (next: URLSearchParams): void => {
98
+ const cursors = options.ns === undefined ? [CURSOR] : [...next.keys()].filter(isCursorParam);
99
+ for (const param of cursors) next.delete(param);
100
+ };
101
+
102
+ const href = (change: ListChange): string =>
103
+ write((next) => {
104
+ dropCursors(next);
105
+ if ('sort' in change) {
106
+ put(next, 'sort', change.sort?.key);
107
+ put(next, 'dir', change.sort?.direction);
108
+ }
109
+ if ('q' in change) put(next, 'q', present(change.q ?? null));
110
+ if ('limit' in change) put(next, 'limit', change.limit?.toString());
111
+ });
112
+
113
+ return {
114
+ sort,
115
+ cursor,
116
+ limit: readLimit(params.get(name('limit')), options.limit ?? DEFAULT_LIMIT),
117
+ q: present(params.get(name('q'))),
118
+ href,
119
+ hrefFor: (to) => write((next) => put(next, CURSOR, to)),
120
+ sortHrefFor: (next) => href({ sort: next }),
121
+ firstHref: cursor === undefined ? undefined : write((next) => put(next, CURSOR, undefined)),
122
+ };
123
+ }
@@ -0,0 +1,23 @@
1
+ // The trim behind a live chart: append the newest point, keep the last `max`. Pure and free of any
2
+ // chart module, so a live island pays for one function — and every point that survives keeps its
3
+ // key, which is what keeps its node (and the focus on it) through the tick (`hitIds`).
4
+
5
+ import { finiteCount } from '@ultimat3/core';
6
+
7
+ export interface LiveWindowOptions {
8
+ /** How many points the window holds, at least 1. A whole number — it counts points. */
9
+ readonly max: number;
10
+ }
11
+
12
+ /** `series` with `point` appended and the oldest dropped past `max`. Never mutates `series`. */
13
+ export function liveWindow<T>(
14
+ series: readonly T[],
15
+ point: T,
16
+ options: LiveWindowOptions,
17
+ ): readonly T[] {
18
+ // `slice(-NaN)` is the whole array and `slice(-Infinity)` too: an unbounded window, which is
19
+ // the leak a live chart left open for an hour is.
20
+ const max = finiteCount('liveWindow', 'max', options.max, 1);
21
+ const next = [...series, point];
22
+ return next.length > max ? next.slice(next.length - max) : next;
23
+ }
package/src/roving.ts CHANGED
@@ -11,6 +11,8 @@
11
11
  */
12
12
  export const MENU_ITEM_SELECTOR = '[role="menuitem"]:not([disabled])';
13
13
  export const TAB_SELECTOR = '[role="tab"]:not([disabled])';
14
+ /** A tree item is an `<li>`, which has no `disabled`: a disabled one carries `aria-disabled`. */
15
+ export const TREE_ITEM_SELECTOR = '[role="treeitem"]:not([aria-disabled="true"])';
14
16
 
15
17
  /** The only thing the tab-stop rule needs to know about an item. */
16
18
  export interface RovingItem {
@@ -45,4 +45,8 @@ export const INERT_SOLID_RUNTIME: SolidRuntime = Object.freeze({
45
45
  createEffect: () => {},
46
46
 
47
47
  onCleanup: () => {},
48
+
49
+ // A server render is one pass: there is nothing to outlive, so a root is the call itself, and
50
+ // its `dispose` has nothing to release.
51
+ createRoot: <T>(fn: (dispose: () => void) => T): T => fn(() => {}),
48
52
  });
@@ -11,8 +11,8 @@ import type { SolidRuntime } from './solid-adapter';
11
11
  let runtime: SolidRuntime | null = null;
12
12
 
13
13
  /**
14
- * Register once, in the app entry, before the first render. Hand it the six named imports —
15
- * `{ createContext, useContext, createSignal, createMemo, createEffect, onCleanup }` — and not
14
+ * Register once, in the app entry, before the first render. Hand it the seven named imports —
15
+ * `{ createContext, useContext, createSignal, createMemo, createEffect, onCleanup, createRoot }` — and not
16
16
  * `import * as solidRuntime`: the namespace registers too, and costs 14.8 kB of unshaken solid-js
17
17
  * per island chunk (`solid-adapter.ts` has the measurement).
18
18
  */
@@ -30,13 +30,13 @@ export interface SolidContext<T> {
30
30
  }
31
31
 
32
32
  /**
33
- * The exact slice of solid-js the design system touches — six functions, and the registration is
34
- * meant to be handed exactly those six as NAMED imports: `setSolidRuntime({ createContext,
35
- * useContext, createSignal, createMemo, createEffect, onCleanup })`. A `typeof import('solid-js')`
33
+ * The exact slice of solid-js the design system touches — seven functions, and the registration is
34
+ * meant to be handed exactly those seven as NAMED imports: `setSolidRuntime({ createContext,
35
+ * useContext, createSignal, createMemo, createEffect, onCleanup, createRoot })`. A `typeof import('solid-js')`
36
36
  * namespace still satisfies this shape and still registers, but a namespace object passed to a
37
37
  * function is one the bundler cannot shake — every export of solid-js stays in the chunk. Measured
38
38
  * with the island bundler's own settings (minified, production, no splitting): the namespace form
39
- * is 28,556 B against 13,708 B for the six picks, 14.8 kB per island that nothing ever calls.
39
+ * is 28,556 B against 13,708 B for the picks (six, then), 14.8 kB per island that nothing ever calls.
40
40
  */
41
41
  export interface SolidRuntime {
42
42
  createContext<T>(defaultValue: T): SolidContext<T>;
@@ -45,6 +45,12 @@ export interface SolidRuntime {
45
45
  createMemo<T>(fn: () => T): Accessor<T>;
46
46
  createEffect(fn: () => void): void;
47
47
  onCleanup(fn: () => void): void;
48
+ /**
49
+ * An owner that outlives the computation it was created in. `DataTable`'s keyed rows need it:
50
+ * Solid disposes what a computation owns each time it re-runs, so a row built inside the body
51
+ * kept its markup and lost every binding in it on the next live update. v30.
52
+ */
53
+ createRoot<T>(fn: (dispose: () => void) => T): T;
48
54
  }
49
55
 
50
56
  /**
@@ -72,7 +78,7 @@ export function solid(): SolidRuntime {
72
78
  // ONE literal, never a concatenation: `fix-scan.ts` reads a single literal in this position
73
79
  // and counts anything else `unreadable`, so a fix split across `+` is a fix the gate stops
74
80
  // checking.
75
- "paste `import { createContext, createEffect, createMemo, createSignal, onCleanup, useContext } from 'solid-js';` at the top of your *.island.tsx and `setSolidRuntime({ createContext, useContext, createSignal, createMemo, createEffect, onCleanup });` as the first line of its mount(), above render() — six named imports, never `import * as`, which keeps all of solid-js in the chunk; a server render needs none",
81
+ "paste `import { createContext, createEffect, createMemo, createRoot, createSignal, onCleanup, useContext } from 'solid-js';` at the top of your *.island.tsx and `setSolidRuntime({ createContext, useContext, createSignal, createMemo, createEffect, onCleanup, createRoot });` as the first line of its mount(), above render() — seven named imports, never `import * as`, which keeps all of solid-js in the chunk; a server render needs none",
76
82
  );
77
83
  }
78
84
  return INERT_SOLID_RUNTIME;