@svgrid/grid 2.1.22 → 2.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.
- package/README.md +9 -2
- package/dist/DockNodeView.svelte +306 -0
- package/dist/DockNodeView.svelte.d.ts +7 -0
- package/dist/DockPopoutHost.svelte +17 -0
- package/dist/DockPopoutHost.svelte.d.ts +14 -0
- package/dist/FlexRender.svelte +96 -96
- package/dist/GridFooter.svelte +178 -178
- package/dist/GridMenus.svelte +83 -3
- package/dist/SvAutoComplete.svelte +5 -3
- package/dist/SvCarousel.svelte +141 -163
- package/dist/SvColorInput.svelte +187 -186
- package/dist/SvColorInput.svelte.d.ts +1 -1
- package/dist/SvComboBox.svelte +7 -3
- package/dist/SvCommand.svelte +28 -85
- package/dist/SvContextMenu.svelte +116 -116
- package/dist/SvCountryInput.svelte +1 -1
- package/dist/SvDateRangeInput.svelte +1 -1
- package/dist/SvDateTimePicker.svelte +9 -3
- package/dist/SvDateTimePicker.svelte.d.ts +3 -0
- package/dist/SvDockLayout.svelte +244 -0
- package/dist/SvDockLayout.svelte.d.ts +77 -0
- package/dist/SvDockManager.svelte +922 -0
- package/dist/SvDockManager.svelte.d.ts +106 -0
- package/dist/SvDrawer.svelte +250 -228
- package/dist/SvDrawer.svelte.d.ts +4 -0
- package/dist/SvDropDownList.svelte +85 -13
- package/dist/SvDropDownList.svelte.d.ts +3 -0
- package/dist/SvField.svelte +21 -4
- package/dist/SvField.svelte.d.ts +1 -0
- package/dist/SvForm.svelte +201 -91
- package/dist/SvForm.svelte.d.ts +15 -22
- package/dist/SvGrid.controller.svelte.d.ts +32 -1
- package/dist/SvGrid.controller.svelte.js +156 -27
- package/dist/SvGrid.css +193 -5
- package/dist/SvGrid.svelte +3131 -2786
- package/dist/SvGrid.types.d.ts +452 -1
- package/dist/SvGridBoard.svelte +2339 -2339
- package/dist/SvGridChart.svelte +1724 -1724
- package/dist/SvGridChartPanel.svelte +485 -485
- package/dist/SvGridDropdown.svelte +689 -682
- package/dist/SvGridSelect.svelte +1 -0
- package/dist/SvGroupCell.svelte +109 -109
- package/dist/SvListBox.svelte +36 -14
- package/dist/SvMaskedInput.svelte +4 -3
- package/dist/SvMaskedInput.svelte.d.ts +1 -1
- package/dist/SvMenu.svelte +124 -124
- package/dist/SvMenuList.svelte +117 -165
- package/dist/SvMenuList.svelte.d.ts +2 -13
- package/dist/SvModal.svelte +12 -29
- package/dist/SvMultiSelect.svelte +1 -0
- package/dist/SvNumberInput.svelte +131 -130
- package/dist/SvNumberInput.svelte.d.ts +1 -1
- package/dist/SvOtpInput.svelte +158 -158
- package/dist/SvPagination.svelte +18 -18
- package/dist/SvPasswordInput.svelte +3 -2
- package/dist/SvPasswordInput.svelte.d.ts +1 -1
- package/dist/SvPhoneInput.svelte +3 -2
- package/dist/SvPhoneInput.svelte.d.ts +1 -1
- package/dist/SvPopover.svelte +139 -139
- package/dist/SvRowGroupPanel.svelte +170 -170
- package/dist/SvScrollArea.svelte +61 -61
- package/dist/SvStepper.svelte +6 -9
- package/dist/SvTagsInput.svelte +3 -2
- package/dist/SvTagsInput.svelte.d.ts +1 -1
- package/dist/SvTooltip.svelte +127 -138
- package/dist/SvTour.svelte +204 -176
- package/dist/SvTree.svelte +377 -377
- package/dist/SvTreeSelect.svelte +230 -229
- package/dist/build-api.js +76 -54
- package/dist/cdn/svgrid.js +10913 -6450
- package/dist/cdn/svgrid.svelte-external.js +9628 -5481
- package/dist/chart-export.js +8 -8
- package/dist/columns.js +6 -0
- package/dist/conditional-formatting.d.ts +67 -3
- package/dist/conditional-formatting.js +124 -17
- package/dist/createCarousel.svelte.d.ts +72 -0
- package/dist/createCarousel.svelte.js +80 -0
- package/dist/createCommand.svelte.d.ts +62 -0
- package/dist/createCommand.svelte.js +109 -0
- package/dist/createForm.svelte.d.ts +62 -0
- package/dist/createForm.svelte.js +374 -0
- package/dist/createMenu.svelte.d.ts +88 -0
- package/dist/createMenu.svelte.js +153 -0
- package/dist/createOverlay.svelte.d.ts +38 -0
- package/dist/createOverlay.svelte.js +68 -0
- package/dist/createPagination.d.ts +74 -0
- package/dist/createPagination.js +71 -0
- package/dist/createPopoverSelect.svelte.js +6 -12
- package/dist/createStepper.d.ts +44 -0
- package/dist/createStepper.js +26 -0
- package/dist/createTooltip.svelte.d.ts +32 -0
- package/dist/createTooltip.svelte.js +61 -0
- package/dist/datetime/timezone.d.ts +36 -0
- package/dist/datetime/timezone.js +110 -0
- package/dist/dock-context.d.ts +52 -0
- package/dist/dock-context.js +1 -0
- package/dist/dock-manager-model.d.ts +136 -0
- package/dist/dock-manager-model.js +514 -0
- package/dist/dock-model.d.ts +105 -0
- package/dist/dock-model.js +288 -0
- package/dist/dock-popout.d.ts +30 -0
- package/dist/dock-popout.js +81 -0
- package/dist/editor-contract.d.ts +2 -0
- package/dist/filter-operators.d.ts +6 -0
- package/dist/filter-operators.js +35 -2
- package/dist/filtering/excel-filters.d.ts +18 -1
- package/dist/filtering/excel-filters.js +56 -0
- package/dist/form-field.d.ts +73 -0
- package/dist/form-field.js +15 -0
- package/dist/index.d.ts +25 -5
- package/dist/index.js +40 -4
- package/dist/list-nav.d.ts +18 -0
- package/dist/list-nav.js +30 -0
- package/dist/list-option.d.ts +2 -0
- package/dist/menu-item.d.ts +20 -0
- package/dist/menu-item.js +1 -0
- package/dist/menus.d.ts +5 -0
- package/dist/menus.js +68 -16
- package/dist/panel-resize.d.ts +25 -0
- package/dist/panel-resize.js +40 -0
- package/dist/popover.d.ts +29 -3
- package/dist/popover.js +22 -6
- package/dist/recurrence.d.ts +33 -7
- package/dist/recurrence.js +151 -13
- package/dist/row-drag.d.ts +8 -0
- package/dist/row-drag.js +11 -0
- package/dist/scheduler-ical.d.ts +30 -0
- package/dist/scheduler-ical.js +180 -0
- package/dist/scheduler-model.d.ts +269 -0
- package/dist/scheduler-model.js +602 -0
- package/dist/scheduler-view.svelte.d.ts +22 -0
- package/dist/scheduler-view.svelte.js +13 -0
- package/dist/spreadsheet.js +20 -12
- package/dist/ui-app.types.d.ts +3 -0
- package/package.json +14 -10
- package/src/DockNodeView.svelte +306 -0
- package/src/DockPopoutHost.svelte +17 -0
- package/src/FlexRender.svelte +96 -96
- package/src/GridFooter.svelte +178 -178
- package/src/GridMenus.svelte +83 -3
- package/src/SvAutoComplete.svelte +5 -3
- package/src/SvCarousel.svelte +141 -163
- package/src/SvCarousel.test.ts +68 -0
- package/src/SvColorInput.svelte +187 -186
- package/src/SvComboBox.svelte +7 -3
- package/src/SvCommand.svelte +28 -85
- package/src/SvCommand.test.ts +78 -0
- package/src/SvContextMenu.svelte +116 -116
- package/src/SvCountryInput.svelte +1 -1
- package/src/SvDateRangeInput.svelte +1 -1
- package/src/SvDateTimePicker.svelte +9 -3
- package/src/SvDockLayout.svelte +244 -0
- package/src/SvDockManager.svelte +922 -0
- package/src/SvDrawer.svelte +250 -228
- package/src/SvDropDownList.svelte +85 -13
- package/src/SvField.svelte +21 -4
- package/src/SvForm.svelte +201 -91
- package/src/SvForm.test.ts +299 -0
- package/src/SvGrid.controller.svelte.ts +3158 -3034
- package/src/SvGrid.css +193 -5
- package/src/SvGrid.svelte +3131 -2786
- package/src/SvGrid.types.ts +1489 -1027
- package/src/SvGridBoard.svelte +2339 -2339
- package/src/SvGridChart.svelte +1724 -1724
- package/src/SvGridChartPanel.svelte +485 -485
- package/src/SvGridDropdown.svelte +689 -682
- package/src/SvGridSelect.svelte +1 -0
- package/src/SvGroupCell.svelte +109 -109
- package/src/SvListBox.svelte +36 -14
- package/src/SvMaskedInput.svelte +4 -3
- package/src/SvMenu.svelte +124 -124
- package/src/SvMenu.test.ts +97 -73
- package/src/SvMenuList.svelte +117 -165
- package/src/SvModal.svelte +12 -29
- package/src/SvModal.test.ts +82 -0
- package/src/SvMultiSelect.svelte +1 -0
- package/src/SvNumberInput.svelte +131 -130
- package/src/SvOtpInput.svelte +158 -158
- package/src/SvPagination.svelte +18 -18
- package/src/SvPasswordInput.svelte +3 -2
- package/src/SvPhoneInput.svelte +3 -2
- package/src/SvPopover.svelte +139 -139
- package/src/SvRowGroupPanel.svelte +170 -170
- package/src/SvScrollArea.svelte +61 -61
- package/src/SvStepper.svelte +6 -9
- package/src/SvTagsInput.svelte +3 -2
- package/src/SvTooltip.svelte +127 -138
- package/src/SvTooltip.test.ts +73 -0
- package/src/SvTour.svelte +204 -176
- package/src/SvTree.svelte +377 -377
- package/src/SvTreeSelect.svelte +230 -229
- package/src/a11y.contract.test.ts +49 -49
- package/src/a11y.test.ts +59 -59
- package/src/a11y.ts +61 -61
- package/src/build-api.ts +870 -847
- package/src/cell-formatting.ts +169 -169
- package/src/cell-render.ts +469 -469
- package/src/chart-export.ts +201 -201
- package/src/chart.ts +2296 -2296
- package/src/collaboration.test.ts +104 -104
- package/src/collaboration.ts +167 -167
- package/src/columns.ts +5 -0
- package/src/conditional-formatting.test.ts +104 -0
- package/src/conditional-formatting.ts +176 -19
- package/src/core.performance.test.ts +30 -30
- package/src/core.ts +1111 -1111
- package/src/createAutocomplete.svelte.ts +132 -132
- package/src/createCarousel.svelte.ts +104 -0
- package/src/createCombobox.svelte.ts +179 -179
- package/src/createCommand.svelte.ts +125 -0
- package/src/createCountryInput.svelte.ts +157 -157
- package/src/createDropdownList.svelte.ts +162 -162
- package/src/createForm.svelte.ts +333 -0
- package/src/createGrid.svelte.ts +42 -42
- package/src/createGrid.test.ts +10 -10
- package/src/createGridState.svelte.ts +17 -17
- package/src/createMenu.svelte.ts +202 -0
- package/src/createOverlay.svelte.ts +101 -0
- package/src/createPagination.test.ts +65 -0
- package/src/createPagination.ts +84 -0
- package/src/createPopoverSelect.svelte.ts +206 -210
- package/src/createStepper.test.ts +62 -0
- package/src/createStepper.ts +61 -0
- package/src/createTooltip.svelte.ts +86 -0
- package/src/createTree.svelte.ts +319 -319
- package/src/datetime/timezone.test.ts +69 -0
- package/src/datetime/timezone.ts +134 -0
- package/src/dock-context.ts +47 -0
- package/src/dock-manager-model.test.ts +275 -0
- package/src/dock-manager-model.ts +593 -0
- package/src/dock-model.test.ts +163 -0
- package/src/dock-model.ts +368 -0
- package/src/dock-popout.ts +94 -0
- package/src/editing.test.ts +859 -859
- package/src/editing.ts +675 -675
- package/src/editor-contract.ts +2 -0
- package/src/export-data-api.test.ts +126 -126
- package/src/export-format.test.ts +107 -107
- package/src/export-format.ts +598 -598
- package/src/filter-operators.test.ts +59 -0
- package/src/filter-operators.ts +35 -2
- package/src/filtering/excel-filters.test.ts +86 -1
- package/src/filtering/excel-filters.ts +65 -0
- package/src/flex-render.ts +3 -3
- package/src/form-field.ts +87 -0
- package/src/index.ts +623 -469
- package/src/keyboard.test.ts +59 -59
- package/src/keyboard.ts +97 -97
- package/src/list-nav.test.ts +49 -0
- package/src/list-nav.ts +29 -0
- package/src/list-option.ts +2 -0
- package/src/menu-item.ts +21 -0
- package/src/menus.test.ts +48 -0
- package/src/menus.ts +639 -582
- package/src/merge-objects.ts +48 -48
- package/src/overlays.test.ts +90 -90
- package/src/panel-resize.ts +52 -0
- package/src/popover.bounds.test.ts +93 -0
- package/src/popover.ts +51 -7
- package/src/recurrence.test.ts +88 -1
- package/src/recurrence.ts +166 -15
- package/src/render-component.ts +28 -28
- package/src/row-drag.ts +10 -0
- package/src/scheduler-ical.test.ts +68 -0
- package/src/scheduler-ical.ts +180 -0
- package/src/scheduler-model.test.ts +546 -0
- package/src/scheduler-model.ts +853 -0
- package/src/scheduler-view.svelte.ts +33 -0
- package/src/selection.test.ts +754 -754
- package/src/selection.ts +600 -600
- package/src/server-data-source.test.ts +289 -289
- package/src/server-data-source.ts +413 -413
- package/src/sparkline.test.ts +68 -68
- package/src/sparkline.ts +169 -169
- package/src/spreadsheet.test.ts +489 -489
- package/src/spreadsheet.ts +312 -304
- package/src/static-functions.ts +11 -11
- package/src/subscribe.ts +38 -38
- package/src/svgrid-wrapper.types.ts +501 -501
- package/src/svgrid.behavior.test.ts +706 -706
- package/src/svgrid.charting.test.ts +527 -527
- package/src/svgrid.effect-driven-filter.svelte.test.ts +116 -0
- package/src/svgrid.features.test.ts +157 -157
- package/src/svgrid.new-features.wrapper.test.ts +251 -251
- package/src/svgrid.wrapper.test.ts +40 -40
- package/src/test-setup.ts +62 -62
- package/src/themes/index.ts +159 -159
- package/src/ui-app.types.ts +3 -0
- package/src/virtual.test.ts +6 -4
- package/src/virtualization/column-virtualizer.test.ts +27 -27
- package/src/virtualization/column-virtualizer.ts +30 -30
- package/src/virtualization/svelte-virtualizer.svelte.ts +26 -26
- package/src/virtualization/types.ts +30 -30
- package/src/virtualization/virtualizer.test.ts +47 -47
- package/src/virtualization/virtualizer.ts +296 -296
|
@@ -10,15 +10,59 @@
|
|
|
10
10
|
* component just paints the result and the logic is unit-testable.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
/** A single gradient stop along the normalized 0..1 domain. */
|
|
14
|
+
export type ColorScaleStop = { offset: number; color: string }
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* How `minValue`/`maxValue` (and the derived column extremes) are read:
|
|
18
|
+
* - `absolute` (default): literal data values.
|
|
19
|
+
* - `percent`: 0..100 positions along the column's own min..max span, so you
|
|
20
|
+
* can say "tint the top 20%" without knowing the numbers up front.
|
|
21
|
+
*/
|
|
22
|
+
export type ScaleBounds = 'absolute' | 'percent'
|
|
23
|
+
|
|
13
24
|
export type ColorScaleFormat = {
|
|
14
25
|
type: 'colorScale'
|
|
15
26
|
/** 2-stop (min/max) or 3-stop (min/mid/max) gradient. Hex colors. */
|
|
16
|
-
min
|
|
27
|
+
min?: string
|
|
17
28
|
mid?: string
|
|
18
|
-
max
|
|
29
|
+
max?: string
|
|
30
|
+
/**
|
|
31
|
+
* N-stop gradient along the normalized domain (offsets 0..1). When present
|
|
32
|
+
* this overrides `min`/`mid`/`max`, enabling banded / traffic-light scales.
|
|
33
|
+
*/
|
|
34
|
+
stops?: ReadonlyArray<ColorScaleStop>
|
|
35
|
+
/**
|
|
36
|
+
* `hue` (default): interpolate between stop colors into an opaque fill.
|
|
37
|
+
* `alpha`: keep a single `base` color and interpolate its *opacity*, so the
|
|
38
|
+
* tint composites over zebra striping, selection, and pinned backgrounds
|
|
39
|
+
* instead of painting over them - Adaptable's "live heat map" look.
|
|
40
|
+
*/
|
|
41
|
+
mode?: 'hue' | 'alpha'
|
|
42
|
+
/** Base color for `alpha` mode. Default `#2563eb`. */
|
|
43
|
+
base?: string
|
|
44
|
+
/** [min, max] opacity for `alpha` mode. Default [0.05, 0.85]. */
|
|
45
|
+
alphaBounds?: readonly [number, number]
|
|
19
46
|
/** Fix the scale; otherwise derived from the column's data. */
|
|
20
47
|
minValue?: number
|
|
21
48
|
maxValue?: number
|
|
49
|
+
/** Interpret `minValue`/`maxValue` as absolute values or 0..100 percents. */
|
|
50
|
+
bounds?: ScaleBounds
|
|
51
|
+
/**
|
|
52
|
+
* Diverging scale pinned at 0: negatives and positives shade outward from a
|
|
53
|
+
* neutral midpoint, symmetric around zero. Ideal for P&L / price deltas.
|
|
54
|
+
*/
|
|
55
|
+
zeroCentred?: boolean
|
|
56
|
+
/** Flip the ramp so the lowest values attract the most attention. */
|
|
57
|
+
reverse?: boolean
|
|
58
|
+
/**
|
|
59
|
+
* Tint by this cell's value as a proportion of another column's value on the
|
|
60
|
+
* SAME row (a field key on the row object), instead of the column extremes.
|
|
61
|
+
* Column comparison - e.g. filled vs target, open vs total.
|
|
62
|
+
*/
|
|
63
|
+
compareColumn?: string
|
|
64
|
+
/** Attach a tooltip showing the raw value or its % position on the ramp. */
|
|
65
|
+
tooltip?: 'value' | 'percent'
|
|
22
66
|
}
|
|
23
67
|
|
|
24
68
|
export type DataBarFormat = {
|
|
@@ -27,6 +71,15 @@ export type DataBarFormat = {
|
|
|
27
71
|
negativeColor?: string
|
|
28
72
|
minValue?: number
|
|
29
73
|
maxValue?: number
|
|
74
|
+
/** Interpret `minValue`/`maxValue` as absolute values or 0..100 percents. */
|
|
75
|
+
bounds?: ScaleBounds
|
|
76
|
+
/**
|
|
77
|
+
* Size the bar by this cell's value as a proportion of another column's
|
|
78
|
+
* value on the same row (a field key), instead of the column extremes.
|
|
79
|
+
*/
|
|
80
|
+
compareColumn?: string
|
|
81
|
+
/** Fill the bar with a left-to-right gradient rather than a flat color. */
|
|
82
|
+
gradient?: boolean
|
|
30
83
|
/** Show the cell's text on top of the bar. Default true. */
|
|
31
84
|
showValue?: boolean
|
|
32
85
|
}
|
|
@@ -66,9 +119,11 @@ export type ResolvedCellFormat = {
|
|
|
66
119
|
background?: string
|
|
67
120
|
color?: string
|
|
68
121
|
fontWeight?: string | number
|
|
69
|
-
dataBar?: { percent: number; color: string; fromRight: boolean }
|
|
122
|
+
dataBar?: { percent: number; color: string; fromRight: boolean; gradient?: boolean }
|
|
70
123
|
icon?: string
|
|
71
124
|
iconOnly?: boolean
|
|
125
|
+
/** Tooltip text (value / percentile), when a format requests one. */
|
|
126
|
+
title?: string
|
|
72
127
|
}
|
|
73
128
|
|
|
74
129
|
export type ColumnStat = { min: number; max: number }
|
|
@@ -158,13 +213,85 @@ export function lerpColor(a: string, b: string, t: number): string {
|
|
|
158
213
|
])
|
|
159
214
|
}
|
|
160
215
|
|
|
216
|
+
/** Build an `rgba()` string from a hex color + opacity. Falls back to the hex. */
|
|
217
|
+
export function rgba(hex: string, alpha: number): string {
|
|
218
|
+
const rgb = parseHex(hex)
|
|
219
|
+
if (!rgb) return hex
|
|
220
|
+
return `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${clamp01(alpha).toFixed(3)})`
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** Color of an N-stop ramp at normalized position `t`. Stops sorted by offset. */
|
|
224
|
+
function stopsColorAt(stops: ReadonlyArray<ColorScaleStop>, t: number): string {
|
|
225
|
+
const sorted = [...stops].sort((a, b) => a.offset - b.offset)
|
|
226
|
+
if (sorted.length === 0) return '#000000'
|
|
227
|
+
if (t <= sorted[0]!.offset) return sorted[0]!.color
|
|
228
|
+
const last = sorted[sorted.length - 1]!
|
|
229
|
+
if (t >= last.offset) return last.color
|
|
230
|
+
for (let i = 0; i < sorted.length - 1; i += 1) {
|
|
231
|
+
const a = sorted[i]!
|
|
232
|
+
const b = sorted[i + 1]!
|
|
233
|
+
if (t >= a.offset && t <= b.offset) {
|
|
234
|
+
const span = b.offset - a.offset || 1
|
|
235
|
+
return lerpColor(a.color, b.color, (t - a.offset) / span)
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return last.color
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** The interpolated color for a color-scale at normalized position `t`. */
|
|
161
242
|
function colorScaleAt(fmt: ColorScaleFormat, t: number): string {
|
|
243
|
+
if (fmt.stops && fmt.stops.length >= 2) return stopsColorAt(fmt.stops, t)
|
|
244
|
+
const min = fmt.min ?? '#ffffff'
|
|
245
|
+
const max = fmt.max ?? '#000000'
|
|
162
246
|
if (fmt.mid) {
|
|
163
247
|
return t <= 0.5
|
|
164
|
-
? lerpColor(
|
|
165
|
-
: lerpColor(fmt.mid,
|
|
248
|
+
? lerpColor(min, fmt.mid, t / 0.5)
|
|
249
|
+
: lerpColor(fmt.mid, max, (t - 0.5) / 0.5)
|
|
166
250
|
}
|
|
167
|
-
return lerpColor(
|
|
251
|
+
return lerpColor(min, max, t)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Normalized position (0..1) of `n` within a format's domain, honoring
|
|
256
|
+
* absolute/percent bounds, zero-centred diverging scales, cross-column
|
|
257
|
+
* comparison, and reverse. Returns null when the domain can't be resolved
|
|
258
|
+
* (e.g. compareColumn missing / zero on the row).
|
|
259
|
+
*/
|
|
260
|
+
function domainT(
|
|
261
|
+
fmt: ColorScaleFormat | DataBarFormat,
|
|
262
|
+
n: number,
|
|
263
|
+
row: unknown,
|
|
264
|
+
stat: ColumnStat | null,
|
|
265
|
+
): number | null {
|
|
266
|
+
let t: number
|
|
267
|
+
|
|
268
|
+
if (fmt.compareColumn) {
|
|
269
|
+
const other = Number((row as Record<string, unknown> | null)?.[fmt.compareColumn])
|
|
270
|
+
if (!Number.isFinite(other) || other === 0) return null
|
|
271
|
+
t = clamp01(n / other)
|
|
272
|
+
} else if (fmt.type === 'colorScale' && fmt.zeroCentred) {
|
|
273
|
+
const dMin = fmt.minValue ?? stat?.min ?? n
|
|
274
|
+
const dMax = fmt.maxValue ?? stat?.max ?? n
|
|
275
|
+
const bound = Math.max(Math.abs(dMin), Math.abs(dMax)) || 1
|
|
276
|
+
t = clamp01(0.5 + n / bound / 2)
|
|
277
|
+
} else {
|
|
278
|
+
const dMin = stat?.min ?? n
|
|
279
|
+
const dMax = stat?.max ?? n
|
|
280
|
+
let lo: number
|
|
281
|
+
let hi: number
|
|
282
|
+
if (fmt.bounds === 'percent') {
|
|
283
|
+
const span = dMax - dMin
|
|
284
|
+
lo = dMin + ((fmt.minValue ?? 0) / 100) * span
|
|
285
|
+
hi = dMin + ((fmt.maxValue ?? 100) / 100) * span
|
|
286
|
+
} else {
|
|
287
|
+
lo = fmt.minValue ?? dMin
|
|
288
|
+
hi = fmt.maxValue ?? dMax
|
|
289
|
+
}
|
|
290
|
+
t = hi === lo ? 0.5 : clamp01((n - lo) / (hi - lo))
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (fmt.type === 'colorScale' && fmt.reverse) t = 1 - t
|
|
294
|
+
return t
|
|
168
295
|
}
|
|
169
296
|
|
|
170
297
|
/**
|
|
@@ -203,23 +330,42 @@ export function resolveCellFormat<TData = unknown>(
|
|
|
203
330
|
if (value == null || value === '' || !Number.isFinite(n)) continue
|
|
204
331
|
|
|
205
332
|
if (fmt.type === 'colorScale') {
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
333
|
+
const t = domainT(fmt, n, row, stat)
|
|
334
|
+
if (t == null) continue
|
|
335
|
+
if (fmt.mode === 'alpha') {
|
|
336
|
+
const [alo, ahi] = fmt.alphaBounds ?? [0.05, 0.85]
|
|
337
|
+
out.background = rgba(fmt.base ?? '#2563eb', alo + (ahi - alo) * t)
|
|
338
|
+
// Translucent tint composites over the row bg; leave text color alone.
|
|
339
|
+
} else {
|
|
340
|
+
out.background = colorScaleAt(fmt, t)
|
|
341
|
+
// The scale fills the whole cell, so keep the text legible against it.
|
|
342
|
+
const c = contrastText(out.background)
|
|
343
|
+
if (c) out.color = c
|
|
344
|
+
}
|
|
345
|
+
if (fmt.tooltip === 'value') out.title = String(value)
|
|
346
|
+
else if (fmt.tooltip === 'percent') out.title = `${Math.round(t * 100)}%`
|
|
213
347
|
} else if (fmt.type === 'dataBar') {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
348
|
+
let percent: number
|
|
349
|
+
if (fmt.compareColumn) {
|
|
350
|
+
const t = domainT(fmt, n, row, stat)
|
|
351
|
+
if (t == null) continue
|
|
352
|
+
percent = t * 100
|
|
353
|
+
} else if (fmt.bounds === 'percent') {
|
|
354
|
+
const t = domainT(fmt, n, row, stat)
|
|
355
|
+
if (t == null) continue
|
|
356
|
+
percent = t * 100
|
|
357
|
+
} else {
|
|
358
|
+
const lo = fmt.minValue ?? Math.min(0, stat?.min ?? 0)
|
|
359
|
+
const hi = fmt.maxValue ?? stat?.max ?? n
|
|
360
|
+
const span = hi - lo || 1
|
|
361
|
+
percent = clamp01((n - lo) / span) * 100
|
|
362
|
+
}
|
|
218
363
|
const negative = n < 0
|
|
219
364
|
out.dataBar = {
|
|
220
365
|
percent,
|
|
221
366
|
color: negative ? (fmt.negativeColor ?? '#ef4444') : fmt.color,
|
|
222
367
|
fromRight: false,
|
|
368
|
+
gradient: fmt.gradient,
|
|
223
369
|
}
|
|
224
370
|
if (fmt.showValue === false) out.color = 'transparent'
|
|
225
371
|
} else if (fmt.type === 'iconSet') {
|
|
@@ -231,9 +377,20 @@ export function resolveCellFormat<TData = unknown>(
|
|
|
231
377
|
return out
|
|
232
378
|
}
|
|
233
379
|
|
|
234
|
-
/**
|
|
380
|
+
/**
|
|
381
|
+
* Whether any format needs a numeric min/max precomputed. Color-scale and
|
|
382
|
+
* data-bar formats do, EXCEPT when they derive their range from another column
|
|
383
|
+
* on the same row (`compareColumn`) - those read the row, not column stats.
|
|
384
|
+
*/
|
|
385
|
+
export function formatNeedsStats(f: ConditionalFormat<any>): boolean {
|
|
386
|
+
return (
|
|
387
|
+
(f.type === 'colorScale' || f.type === 'dataBar') &&
|
|
388
|
+
!('compareColumn' in f && f.compareColumn)
|
|
389
|
+
)
|
|
390
|
+
}
|
|
391
|
+
|
|
235
392
|
export function formatsNeedingStats(
|
|
236
393
|
formats: ReadonlyArray<ConditionalFormat<any>>,
|
|
237
394
|
): boolean {
|
|
238
|
-
return formats.some(
|
|
395
|
+
return formats.some(formatNeedsStats)
|
|
239
396
|
}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { createCoreRowModel, createSortedRowModel, createSvGrid, sortFns, tableFeatures } from './index'
|
|
3
|
-
|
|
4
|
-
describe('core performance smoke', () => {
|
|
5
|
-
it('handles large synthetic shape with bounded row model call', () => {
|
|
6
|
-
const columns = Array.from({ length: 50 }, (_, index) => ({
|
|
7
|
-
field: `c${index}`,
|
|
8
|
-
editorType: 'number' as const,
|
|
9
|
-
}))
|
|
10
|
-
const data = Array.from({ length: 5000 }, (_, rowIndex) => {
|
|
11
|
-
const row: Record<string, number> = {}
|
|
12
|
-
for (let col = 0; col < 50; col += 1) row[`c${col}`] = rowIndex + col
|
|
13
|
-
return row
|
|
14
|
-
})
|
|
15
|
-
const grid = createSvGrid({
|
|
16
|
-
_features: tableFeatures({}),
|
|
17
|
-
_rowModels: {
|
|
18
|
-
coreRowModel: createCoreRowModel(),
|
|
19
|
-
sortedRowModel: createSortedRowModel(sortFns),
|
|
20
|
-
},
|
|
21
|
-
columns,
|
|
22
|
-
data,
|
|
23
|
-
state: { sorting: [{ id: 'c0', desc: true }, { id: 'c1', desc: false }] },
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
const rows = grid.getRowModel().rows
|
|
27
|
-
expect(rows.length).toBe(5000)
|
|
28
|
-
expect(rows[0]?.getCellValueByColumnId('c0')).toBe(4999)
|
|
29
|
-
})
|
|
30
|
-
})
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { createCoreRowModel, createSortedRowModel, createSvGrid, sortFns, tableFeatures } from './index'
|
|
3
|
+
|
|
4
|
+
describe('core performance smoke', () => {
|
|
5
|
+
it('handles large synthetic shape with bounded row model call', () => {
|
|
6
|
+
const columns = Array.from({ length: 50 }, (_, index) => ({
|
|
7
|
+
field: `c${index}`,
|
|
8
|
+
editorType: 'number' as const,
|
|
9
|
+
}))
|
|
10
|
+
const data = Array.from({ length: 5000 }, (_, rowIndex) => {
|
|
11
|
+
const row: Record<string, number> = {}
|
|
12
|
+
for (let col = 0; col < 50; col += 1) row[`c${col}`] = rowIndex + col
|
|
13
|
+
return row
|
|
14
|
+
})
|
|
15
|
+
const grid = createSvGrid({
|
|
16
|
+
_features: tableFeatures({}),
|
|
17
|
+
_rowModels: {
|
|
18
|
+
coreRowModel: createCoreRowModel(),
|
|
19
|
+
sortedRowModel: createSortedRowModel(sortFns),
|
|
20
|
+
},
|
|
21
|
+
columns,
|
|
22
|
+
data,
|
|
23
|
+
state: { sorting: [{ id: 'c0', desc: true }, { id: 'c1', desc: false }] },
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const rows = grid.getRowModel().rows
|
|
27
|
+
expect(rows.length).toBe(5000)
|
|
28
|
+
expect(rows[0]?.getCellValueByColumnId('c0')).toBe(4999)
|
|
29
|
+
})
|
|
30
|
+
})
|