@svgrid/grid 1.1.1 → 1.2.1
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/FlexRender.svelte +96 -96
- package/dist/SvGrid.controller.svelte.js +17 -6
- package/dist/SvGrid.css +2012 -2012
- package/dist/SvGrid.svelte +2571 -2346
- package/dist/SvGridDropdown.svelte +7 -3
- package/dist/build-api.js +2 -2
- package/dist/cdn/svgrid.js +13504 -0
- package/dist/cdn/svgrid.svelte-external.js +11188 -0
- package/dist/cell-values.d.ts +1 -1
- package/dist/cell-values.js +7 -7
- package/dist/column-types.js +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +2 -2
- package/dist/summaries.js +4 -4
- package/package.json +12 -2
- package/src/FlexRender.svelte +96 -96
- package/src/SvGrid.controller.svelte.ts +2363 -2352
- package/src/SvGrid.css +2012 -2012
- package/src/SvGrid.svelte +2571 -2346
- package/src/SvGrid.types.ts +537 -537
- package/src/SvGridDropdown.svelte +7 -3
- package/src/a11y.contract.test.ts +49 -49
- package/src/a11y.test.ts +59 -59
- package/src/a11y.ts +59 -59
- package/src/build-api.ts +683 -683
- package/src/cell-formatting.ts +169 -169
- package/src/cell-values.ts +4 -4
- package/src/column-types.ts +1 -1
- package/src/core.performance.test.ts +30 -30
- package/src/core.ts +1077 -1077
- package/src/createGrid.svelte.ts +42 -42
- package/src/createGrid.test.ts +10 -10
- package/src/createGridState.svelte.ts +17 -17
- package/src/editing.ts +669 -669
- package/src/flex-render.ts +3 -3
- package/src/index.ts +208 -208
- package/src/keyboard.test.ts +59 -59
- package/src/keyboard.ts +97 -97
- package/src/merge-objects.ts +48 -48
- package/src/render-component.ts +28 -28
- package/src/spreadsheet.test.ts +489 -489
- package/src/spreadsheet.ts +304 -304
- package/src/static-functions.ts +11 -11
- package/src/subscribe.ts +38 -38
- package/src/summaries.ts +4 -4
- package/src/svgrid-wrapper.types.ts +412 -412
- package/src/svgrid.features.test.ts +157 -157
- package/src/svgrid.wrapper.test.ts +40 -40
- 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
- package/dist/SvGrid.helpers.test.d.ts +0 -1
- package/dist/SvGrid.helpers.test.js +0 -298
- package/dist/SvGridChart.test.d.ts +0 -1
- package/dist/SvGridChart.test.js +0 -62
- package/dist/a11y.contract.test.d.ts +0 -1
- package/dist/a11y.contract.test.js +0 -39
- package/dist/a11y.test.d.ts +0 -1
- package/dist/a11y.test.js +0 -44
- package/dist/aligned-grids.test.d.ts +0 -1
- package/dist/aligned-grids.test.js +0 -75
- package/dist/build-api.coverage.test.d.ts +0 -20
- package/dist/build-api.coverage.test.js +0 -505
- package/dist/cell-formatting.test.d.ts +0 -1
- package/dist/cell-formatting.test.js +0 -234
- package/dist/cell-render.test.d.ts +0 -1
- package/dist/cell-render.test.js +0 -338
- package/dist/chart-export.test.d.ts +0 -1
- package/dist/chart-export.test.js +0 -302
- package/dist/chart.coverage.test.d.ts +0 -1
- package/dist/chart.coverage.test.js +0 -748
- package/dist/chart.test.d.ts +0 -1
- package/dist/chart.test.js +0 -289
- package/dist/clipboard.test.d.ts +0 -1
- package/dist/clipboard.test.js +0 -700
- package/dist/collaboration.coverage.test.d.ts +0 -1
- package/dist/collaboration.coverage.test.js +0 -200
- package/dist/collaboration.test.d.ts +0 -1
- package/dist/collaboration.test.js +0 -65
- package/dist/column-groups.test.d.ts +0 -1
- package/dist/column-groups.test.js +0 -56
- package/dist/column-types.test.d.ts +0 -1
- package/dist/column-types.test.js +0 -62
- package/dist/columns.test.d.ts +0 -1
- package/dist/columns.test.js +0 -625
- package/dist/conditional-formatting.test.d.ts +0 -1
- package/dist/conditional-formatting.test.js +0 -87
- package/dist/core.coverage.test.d.ts +0 -1
- package/dist/core.coverage.test.js +0 -186
- package/dist/core.performance.test.d.ts +0 -1
- package/dist/core.performance.test.js +0 -29
- package/dist/createGrid.test.d.ts +0 -1
- package/dist/createGrid.test.js +0 -9
- package/dist/editing.test.d.ts +0 -1
- package/dist/editing.test.js +0 -732
- package/dist/editors/cell-editors.coverage.test.d.ts +0 -1
- package/dist/editors/cell-editors.coverage.test.js +0 -139
- package/dist/editors/cell-editors.test.d.ts +0 -1
- package/dist/editors/cell-editors.test.js +0 -75
- package/dist/facet-buckets.test.d.ts +0 -1
- package/dist/facet-buckets.test.js +0 -296
- package/dist/fill-patterns.test.d.ts +0 -1
- package/dist/fill-patterns.test.js +0 -81
- package/dist/filter-operators.test.d.ts +0 -1
- package/dist/filter-operators.test.js +0 -135
- package/dist/filtering/excel-filters.test.d.ts +0 -1
- package/dist/filtering/excel-filters.test.js +0 -116
- package/dist/filtering/locale-filter.test.d.ts +0 -13
- package/dist/filtering/locale-filter.test.js +0 -189
- package/dist/flex-render.test.d.ts +0 -1
- package/dist/flex-render.test.js +0 -142
- package/dist/group-aggregate.test.d.ts +0 -1
- package/dist/group-aggregate.test.js +0 -32
- package/dist/hyperformula-adapter.test.d.ts +0 -1
- package/dist/hyperformula-adapter.test.js +0 -205
- package/dist/keyboard-handlers.coverage.test.d.ts +0 -1
- package/dist/keyboard-handlers.coverage.test.js +0 -495
- package/dist/keyboard.test.d.ts +0 -1
- package/dist/keyboard.test.js +0 -27
- package/dist/menus.test.d.ts +0 -1
- package/dist/menus.test.js +0 -560
- package/dist/named-views.coverage.test.d.ts +0 -1
- package/dist/named-views.coverage.test.js +0 -180
- package/dist/named-views.test.d.ts +0 -1
- package/dist/named-views.test.js +0 -57
- package/dist/new-features.test.d.ts +0 -1
- package/dist/new-features.test.js +0 -183
- package/dist/render-component.test.d.ts +0 -1
- package/dist/render-component.test.js +0 -41
- package/dist/row-drag.test.d.ts +0 -1
- package/dist/row-drag.test.js +0 -142
- package/dist/row-resize.test.d.ts +0 -1
- package/dist/row-resize.test.js +0 -329
- package/dist/scroll-sync.test.d.ts +0 -1
- package/dist/scroll-sync.test.js +0 -290
- package/dist/selection.multi-range.test.d.ts +0 -1
- package/dist/selection.multi-range.test.js +0 -55
- package/dist/selection.test.d.ts +0 -1
- package/dist/selection.test.js +0 -647
- package/dist/server-data-source.coverage.test.d.ts +0 -1
- package/dist/server-data-source.coverage.test.js +0 -154
- package/dist/server-data-source.test.d.ts +0 -1
- package/dist/server-data-source.test.js +0 -81
- package/dist/sparkline.test.d.ts +0 -1
- package/dist/sparkline.test.js +0 -52
- package/dist/spreadsheet.test.d.ts +0 -1
- package/dist/spreadsheet.test.js +0 -446
- package/dist/subscribe.test.d.ts +0 -1
- package/dist/subscribe.test.js +0 -93
- package/dist/svgrid.api-extensions.test.d.ts +0 -14
- package/dist/svgrid.api-extensions.test.js +0 -334
- package/dist/svgrid.api.test.d.ts +0 -15
- package/dist/svgrid.api.test.js +0 -169
- package/dist/svgrid.behavior.test.d.ts +0 -15
- package/dist/svgrid.behavior.test.js +0 -625
- package/dist/svgrid.column-reorder.test.d.ts +0 -15
- package/dist/svgrid.column-reorder.test.js +0 -224
- package/dist/svgrid.comments-autocomplete.test.d.ts +0 -1
- package/dist/svgrid.comments-autocomplete.test.js +0 -96
- package/dist/svgrid.context-menu.test.d.ts +0 -1
- package/dist/svgrid.context-menu.test.js +0 -102
- package/dist/svgrid.features.test.d.ts +0 -1
- package/dist/svgrid.features.test.js +0 -129
- package/dist/svgrid.interaction.test.d.ts +0 -9
- package/dist/svgrid.interaction.test.js +0 -349
- package/dist/svgrid.locale-filtering.test.d.ts +0 -15
- package/dist/svgrid.locale-filtering.test.js +0 -261
- package/dist/svgrid.new-features.wrapper.test.d.ts +0 -1
- package/dist/svgrid.new-features.wrapper.test.js +0 -194
- package/dist/svgrid.row-pinning.test.d.ts +0 -14
- package/dist/svgrid.row-pinning.test.js +0 -250
- package/dist/svgrid.set-filter.test.d.ts +0 -17
- package/dist/svgrid.set-filter.test.js +0 -268
- package/dist/svgrid.wrapper.test.d.ts +0 -1
- package/dist/svgrid.wrapper.test.js +0 -59
- package/dist/test-setup.d.ts +0 -1
- package/dist/test-setup.js +0 -35
- package/dist/transaction.test.d.ts +0 -1
- package/dist/transaction.test.js +0 -89
- package/dist/virtualization/column-virtualizer.test.d.ts +0 -1
- package/dist/virtualization/column-virtualizer.test.js +0 -25
- package/dist/virtualization/scroll-scaling.test.d.ts +0 -1
- package/dist/virtualization/scroll-scaling.test.js +0 -127
- package/dist/virtualization/virtualizer.test.d.ts +0 -1
- package/dist/virtualization/virtualizer.test.js +0 -41
package/src/cell-formatting.ts
CHANGED
|
@@ -1,169 +1,169 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helpers for SvGrid column `format` presets (numbers, currency, percent, date patterns).
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/** Map shortcut date patterns to Intl options (merged with caller `options`). */
|
|
6
|
-
export function resolveDatePattern(
|
|
7
|
-
pattern: string | undefined,
|
|
8
|
-
kind: 'date' | 'datetime',
|
|
9
|
-
): Intl.DateTimeFormatOptions | undefined {
|
|
10
|
-
if (!pattern) return undefined
|
|
11
|
-
|
|
12
|
-
const p = pattern.trim()
|
|
13
|
-
|
|
14
|
-
switch (p) {
|
|
15
|
-
/** Short numeric local date (no weekday). */
|
|
16
|
-
case 'd':
|
|
17
|
-
return kind === 'datetime'
|
|
18
|
-
? {
|
|
19
|
-
year: 'numeric',
|
|
20
|
-
month: 'numeric',
|
|
21
|
-
day: 'numeric',
|
|
22
|
-
hour: 'numeric',
|
|
23
|
-
minute: 'numeric',
|
|
24
|
-
}
|
|
25
|
-
: { year: 'numeric', month: 'numeric', day: 'numeric' }
|
|
26
|
-
/** Long spelled-out date (+ time if datetime). */
|
|
27
|
-
case 'D':
|
|
28
|
-
return kind === 'datetime'
|
|
29
|
-
? {
|
|
30
|
-
weekday: 'long',
|
|
31
|
-
year: 'numeric',
|
|
32
|
-
month: 'long',
|
|
33
|
-
day: 'numeric',
|
|
34
|
-
hour: 'numeric',
|
|
35
|
-
minute: 'numeric',
|
|
36
|
-
}
|
|
37
|
-
: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }
|
|
38
|
-
/** ISO-friendly yyyy-mm-dd (with time when datetime). */
|
|
39
|
-
case 'y-m-d':
|
|
40
|
-
return kind === 'datetime'
|
|
41
|
-
? {
|
|
42
|
-
year: 'numeric',
|
|
43
|
-
month: '2-digit',
|
|
44
|
-
day: '2-digit',
|
|
45
|
-
hour: '2-digit',
|
|
46
|
-
minute: '2-digit',
|
|
47
|
-
hour12: false,
|
|
48
|
-
}
|
|
49
|
-
: { year: 'numeric', month: '2-digit', day: '2-digit' }
|
|
50
|
-
case 'medium':
|
|
51
|
-
return { dateStyle: 'medium', timeStyle: kind === 'datetime' ? 'short' : undefined }
|
|
52
|
-
case 'short':
|
|
53
|
-
return { dateStyle: 'short', timeStyle: kind === 'datetime' ? 'short' : undefined }
|
|
54
|
-
case 'long':
|
|
55
|
-
return { dateStyle: 'long', timeStyle: kind === 'datetime' ? 'short' : undefined }
|
|
56
|
-
default:
|
|
57
|
-
return undefined
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
type NumericFormatInput = {
|
|
62
|
-
type: 'number' | 'currency' | 'percent'
|
|
63
|
-
locales?: string | string[]
|
|
64
|
-
currency?: string
|
|
65
|
-
/** When type is percent: treat value as 0–100 instead of Intl’s 0–1 fraction */
|
|
66
|
-
valueIsPercentPoints?: boolean
|
|
67
|
-
options?: Intl.NumberFormatOptions
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* `Intl.NumberFormat` is one of the most expensive constructors in the
|
|
72
|
-
* platform - building one per cell on every scroll makes large grids
|
|
73
|
-
* noticeably stutter. Cache instances by config signature (locale + style
|
|
74
|
-
* + currency + options).
|
|
75
|
-
*/
|
|
76
|
-
const numberFormatterCache = new Map<string, Intl.NumberFormat>()
|
|
77
|
-
function getNumberFormatter(
|
|
78
|
-
locales: string | string[] | undefined,
|
|
79
|
-
options: Intl.NumberFormatOptions,
|
|
80
|
-
): Intl.NumberFormat {
|
|
81
|
-
// Stable key - for normal column configs the options object is reused
|
|
82
|
-
// (declared in module scope), so this stringifies a small static shape.
|
|
83
|
-
const key =
|
|
84
|
-
(Array.isArray(locales) ? locales.join(',') : locales ?? '') +
|
|
85
|
-
'|' +
|
|
86
|
-
(options.style ?? '') +
|
|
87
|
-
'|' +
|
|
88
|
-
(options.currency ?? '') +
|
|
89
|
-
'|' +
|
|
90
|
-
(options.minimumFractionDigits ?? '') +
|
|
91
|
-
'|' +
|
|
92
|
-
(options.maximumFractionDigits ?? '') +
|
|
93
|
-
'|' +
|
|
94
|
-
(options.useGrouping ?? '') +
|
|
95
|
-
'|' +
|
|
96
|
-
(options.currencyDisplay ?? '') +
|
|
97
|
-
'|' +
|
|
98
|
-
(options.notation ?? '')
|
|
99
|
-
let fmt = numberFormatterCache.get(key)
|
|
100
|
-
if (!fmt) {
|
|
101
|
-
fmt = new Intl.NumberFormat(locales, options)
|
|
102
|
-
numberFormatterCache.set(key, fmt)
|
|
103
|
-
}
|
|
104
|
-
return fmt
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** Cache of `Intl.DateTimeFormat` by `(locale, options)` signature. */
|
|
108
|
-
const dateFormatterCache = new Map<string, Intl.DateTimeFormat>()
|
|
109
|
-
export function getDateFormatter(
|
|
110
|
-
locales: string | string[] | undefined,
|
|
111
|
-
options: Intl.DateTimeFormatOptions,
|
|
112
|
-
): Intl.DateTimeFormat {
|
|
113
|
-
const key =
|
|
114
|
-
(Array.isArray(locales) ? locales.join(',') : locales ?? '') +
|
|
115
|
-
'|' +
|
|
116
|
-
(options.dateStyle ?? '') +
|
|
117
|
-
'|' +
|
|
118
|
-
(options.timeStyle ?? '') +
|
|
119
|
-
'|' +
|
|
120
|
-
(options.year ?? '') +
|
|
121
|
-
'|' +
|
|
122
|
-
(options.month ?? '') +
|
|
123
|
-
'|' +
|
|
124
|
-
(options.day ?? '') +
|
|
125
|
-
'|' +
|
|
126
|
-
(options.hour ?? '') +
|
|
127
|
-
'|' +
|
|
128
|
-
(options.minute ?? '') +
|
|
129
|
-
'|' +
|
|
130
|
-
(options.second ?? '') +
|
|
131
|
-
'|' +
|
|
132
|
-
(options.weekday ?? '') +
|
|
133
|
-
'|' +
|
|
134
|
-
(options.hour12 ?? '')
|
|
135
|
-
let fmt = dateFormatterCache.get(key)
|
|
136
|
-
if (!fmt) {
|
|
137
|
-
fmt = new Intl.DateTimeFormat(locales, options)
|
|
138
|
-
dateFormatterCache.set(key, fmt)
|
|
139
|
-
}
|
|
140
|
-
return fmt
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/** Format a numeric value for number / currency / percent column formats. */
|
|
144
|
-
export function formatNumericWithConfig(value: unknown, config: NumericFormatInput): string {
|
|
145
|
-
const n = typeof value === 'number' ? value : Number(value)
|
|
146
|
-
if (!Number.isFinite(n)) return String(value ?? '')
|
|
147
|
-
|
|
148
|
-
const locales = config.locales
|
|
149
|
-
|
|
150
|
-
if (config.type === 'currency') {
|
|
151
|
-
return getNumberFormatter(locales, {
|
|
152
|
-
style: 'currency',
|
|
153
|
-
currency: config.currency ?? 'USD',
|
|
154
|
-
...config.options,
|
|
155
|
-
}).format(n)
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (config.type === 'percent') {
|
|
159
|
-
const frac = config.valueIsPercentPoints === true ? n / 100 : n
|
|
160
|
-
return getNumberFormatter(locales, {
|
|
161
|
-
style: 'percent',
|
|
162
|
-
minimumFractionDigits: 0,
|
|
163
|
-
maximumFractionDigits: 2,
|
|
164
|
-
...config.options,
|
|
165
|
-
}).format(frac)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return getNumberFormatter(locales, config.options ?? {}).format(n)
|
|
169
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Helpers for SvGrid column `format` presets (numbers, currency, percent, date patterns).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** Map shortcut date patterns to Intl options (merged with caller `options`). */
|
|
6
|
+
export function resolveDatePattern(
|
|
7
|
+
pattern: string | undefined,
|
|
8
|
+
kind: 'date' | 'datetime',
|
|
9
|
+
): Intl.DateTimeFormatOptions | undefined {
|
|
10
|
+
if (!pattern) return undefined
|
|
11
|
+
|
|
12
|
+
const p = pattern.trim()
|
|
13
|
+
|
|
14
|
+
switch (p) {
|
|
15
|
+
/** Short numeric local date (no weekday). */
|
|
16
|
+
case 'd':
|
|
17
|
+
return kind === 'datetime'
|
|
18
|
+
? {
|
|
19
|
+
year: 'numeric',
|
|
20
|
+
month: 'numeric',
|
|
21
|
+
day: 'numeric',
|
|
22
|
+
hour: 'numeric',
|
|
23
|
+
minute: 'numeric',
|
|
24
|
+
}
|
|
25
|
+
: { year: 'numeric', month: 'numeric', day: 'numeric' }
|
|
26
|
+
/** Long spelled-out date (+ time if datetime). */
|
|
27
|
+
case 'D':
|
|
28
|
+
return kind === 'datetime'
|
|
29
|
+
? {
|
|
30
|
+
weekday: 'long',
|
|
31
|
+
year: 'numeric',
|
|
32
|
+
month: 'long',
|
|
33
|
+
day: 'numeric',
|
|
34
|
+
hour: 'numeric',
|
|
35
|
+
minute: 'numeric',
|
|
36
|
+
}
|
|
37
|
+
: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }
|
|
38
|
+
/** ISO-friendly yyyy-mm-dd (with time when datetime). */
|
|
39
|
+
case 'y-m-d':
|
|
40
|
+
return kind === 'datetime'
|
|
41
|
+
? {
|
|
42
|
+
year: 'numeric',
|
|
43
|
+
month: '2-digit',
|
|
44
|
+
day: '2-digit',
|
|
45
|
+
hour: '2-digit',
|
|
46
|
+
minute: '2-digit',
|
|
47
|
+
hour12: false,
|
|
48
|
+
}
|
|
49
|
+
: { year: 'numeric', month: '2-digit', day: '2-digit' }
|
|
50
|
+
case 'medium':
|
|
51
|
+
return { dateStyle: 'medium', timeStyle: kind === 'datetime' ? 'short' : undefined }
|
|
52
|
+
case 'short':
|
|
53
|
+
return { dateStyle: 'short', timeStyle: kind === 'datetime' ? 'short' : undefined }
|
|
54
|
+
case 'long':
|
|
55
|
+
return { dateStyle: 'long', timeStyle: kind === 'datetime' ? 'short' : undefined }
|
|
56
|
+
default:
|
|
57
|
+
return undefined
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
type NumericFormatInput = {
|
|
62
|
+
type: 'number' | 'currency' | 'percent'
|
|
63
|
+
locales?: string | string[]
|
|
64
|
+
currency?: string
|
|
65
|
+
/** When type is percent: treat value as 0–100 instead of Intl’s 0–1 fraction */
|
|
66
|
+
valueIsPercentPoints?: boolean
|
|
67
|
+
options?: Intl.NumberFormatOptions
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* `Intl.NumberFormat` is one of the most expensive constructors in the
|
|
72
|
+
* platform - building one per cell on every scroll makes large grids
|
|
73
|
+
* noticeably stutter. Cache instances by config signature (locale + style
|
|
74
|
+
* + currency + options).
|
|
75
|
+
*/
|
|
76
|
+
const numberFormatterCache = new Map<string, Intl.NumberFormat>()
|
|
77
|
+
function getNumberFormatter(
|
|
78
|
+
locales: string | string[] | undefined,
|
|
79
|
+
options: Intl.NumberFormatOptions,
|
|
80
|
+
): Intl.NumberFormat {
|
|
81
|
+
// Stable key - for normal column configs the options object is reused
|
|
82
|
+
// (declared in module scope), so this stringifies a small static shape.
|
|
83
|
+
const key =
|
|
84
|
+
(Array.isArray(locales) ? locales.join(',') : locales ?? '') +
|
|
85
|
+
'|' +
|
|
86
|
+
(options.style ?? '') +
|
|
87
|
+
'|' +
|
|
88
|
+
(options.currency ?? '') +
|
|
89
|
+
'|' +
|
|
90
|
+
(options.minimumFractionDigits ?? '') +
|
|
91
|
+
'|' +
|
|
92
|
+
(options.maximumFractionDigits ?? '') +
|
|
93
|
+
'|' +
|
|
94
|
+
(options.useGrouping ?? '') +
|
|
95
|
+
'|' +
|
|
96
|
+
(options.currencyDisplay ?? '') +
|
|
97
|
+
'|' +
|
|
98
|
+
(options.notation ?? '')
|
|
99
|
+
let fmt = numberFormatterCache.get(key)
|
|
100
|
+
if (!fmt) {
|
|
101
|
+
fmt = new Intl.NumberFormat(locales, options)
|
|
102
|
+
numberFormatterCache.set(key, fmt)
|
|
103
|
+
}
|
|
104
|
+
return fmt
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Cache of `Intl.DateTimeFormat` by `(locale, options)` signature. */
|
|
108
|
+
const dateFormatterCache = new Map<string, Intl.DateTimeFormat>()
|
|
109
|
+
export function getDateFormatter(
|
|
110
|
+
locales: string | string[] | undefined,
|
|
111
|
+
options: Intl.DateTimeFormatOptions,
|
|
112
|
+
): Intl.DateTimeFormat {
|
|
113
|
+
const key =
|
|
114
|
+
(Array.isArray(locales) ? locales.join(',') : locales ?? '') +
|
|
115
|
+
'|' +
|
|
116
|
+
(options.dateStyle ?? '') +
|
|
117
|
+
'|' +
|
|
118
|
+
(options.timeStyle ?? '') +
|
|
119
|
+
'|' +
|
|
120
|
+
(options.year ?? '') +
|
|
121
|
+
'|' +
|
|
122
|
+
(options.month ?? '') +
|
|
123
|
+
'|' +
|
|
124
|
+
(options.day ?? '') +
|
|
125
|
+
'|' +
|
|
126
|
+
(options.hour ?? '') +
|
|
127
|
+
'|' +
|
|
128
|
+
(options.minute ?? '') +
|
|
129
|
+
'|' +
|
|
130
|
+
(options.second ?? '') +
|
|
131
|
+
'|' +
|
|
132
|
+
(options.weekday ?? '') +
|
|
133
|
+
'|' +
|
|
134
|
+
(options.hour12 ?? '')
|
|
135
|
+
let fmt = dateFormatterCache.get(key)
|
|
136
|
+
if (!fmt) {
|
|
137
|
+
fmt = new Intl.DateTimeFormat(locales, options)
|
|
138
|
+
dateFormatterCache.set(key, fmt)
|
|
139
|
+
}
|
|
140
|
+
return fmt
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Format a numeric value for number / currency / percent column formats. */
|
|
144
|
+
export function formatNumericWithConfig(value: unknown, config: NumericFormatInput): string {
|
|
145
|
+
const n = typeof value === 'number' ? value : Number(value)
|
|
146
|
+
if (!Number.isFinite(n)) return String(value ?? '')
|
|
147
|
+
|
|
148
|
+
const locales = config.locales
|
|
149
|
+
|
|
150
|
+
if (config.type === 'currency') {
|
|
151
|
+
return getNumberFormatter(locales, {
|
|
152
|
+
style: 'currency',
|
|
153
|
+
currency: config.currency ?? 'USD',
|
|
154
|
+
...config.options,
|
|
155
|
+
}).format(n)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (config.type === 'percent') {
|
|
159
|
+
const frac = config.valueIsPercentPoints === true ? n / 100 : n
|
|
160
|
+
return getNumberFormatter(locales, {
|
|
161
|
+
style: 'percent',
|
|
162
|
+
minimumFractionDigits: 0,
|
|
163
|
+
maximumFractionDigits: 2,
|
|
164
|
+
...config.options,
|
|
165
|
+
}).format(frac)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return getNumberFormatter(locales, config.options ?? {}).format(n)
|
|
169
|
+
}
|
package/src/cell-values.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { formatNumericWithConfig } from "./cell-formatting";
|
|
|
13
13
|
|
|
14
14
|
export function getColumnBaseValue<TData extends RowData>(row: Row<TData>, column: Column<TData>) {
|
|
15
15
|
const def = column.columnDef;
|
|
16
|
-
if (def.
|
|
16
|
+
if (def.fieldFn) return def.fieldFn(row.original);
|
|
17
17
|
if (def.field) return row.original[def.field];
|
|
18
18
|
return row.getCellValueByColumnId(column.id);
|
|
19
19
|
}
|
|
@@ -85,7 +85,7 @@ export function getColumnAlign<TData extends RowData>(column: Column<TData>): "l
|
|
|
85
85
|
/**
|
|
86
86
|
* Read a cell value from a PINNED row. Pinned rows aren't bound to a
|
|
87
87
|
* TanStack Row<TData>, so we resolve the value directly off the raw
|
|
88
|
-
* TData via `
|
|
88
|
+
* TData via `fieldFn` or `field`. Mirrors `getColumnBaseValue`'s
|
|
89
89
|
* lookup path minus the Row indirection.
|
|
90
90
|
*/
|
|
91
91
|
export function getPinnedCellValue<TData extends RowData>(
|
|
@@ -93,7 +93,7 @@ export function getPinnedCellValue<TData extends RowData>(
|
|
|
93
93
|
column: Column<TData>,
|
|
94
94
|
): unknown {
|
|
95
95
|
const def = column.columnDef;
|
|
96
|
-
if (def.
|
|
96
|
+
if (def.fieldFn) return def.fieldFn(rowData);
|
|
97
97
|
const field = def.field as string | undefined;
|
|
98
98
|
if (!field) return undefined;
|
|
99
99
|
return (rowData as unknown as Record<string, unknown>)[field];
|
|
@@ -101,7 +101,7 @@ export function getPinnedCellValue<TData extends RowData>(
|
|
|
101
101
|
|
|
102
102
|
export function getColumnAccessorValue<TData extends RowData>(rowData: TData, column: Column<TData>) {
|
|
103
103
|
const def = column.columnDef;
|
|
104
|
-
if (def.
|
|
104
|
+
if (def.fieldFn) return def.fieldFn(rowData);
|
|
105
105
|
if (def.field) return rowData[def.field];
|
|
106
106
|
return undefined;
|
|
107
107
|
}
|
package/src/column-types.ts
CHANGED
|
@@ -67,7 +67,7 @@ export function resolveColumnTypes(
|
|
|
67
67
|
if (!dt && infer && !hasExplicitEditor && sampleRow != null) {
|
|
68
68
|
const field = col.field;
|
|
69
69
|
const raw =
|
|
70
|
-
col.
|
|
70
|
+
col.fieldFn?.(sampleRow) ??
|
|
71
71
|
(typeof field === "string" ? (sampleRow as Record<string, unknown>)[field] : undefined);
|
|
72
72
|
dt = inferCellDataType(raw);
|
|
73
73
|
}
|
|
@@ -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
|
+
})
|