@svgrid/grid 2.6.23 → 3.0.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/CHANGELOG.md +88 -88
- package/README.md +199 -199
- package/dist/FlexRender.svelte +96 -96
- package/dist/GridFooter.svelte +181 -181
- package/dist/SvAutoComplete.svelte +169 -169
- package/dist/SvAvatar.svelte +75 -75
- package/dist/SvCalendar.svelte +503 -503
- package/dist/SvCarousel.svelte +141 -141
- package/dist/SvCheckBox.svelte +102 -102
- package/dist/SvCircularProgress.svelte +109 -109
- package/dist/SvColorInput.svelte +181 -181
- package/dist/SvComboBox.svelte +279 -279
- package/dist/SvContextMenu.svelte +116 -116
- package/dist/SvCountryInput.svelte +163 -163
- package/dist/SvDrawer.svelte +254 -254
- package/dist/SvDropDownList.svelte +378 -378
- package/dist/SvDurationInput.svelte +126 -126
- package/dist/SvField.svelte +293 -293
- package/dist/SvForm.svelte +437 -437
- package/dist/SvGridCellEditor.svelte +744 -744
- package/dist/SvGridChart.svelte +1716 -1716
- package/dist/SvGridChartPanel.svelte +485 -485
- package/dist/SvGridChartView.svelte +70 -70
- package/dist/SvGridDropdown.svelte +728 -728
- package/dist/SvGridSelect.svelte +270 -270
- package/dist/SvGroupCell.svelte +116 -116
- package/dist/SvListBox.svelte +334 -334
- package/dist/SvMaskedInput.svelte +122 -122
- package/dist/SvMenu.svelte +124 -124
- package/dist/SvMenuList.svelte +146 -146
- package/dist/SvMultiSelect.svelte +293 -293
- package/dist/SvNumberInput.svelte +172 -172
- package/dist/SvOtpInput.svelte +158 -158
- package/dist/SvPasswordInput.svelte +151 -151
- package/dist/SvPhoneInput.svelte +133 -133
- package/dist/SvPopover.svelte +197 -197
- package/dist/SvProgress.svelte +116 -116
- package/dist/SvRadioGroup.svelte +107 -107
- package/dist/SvRating.svelte +112 -112
- package/dist/SvResult.svelte +73 -73
- package/dist/SvRichText.svelte +211 -211
- package/dist/SvRowGroupPanel.svelte +170 -170
- package/dist/SvScrollArea.svelte +61 -61
- package/dist/SvSlider.svelte +203 -203
- package/dist/SvSwitchButton.svelte +108 -108
- package/dist/SvTagsInput.svelte +115 -115
- package/dist/SvTextInput.svelte +147 -147
- package/dist/SvTimePicker.svelte +245 -245
- package/dist/SvToaster.svelte +159 -159
- package/dist/SvToggleButton.svelte +85 -85
- package/dist/SvTooltip.svelte +161 -161
- package/dist/SvTour.svelte +208 -208
- package/dist/SvTree.svelte +444 -444
- package/dist/SvTreeSelect.svelte +239 -239
- package/dist/cdn/{GridMenus-BzWXQjv3.js → GridMenus-DMihUtma.js} +3 -3
- package/dist/cdn/{GridMenus-xr_rHx8F.js → GridMenus-nmNDj1a3.js} +3 -3
- package/dist/cdn/{SvDateRangeInput-DMLKmGEc.js → SvDateRangeInput-Bh0A0JkF.js} +1 -1
- package/dist/cdn/{SvDateRangeInput-CaOuMs8O.js → SvDateRangeInput-DflbiP7N.js} +1 -1
- package/dist/cdn/{SvDateTimePicker-sonaH0oh.js → SvDateTimePicker-BWwpfB_o.js} +1 -1
- package/dist/cdn/{SvDateTimePicker-CCbDZNZB.js → SvDateTimePicker-Bivn8dAP.js} +1 -1
- package/dist/cdn/{SvGridCellEditor-BAPSC7EL.js → SvGridCellEditor-AXL8cHGO.js} +1 -1
- package/dist/cdn/{SvGridCellEditor-BwzmUWtL.js → SvGridCellEditor-Ba7rY3eu.js} +1 -1
- package/dist/cdn/{SvGridChart-BwVos976.js → SvGridChart-Bs2GIR2Q.js} +1 -1
- package/dist/cdn/{SvGridChart-BEJmNNx9.js → SvGridChart-CwhFz7GV.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-BOknOkrP.js → SvGridChartPanel-1WXuStzM.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-D2PjII4O.js → SvGridChartPanel-e5_nqNP9.js} +1 -1
- package/dist/cdn/{SvGridChartView-00LPUHL1.js → SvGridChartView-SmPW10dI.js} +1 -1
- package/dist/cdn/{SvGridChartView-BhUEJ5ki.js → SvGridChartView-eSPuJE6g.js} +1 -1
- package/dist/cdn/{SvGridDropdown-D0VdjeR8.js → SvGridDropdown-B1ZcLpgs.js} +1 -1
- package/dist/cdn/{SvGridDropdown-D13MtJ2j.js → SvGridDropdown-CtdbHcIS.js} +1 -1
- package/dist/cdn/{date-format-BnnHlqGw.js → date-format-CcP1tafP.js} +2 -2
- package/dist/cdn/{date-format-BNii4zeD.js → date-format-DZT7T1wf.js} +2 -2
- package/dist/cdn/{row-drag-touch-Ddaa-QeB.js → row-drag-touch-CycRR65n.js} +12 -10
- package/dist/cdn/{src-skQN5eqh.js → src-B_YS5AOc.js} +45 -45
- package/dist/cdn/{src-DGo7IHug.js → src-DYXXpuSk.js} +44 -44
- package/dist/cdn/svgrid.js +7 -7
- package/dist/cdn/svgrid.svelte-external.js +7 -7
- package/dist/chart-export.js +8 -8
- package/dist/row-drag-touch.d.ts +5 -1
- package/dist/row-drag-touch.js +15 -4
- package/dist/row-drag.js +7 -3
- package/package.json +11 -11
- package/src/FlexRender.svelte +96 -96
- package/src/GridFooter.svelte +181 -181
- package/src/SvAutoComplete.svelte +169 -169
- package/src/SvAvatar.svelte +75 -75
- package/src/SvCalendar.svelte +503 -503
- package/src/SvCalendar.test.ts +226 -226
- package/src/SvCarousel.svelte +141 -141
- package/src/SvCheckBox.svelte +102 -102
- package/src/SvCircularProgress.svelte +109 -109
- package/src/SvColorInput.svelte +181 -181
- package/src/SvComboBox.svelte +279 -279
- package/src/SvContextMenu.svelte +116 -116
- package/src/SvCountryInput.svelte +163 -163
- package/src/SvDrawer.svelte +254 -254
- package/src/SvDropDownList.svelte +378 -378
- package/src/SvDurationInput.svelte +126 -126
- package/src/SvField.svelte +293 -293
- package/src/SvForm.svelte +437 -437
- package/src/SvForm.test.ts +411 -411
- package/src/SvGrid.types.ts +2092 -2092
- package/src/SvGridCellEditor.svelte +744 -744
- package/src/SvGridChart.svelte +1716 -1716
- package/src/SvGridChartPanel.svelte +485 -485
- package/src/SvGridChartView.svelte +70 -70
- package/src/SvGridDropdown.svelte +728 -728
- package/src/SvGridSelect.svelte +270 -270
- package/src/SvGroupCell.svelte +116 -116
- package/src/SvListBox.svelte +334 -334
- package/src/SvMaskedInput.svelte +122 -122
- package/src/SvMenu.svelte +124 -124
- package/src/SvMenu.test.ts +97 -97
- package/src/SvMenuList.svelte +146 -146
- package/src/SvMultiSelect.svelte +293 -293
- package/src/SvNumberInput.svelte +172 -172
- package/src/SvOtpInput.svelte +158 -158
- package/src/SvPasswordInput.svelte +151 -151
- package/src/SvPhoneInput.svelte +133 -133
- package/src/SvPopover.svelte +197 -197
- package/src/SvProgress.svelte +116 -116
- package/src/SvRadioGroup.svelte +107 -107
- package/src/SvRating.svelte +112 -112
- package/src/SvResult.svelte +73 -73
- package/src/SvRichText.svelte +211 -211
- package/src/SvRowGroupPanel.svelte +170 -170
- package/src/SvScrollArea.svelte +61 -61
- package/src/SvSlider.svelte +203 -203
- package/src/SvSwitchButton.svelte +108 -108
- package/src/SvTagsInput.svelte +115 -115
- package/src/SvTextInput.svelte +147 -147
- package/src/SvTimePicker.svelte +245 -245
- package/src/SvToaster.svelte +159 -159
- package/src/SvToaster.test.ts +95 -95
- package/src/SvToggleButton.svelte +85 -85
- package/src/SvTooltip.svelte +161 -161
- package/src/SvTour.svelte +208 -208
- package/src/SvTree.svelte +444 -444
- package/src/SvTreeSelect.svelte +239 -239
- package/src/a11y/dismissable.test.ts +119 -119
- package/src/a11y/dismissable.ts +114 -114
- package/src/a11y.contract.test.ts +49 -49
- package/src/a11y.test.ts +59 -59
- package/src/a11y.ts +61 -61
- package/src/ai.test.ts +502 -502
- package/src/ai.ts +1419 -1419
- package/src/build-api.coverage.test.ts +633 -633
- package/src/build-api.ts +846 -846
- package/src/builtin-editors.grid.test.ts +83 -83
- package/src/cell-formatting.ts +171 -171
- package/src/cell-render.test.ts +513 -513
- package/src/cell-render.ts +496 -496
- package/src/cell-values.ts +148 -148
- package/src/chart-export.ts +202 -202
- package/src/chart-view.svelte.ts +36 -36
- package/src/chart.ts +2321 -2321
- package/src/collaboration.test.ts +104 -104
- package/src/collaboration.ts +167 -167
- package/src/column-groups.ts +78 -78
- package/src/core.performance.test.ts +30 -30
- package/src/core.ts +1865 -1865
- package/src/createAutocomplete.svelte.ts +132 -132
- package/src/createCombobox.svelte.ts +191 -191
- package/src/createCountryInput.svelte.ts +157 -157
- package/src/createDropdownList.svelte.ts +168 -168
- package/src/createForm.svelte.ts +386 -386
- package/src/createGrid.svelte.ts +42 -42
- package/src/createGrid.test.ts +10 -10
- package/src/createGridState.svelte.ts +17 -17
- package/src/createListbox.svelte.ts +250 -250
- package/src/createMenu.svelte.ts +224 -224
- package/src/createPopoverSelect.svelte.ts +213 -213
- package/src/createSlider.svelte.ts +191 -191
- package/src/createTooltip.svelte.ts +144 -144
- package/src/createTree.svelte.ts +322 -322
- package/src/datetime/date-core.ts +206 -206
- package/src/datetime/date-restrict.ts +61 -61
- package/src/datetime/timezone.ts +135 -135
- package/src/dock-manager-model.ts +596 -596
- package/src/dock-model.ts +374 -374
- package/src/editing.test.ts +974 -974
- package/src/editing.ts +609 -609
- package/src/editor-contract.ts +171 -171
- package/src/editor-registry.grid.test.ts +144 -144
- package/src/editor-registry.ts +122 -122
- package/src/export-data-api.test.ts +126 -126
- package/src/export-format.test.ts +107 -107
- package/src/export-format.ts +601 -601
- package/src/filter-operators.ts +160 -160
- package/src/filtering/excel-filters.ts +325 -325
- package/src/flex-render.ts +3 -3
- package/src/form-field.ts +127 -127
- package/src/group-display.test.ts +167 -167
- package/src/group-display.ts +200 -200
- package/src/headless.ts +87 -87
- package/src/js-scroller.svelte.ts +173 -173
- package/src/keyboard-handlers.ts +270 -270
- package/src/keyboard.test.ts +59 -59
- package/src/keyboard.ts +97 -97
- package/src/list-nav.test.ts +49 -49
- package/src/list-nav.ts +29 -29
- package/src/list-option.test.ts +56 -56
- package/src/list-option.ts +179 -179
- package/src/menus.ts +597 -597
- package/src/merge-objects.ts +48 -48
- package/src/overlays.test.ts +90 -90
- package/src/positioning.ts +268 -268
- package/src/render-component.ts +28 -28
- package/src/row-drag-touch.ts +20 -5
- package/src/row-drag.test.ts +401 -353
- package/src/row-drag.ts +419 -415
- package/src/row-resize.test.ts +524 -524
- package/src/row-resize.ts +228 -228
- package/src/scheduler-ical.ts +181 -181
- package/src/scheduler-model.test.ts +562 -562
- package/src/scheduler-model.ts +873 -873
- package/src/selection.test.ts +885 -885
- package/src/server-data-source.test.ts +383 -383
- package/src/server-data-source.ts +469 -469
- package/src/sparkline.test.ts +68 -68
- package/src/sparkline.ts +169 -169
- package/src/spreadsheet.test.ts +488 -488
- package/src/spreadsheet.ts +312 -312
- package/src/static-functions.ts +11 -11
- package/src/subscribe.ts +38 -38
- package/src/summaries.ts +113 -113
- package/src/svgrid-wrapper.types.ts +563 -563
- package/src/svgrid.async-editor-options.test.ts +273 -273
- package/src/svgrid.auto-row-height.test.ts +204 -204
- package/src/svgrid.behavior.test.ts +910 -910
- package/src/svgrid.charting.test.ts +534 -534
- package/src/svgrid.comments-autocomplete.test.ts +127 -127
- package/src/svgrid.context-menu.test.ts +147 -147
- package/src/svgrid.features.test.ts +157 -157
- package/src/svgrid.filter-depth.test.ts +163 -163
- package/src/svgrid.filter-menu-listbox.svelte.test.ts +377 -377
- package/src/svgrid.filter-menu-scroll.test.ts +112 -112
- package/src/svgrid.grand-total.test.ts +188 -188
- package/src/svgrid.group-display-mode.test.ts +171 -171
- package/src/svgrid.group-footers.test.ts +121 -121
- package/src/svgrid.group-pagination.test.ts +153 -153
- package/src/svgrid.new-features.wrapper.test.ts +251 -251
- package/src/svgrid.tree-data.test.ts +186 -186
- package/src/svgrid.wrapper.test.ts +63 -63
- package/src/svgriddropdown.async-panel.svelte.test.ts +195 -195
- package/src/test-setup.ts +62 -62
- package/src/themes/index.ts +288 -288
- package/src/toast-store.svelte.ts +250 -250
- package/src/toast-store.test.ts +147 -147
- package/src/tree-row-model.test.ts +168 -168
- package/src/ui-buttons.test.ts +144 -144
- package/src/ui-inputs.test.ts +118 -118
- package/src/ui-localization.test.ts +113 -113
- package/src/ui-range.test.ts +70 -70
- package/src/ui-selection.test.ts +155 -155
- package/src/ui-tier1.test.ts +142 -142
- package/src/virtual.test.ts +88 -88
- 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 +322 -322
package/src/cell-values.ts
CHANGED
|
@@ -1,148 +1,148 @@
|
|
|
1
|
-
// Pure column/cell value access + display-formatting helpers. They operate
|
|
2
|
-
// only on their Column/Row/data arguments (plus the numeric formatter), so
|
|
3
|
-
// they hold no grid state and live outside the controller.
|
|
4
|
-
import type {
|
|
5
|
-
CellFormatConfig,
|
|
6
|
-
Column,
|
|
7
|
-
ColumnDef,
|
|
8
|
-
Row,
|
|
9
|
-
RowData,
|
|
10
|
-
TableFeatures,
|
|
11
|
-
} from "./index";
|
|
12
|
-
import { formatNumericWithConfig } from "./cell-formatting";
|
|
13
|
-
|
|
14
|
-
export function getColumnBaseValue<TData extends RowData>(row: Row<TData>, column: Column<TData>) {
|
|
15
|
-
const def = column.columnDef;
|
|
16
|
-
if (def.fieldFn) return def.fieldFn(row.original);
|
|
17
|
-
if (def.field) return row.original[def.field];
|
|
18
|
-
return row.getCellValueByColumnId(column.id);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Map a visible row back to its slot in the data array.
|
|
23
|
-
*
|
|
24
|
-
* The bulk writers (paste, clear) rebuild `internalData` immutably, so unlike
|
|
25
|
-
* the inline editor - which mutates `row.original` in place and never needs an
|
|
26
|
-
* index - they have to locate the slot first. They used to read it as
|
|
27
|
-
* `Number(row.id)`, which is only the array index under the DEFAULT `getRowId`.
|
|
28
|
-
* A grid with `getRowId={(t) => String(t.id)}` over 1-based ids wrote one row
|
|
29
|
-
* BELOW the selection on every paste, and one with non-numeric ids ('PLAT-412')
|
|
30
|
-
* parsed to NaN and dropped the write silently.
|
|
31
|
-
*
|
|
32
|
-
* Identity is the reliable key: the row model's `original` IS the object in
|
|
33
|
-
* `data`. Returns a lookup rather than a per-row scan so a multi-row paste
|
|
34
|
-
* stays O(n) instead of O(n * rows).
|
|
35
|
-
*/
|
|
36
|
-
export function createDataIndexLookup<TData extends RowData>(
|
|
37
|
-
data: ReadonlyArray<TData>,
|
|
38
|
-
): (row: Row<TData>) => number {
|
|
39
|
-
const byRef = new Map<unknown, number>();
|
|
40
|
-
for (let i = 0; i < data.length; i += 1) {
|
|
41
|
-
// First slot wins: with a duplicated object reference in `data`, writing
|
|
42
|
-
// the earlier one matches what the row model itself resolves to.
|
|
43
|
-
if (!byRef.has(data[i])) byRef.set(data[i], i);
|
|
44
|
-
}
|
|
45
|
-
return (row) => {
|
|
46
|
-
const hit = byRef.get(row?.original);
|
|
47
|
-
return hit === undefined ? -1 : hit;
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function isGroupRow<TData extends RowData>(row: Row<TData>) {
|
|
52
|
-
// Tree rows are expandable too, but they are real data rows - rendering one as
|
|
53
|
-
// a full-width banner would swallow its cells. Only grouping's synthetic rows
|
|
54
|
-
// are banners.
|
|
55
|
-
if ((row as { __treeRow?: boolean }).__treeRow) return false;
|
|
56
|
-
return typeof row.getCanExpand === "function" && row.getCanExpand();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function toolPanelHeaderLabel<TData extends RowData>(column: Column<TData>): string {
|
|
60
|
-
const h = column.columnDef.header;
|
|
61
|
-
return typeof h === "string" ? h : column.id;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** Apply the column's `format` config to a raw numeric summary value
|
|
65
|
-
* (sum / avg / etc.). Mirrors the currency/number/percent branches in
|
|
66
|
-
* `formatCellValue` so a totaled salary column shows "$1,234,567" in
|
|
67
|
-
* the footer instead of "1234567". Per-row `formatter` functions are
|
|
68
|
-
* intentionally NOT invoked here - they may close over row state. */
|
|
69
|
-
export function formatSummaryNumeric<TData extends RowData>(column: Column<TData>, value: number): string {
|
|
70
|
-
const formatConfig = column.columnDef.format as
|
|
71
|
-
| CellFormatConfig
|
|
72
|
-
| undefined;
|
|
73
|
-
if (
|
|
74
|
-
formatConfig &&
|
|
75
|
-
(formatConfig.type === "number" ||
|
|
76
|
-
formatConfig.type === "currency" ||
|
|
77
|
-
formatConfig.type === "percent")
|
|
78
|
-
) {
|
|
79
|
-
return formatNumericWithConfig(value, {
|
|
80
|
-
type: formatConfig.type,
|
|
81
|
-
locales: formatConfig.locales,
|
|
82
|
-
currency:
|
|
83
|
-
formatConfig.type === "currency"
|
|
84
|
-
? (formatConfig.currency ?? "USD")
|
|
85
|
-
: undefined,
|
|
86
|
-
valueIsPercentPoints:
|
|
87
|
-
formatConfig.type === "percent"
|
|
88
|
-
? formatConfig.valueIsPercentPoints
|
|
89
|
-
: undefined,
|
|
90
|
-
options: formatConfig.options,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
return String(value);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Effective horizontal alignment for a column. Honors the explicit
|
|
98
|
-
* `align` prop on the ColumnDef; otherwise picks a sensible default
|
|
99
|
-
* based on `editorType`:
|
|
100
|
-
* number / date / datetime → 'right'
|
|
101
|
-
* checkbox → 'center'
|
|
102
|
-
* everything else → 'left'
|
|
103
|
-
*/
|
|
104
|
-
export function getColumnAlign<TData extends RowData>(column: Column<TData>): "left" | "center" | "right" {
|
|
105
|
-
const explicit = column.columnDef.align;
|
|
106
|
-
if (explicit) return explicit;
|
|
107
|
-
const editorType = column.columnDef.editorType;
|
|
108
|
-
if (
|
|
109
|
-
editorType === "number" ||
|
|
110
|
-
editorType === "date" ||
|
|
111
|
-
editorType === "datetime"
|
|
112
|
-
) {
|
|
113
|
-
return "right";
|
|
114
|
-
}
|
|
115
|
-
if (editorType === "checkbox") return "center";
|
|
116
|
-
return "left";
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Read a cell value from a PINNED row. Pinned rows aren't bound to a
|
|
121
|
-
* TanStack Row<TData>, so we resolve the value directly off the raw
|
|
122
|
-
* TData via `fieldFn` or `field`. Mirrors `getColumnBaseValue`'s
|
|
123
|
-
* lookup path minus the Row indirection.
|
|
124
|
-
*/
|
|
125
|
-
export function getPinnedCellValue<TData extends RowData>(
|
|
126
|
-
rowData: TData,
|
|
127
|
-
column: Column<TData>,
|
|
128
|
-
): unknown {
|
|
129
|
-
const def = column.columnDef;
|
|
130
|
-
if (def.fieldFn) return def.fieldFn(rowData);
|
|
131
|
-
const field = def.field as string | undefined;
|
|
132
|
-
if (!field) return undefined;
|
|
133
|
-
return (rowData as unknown as Record<string, unknown>)[field];
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export function getColumnAccessorValue<TData extends RowData>(rowData: TData, column: Column<TData>) {
|
|
137
|
-
const def = column.columnDef;
|
|
138
|
-
if (def.fieldFn) return def.fieldFn(rowData);
|
|
139
|
-
if (def.field) return rowData[def.field];
|
|
140
|
-
return undefined;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export function columnDefMatchesId<TFeatures extends TableFeatures, TData extends RowData>(
|
|
144
|
-
def: ColumnDef<TFeatures, TData>,
|
|
145
|
-
columnId: string,
|
|
146
|
-
): boolean {
|
|
147
|
-
return (def.id ?? def.field ?? null) === columnId;
|
|
148
|
-
}
|
|
1
|
+
// Pure column/cell value access + display-formatting helpers. They operate
|
|
2
|
+
// only on their Column/Row/data arguments (plus the numeric formatter), so
|
|
3
|
+
// they hold no grid state and live outside the controller.
|
|
4
|
+
import type {
|
|
5
|
+
CellFormatConfig,
|
|
6
|
+
Column,
|
|
7
|
+
ColumnDef,
|
|
8
|
+
Row,
|
|
9
|
+
RowData,
|
|
10
|
+
TableFeatures,
|
|
11
|
+
} from "./index";
|
|
12
|
+
import { formatNumericWithConfig } from "./cell-formatting";
|
|
13
|
+
|
|
14
|
+
export function getColumnBaseValue<TData extends RowData>(row: Row<TData>, column: Column<TData>) {
|
|
15
|
+
const def = column.columnDef;
|
|
16
|
+
if (def.fieldFn) return def.fieldFn(row.original);
|
|
17
|
+
if (def.field) return row.original[def.field];
|
|
18
|
+
return row.getCellValueByColumnId(column.id);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Map a visible row back to its slot in the data array.
|
|
23
|
+
*
|
|
24
|
+
* The bulk writers (paste, clear) rebuild `internalData` immutably, so unlike
|
|
25
|
+
* the inline editor - which mutates `row.original` in place and never needs an
|
|
26
|
+
* index - they have to locate the slot first. They used to read it as
|
|
27
|
+
* `Number(row.id)`, which is only the array index under the DEFAULT `getRowId`.
|
|
28
|
+
* A grid with `getRowId={(t) => String(t.id)}` over 1-based ids wrote one row
|
|
29
|
+
* BELOW the selection on every paste, and one with non-numeric ids ('PLAT-412')
|
|
30
|
+
* parsed to NaN and dropped the write silently.
|
|
31
|
+
*
|
|
32
|
+
* Identity is the reliable key: the row model's `original` IS the object in
|
|
33
|
+
* `data`. Returns a lookup rather than a per-row scan so a multi-row paste
|
|
34
|
+
* stays O(n) instead of O(n * rows).
|
|
35
|
+
*/
|
|
36
|
+
export function createDataIndexLookup<TData extends RowData>(
|
|
37
|
+
data: ReadonlyArray<TData>,
|
|
38
|
+
): (row: Row<TData>) => number {
|
|
39
|
+
const byRef = new Map<unknown, number>();
|
|
40
|
+
for (let i = 0; i < data.length; i += 1) {
|
|
41
|
+
// First slot wins: with a duplicated object reference in `data`, writing
|
|
42
|
+
// the earlier one matches what the row model itself resolves to.
|
|
43
|
+
if (!byRef.has(data[i])) byRef.set(data[i], i);
|
|
44
|
+
}
|
|
45
|
+
return (row) => {
|
|
46
|
+
const hit = byRef.get(row?.original);
|
|
47
|
+
return hit === undefined ? -1 : hit;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function isGroupRow<TData extends RowData>(row: Row<TData>) {
|
|
52
|
+
// Tree rows are expandable too, but they are real data rows - rendering one as
|
|
53
|
+
// a full-width banner would swallow its cells. Only grouping's synthetic rows
|
|
54
|
+
// are banners.
|
|
55
|
+
if ((row as { __treeRow?: boolean }).__treeRow) return false;
|
|
56
|
+
return typeof row.getCanExpand === "function" && row.getCanExpand();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function toolPanelHeaderLabel<TData extends RowData>(column: Column<TData>): string {
|
|
60
|
+
const h = column.columnDef.header;
|
|
61
|
+
return typeof h === "string" ? h : column.id;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Apply the column's `format` config to a raw numeric summary value
|
|
65
|
+
* (sum / avg / etc.). Mirrors the currency/number/percent branches in
|
|
66
|
+
* `formatCellValue` so a totaled salary column shows "$1,234,567" in
|
|
67
|
+
* the footer instead of "1234567". Per-row `formatter` functions are
|
|
68
|
+
* intentionally NOT invoked here - they may close over row state. */
|
|
69
|
+
export function formatSummaryNumeric<TData extends RowData>(column: Column<TData>, value: number): string {
|
|
70
|
+
const formatConfig = column.columnDef.format as
|
|
71
|
+
| CellFormatConfig
|
|
72
|
+
| undefined;
|
|
73
|
+
if (
|
|
74
|
+
formatConfig &&
|
|
75
|
+
(formatConfig.type === "number" ||
|
|
76
|
+
formatConfig.type === "currency" ||
|
|
77
|
+
formatConfig.type === "percent")
|
|
78
|
+
) {
|
|
79
|
+
return formatNumericWithConfig(value, {
|
|
80
|
+
type: formatConfig.type,
|
|
81
|
+
locales: formatConfig.locales,
|
|
82
|
+
currency:
|
|
83
|
+
formatConfig.type === "currency"
|
|
84
|
+
? (formatConfig.currency ?? "USD")
|
|
85
|
+
: undefined,
|
|
86
|
+
valueIsPercentPoints:
|
|
87
|
+
formatConfig.type === "percent"
|
|
88
|
+
? formatConfig.valueIsPercentPoints
|
|
89
|
+
: undefined,
|
|
90
|
+
options: formatConfig.options,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return String(value);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Effective horizontal alignment for a column. Honors the explicit
|
|
98
|
+
* `align` prop on the ColumnDef; otherwise picks a sensible default
|
|
99
|
+
* based on `editorType`:
|
|
100
|
+
* number / date / datetime → 'right'
|
|
101
|
+
* checkbox → 'center'
|
|
102
|
+
* everything else → 'left'
|
|
103
|
+
*/
|
|
104
|
+
export function getColumnAlign<TData extends RowData>(column: Column<TData>): "left" | "center" | "right" {
|
|
105
|
+
const explicit = column.columnDef.align;
|
|
106
|
+
if (explicit) return explicit;
|
|
107
|
+
const editorType = column.columnDef.editorType;
|
|
108
|
+
if (
|
|
109
|
+
editorType === "number" ||
|
|
110
|
+
editorType === "date" ||
|
|
111
|
+
editorType === "datetime"
|
|
112
|
+
) {
|
|
113
|
+
return "right";
|
|
114
|
+
}
|
|
115
|
+
if (editorType === "checkbox") return "center";
|
|
116
|
+
return "left";
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Read a cell value from a PINNED row. Pinned rows aren't bound to a
|
|
121
|
+
* TanStack Row<TData>, so we resolve the value directly off the raw
|
|
122
|
+
* TData via `fieldFn` or `field`. Mirrors `getColumnBaseValue`'s
|
|
123
|
+
* lookup path minus the Row indirection.
|
|
124
|
+
*/
|
|
125
|
+
export function getPinnedCellValue<TData extends RowData>(
|
|
126
|
+
rowData: TData,
|
|
127
|
+
column: Column<TData>,
|
|
128
|
+
): unknown {
|
|
129
|
+
const def = column.columnDef;
|
|
130
|
+
if (def.fieldFn) return def.fieldFn(rowData);
|
|
131
|
+
const field = def.field as string | undefined;
|
|
132
|
+
if (!field) return undefined;
|
|
133
|
+
return (rowData as unknown as Record<string, unknown>)[field];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function getColumnAccessorValue<TData extends RowData>(rowData: TData, column: Column<TData>) {
|
|
137
|
+
const def = column.columnDef;
|
|
138
|
+
if (def.fieldFn) return def.fieldFn(rowData);
|
|
139
|
+
if (def.field) return rowData[def.field];
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function columnDefMatchesId<TFeatures extends TableFeatures, TData extends RowData>(
|
|
144
|
+
def: ColumnDef<TFeatures, TData>,
|
|
145
|
+
columnId: string,
|
|
146
|
+
): boolean {
|
|
147
|
+
return (def.id ?? def.field ?? null) === columnId;
|
|
148
|
+
}
|