@cueplusplus/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/dist/charts/_token.js +39 -0
- package/dist/charts/container.d.ts +58 -0
- package/dist/charts/container.js +77 -0
- package/dist/charts/index.d.ts +5 -0
- package/dist/charts/index.js +5 -0
- package/dist/charts/ramps.d.ts +140 -0
- package/dist/charts/ramps.js +615 -0
- package/dist/charts/theme.d.ts +112 -0
- package/dist/charts/theme.js +165 -0
- package/dist/charts/tones.d.ts +111 -0
- package/dist/charts/tones.js +127 -0
- package/dist/chat/_glyphs.js +55 -0
- package/dist/chat/agent-color.d.ts +84 -0
- package/dist/chat/agent-color.js +101 -0
- package/dist/chat/agent-pile.d.ts +55 -0
- package/dist/chat/agent-pile.js +121 -0
- package/dist/chat/ask-box.d.ts +88 -0
- package/dist/chat/ask-box.js +341 -0
- package/dist/chat/composer.d.ts +66 -0
- package/dist/chat/composer.js +144 -0
- package/dist/chat/delegation-card.d.ts +60 -0
- package/dist/chat/delegation-card.js +129 -0
- package/dist/chat/index.d.ts +8 -0
- package/dist/chat/index.js +8 -0
- package/dist/chat/message-list.d.ts +39 -0
- package/dist/chat/message-list.js +105 -0
- package/dist/chat/message.d.ts +47 -0
- package/dist/chat/message.js +108 -0
- package/dist/chrome/_glyphs.js +101 -0
- package/dist/chrome/_tabs-scroll.d.ts +62 -0
- package/dist/chrome/_tabs-scroll.js +68 -0
- package/dist/chrome/_tree.d.ts +75 -0
- package/dist/chrome/_tree.js +49 -0
- package/dist/chrome/empty-state.d.ts +37 -0
- package/dist/chrome/empty-state.js +57 -0
- package/dist/chrome/eyebrow.d.ts +29 -0
- package/dist/chrome/eyebrow.js +36 -0
- package/dist/chrome/index.d.ts +17 -0
- package/dist/chrome/index.js +17 -0
- package/dist/chrome/navigation-menu.d.ts +80 -0
- package/dist/chrome/navigation-menu.js +121 -0
- package/dist/chrome/page-shell.d.ts +38 -0
- package/dist/chrome/page-shell.js +66 -0
- package/dist/chrome/panel.d.ts +55 -0
- package/dist/chrome/panel.js +67 -0
- package/dist/chrome/row.d.ts +82 -0
- package/dist/chrome/row.js +106 -0
- package/dist/chrome/scroll-area.d.ts +39 -0
- package/dist/chrome/scroll-area.js +70 -0
- package/dist/chrome/section-header.d.ts +42 -0
- package/dist/chrome/section-header.js +79 -0
- package/dist/chrome/segmented-control.d.ts +58 -0
- package/dist/chrome/segmented-control.js +76 -0
- package/dist/chrome/status-bar.d.ts +46 -0
- package/dist/chrome/status-bar.js +56 -0
- package/dist/chrome/tabs.d.ts +80 -0
- package/dist/chrome/tabs.js +176 -0
- package/dist/chrome/title-bar.d.ts +37 -0
- package/dist/chrome/title-bar.js +45 -0
- package/dist/chrome/toolbar.d.ts +46 -0
- package/dist/chrome/toolbar.js +62 -0
- package/dist/chrome/tree.d.ts +98 -0
- package/dist/chrome/tree.js +248 -0
- package/dist/color/_checker.js +14 -0
- package/dist/color/_convert.d.ts +52 -0
- package/dist/color/_convert.js +66 -0
- package/dist/color/_glyphs.js +28 -0
- package/dist/color/_thumb.js +15 -0
- package/dist/color/_value.js +28 -0
- package/dist/color/color-area.d.ts +27 -0
- package/dist/color/color-area.js +40 -0
- package/dist/color/color-field.d.ts +32 -0
- package/dist/color/color-field.js +43 -0
- package/dist/color/color-picker.d.ts +71 -0
- package/dist/color/color-picker.js +178 -0
- package/dist/color/color-slider.d.ts +31 -0
- package/dist/color/color-slider.js +51 -0
- package/dist/color/color-swatch.d.ts +32 -0
- package/dist/color/color-swatch.js +44 -0
- package/dist/color/index.d.ts +7 -0
- package/dist/color/index.js +7 -0
- package/dist/configurator/_export.d.ts +78 -0
- package/dist/configurator/_export.js +261 -0
- package/dist/configurator/_glyphs.js +92 -0
- package/dist/configurator/_overrides.d.ts +247 -0
- package/dist/configurator/_overrides.js +514 -0
- package/dist/configurator/configurator.d.ts +71 -0
- package/dist/configurator/configurator.js +279 -0
- package/dist/configurator/export-dialog.d.ts +30 -0
- package/dist/configurator/export-dialog.js +121 -0
- package/dist/configurator/index.d.ts +8 -0
- package/dist/configurator/index.js +8 -0
- package/dist/configurator/panel-sections.d.ts +86 -0
- package/dist/configurator/panel-sections.js +316 -0
- package/dist/configurator/token-editor.d.ts +74 -0
- package/dist/configurator/token-editor.js +149 -0
- package/dist/configurator/use-zoom.d.ts +87 -0
- package/dist/configurator/use-zoom.js +113 -0
- package/dist/date/_glyphs.js +34 -0
- package/dist/date/_segments.js +55 -0
- package/dist/date/_trigger.js +31 -0
- package/dist/date/calendar.d.ts +25 -0
- package/dist/date/calendar.js +125 -0
- package/dist/date/date-field.d.ts +34 -0
- package/dist/date/date-field.js +41 -0
- package/dist/date/date-picker.d.ts +69 -0
- package/dist/date/date-picker.js +89 -0
- package/dist/date/date-range-picker.d.ts +65 -0
- package/dist/date/date-range-picker.js +92 -0
- package/dist/date/index.d.ts +6 -0
- package/dist/date/index.js +6 -0
- package/dist/date/time-field.d.ts +29 -0
- package/dist/date/time-field.js +36 -0
- package/dist/dmx/_ramp.d.ts +77 -0
- package/dist/dmx/_ramp.js +169 -0
- package/dist/dmx/_readout.js +53 -0
- package/dist/dmx/_universe.d.ts +105 -0
- package/dist/dmx/_universe.js +112 -0
- package/dist/dmx/channel-matrix.d.ts +81 -0
- package/dist/dmx/channel-matrix.js +285 -0
- package/dist/dmx/dmx-bar.d.ts +50 -0
- package/dist/dmx/dmx-bar.js +107 -0
- package/dist/dmx/dmx-strip.d.ts +41 -0
- package/dist/dmx/dmx-strip.js +196 -0
- package/dist/dmx/index.d.ts +7 -0
- package/dist/dmx/index.js +7 -0
- package/dist/dmx/universe-grid.d.ts +61 -0
- package/dist/dmx/universe-grid.js +182 -0
- package/dist/flow/_frame.d.ts +52 -0
- package/dist/flow/_frame.js +38 -0
- package/dist/flow/controls.d.ts +41 -0
- package/dist/flow/controls.js +53 -0
- package/dist/flow/flow.css +121 -0
- package/dist/flow/handles.d.ts +40 -0
- package/dist/flow/handles.js +61 -0
- package/dist/flow/index.d.ts +7 -0
- package/dist/flow/index.js +7 -0
- package/dist/flow/node-card.d.ts +71 -0
- package/dist/flow/node-card.js +102 -0
- package/dist/flow/signal-edge.d.ts +60 -0
- package/dist/flow/signal-edge.js +108 -0
- package/dist/flow/use-flow-theme.d.ts +69 -0
- package/dist/flow/use-flow-theme.js +109 -0
- package/dist/forms/_chassis.d.ts +64 -0
- package/dist/forms/_chassis.js +59 -0
- package/dist/forms/_glyphs.js +143 -0
- package/dist/forms/_listbox.js +55 -0
- package/dist/forms/autocomplete.d.ts +61 -0
- package/dist/forms/autocomplete.js +88 -0
- package/dist/forms/button-group.d.ts +47 -0
- package/dist/forms/button-group.js +52 -0
- package/dist/forms/checkbox.d.ts +51 -0
- package/dist/forms/checkbox.js +98 -0
- package/dist/forms/combobox.d.ts +73 -0
- package/dist/forms/combobox.js +108 -0
- package/dist/forms/env-var-input.d.ts +74 -0
- package/dist/forms/env-var-input.js +116 -0
- package/dist/forms/field.d.ts +89 -0
- package/dist/forms/field.js +102 -0
- package/dist/forms/file-upload.d.ts +113 -0
- package/dist/forms/file-upload.js +232 -0
- package/dist/forms/index.d.ts +26 -0
- package/dist/forms/index.js +26 -0
- package/dist/forms/input-group.d.ts +31 -0
- package/dist/forms/input-group.js +54 -0
- package/dist/forms/input.d.ts +33 -0
- package/dist/forms/input.js +36 -0
- package/dist/forms/multi-select.d.ts +62 -0
- package/dist/forms/multi-select.js +107 -0
- package/dist/forms/number-field.d.ts +38 -0
- package/dist/forms/number-field.js +64 -0
- package/dist/forms/otp-field.d.ts +54 -0
- package/dist/forms/otp-field.js +59 -0
- package/dist/forms/password-input.d.ts +46 -0
- package/dist/forms/password-input.js +62 -0
- package/dist/forms/radio-group.d.ts +50 -0
- package/dist/forms/radio-group.js +64 -0
- package/dist/forms/rating.d.ts +69 -0
- package/dist/forms/rating.js +103 -0
- package/dist/forms/scrub-input.d.ts +81 -0
- package/dist/forms/scrub-input.js +249 -0
- package/dist/forms/search-input.d.ts +54 -0
- package/dist/forms/search-input.js +112 -0
- package/dist/forms/select.d.ts +75 -0
- package/dist/forms/select.js +91 -0
- package/dist/forms/slider.d.ts +44 -0
- package/dist/forms/slider.js +65 -0
- package/dist/forms/switch.d.ts +36 -0
- package/dist/forms/switch.js +71 -0
- package/dist/forms/tags-input.d.ts +69 -0
- package/dist/forms/tags-input.js +148 -0
- package/dist/forms/textarea.d.ts +27 -0
- package/dist/forms/textarea.js +37 -0
- package/dist/forms/toggle-group.d.ts +41 -0
- package/dist/forms/toggle-group.js +56 -0
- package/dist/forms/toggle.d.ts +41 -0
- package/dist/forms/toggle.js +100 -0
- package/dist/index.d.ts +112 -0
- package/dist/index.js +104 -0
- package/dist/instruments/_ansi.js +116 -0
- package/dist/instruments/_glyphs.js +90 -0
- package/dist/instruments/_motion.js +56 -0
- package/dist/instruments/_rem.js +21 -0
- package/dist/instruments/app-window-frame.d.ts +48 -0
- package/dist/instruments/app-window-frame.js +76 -0
- package/dist/instruments/copy-button.d.ts +41 -0
- package/dist/instruments/copy-button.js +112 -0
- package/dist/instruments/data-table.d.ts +168 -0
- package/dist/instruments/data-table.js +212 -0
- package/dist/instruments/group-bar.d.ts +63 -0
- package/dist/instruments/group-bar.js +122 -0
- package/dist/instruments/index.d.ts +13 -0
- package/dist/instruments/index.js +13 -0
- package/dist/instruments/log-viewer.d.ts +74 -0
- package/dist/instruments/log-viewer.js +215 -0
- package/dist/instruments/meter.d.ts +77 -0
- package/dist/instruments/meter.js +96 -0
- package/dist/instruments/progress.d.ts +45 -0
- package/dist/instruments/progress.js +61 -0
- package/dist/instruments/seam-grid.d.ts +66 -0
- package/dist/instruments/seam-grid.js +78 -0
- package/dist/instruments/sparkline.d.ts +39 -0
- package/dist/instruments/sparkline.js +85 -0
- package/dist/instruments/stat.d.ts +35 -0
- package/dist/instruments/stat.js +59 -0
- package/dist/instruments/table.d.ts +51 -0
- package/dist/instruments/table.js +92 -0
- package/dist/instruments/terminal-frame.d.ts +89 -0
- package/dist/instruments/terminal-frame.js +256 -0
- package/dist/instruments/two-step-button.d.ts +47 -0
- package/dist/instruments/two-step-button.js +147 -0
- package/dist/instruments/usage-chart.d.ts +55 -0
- package/dist/instruments/usage-chart.js +235 -0
- package/dist/layout/_collapse.js +46 -0
- package/dist/layout/_glyphs.js +45 -0
- package/dist/layout/accordion.d.ts +52 -0
- package/dist/layout/accordion.js +81 -0
- package/dist/layout/breadcrumb.d.ts +35 -0
- package/dist/layout/breadcrumb.js +67 -0
- package/dist/layout/card.d.ts +51 -0
- package/dist/layout/card.js +76 -0
- package/dist/layout/carousel.d.ts +96 -0
- package/dist/layout/carousel.js +211 -0
- package/dist/layout/collapsible.d.ts +74 -0
- package/dist/layout/collapsible.js +126 -0
- package/dist/layout/container.d.ts +27 -0
- package/dist/layout/container.js +40 -0
- package/dist/layout/description-list.d.ts +24 -0
- package/dist/layout/description-list.js +37 -0
- package/dist/layout/grid.d.ts +40 -0
- package/dist/layout/grid.js +48 -0
- package/dist/layout/index.d.ts +15 -0
- package/dist/layout/index.js +15 -0
- package/dist/layout/item.d.ts +65 -0
- package/dist/layout/item.js +100 -0
- package/dist/layout/link.d.ts +48 -0
- package/dist/layout/link.js +63 -0
- package/dist/layout/pagination.d.ts +54 -0
- package/dist/layout/pagination.js +121 -0
- package/dist/layout/resizable.d.ts +38 -0
- package/dist/layout/resizable.js +68 -0
- package/dist/layout/sidebar.d.ts +67 -0
- package/dist/layout/sidebar.js +129 -0
- package/dist/layout/stack.d.ts +46 -0
- package/dist/layout/stack.js +62 -0
- package/dist/layout/stepper.d.ts +49 -0
- package/dist/layout/stepper.js +81 -0
- package/dist/layout/timeline.d.ts +43 -0
- package/dist/layout/timeline.js +63 -0
- package/dist/lib/aria-class.js +24 -0
- package/dist/lib/cn.js +18 -0
- package/dist/lib/compose.js +38 -0
- package/dist/lib/cva.d.ts +18 -0
- package/dist/lib/cva.js +65 -0
- package/dist/midi/_notes.d.ts +101 -0
- package/dist/midi/_notes.js +183 -0
- package/dist/midi/_ruler.d.ts +100 -0
- package/dist/midi/_ruler.js +105 -0
- package/dist/midi/_time.d.ts +107 -0
- package/dist/midi/_time.js +130 -0
- package/dist/midi/index.d.ts +9 -0
- package/dist/midi/index.js +9 -0
- package/dist/midi/musical-time-input.d.ts +48 -0
- package/dist/midi/musical-time-input.js +154 -0
- package/dist/midi/piano-keyboard.d.ts +50 -0
- package/dist/midi/piano-keyboard.js +193 -0
- package/dist/midi/spectrum-visualizer.d.ts +65 -0
- package/dist/midi/spectrum-visualizer.js +213 -0
- package/dist/midi/threshold-rail.d.ts +72 -0
- package/dist/midi/threshold-rail.js +214 -0
- package/dist/midi/timeline-ruler.d.ts +83 -0
- package/dist/midi/timeline-ruler.js +152 -0
- package/dist/overlays/_debounce.js +34 -0
- package/dist/overlays/_glyphs.js +59 -0
- package/dist/overlays/_surface.d.ts +70 -0
- package/dist/overlays/_surface.js +70 -0
- package/dist/overlays/_wheel.js +42 -0
- package/dist/overlays/alert-dialog.d.ts +67 -0
- package/dist/overlays/alert-dialog.js +117 -0
- package/dist/overlays/command-palette.d.ts +93 -0
- package/dist/overlays/command-palette.js +193 -0
- package/dist/overlays/context-menu.d.ts +64 -0
- package/dist/overlays/context-menu.js +78 -0
- package/dist/overlays/dialog.d.ts +72 -0
- package/dist/overlays/dialog.js +124 -0
- package/dist/overlays/drawer.d.ts +75 -0
- package/dist/overlays/drawer.js +151 -0
- package/dist/overlays/dropdown-menu.d.ts +79 -0
- package/dist/overlays/dropdown-menu.js +156 -0
- package/dist/overlays/hover-card.d.ts +58 -0
- package/dist/overlays/hover-card.js +91 -0
- package/dist/overlays/index.d.ts +15 -0
- package/dist/overlays/index.js +15 -0
- package/dist/overlays/info-tip.d.ts +41 -0
- package/dist/overlays/info-tip.js +45 -0
- package/dist/overlays/menubar.d.ts +72 -0
- package/dist/overlays/menubar.js +100 -0
- package/dist/overlays/popover.d.ts +66 -0
- package/dist/overlays/popover.js +114 -0
- package/dist/overlays/sheet.d.ts +78 -0
- package/dist/overlays/sheet.js +131 -0
- package/dist/overlays/toast.d.ts +106 -0
- package/dist/overlays/toast.js +146 -0
- package/dist/overlays/tooltip.d.ts +57 -0
- package/dist/overlays/tooltip.js +95 -0
- package/dist/primitives/avatar.d.ts +51 -0
- package/dist/primitives/avatar.js +93 -0
- package/dist/primitives/button.d.ts +46 -0
- package/dist/primitives/button.js +94 -0
- package/dist/primitives/chip.d.ts +47 -0
- package/dist/primitives/chip.js +152 -0
- package/dist/primitives/icon-button.d.ts +41 -0
- package/dist/primitives/icon-button.js +59 -0
- package/dist/primitives/index.d.ts +10 -0
- package/dist/primitives/index.js +10 -0
- package/dist/primitives/kbd.d.ts +17 -0
- package/dist/primitives/kbd.js +24 -0
- package/dist/primitives/separator.d.ts +25 -0
- package/dist/primitives/separator.js +30 -0
- package/dist/primitives/skeleton.d.ts +20 -0
- package/dist/primitives/skeleton.js +27 -0
- package/dist/primitives/spinner.d.ts +26 -0
- package/dist/primitives/spinner.js +31 -0
- package/dist/primitives/status-dot.d.ts +44 -0
- package/dist/primitives/status-dot.js +50 -0
- package/dist/styles.css +19 -0
- package/dist/system/density.d.ts +33 -0
- package/dist/system/density.js +49 -0
- package/dist/system/index.d.ts +8 -0
- package/dist/system/index.js +7 -0
- package/dist/system/portal.d.ts +51 -0
- package/dist/system/portal.js +122 -0
- package/dist/system/prepaint.d.ts +38 -0
- package/dist/system/prepaint.js +37 -0
- package/dist/system/theme-provider.d.ts +72 -0
- package/dist/system/theme-provider.js +252 -0
- package/dist/system/use-density.d.ts +33 -0
- package/dist/system/use-density.js +84 -0
- package/dist/system/use-isomorphic-layout-effect.js +15 -0
- package/dist/system/use-theme.d.ts +19 -0
- package/dist/system/use-theme.js +25 -0
- package/dist/theming/_presets.d.ts +11 -0
- package/dist/theming/_presets.js +487 -0
- package/dist/theming/contrast.d.ts +110 -0
- package/dist/theming/contrast.js +167 -0
- package/dist/theming/create-theme.d.ts +165 -0
- package/dist/theming/create-theme.js +442 -0
- package/dist/theming/index.d.ts +5 -0
- package/dist/theming/index.js +5 -0
- package/dist/theming/serialize.d.ts +145 -0
- package/dist/theming/serialize.js +165 -0
- package/package.json +216 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { SearchInput } from "../forms/search-input.js";
|
|
4
|
+
import { ChevronLeftGlyph, ChevronRightGlyph, ChevronsLeftGlyph, ChevronsRightGlyph } from "./_glyphs.js";
|
|
5
|
+
import { IconButton } from "../primitives/icon-button.js";
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { columnFilteringFeature, createColumnHelper, createFilteredRowModel, createPaginatedRowModel, createSortedRowModel, filterFn_inNumberRange, filterFn_includesString, flexRender, globalFilteringFeature, rowPaginationFeature, rowSortingFeature, sortFn_alphanumeric, sortFn_basic, sortFn_datetime, sortFn_text, tableFeatures, useTable } from "@tanstack/react-table";
|
|
9
|
+
//#region src/instruments/data-table.tsx
|
|
10
|
+
/**
|
|
11
|
+
* The console table recipe. Not a component — deliberately.
|
|
12
|
+
*
|
|
13
|
+
* A `<DataTable columns={…} data={…} />` monolith has to own the markup of
|
|
14
|
+
* every cell, every header and every empty state, and the first column that
|
|
15
|
+
* needs a `Chip` or a `TwoStepButton` in it starts a prop-drilling arms race
|
|
16
|
+
* that ends with a component nobody can read. TanStack v9's whole point is that
|
|
17
|
+
* the markup stays yours and only the *logic* is shared, so what this module
|
|
18
|
+
* ships is the wiring:
|
|
19
|
+
*
|
|
20
|
+
* - {@link cueTableFeatures} — one opt-in feature set, so v9 can tree-shake
|
|
21
|
+
* everything the console does not use (grouping, faceting, pinning,
|
|
22
|
+
* virtualised column sizing).
|
|
23
|
+
* - {@link useCueTable} — that feature set, pre-bound, with sensible console
|
|
24
|
+
* defaults.
|
|
25
|
+
* - {@link createCueColumnHelper} — the column helper with the features
|
|
26
|
+
* already applied, so column defs infer.
|
|
27
|
+
* - {@link DataTableToolbar} / {@link DataTablePagination} — the two pieces of
|
|
28
|
+
* chrome every table needs and nobody enjoys writing twice.
|
|
29
|
+
*
|
|
30
|
+
* The rows render through the Phase 1 `Table`. There is a fully worked example
|
|
31
|
+
* in `test/instruments/data-table.test.tsx`.
|
|
32
|
+
*
|
|
33
|
+
* Ships from `@cueplusplus/ui/instruments/data-table`: `@tanstack/react-table`
|
|
34
|
+
* is an optional peer, and the core bundle must not require it.
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* Sorting, column filtering, global filtering and pagination — and nothing
|
|
38
|
+
* else.
|
|
39
|
+
*
|
|
40
|
+
* Named functions are registered individually rather than by spreading the
|
|
41
|
+
* built-in registries, because spreading puts every sort and filter
|
|
42
|
+
* implementation in the bundle whether or not a column names one.
|
|
43
|
+
*/
|
|
44
|
+
const cueTableFeatures = tableFeatures({
|
|
45
|
+
columnFilteringFeature,
|
|
46
|
+
globalFilteringFeature,
|
|
47
|
+
rowPaginationFeature,
|
|
48
|
+
rowSortingFeature,
|
|
49
|
+
filteredRowModel: createFilteredRowModel(),
|
|
50
|
+
paginatedRowModel: createPaginatedRowModel(),
|
|
51
|
+
sortedRowModel: createSortedRowModel(),
|
|
52
|
+
filterFns: {
|
|
53
|
+
includesString: filterFn_includesString,
|
|
54
|
+
inNumberRange: filterFn_inNumberRange
|
|
55
|
+
},
|
|
56
|
+
sortFns: {
|
|
57
|
+
alphanumeric: sortFn_alphanumeric,
|
|
58
|
+
basic: sortFn_basic,
|
|
59
|
+
datetime: sortFn_datetime,
|
|
60
|
+
text: sortFn_text
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
/**
|
|
64
|
+
* A TanStack v9 table wired for the console.
|
|
65
|
+
*
|
|
66
|
+
* Adds one default on top of the feature set: `globalFilterFn: "includesString"`,
|
|
67
|
+
* which is what a single search box over a console table always means. Override
|
|
68
|
+
* it, or any other option, by passing it.
|
|
69
|
+
*
|
|
70
|
+
* @param options - Everything `useTable` takes except `features`.
|
|
71
|
+
* @returns The table instance, ready to render through `Table`.
|
|
72
|
+
* @example
|
|
73
|
+
* const table = useCueTable({ data, columns, state: { globalFilter }, onGlobalFilterChange });
|
|
74
|
+
*/
|
|
75
|
+
function useCueTable(options) {
|
|
76
|
+
return useTable({
|
|
77
|
+
features: cueTableFeatures,
|
|
78
|
+
globalFilterFn: "includesString",
|
|
79
|
+
...options
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A column helper with {@link cueTableFeatures} already bound.
|
|
84
|
+
*
|
|
85
|
+
* @returns TanStack's `accessor` / `display` / `group` / `columns` builders.
|
|
86
|
+
* @example
|
|
87
|
+
* const helper = createCueColumnHelper<Fixture>();
|
|
88
|
+
* const columns = [helper.accessor("name", { header: "Fixture" })];
|
|
89
|
+
*/
|
|
90
|
+
function createCueColumnHelper() {
|
|
91
|
+
return createColumnHelper();
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The strip above a table: one search box, a match count, your controls.
|
|
95
|
+
*
|
|
96
|
+
* The count is the part worth having as a component. "12/340" next to a filter
|
|
97
|
+
* box is the difference between "the table is empty" and "the filter is too
|
|
98
|
+
* tight", and it is the first thing left out of a hand-rolled toolbar.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* <DataTableToolbar value={q} onValueChange={setQ} count={table.getRowCount()} total={data.length}>
|
|
102
|
+
* <Button variant="ghost" size="sm">Export</Button>
|
|
103
|
+
* </DataTableToolbar>
|
|
104
|
+
*/
|
|
105
|
+
const DataTableToolbar = React.forwardRef(function DataTableToolbar({ className, value, onValueChange, placeholder = "Filter…", searchLabel = "Filter rows", count, total, children, ...elementProps }, ref) {
|
|
106
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
107
|
+
ref,
|
|
108
|
+
"data-slot": "data-table-toolbar",
|
|
109
|
+
className: cn("flex min-w-0 items-center gap-(--cue-space-3) py-(--cue-space-3)", className),
|
|
110
|
+
...elementProps,
|
|
111
|
+
children: [
|
|
112
|
+
/* @__PURE__ */ jsx(SearchInput, {
|
|
113
|
+
size: "sm",
|
|
114
|
+
"aria-label": searchLabel,
|
|
115
|
+
placeholder,
|
|
116
|
+
value,
|
|
117
|
+
onValueChange,
|
|
118
|
+
className: "max-w-[16rem] min-w-0 flex-1"
|
|
119
|
+
}),
|
|
120
|
+
count === void 0 || total === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
121
|
+
"data-slot": "data-table-count",
|
|
122
|
+
className: "shrink-0 font-mono text-(length:--cue-text-label) tabular-nums text-fg-subtle",
|
|
123
|
+
children: `${count}/${total}`
|
|
124
|
+
}),
|
|
125
|
+
children === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
126
|
+
className: "ml-auto flex shrink-0 items-center gap-(--cue-space-2)",
|
|
127
|
+
children
|
|
128
|
+
})
|
|
129
|
+
]
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
const DEFAULT_PAGER_LABELS = {
|
|
133
|
+
first: "First page",
|
|
134
|
+
previous: "Previous page",
|
|
135
|
+
next: "Next page",
|
|
136
|
+
last: "Last page"
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* The pager: four buttons, the position, and the row count.
|
|
140
|
+
*
|
|
141
|
+
* First and last are present because a console table is often sorted to put the
|
|
142
|
+
* interesting row at one end, and stepping there one page at a time is not a
|
|
143
|
+
* navigation strategy. Every button is an `IconButton` with a real accessible
|
|
144
|
+
* name — an arrow glyph alone announces as nothing.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* <DataTablePagination table={table} />
|
|
148
|
+
*/
|
|
149
|
+
const DataTablePagination = React.forwardRef(function DataTablePagination({ className, table, labels, formatPosition = (page, pages) => `${page} / ${pages}`, formatRowCount = (rows) => `${rows} row${rows === 1 ? "" : "s"}`, ...elementProps }, ref) {
|
|
150
|
+
const names = {
|
|
151
|
+
...DEFAULT_PAGER_LABELS,
|
|
152
|
+
...labels
|
|
153
|
+
};
|
|
154
|
+
const pages = Math.max(1, table.getPageCount());
|
|
155
|
+
const page = (table.state.pagination?.pageIndex ?? 0) + 1;
|
|
156
|
+
const canPrevious = table.getCanPreviousPage();
|
|
157
|
+
const canNext = table.getCanNextPage();
|
|
158
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
159
|
+
ref,
|
|
160
|
+
"data-slot": "data-table-pagination",
|
|
161
|
+
className: cn("flex min-w-0 items-center gap-(--cue-space-3) py-(--cue-space-3) font-mono text-(length:--cue-text-label) text-fg-subtle", className),
|
|
162
|
+
...elementProps,
|
|
163
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
164
|
+
"data-slot": "data-table-rows",
|
|
165
|
+
className: "tabular-nums",
|
|
166
|
+
children: formatRowCount(table.getRowCount())
|
|
167
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
168
|
+
className: "ml-auto flex items-center gap-(--cue-space-1)",
|
|
169
|
+
children: [
|
|
170
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
171
|
+
size: "sm",
|
|
172
|
+
variant: "ghost",
|
|
173
|
+
"aria-label": names.first,
|
|
174
|
+
icon: ChevronsLeftGlyph,
|
|
175
|
+
disabled: !canPrevious,
|
|
176
|
+
onClick: () => table.firstPage()
|
|
177
|
+
}),
|
|
178
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
179
|
+
size: "sm",
|
|
180
|
+
variant: "ghost",
|
|
181
|
+
"aria-label": names.previous,
|
|
182
|
+
icon: ChevronLeftGlyph,
|
|
183
|
+
disabled: !canPrevious,
|
|
184
|
+
onClick: () => table.previousPage()
|
|
185
|
+
}),
|
|
186
|
+
/* @__PURE__ */ jsx("span", {
|
|
187
|
+
"data-slot": "data-table-position",
|
|
188
|
+
className: "px-(--cue-space-3) tabular-nums text-fg",
|
|
189
|
+
children: formatPosition(page, pages)
|
|
190
|
+
}),
|
|
191
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
192
|
+
size: "sm",
|
|
193
|
+
variant: "ghost",
|
|
194
|
+
"aria-label": names.next,
|
|
195
|
+
icon: ChevronRightGlyph,
|
|
196
|
+
disabled: !canNext,
|
|
197
|
+
onClick: () => table.nextPage()
|
|
198
|
+
}),
|
|
199
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
200
|
+
size: "sm",
|
|
201
|
+
variant: "ghost",
|
|
202
|
+
"aria-label": names.last,
|
|
203
|
+
icon: ChevronsRightGlyph,
|
|
204
|
+
disabled: !canNext,
|
|
205
|
+
onClick: () => table.lastPage()
|
|
206
|
+
})
|
|
207
|
+
]
|
|
208
|
+
})]
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
//#endregion
|
|
212
|
+
export { DataTablePagination, DataTableToolbar, createCueColumnHelper, cueTableFeatures, flexRender, useCueTable };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/instruments/group-bar.d.ts
|
|
3
|
+
/** Ink for one segment, in the shared status vocabulary plus `neutral`. */
|
|
4
|
+
type GroupBarTone = "neutral" | "accent" | "ok" | "busy" | "warn" | "danger" | "info";
|
|
5
|
+
/** One slice of the distribution. */
|
|
6
|
+
interface GroupBarItem {
|
|
7
|
+
/** Stable key. Defaults to the label, which is normally unique already. */
|
|
8
|
+
id?: string;
|
|
9
|
+
/** What this slice is. Used in the legend and in the accessible summary. */
|
|
10
|
+
label: string;
|
|
11
|
+
/** The quantity. Shares are computed against the sum; zero and below are dropped. */
|
|
12
|
+
value: number;
|
|
13
|
+
/** Ink for the slice. Defaults to `"neutral"`. */
|
|
14
|
+
tone?: GroupBarTone;
|
|
15
|
+
}
|
|
16
|
+
interface GroupBarProps extends Omit<React.ComponentPropsWithoutRef<"div">, "children"> {
|
|
17
|
+
/** The slices, in display order. */
|
|
18
|
+
items: readonly GroupBarItem[];
|
|
19
|
+
/** Strip height in px at the 16px root, emitted as `rem`. Defaults to `6`. */
|
|
20
|
+
height?: number;
|
|
21
|
+
/** What the distribution is *of*. Required in practice — it names the graphic. */
|
|
22
|
+
label?: string;
|
|
23
|
+
/** List the slices with their shares underneath the strip. */
|
|
24
|
+
legend?: boolean;
|
|
25
|
+
/** Format one share for the summary and the legend. Defaults to `"42%"`. */
|
|
26
|
+
formatShare?: (share: number, item: GroupBarItem) => string;
|
|
27
|
+
/** What to say when every slice is empty. Defaults to `"no data"`. */
|
|
28
|
+
emptyLabel?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The distribution strip: one flex cell per group, weighted by its value.
|
|
32
|
+
*
|
|
33
|
+
* A stacked bar with no axis and no numbers — the shape *is* the reading. Three
|
|
34
|
+
* rules keep it honest:
|
|
35
|
+
*
|
|
36
|
+
* 1. **Empty groups get no cell.** A minimum width is what makes a two-pixel
|
|
37
|
+
* sliver visible, and a minimum width on a zero would draw a group that is
|
|
38
|
+
* not there.
|
|
39
|
+
* 2. **The percentages add to 100.** Shares are rounded by largest remainder,
|
|
40
|
+
* so the legend never sums to 99 and never to 101.
|
|
41
|
+
* 3. **Colour is never the only channel.** The strip is a `role="img"` whose
|
|
42
|
+
* accessible name spells the whole distribution out (WCAG 1.4.1); the legend
|
|
43
|
+
* repeats it in text when there is room for one.
|
|
44
|
+
*
|
|
45
|
+
* The cells are divided by the same 1px seam as `SeamList`, so a distribution
|
|
46
|
+
* strip and a seam list sitting in the same panel share one hairline language.
|
|
47
|
+
*
|
|
48
|
+
* Static markup — no `"use client"`.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* <GroupBar
|
|
52
|
+
* label="Universe load"
|
|
53
|
+
* items={[
|
|
54
|
+
* { label: "dimmers", value: 212, tone: "accent" },
|
|
55
|
+
* { label: "movers", value: 96, tone: "info" },
|
|
56
|
+
* { label: "free", value: 204 },
|
|
57
|
+
* ]}
|
|
58
|
+
* legend
|
|
59
|
+
* />
|
|
60
|
+
*/
|
|
61
|
+
declare const GroupBar: React.ForwardRefExoticComponent<GroupBarProps & React.RefAttributes<HTMLDivElement>>;
|
|
62
|
+
//#endregion
|
|
63
|
+
export { GroupBar, GroupBarItem, GroupBarProps, GroupBarTone };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { cn } from "../lib/cn.js";
|
|
2
|
+
import { toRem } from "./_rem.js";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/instruments/group-bar.tsx
|
|
6
|
+
const CELL_TONES = {
|
|
7
|
+
neutral: "bg-fg-subtle",
|
|
8
|
+
accent: "bg-accent",
|
|
9
|
+
ok: "bg-ok",
|
|
10
|
+
busy: "bg-busy",
|
|
11
|
+
warn: "bg-warn",
|
|
12
|
+
danger: "bg-danger",
|
|
13
|
+
info: "bg-info"
|
|
14
|
+
};
|
|
15
|
+
const LEGEND_TONES = {
|
|
16
|
+
neutral: "text-fg-subtle",
|
|
17
|
+
accent: "text-accent",
|
|
18
|
+
ok: "text-ok",
|
|
19
|
+
busy: "text-busy",
|
|
20
|
+
warn: "text-warn",
|
|
21
|
+
danger: "text-danger",
|
|
22
|
+
info: "text-info"
|
|
23
|
+
};
|
|
24
|
+
/** Default strip height in px at the 16px root — thin enough to sit under a `Stat`. */
|
|
25
|
+
const DEFAULT_HEIGHT_PX = 6;
|
|
26
|
+
/** Percentages that add up: largest-remainder, so the row never reads 99%. */
|
|
27
|
+
function shares(values) {
|
|
28
|
+
const total = values.reduce((sum, value) => sum + value, 0);
|
|
29
|
+
if (total <= 0) return values.map(() => 0);
|
|
30
|
+
const exact = values.map((value) => value / total * 100);
|
|
31
|
+
const floors = exact.map((value) => Math.floor(value));
|
|
32
|
+
let remainder = 100 - floors.reduce((sum, value) => sum + value, 0);
|
|
33
|
+
const order = exact.map((value, index) => ({
|
|
34
|
+
index,
|
|
35
|
+
fraction: value - Math.floor(value)
|
|
36
|
+
})).sort((a, b) => b.fraction - a.fraction);
|
|
37
|
+
const result = [...floors];
|
|
38
|
+
for (const { index } of order) {
|
|
39
|
+
if (remainder <= 0) break;
|
|
40
|
+
result[index] = result[index] + 1;
|
|
41
|
+
remainder -= 1;
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The distribution strip: one flex cell per group, weighted by its value.
|
|
47
|
+
*
|
|
48
|
+
* A stacked bar with no axis and no numbers — the shape *is* the reading. Three
|
|
49
|
+
* rules keep it honest:
|
|
50
|
+
*
|
|
51
|
+
* 1. **Empty groups get no cell.** A minimum width is what makes a two-pixel
|
|
52
|
+
* sliver visible, and a minimum width on a zero would draw a group that is
|
|
53
|
+
* not there.
|
|
54
|
+
* 2. **The percentages add to 100.** Shares are rounded by largest remainder,
|
|
55
|
+
* so the legend never sums to 99 and never to 101.
|
|
56
|
+
* 3. **Colour is never the only channel.** The strip is a `role="img"` whose
|
|
57
|
+
* accessible name spells the whole distribution out (WCAG 1.4.1); the legend
|
|
58
|
+
* repeats it in text when there is room for one.
|
|
59
|
+
*
|
|
60
|
+
* The cells are divided by the same 1px seam as `SeamList`, so a distribution
|
|
61
|
+
* strip and a seam list sitting in the same panel share one hairline language.
|
|
62
|
+
*
|
|
63
|
+
* Static markup — no `"use client"`.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* <GroupBar
|
|
67
|
+
* label="Universe load"
|
|
68
|
+
* items={[
|
|
69
|
+
* { label: "dimmers", value: 212, tone: "accent" },
|
|
70
|
+
* { label: "movers", value: 96, tone: "info" },
|
|
71
|
+
* { label: "free", value: 204 },
|
|
72
|
+
* ]}
|
|
73
|
+
* legend
|
|
74
|
+
* />
|
|
75
|
+
*/
|
|
76
|
+
const GroupBar = React.forwardRef(function GroupBar({ className, items, height = DEFAULT_HEIGHT_PX, label, legend = false, formatShare = (share) => `${share}%`, emptyLabel = "no data", ...elementProps }, ref) {
|
|
77
|
+
const present = items.filter((item) => item.value > 0);
|
|
78
|
+
const percentages = shares(present.map((item) => item.value));
|
|
79
|
+
const empty = present.length === 0;
|
|
80
|
+
const summary = empty ? emptyLabel : present.map((item, index) => `${item.label} ${formatShare(percentages[index], item)}`).join(", ");
|
|
81
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
82
|
+
ref,
|
|
83
|
+
"data-slot": "group-bar",
|
|
84
|
+
"data-empty": empty ? "true" : void 0,
|
|
85
|
+
className: cn("flex min-w-0 flex-col gap-(--cue-space-3)", className),
|
|
86
|
+
...elementProps,
|
|
87
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
88
|
+
role: "img",
|
|
89
|
+
"aria-label": label === void 0 ? summary : `${label}: ${summary}`,
|
|
90
|
+
"data-slot": "group-bar-track",
|
|
91
|
+
className: "flex w-full gap-px overflow-hidden rounded-(--radius-control) bg-border",
|
|
92
|
+
style: { height: toRem(height) },
|
|
93
|
+
children: present.map((item) => /* @__PURE__ */ jsx("span", {
|
|
94
|
+
"aria-hidden": "true",
|
|
95
|
+
"data-slot": "group-bar-cell",
|
|
96
|
+
"data-tone": item.tone ?? "neutral",
|
|
97
|
+
className: cn("min-w-[2px] shrink-0", CELL_TONES[item.tone ?? "neutral"]),
|
|
98
|
+
style: {
|
|
99
|
+
flexGrow: item.value,
|
|
100
|
+
flexBasis: 0
|
|
101
|
+
}
|
|
102
|
+
}, item.id ?? item.label))
|
|
103
|
+
}), legend && !empty ? /* @__PURE__ */ jsx("div", {
|
|
104
|
+
"aria-hidden": "true",
|
|
105
|
+
"data-slot": "group-bar-legend",
|
|
106
|
+
className: "flex flex-wrap items-center gap-x-(--cue-space-5) gap-y-(--cue-space-2) font-mono text-(length:--cue-text-label) text-fg-muted",
|
|
107
|
+
children: present.map((item, index) => /* @__PURE__ */ jsxs("span", {
|
|
108
|
+
className: "inline-flex items-center gap-(--cue-space-2)",
|
|
109
|
+
children: [
|
|
110
|
+
/* @__PURE__ */ jsx("span", { className: cn("size-[0.375rem] shrink-0 rounded-full", CELL_TONES[item.tone ?? "neutral"]) }),
|
|
111
|
+
/* @__PURE__ */ jsx("span", { children: item.label }),
|
|
112
|
+
/* @__PURE__ */ jsx("span", {
|
|
113
|
+
className: cn("tabular-nums", LEGEND_TONES[item.tone ?? "neutral"]),
|
|
114
|
+
children: formatShare(percentages[index], item)
|
|
115
|
+
})
|
|
116
|
+
]
|
|
117
|
+
}, item.id ?? item.label))
|
|
118
|
+
}) : null]
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
//#endregion
|
|
122
|
+
export { GroupBar };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AppWindowFrame, AppWindowFrameProps } from "./app-window-frame.js";
|
|
2
|
+
import { CopyButton, CopyButtonProps } from "./copy-button.js";
|
|
3
|
+
import { GroupBar, GroupBarItem, GroupBarProps, GroupBarTone } from "./group-bar.js";
|
|
4
|
+
import { Meter, MeterProps, MeterProvenance, MeterTone } from "./meter.js";
|
|
5
|
+
import { Progress, ProgressProps } from "./progress.js";
|
|
6
|
+
import { SeamCell, SeamCellProps, SeamGrid, SeamGridProps, SeamGround } from "./seam-grid.js";
|
|
7
|
+
import { Sparkline, SparklineProps } from "./sparkline.js";
|
|
8
|
+
import { Stat, StatProps, StatTone } from "./stat.js";
|
|
9
|
+
import { Table, TableCaptionProps, TableCellProps, TableHeadProps, TableRootProps, TableRowProps, TableSectionProps } from "./table.js";
|
|
10
|
+
import { TerminalFrame, TerminalFrameLine, TerminalFrameProps, TerminalLine, TerminalLineTone, TerminalScript, TerminalStep } from "./terminal-frame.js";
|
|
11
|
+
import { TwoStepButton, TwoStepButtonProps, TwoStepTone } from "./two-step-button.js";
|
|
12
|
+
import { UsageChart, UsageChartPoint, UsageChartProps, UsageChartTone } from "./usage-chart.js";
|
|
13
|
+
export { AppWindowFrame, type AppWindowFrameProps, CopyButton, type CopyButtonProps, GroupBar, type GroupBarItem, type GroupBarProps, type GroupBarTone, Meter, type MeterProps, type MeterProvenance, type MeterTone, Progress, type ProgressProps, SeamCell, type SeamCellProps, SeamGrid, type SeamGridProps, type SeamGround, Sparkline, type SparklineProps, Stat, type StatProps, type StatTone, Table, type TableCaptionProps, type TableCellProps, type TableHeadProps, type TableRootProps, type TableRowProps, type TableSectionProps, TerminalFrame, type TerminalFrameLine, type TerminalFrameProps, type TerminalLine, type TerminalLineTone, type TerminalScript, type TerminalStep, TwoStepButton, type TwoStepButtonProps, type TwoStepTone, UsageChart, type UsageChartPoint, type UsageChartProps, type UsageChartTone };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AppWindowFrame } from "./app-window-frame.js";
|
|
2
|
+
import { CopyButton } from "./copy-button.js";
|
|
3
|
+
import { GroupBar } from "./group-bar.js";
|
|
4
|
+
import { Meter } from "./meter.js";
|
|
5
|
+
import { Progress } from "./progress.js";
|
|
6
|
+
import { SeamCell, SeamGrid } from "./seam-grid.js";
|
|
7
|
+
import { Sparkline } from "./sparkline.js";
|
|
8
|
+
import { Stat } from "./stat.js";
|
|
9
|
+
import { Table } from "./table.js";
|
|
10
|
+
import { TerminalFrame } from "./terminal-frame.js";
|
|
11
|
+
import { TwoStepButton } from "./two-step-button.js";
|
|
12
|
+
import { UsageChart } from "./usage-chart.js";
|
|
13
|
+
export { AppWindowFrame, CopyButton, GroupBar, Meter, Progress, SeamCell, SeamGrid, Sparkline, Stat, Table, TerminalFrame, TwoStepButton, UsageChart };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/instruments/log-viewer.d.ts
|
|
3
|
+
/** The four levels a process actually emits. */
|
|
4
|
+
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
5
|
+
/** One line of output. */
|
|
6
|
+
interface LogLine {
|
|
7
|
+
/** Stable identity. Used as the virtualiser's key, so it must not repeat. */
|
|
8
|
+
id: string;
|
|
9
|
+
/** Epoch ms. Rendered through `formatTimestamp` when present. */
|
|
10
|
+
ts?: number;
|
|
11
|
+
/** Severity. Drives the row's ink and the filter strip. */
|
|
12
|
+
level?: LogLevel;
|
|
13
|
+
/** The line, verbatim — escape sequences and all. */
|
|
14
|
+
text: string;
|
|
15
|
+
/** Parse `text` as ANSI. Off by default: most streams are plain. */
|
|
16
|
+
ansi?: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface LogViewerProps extends Omit<React.ComponentPropsWithoutRef<"div">, "children" | "onScroll"> {
|
|
19
|
+
/** The buffer, oldest first. */
|
|
20
|
+
lines: readonly LogLine[];
|
|
21
|
+
/** Stick to the bottom as lines arrive. Defaults to `true`. */
|
|
22
|
+
follow?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Which levels get a filter chip. Defaults to the levels present in `lines`;
|
|
25
|
+
* `false` hides the strip entirely. Levels with no chip are always shown.
|
|
26
|
+
*/
|
|
27
|
+
filters?: readonly LogLevel[] | false;
|
|
28
|
+
/** Viewer height in px at the 16px root. */
|
|
29
|
+
height: number;
|
|
30
|
+
/** Row height in px. Defaults to the short control rung at the ambient density. */
|
|
31
|
+
rowHeight?: number;
|
|
32
|
+
/** Cap on retained lines; the oldest are dropped. Defaults to `5000`. */
|
|
33
|
+
maxLines?: number;
|
|
34
|
+
/** Render a line's timestamp. Defaults to a local `HH:MM:SS`. */
|
|
35
|
+
formatTimestamp?: (ts: number) => string;
|
|
36
|
+
/** What to say when there is nothing to show. Defaults to `"No output"`. */
|
|
37
|
+
emptyLabel?: string;
|
|
38
|
+
/** Label for the catch-up pill. Defaults to `"3 new lines"`. */
|
|
39
|
+
newLinesLabel?: (count: number) => string;
|
|
40
|
+
/** Accessible name for the log region. Required in practice — name the stream. */
|
|
41
|
+
"aria-label"?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A virtualised log tail: ANSI colour, level filters, and stick-to-bottom.
|
|
45
|
+
*
|
|
46
|
+
* The four things a log pane has to get right, and the reasons each one is not
|
|
47
|
+
* optional:
|
|
48
|
+
*
|
|
49
|
+
* - **Virtualised.** Five thousand DOM rows is a frozen tab. Rows are fixed at
|
|
50
|
+
* the short control rung so the virtualiser never has to measure, which is
|
|
51
|
+
* also what keeps the scrollbar honest while lines stream in.
|
|
52
|
+
* - **ANSI as data, never as HTML.** `anser` will happily hand back a markup
|
|
53
|
+
* string, and the moment that reaches `dangerouslySetInnerHTML` any process
|
|
54
|
+
* that prints a `<script>` owns the console watching it. Colour arrives here
|
|
55
|
+
* as spans of *text* with resolved token colours (see `_ansi.ts`).
|
|
56
|
+
* - **Following is a mode, not a scroll.** While pinned to the bottom the view
|
|
57
|
+
* follows; scroll up and it stops and starts counting, so reading something
|
|
58
|
+
* is never fought by the stream. The count comes back as a pill, not as a
|
|
59
|
+
* jump.
|
|
60
|
+
* - **A cap.** An unbounded buffer is a memory leak with a progress bar. The
|
|
61
|
+
* head is dropped past `maxLines`.
|
|
62
|
+
*
|
|
63
|
+
* Ships from `@cueplusplus/ui/instruments/log-viewer`: it needs
|
|
64
|
+
* `@tanstack/react-virtual` and `anser`, both optional peers, and neither
|
|
65
|
+
* belongs in the bundle of an app that renders no logs.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* <LogViewer aria-label="Build output" height={320} lines={lines} />
|
|
69
|
+
* @example
|
|
70
|
+
* <LogViewer aria-label="Worker" height={200} follow={false} filters={["warn", "error"]} lines={lines} />
|
|
71
|
+
*/
|
|
72
|
+
declare const LogViewer: React.ForwardRefExoticComponent<LogViewerProps & React.RefAttributes<HTMLDivElement>>;
|
|
73
|
+
//#endregion
|
|
74
|
+
export { LogLevel, LogLine, LogViewer, LogViewerProps };
|