@svgrid/grid 3.0.0 → 3.0.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/CHANGELOG.md +116 -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 +748 -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-DMihUtma.js → GridMenus-CYzOvmNQ.js} +3 -3
- package/dist/cdn/{GridMenus-nmNDj1a3.js → GridMenus-DFB6iwF8.js} +3 -3
- package/dist/cdn/{SvDateRangeInput-DflbiP7N.js → SvDateRangeInput-CaOuMs8O.js} +1 -1
- package/dist/cdn/{SvDateRangeInput-Bh0A0JkF.js → SvDateRangeInput-DMLKmGEc.js} +1 -1
- package/dist/cdn/{SvDateTimePicker-Bivn8dAP.js → SvDateTimePicker-CCbDZNZB.js} +1 -1
- package/dist/cdn/{SvDateTimePicker-BWwpfB_o.js → SvDateTimePicker-sonaH0oh.js} +1 -1
- package/dist/cdn/{SvGridCellEditor-Ba7rY3eu.js → SvGridCellEditor-BWnTi2N7.js} +2 -2
- package/dist/cdn/{SvGridCellEditor-AXL8cHGO.js → SvGridCellEditor-CjEJMJKc.js} +2 -2
- package/dist/cdn/{SvGridChart-CwhFz7GV.js → SvGridChart-BEJmNNx9.js} +1 -1
- package/dist/cdn/{SvGridChart-Bs2GIR2Q.js → SvGridChart-BwVos976.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-1WXuStzM.js → SvGridChartPanel-BOknOkrP.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-e5_nqNP9.js → SvGridChartPanel-D2PjII4O.js} +1 -1
- package/dist/cdn/{SvGridChartView-SmPW10dI.js → SvGridChartView-00LPUHL1.js} +1 -1
- package/dist/cdn/{SvGridChartView-eSPuJE6g.js → SvGridChartView-BhUEJ5ki.js} +1 -1
- package/dist/cdn/{SvGridDropdown-B1ZcLpgs.js → SvGridDropdown-D0VdjeR8.js} +1 -1
- package/dist/cdn/{SvGridDropdown-CtdbHcIS.js → SvGridDropdown-D13MtJ2j.js} +1 -1
- package/dist/cdn/{date-format-DZT7T1wf.js → date-format-BNii4zeD.js} +2 -2
- package/dist/cdn/{date-format-CcP1tafP.js → date-format-BnnHlqGw.js} +2 -2
- package/dist/cdn/{src-B_YS5AOc.js → src-C8QjSaq-.js} +42 -44
- package/dist/cdn/{src-DYXXpuSk.js → src-D0hO2eYN.js} +41 -43
- 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/editing.js +22 -13
- 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 +748 -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 +618 -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.test.ts +401 -401
- package/src/row-drag.ts +419 -419
- 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 +382 -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/dist/FlexRender.svelte
CHANGED
|
@@ -1,96 +1,96 @@
|
|
|
1
|
-
<script
|
|
2
|
-
lang="ts"
|
|
3
|
-
generics="TData extends RowData"
|
|
4
|
-
>
|
|
5
|
-
import { isFunction } from './core'
|
|
6
|
-
import {
|
|
7
|
-
RenderComponentConfig,
|
|
8
|
-
RenderSnippetConfig,
|
|
9
|
-
} from './render-component'
|
|
10
|
-
import type {
|
|
11
|
-
Cell,
|
|
12
|
-
CellContext,
|
|
13
|
-
ColumnDefTemplate,
|
|
14
|
-
Header,
|
|
15
|
-
HeaderContext,
|
|
16
|
-
RowData,
|
|
17
|
-
} from './core'
|
|
18
|
-
|
|
19
|
-
type Props =
|
|
20
|
-
| {
|
|
21
|
-
content?: ColumnDefTemplate<
|
|
22
|
-
| HeaderContext<TData>
|
|
23
|
-
| CellContext<TData>
|
|
24
|
-
>
|
|
25
|
-
context:
|
|
26
|
-
| HeaderContext<TData>
|
|
27
|
-
| CellContext<TData>
|
|
28
|
-
cell?: never
|
|
29
|
-
header?: never
|
|
30
|
-
footer?: never
|
|
31
|
-
}
|
|
32
|
-
| {
|
|
33
|
-
cell: Cell<TData>
|
|
34
|
-
content?: never
|
|
35
|
-
context?: never
|
|
36
|
-
header?: never
|
|
37
|
-
footer?: never
|
|
38
|
-
}
|
|
39
|
-
| {
|
|
40
|
-
header: Header<TData>
|
|
41
|
-
content?: never
|
|
42
|
-
context?: never
|
|
43
|
-
cell?: never
|
|
44
|
-
footer?: never
|
|
45
|
-
}
|
|
46
|
-
| {
|
|
47
|
-
footer: Header<TData>
|
|
48
|
-
content?: never
|
|
49
|
-
context?: never
|
|
50
|
-
cell?: never
|
|
51
|
-
header?: never
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
let props: Props = $props()
|
|
55
|
-
|
|
56
|
-
const resolved = $derived.by(() => {
|
|
57
|
-
if ('cell' in props && props.cell) {
|
|
58
|
-
return {
|
|
59
|
-
content: props.cell.column.columnDef.cell,
|
|
60
|
-
context: props.cell.getContext(),
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if ('header' in props && props.header) {
|
|
64
|
-
return {
|
|
65
|
-
content: props.header.column.columnDef.header,
|
|
66
|
-
context: props.header.getContext(),
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if ('footer' in props && props.footer) {
|
|
70
|
-
return {
|
|
71
|
-
content: props.footer.column.columnDef.footer,
|
|
72
|
-
context: props.footer.getContext(),
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
content: props.content,
|
|
77
|
-
context: props.context,
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
const result = $derived(
|
|
82
|
-
isFunction(resolved.content)
|
|
83
|
-
? resolved.content(resolved.context as any)
|
|
84
|
-
: undefined,
|
|
85
|
-
)
|
|
86
|
-
</script>
|
|
87
|
-
|
|
88
|
-
{#if typeof resolved.content === 'string'}
|
|
89
|
-
{resolved.content}
|
|
90
|
-
{:else if result instanceof RenderComponentConfig}
|
|
91
|
-
<result.component {...result.props} />
|
|
92
|
-
{:else if result instanceof RenderSnippetConfig}
|
|
93
|
-
{@render result.snippet(result.params)}
|
|
94
|
-
{:else if result !== undefined}
|
|
95
|
-
{result}
|
|
96
|
-
{/if}
|
|
1
|
+
<script
|
|
2
|
+
lang="ts"
|
|
3
|
+
generics="TData extends RowData"
|
|
4
|
+
>
|
|
5
|
+
import { isFunction } from './core'
|
|
6
|
+
import {
|
|
7
|
+
RenderComponentConfig,
|
|
8
|
+
RenderSnippetConfig,
|
|
9
|
+
} from './render-component'
|
|
10
|
+
import type {
|
|
11
|
+
Cell,
|
|
12
|
+
CellContext,
|
|
13
|
+
ColumnDefTemplate,
|
|
14
|
+
Header,
|
|
15
|
+
HeaderContext,
|
|
16
|
+
RowData,
|
|
17
|
+
} from './core'
|
|
18
|
+
|
|
19
|
+
type Props =
|
|
20
|
+
| {
|
|
21
|
+
content?: ColumnDefTemplate<
|
|
22
|
+
| HeaderContext<TData>
|
|
23
|
+
| CellContext<TData>
|
|
24
|
+
>
|
|
25
|
+
context:
|
|
26
|
+
| HeaderContext<TData>
|
|
27
|
+
| CellContext<TData>
|
|
28
|
+
cell?: never
|
|
29
|
+
header?: never
|
|
30
|
+
footer?: never
|
|
31
|
+
}
|
|
32
|
+
| {
|
|
33
|
+
cell: Cell<TData>
|
|
34
|
+
content?: never
|
|
35
|
+
context?: never
|
|
36
|
+
header?: never
|
|
37
|
+
footer?: never
|
|
38
|
+
}
|
|
39
|
+
| {
|
|
40
|
+
header: Header<TData>
|
|
41
|
+
content?: never
|
|
42
|
+
context?: never
|
|
43
|
+
cell?: never
|
|
44
|
+
footer?: never
|
|
45
|
+
}
|
|
46
|
+
| {
|
|
47
|
+
footer: Header<TData>
|
|
48
|
+
content?: never
|
|
49
|
+
context?: never
|
|
50
|
+
cell?: never
|
|
51
|
+
header?: never
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let props: Props = $props()
|
|
55
|
+
|
|
56
|
+
const resolved = $derived.by(() => {
|
|
57
|
+
if ('cell' in props && props.cell) {
|
|
58
|
+
return {
|
|
59
|
+
content: props.cell.column.columnDef.cell,
|
|
60
|
+
context: props.cell.getContext(),
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if ('header' in props && props.header) {
|
|
64
|
+
return {
|
|
65
|
+
content: props.header.column.columnDef.header,
|
|
66
|
+
context: props.header.getContext(),
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if ('footer' in props && props.footer) {
|
|
70
|
+
return {
|
|
71
|
+
content: props.footer.column.columnDef.footer,
|
|
72
|
+
context: props.footer.getContext(),
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
content: props.content,
|
|
77
|
+
context: props.context,
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
const result = $derived(
|
|
82
|
+
isFunction(resolved.content)
|
|
83
|
+
? resolved.content(resolved.context as any)
|
|
84
|
+
: undefined,
|
|
85
|
+
)
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
{#if typeof resolved.content === 'string'}
|
|
89
|
+
{resolved.content}
|
|
90
|
+
{:else if result instanceof RenderComponentConfig}
|
|
91
|
+
<result.component {...result.props} />
|
|
92
|
+
{:else if result instanceof RenderSnippetConfig}
|
|
93
|
+
{@render result.snippet(result.params)}
|
|
94
|
+
{:else if result !== undefined}
|
|
95
|
+
{result}
|
|
96
|
+
{/if}
|
package/dist/GridFooter.svelte
CHANGED
|
@@ -1,181 +1,181 @@
|
|
|
1
|
-
<script lang="ts" generics="TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData">
|
|
2
|
-
import {
|
|
3
|
-
type RowData,
|
|
4
|
-
type TableFeatures,
|
|
5
|
-
} from "./index";
|
|
6
|
-
import "./sv-grid-scrollbar";
|
|
7
|
-
import {
|
|
8
|
-
fmtStat,
|
|
9
|
-
} from "./SvGrid.helpers";
|
|
10
|
-
import type { SvGridController } from "./SvGrid.controller.svelte";
|
|
11
|
-
|
|
12
|
-
let {
|
|
13
|
-
ctrl,
|
|
14
|
-
pager = true,
|
|
15
|
-
showStatus = true,
|
|
16
|
-
top = false,
|
|
17
|
-
pageSizeOptions,
|
|
18
|
-
}: {
|
|
19
|
-
ctrl: SvGridController<TFeatures, TData>;
|
|
20
|
-
/** Render the pagination controls in this instance. */
|
|
21
|
-
pager?: boolean;
|
|
22
|
-
/** Render the status bar in this instance. */
|
|
23
|
-
showStatus?: boolean;
|
|
24
|
-
/** This is a top-positioned footer (styling only). */
|
|
25
|
-
top?: boolean;
|
|
26
|
-
/** Page-size choices for the selector. Defaults to `[10, 25, 50, 100]`. */
|
|
27
|
-
pageSizeOptions?: number[];
|
|
28
|
-
} = $props();
|
|
29
|
-
|
|
30
|
-
// SvGridDropdown is ~22 KB and exists here only to pick one of four numbers.
|
|
31
|
-
// Importing it statically also dragged it into the base bundle and silently
|
|
32
|
-
// defeated the lazy `import()` in SvGrid.svelte, which loads the same
|
|
33
|
-
// component as a cell editor. So the closed trigger below is plain markup
|
|
34
|
-
// reusing the dropdown's own classes (identical appearance), and the real
|
|
35
|
-
// component is fetched on first open. Keep this lazy: a static import here
|
|
36
|
-
// re-breaks the cell-editor split too, not just the footer.
|
|
37
|
-
let PageSizeDropdown = $state<typeof import("./SvGridDropdown.svelte").default | null>(null);
|
|
38
|
-
let loadingPageSize = $state(false);
|
|
39
|
-
|
|
40
|
-
async function openPageSize() {
|
|
41
|
-
if (PageSizeDropdown || loadingPageSize) return;
|
|
42
|
-
loadingPageSize = true;
|
|
43
|
-
try {
|
|
44
|
-
PageSizeDropdown = (await import("./SvGridDropdown.svelte")).default;
|
|
45
|
-
} finally {
|
|
46
|
-
loadingPageSize = false;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// View facade: re-bind the controller's reactive members so the markup
|
|
51
|
-
// (moved verbatim from SvGrid.svelte) stays identical.
|
|
52
|
-
const paginationEnabled = $derived(ctrl.paginationEnabled);
|
|
53
|
-
const statusBarEnabled = $derived(ctrl.statusBarEnabled);
|
|
54
|
-
const statusBarAggregates = $derived(ctrl.statusBarAggregates);
|
|
55
|
-
const statusBarStats = $derived(ctrl.statusBarStats);
|
|
56
|
-
const changePage = $derived(ctrl.changePage);
|
|
57
|
-
const goToPage = $derived(ctrl.goToPage);
|
|
58
|
-
const setPageSize = $derived(ctrl.setPageSize);
|
|
59
|
-
const messages = $derived(ctrl.messages);
|
|
60
|
-
</script>
|
|
61
|
-
|
|
62
|
-
{#if showStatus && statusBarEnabled && statusBarStats}
|
|
63
|
-
{@const s = statusBarStats}
|
|
64
|
-
<div class="sv-grid-status-bar" role="status" aria-live="polite">
|
|
65
|
-
{#each statusBarAggregates as agg (agg)}
|
|
66
|
-
{#if agg === "count"}
|
|
67
|
-
<span class="sv-grid-status-item"
|
|
68
|
-
><span class="sv-grid-status-label">{messages.statCount}</span>{fmtStat(s.count)}</span
|
|
69
|
-
>
|
|
70
|
-
{:else if agg === "numericCount"}
|
|
71
|
-
<span class="sv-grid-status-item"
|
|
72
|
-
><span class="sv-grid-status-label">Numeric</span>{fmtStat(s.numericCount)}</span
|
|
73
|
-
>
|
|
74
|
-
{:else if s.numericCount > 0 && agg === "sum"}
|
|
75
|
-
<span class="sv-grid-status-item"
|
|
76
|
-
><span class="sv-grid-status-label">{messages.statSum}</span>{fmtStat(s.sum)}</span
|
|
77
|
-
>
|
|
78
|
-
{:else if s.numericCount > 0 && agg === "avg"}
|
|
79
|
-
<span class="sv-grid-status-item"
|
|
80
|
-
><span class="sv-grid-status-label">{messages.statAvg}</span>{fmtStat(s.avg)}</span
|
|
81
|
-
>
|
|
82
|
-
{:else if s.numericCount > 0 && agg === "min"}
|
|
83
|
-
<span class="sv-grid-status-item"
|
|
84
|
-
><span class="sv-grid-status-label">{messages.statMin}</span>{fmtStat(s.min)}</span
|
|
85
|
-
>
|
|
86
|
-
{:else if s.numericCount > 0 && agg === "max"}
|
|
87
|
-
<span class="sv-grid-status-item"
|
|
88
|
-
><span class="sv-grid-status-label">{messages.statMax}</span>{fmtStat(s.max)}</span
|
|
89
|
-
>
|
|
90
|
-
{/if}
|
|
91
|
-
{/each}
|
|
92
|
-
</div>
|
|
93
|
-
{/if}
|
|
94
|
-
|
|
95
|
-
{#if pager && paginationEnabled}
|
|
96
|
-
{@const totalRows = ctrl.paginationTotalRows}
|
|
97
|
-
{@const pageSize = ctrl.paginationPageSize}
|
|
98
|
-
{@const pageCount = Math.max(1, Math.ceil(totalRows / pageSize))}
|
|
99
|
-
{@const currentPage = Math.min(ctrl.paginationPageIndex + 1, pageCount)}
|
|
100
|
-
{@const rangeStart =
|
|
101
|
-
totalRows === 0 ? 0 : (currentPage - 1) * pageSize + 1}
|
|
102
|
-
{@const rangeEnd = Math.min(totalRows, currentPage * pageSize)}
|
|
103
|
-
{@const onFirst = currentPage <= 1}
|
|
104
|
-
{@const onLast = currentPage >= pageCount}
|
|
105
|
-
{@const sizes = pageSizeOptions && pageSizeOptions.length ? pageSizeOptions : [10, 25, 50, 100]}
|
|
106
|
-
<div class="sv-grid-pagination" class:sv-grid-pagination-top={top} role="navigation" aria-label="Pagination">
|
|
107
|
-
<div class="sv-grid-pagination-pagesize">
|
|
108
|
-
<span>{messages.pageSize}</span>
|
|
109
|
-
<div class="sv-grid-pagination-pagesize-dd">
|
|
110
|
-
{#if PageSizeDropdown}
|
|
111
|
-
<!-- autoOpen so the click that triggered the load also opens the
|
|
112
|
-
panel, rather than making the user click a second time. -->
|
|
113
|
-
<PageSizeDropdown
|
|
114
|
-
options={sizes.map((n) => ({ value: n, label: String(n) }))}
|
|
115
|
-
value={pageSize}
|
|
116
|
-
autoOpen={true}
|
|
117
|
-
onChange={(v) => setPageSize(Number(v))}
|
|
118
|
-
/>
|
|
119
|
-
{:else}
|
|
120
|
-
<!-- Mirrors SvGridDropdown's closed trigger (same classes, same
|
|
121
|
-
ARIA). Its box styling comes from the global
|
|
122
|
-
.sv-grid-pagination-pagesize-dd rules in SvGrid.css, NOT from
|
|
123
|
-
SvGridDropdown's scoped styles (those only exist once the chunk
|
|
124
|
-
loads) - so keep the two in step or the placeholder renders as
|
|
125
|
-
a stock <button> until the first click. -->
|
|
126
|
-
<div class="sv-grid-dropdown">
|
|
127
|
-
<button
|
|
128
|
-
type="button"
|
|
129
|
-
class="sv-grid-dropdown-trigger"
|
|
130
|
-
aria-haspopup="listbox"
|
|
131
|
-
aria-expanded="false"
|
|
132
|
-
onclick={openPageSize}
|
|
133
|
-
>
|
|
134
|
-
<span class="sv-grid-dropdown-label">{pageSize}</span>
|
|
135
|
-
<span class="sv-grid-dropdown-caret" aria-hidden="true">▾</span>
|
|
136
|
-
</button>
|
|
137
|
-
</div>
|
|
138
|
-
{/if}
|
|
139
|
-
</div>
|
|
140
|
-
</div>
|
|
141
|
-
<span class="sv-grid-pagination-range">
|
|
142
|
-
<strong>{rangeStart.toLocaleString()}</strong> to
|
|
143
|
-
<strong>{rangeEnd.toLocaleString()}</strong> of
|
|
144
|
-
<strong>{totalRows.toLocaleString()}</strong>
|
|
145
|
-
</span>
|
|
146
|
-
<div class="sv-grid-pagination-nav">
|
|
147
|
-
<button
|
|
148
|
-
type="button"
|
|
149
|
-
class="sv-grid-pagination-btn"
|
|
150
|
-
disabled={onFirst}
|
|
151
|
-
onclick={() => goToPage(0)}
|
|
152
|
-
aria-label={messages.firstPage}>⇤</button
|
|
153
|
-
>
|
|
154
|
-
<button
|
|
155
|
-
type="button"
|
|
156
|
-
class="sv-grid-pagination-btn"
|
|
157
|
-
disabled={onFirst}
|
|
158
|
-
onclick={() => changePage(-1)}
|
|
159
|
-
aria-label={messages.prevPage}>‹</button
|
|
160
|
-
>
|
|
161
|
-
<span class="sv-grid-pagination-label">
|
|
162
|
-
{messages.page} <strong>{currentPage.toLocaleString()}</strong> {messages.of}
|
|
163
|
-
<strong>{pageCount.toLocaleString()}</strong>
|
|
164
|
-
</span>
|
|
165
|
-
<button
|
|
166
|
-
type="button"
|
|
167
|
-
class="sv-grid-pagination-btn"
|
|
168
|
-
disabled={onLast}
|
|
169
|
-
onclick={() => changePage(1)}
|
|
170
|
-
aria-label={messages.nextPage}>›</button
|
|
171
|
-
>
|
|
172
|
-
<button
|
|
173
|
-
type="button"
|
|
174
|
-
class="sv-grid-pagination-btn"
|
|
175
|
-
disabled={onLast}
|
|
176
|
-
onclick={() => goToPage(pageCount - 1)}
|
|
177
|
-
aria-label={messages.lastPage}>⇥</button
|
|
178
|
-
>
|
|
179
|
-
</div>
|
|
180
|
-
</div>
|
|
181
|
-
{/if}
|
|
1
|
+
<script lang="ts" generics="TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData">
|
|
2
|
+
import {
|
|
3
|
+
type RowData,
|
|
4
|
+
type TableFeatures,
|
|
5
|
+
} from "./index";
|
|
6
|
+
import "./sv-grid-scrollbar";
|
|
7
|
+
import {
|
|
8
|
+
fmtStat,
|
|
9
|
+
} from "./SvGrid.helpers";
|
|
10
|
+
import type { SvGridController } from "./SvGrid.controller.svelte";
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
ctrl,
|
|
14
|
+
pager = true,
|
|
15
|
+
showStatus = true,
|
|
16
|
+
top = false,
|
|
17
|
+
pageSizeOptions,
|
|
18
|
+
}: {
|
|
19
|
+
ctrl: SvGridController<TFeatures, TData>;
|
|
20
|
+
/** Render the pagination controls in this instance. */
|
|
21
|
+
pager?: boolean;
|
|
22
|
+
/** Render the status bar in this instance. */
|
|
23
|
+
showStatus?: boolean;
|
|
24
|
+
/** This is a top-positioned footer (styling only). */
|
|
25
|
+
top?: boolean;
|
|
26
|
+
/** Page-size choices for the selector. Defaults to `[10, 25, 50, 100]`. */
|
|
27
|
+
pageSizeOptions?: number[];
|
|
28
|
+
} = $props();
|
|
29
|
+
|
|
30
|
+
// SvGridDropdown is ~22 KB and exists here only to pick one of four numbers.
|
|
31
|
+
// Importing it statically also dragged it into the base bundle and silently
|
|
32
|
+
// defeated the lazy `import()` in SvGrid.svelte, which loads the same
|
|
33
|
+
// component as a cell editor. So the closed trigger below is plain markup
|
|
34
|
+
// reusing the dropdown's own classes (identical appearance), and the real
|
|
35
|
+
// component is fetched on first open. Keep this lazy: a static import here
|
|
36
|
+
// re-breaks the cell-editor split too, not just the footer.
|
|
37
|
+
let PageSizeDropdown = $state<typeof import("./SvGridDropdown.svelte").default | null>(null);
|
|
38
|
+
let loadingPageSize = $state(false);
|
|
39
|
+
|
|
40
|
+
async function openPageSize() {
|
|
41
|
+
if (PageSizeDropdown || loadingPageSize) return;
|
|
42
|
+
loadingPageSize = true;
|
|
43
|
+
try {
|
|
44
|
+
PageSizeDropdown = (await import("./SvGridDropdown.svelte")).default;
|
|
45
|
+
} finally {
|
|
46
|
+
loadingPageSize = false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// View facade: re-bind the controller's reactive members so the markup
|
|
51
|
+
// (moved verbatim from SvGrid.svelte) stays identical.
|
|
52
|
+
const paginationEnabled = $derived(ctrl.paginationEnabled);
|
|
53
|
+
const statusBarEnabled = $derived(ctrl.statusBarEnabled);
|
|
54
|
+
const statusBarAggregates = $derived(ctrl.statusBarAggregates);
|
|
55
|
+
const statusBarStats = $derived(ctrl.statusBarStats);
|
|
56
|
+
const changePage = $derived(ctrl.changePage);
|
|
57
|
+
const goToPage = $derived(ctrl.goToPage);
|
|
58
|
+
const setPageSize = $derived(ctrl.setPageSize);
|
|
59
|
+
const messages = $derived(ctrl.messages);
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
{#if showStatus && statusBarEnabled && statusBarStats}
|
|
63
|
+
{@const s = statusBarStats}
|
|
64
|
+
<div class="sv-grid-status-bar" role="status" aria-live="polite">
|
|
65
|
+
{#each statusBarAggregates as agg (agg)}
|
|
66
|
+
{#if agg === "count"}
|
|
67
|
+
<span class="sv-grid-status-item"
|
|
68
|
+
><span class="sv-grid-status-label">{messages.statCount}</span>{fmtStat(s.count)}</span
|
|
69
|
+
>
|
|
70
|
+
{:else if agg === "numericCount"}
|
|
71
|
+
<span class="sv-grid-status-item"
|
|
72
|
+
><span class="sv-grid-status-label">Numeric</span>{fmtStat(s.numericCount)}</span
|
|
73
|
+
>
|
|
74
|
+
{:else if s.numericCount > 0 && agg === "sum"}
|
|
75
|
+
<span class="sv-grid-status-item"
|
|
76
|
+
><span class="sv-grid-status-label">{messages.statSum}</span>{fmtStat(s.sum)}</span
|
|
77
|
+
>
|
|
78
|
+
{:else if s.numericCount > 0 && agg === "avg"}
|
|
79
|
+
<span class="sv-grid-status-item"
|
|
80
|
+
><span class="sv-grid-status-label">{messages.statAvg}</span>{fmtStat(s.avg)}</span
|
|
81
|
+
>
|
|
82
|
+
{:else if s.numericCount > 0 && agg === "min"}
|
|
83
|
+
<span class="sv-grid-status-item"
|
|
84
|
+
><span class="sv-grid-status-label">{messages.statMin}</span>{fmtStat(s.min)}</span
|
|
85
|
+
>
|
|
86
|
+
{:else if s.numericCount > 0 && agg === "max"}
|
|
87
|
+
<span class="sv-grid-status-item"
|
|
88
|
+
><span class="sv-grid-status-label">{messages.statMax}</span>{fmtStat(s.max)}</span
|
|
89
|
+
>
|
|
90
|
+
{/if}
|
|
91
|
+
{/each}
|
|
92
|
+
</div>
|
|
93
|
+
{/if}
|
|
94
|
+
|
|
95
|
+
{#if pager && paginationEnabled}
|
|
96
|
+
{@const totalRows = ctrl.paginationTotalRows}
|
|
97
|
+
{@const pageSize = ctrl.paginationPageSize}
|
|
98
|
+
{@const pageCount = Math.max(1, Math.ceil(totalRows / pageSize))}
|
|
99
|
+
{@const currentPage = Math.min(ctrl.paginationPageIndex + 1, pageCount)}
|
|
100
|
+
{@const rangeStart =
|
|
101
|
+
totalRows === 0 ? 0 : (currentPage - 1) * pageSize + 1}
|
|
102
|
+
{@const rangeEnd = Math.min(totalRows, currentPage * pageSize)}
|
|
103
|
+
{@const onFirst = currentPage <= 1}
|
|
104
|
+
{@const onLast = currentPage >= pageCount}
|
|
105
|
+
{@const sizes = pageSizeOptions && pageSizeOptions.length ? pageSizeOptions : [10, 25, 50, 100]}
|
|
106
|
+
<div class="sv-grid-pagination" class:sv-grid-pagination-top={top} role="navigation" aria-label="Pagination">
|
|
107
|
+
<div class="sv-grid-pagination-pagesize">
|
|
108
|
+
<span>{messages.pageSize}</span>
|
|
109
|
+
<div class="sv-grid-pagination-pagesize-dd">
|
|
110
|
+
{#if PageSizeDropdown}
|
|
111
|
+
<!-- autoOpen so the click that triggered the load also opens the
|
|
112
|
+
panel, rather than making the user click a second time. -->
|
|
113
|
+
<PageSizeDropdown
|
|
114
|
+
options={sizes.map((n) => ({ value: n, label: String(n) }))}
|
|
115
|
+
value={pageSize}
|
|
116
|
+
autoOpen={true}
|
|
117
|
+
onChange={(v) => setPageSize(Number(v))}
|
|
118
|
+
/>
|
|
119
|
+
{:else}
|
|
120
|
+
<!-- Mirrors SvGridDropdown's closed trigger (same classes, same
|
|
121
|
+
ARIA). Its box styling comes from the global
|
|
122
|
+
.sv-grid-pagination-pagesize-dd rules in SvGrid.css, NOT from
|
|
123
|
+
SvGridDropdown's scoped styles (those only exist once the chunk
|
|
124
|
+
loads) - so keep the two in step or the placeholder renders as
|
|
125
|
+
a stock <button> until the first click. -->
|
|
126
|
+
<div class="sv-grid-dropdown">
|
|
127
|
+
<button
|
|
128
|
+
type="button"
|
|
129
|
+
class="sv-grid-dropdown-trigger"
|
|
130
|
+
aria-haspopup="listbox"
|
|
131
|
+
aria-expanded="false"
|
|
132
|
+
onclick={openPageSize}
|
|
133
|
+
>
|
|
134
|
+
<span class="sv-grid-dropdown-label">{pageSize}</span>
|
|
135
|
+
<span class="sv-grid-dropdown-caret" aria-hidden="true">▾</span>
|
|
136
|
+
</button>
|
|
137
|
+
</div>
|
|
138
|
+
{/if}
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
<span class="sv-grid-pagination-range">
|
|
142
|
+
<strong>{rangeStart.toLocaleString()}</strong> to
|
|
143
|
+
<strong>{rangeEnd.toLocaleString()}</strong> of
|
|
144
|
+
<strong>{totalRows.toLocaleString()}</strong>
|
|
145
|
+
</span>
|
|
146
|
+
<div class="sv-grid-pagination-nav">
|
|
147
|
+
<button
|
|
148
|
+
type="button"
|
|
149
|
+
class="sv-grid-pagination-btn"
|
|
150
|
+
disabled={onFirst}
|
|
151
|
+
onclick={() => goToPage(0)}
|
|
152
|
+
aria-label={messages.firstPage}>⇤</button
|
|
153
|
+
>
|
|
154
|
+
<button
|
|
155
|
+
type="button"
|
|
156
|
+
class="sv-grid-pagination-btn"
|
|
157
|
+
disabled={onFirst}
|
|
158
|
+
onclick={() => changePage(-1)}
|
|
159
|
+
aria-label={messages.prevPage}>‹</button
|
|
160
|
+
>
|
|
161
|
+
<span class="sv-grid-pagination-label">
|
|
162
|
+
{messages.page} <strong>{currentPage.toLocaleString()}</strong> {messages.of}
|
|
163
|
+
<strong>{pageCount.toLocaleString()}</strong>
|
|
164
|
+
</span>
|
|
165
|
+
<button
|
|
166
|
+
type="button"
|
|
167
|
+
class="sv-grid-pagination-btn"
|
|
168
|
+
disabled={onLast}
|
|
169
|
+
onclick={() => changePage(1)}
|
|
170
|
+
aria-label={messages.nextPage}>›</button
|
|
171
|
+
>
|
|
172
|
+
<button
|
|
173
|
+
type="button"
|
|
174
|
+
class="sv-grid-pagination-btn"
|
|
175
|
+
disabled={onLast}
|
|
176
|
+
onclick={() => goToPage(pageCount - 1)}
|
|
177
|
+
aria-label={messages.lastPage}>⇥</button
|
|
178
|
+
>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
{/if}
|