@svgrid/grid 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +137 -39
- package/dist/GridFooter.svelte +164 -0
- package/dist/GridFooter.svelte.d.ts +29 -0
- package/dist/GridMenus.svelte +570 -0
- package/dist/GridMenus.svelte.d.ts +31 -0
- package/dist/SvGrid.controller.svelte.d.ts +429 -0
- package/dist/SvGrid.controller.svelte.js +1732 -0
- package/dist/SvGrid.css +1709 -0
- package/dist/SvGrid.helpers.d.ts +35 -0
- package/dist/SvGrid.helpers.js +160 -0
- package/dist/SvGrid.svelte +344 -7043
- package/dist/SvGrid.svelte.d.ts +4 -357
- package/dist/SvGrid.types.d.ts +436 -0
- package/dist/SvGrid.types.js +1 -0
- package/dist/SvGridChart.svelte +1060 -23
- package/dist/SvGridChart.svelte.d.ts +17 -0
- package/dist/build-api.d.ts +5 -0
- package/dist/build-api.js +527 -0
- package/dist/cell-render.d.ts +15 -0
- package/dist/cell-render.js +246 -0
- package/dist/cell-values.d.ts +28 -0
- package/dist/cell-values.js +89 -0
- package/dist/chart.d.ts +370 -3
- package/dist/chart.js +1135 -42
- package/dist/clipboard.d.ts +15 -0
- package/dist/clipboard.js +356 -0
- package/dist/columns.d.ts +30 -0
- package/dist/columns.js +277 -0
- package/dist/core.d.ts +1 -1
- package/dist/css.d.ts +3 -0
- package/dist/editing.d.ts +24 -0
- package/dist/editing.js +343 -0
- package/dist/editors/cell-editors.d.ts +1 -1
- package/dist/facet-buckets.d.ts +13 -0
- package/dist/facet-buckets.js +54 -0
- package/dist/features.d.ts +5 -0
- package/dist/features.js +30 -0
- package/dist/filter-operators.d.ts +16 -0
- package/dist/filter-operators.js +69 -0
- package/dist/hyperformula-adapter.d.ts +82 -0
- package/dist/hyperformula-adapter.js +73 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +5 -2
- package/dist/keyboard-handlers.d.ts +7 -0
- package/dist/keyboard-handlers.js +197 -0
- package/dist/menus.d.ts +40 -0
- package/dist/menus.js +389 -0
- package/dist/named-views.d.ts +27 -0
- package/dist/named-views.js +39 -0
- package/dist/row-resize.d.ts +43 -0
- package/dist/row-resize.js +158 -0
- package/dist/scroll-sync.d.ts +9 -0
- package/dist/scroll-sync.js +86 -0
- package/dist/selection.d.ts +26 -0
- package/dist/selection.js +387 -0
- package/dist/spreadsheet.d.ts +80 -0
- package/dist/spreadsheet.js +194 -0
- package/dist/summaries.d.ts +12 -0
- package/dist/summaries.js +65 -0
- package/dist/svgrid-wrapper.types.d.ts +12 -1
- package/dist/svgrid.comments-autocomplete.test.d.ts +1 -0
- package/dist/svgrid.comments-autocomplete.test.js +96 -0
- package/dist/svgrid.context-menu.test.d.ts +1 -0
- package/dist/svgrid.context-menu.test.js +102 -0
- package/dist/svgrid.new-features.wrapper.test.js +30 -4
- package/dist/svgrid.wrapper.test.js +27 -1
- package/dist/virtualization/column-virtualizer.d.ts +2 -0
- package/dist/virtualization/scroll-scaling.d.ts +28 -0
- package/dist/virtualization/scroll-scaling.js +64 -0
- package/dist/virtualization/scroll-scaling.test.d.ts +1 -0
- package/dist/virtualization/scroll-scaling.test.js +86 -0
- package/dist/virtualization/svelte-virtualizer.svelte.d.ts +2 -0
- package/dist/virtualization/svelte-virtualizer.svelte.js +2 -0
- package/dist/virtualization/virtualizer.d.ts +7 -0
- package/dist/virtualization/virtualizer.js +30 -0
- package/package.json +1 -1
- package/src/GridFooter.svelte +164 -0
- package/src/GridMenus.svelte +570 -0
- package/src/SvGrid.controller.svelte.ts +2195 -0
- package/src/SvGrid.css +1747 -0
- package/src/SvGrid.helpers.test.ts +415 -0
- package/src/SvGrid.helpers.ts +185 -0
- package/src/SvGrid.svelte +348 -7043
- package/src/SvGrid.types.ts +456 -0
- package/src/SvGridChart.svelte +1060 -23
- package/src/build-api.coverage.test.ts +532 -0
- package/src/build-api.ts +663 -0
- package/src/cell-render.test.ts +451 -0
- package/src/cell-render.ts +426 -0
- package/src/cell-values.ts +114 -0
- package/src/chart-export.test.ts +370 -0
- package/src/chart.coverage.test.ts +814 -0
- package/src/chart.ts +1352 -47
- package/src/clipboard.test.ts +731 -0
- package/src/clipboard.ts +524 -0
- package/src/collaboration.coverage.test.ts +220 -0
- package/src/columns.test.ts +702 -0
- package/src/columns.ts +419 -0
- package/src/core.ts +8 -0
- package/src/css.d.ts +3 -0
- package/src/editing.test.ts +837 -0
- package/src/editing.ts +513 -0
- package/src/editors/cell-editors.coverage.test.ts +156 -0
- package/src/editors/cell-editors.ts +1 -0
- package/src/facet-buckets.test.ts +353 -0
- package/src/facet-buckets.ts +67 -0
- package/src/features.ts +128 -0
- package/src/filter-operators.test.ts +174 -0
- package/src/filter-operators.ts +87 -0
- package/src/hyperformula-adapter.test.ts +256 -0
- package/src/hyperformula-adapter.ts +124 -0
- package/src/index.ts +37 -0
- package/src/keyboard-handlers.coverage.test.ts +560 -0
- package/src/keyboard-handlers.ts +353 -0
- package/src/keyboard.ts +97 -97
- package/src/menus.test.ts +620 -0
- package/src/menus.ts +554 -0
- package/src/named-views.coverage.test.ts +210 -0
- package/src/named-views.ts +48 -0
- package/src/row-resize.test.ts +369 -0
- package/src/row-resize.ts +171 -0
- package/src/scroll-sync.test.ts +330 -0
- package/src/scroll-sync.ts +216 -0
- package/src/selection.test.ts +722 -0
- package/src/selection.ts +545 -0
- package/src/server-data-source.coverage.test.ts +180 -0
- package/src/spreadsheet.test.ts +445 -0
- package/src/spreadsheet.ts +246 -0
- package/src/summaries.ts +204 -0
- package/src/sv-grid-scrollbar.ts +13 -1
- package/src/svgrid-wrapper.types.ts +12 -1
- package/src/svgrid.behavior.test.ts +22 -0
- package/src/svgrid.comments-autocomplete.test.ts +112 -0
- package/src/svgrid.context-menu.test.ts +126 -0
- package/src/svgrid.interaction.test.ts +30 -0
- package/src/svgrid.new-features.wrapper.test.ts +65 -4
- package/src/svgrid.wrapper.test.ts +27 -1
- package/src/test-setup.ts +9 -6
- package/src/virtualization/scroll-scaling.test.ts +148 -0
- package/src/virtualization/scroll-scaling.ts +121 -0
- package/src/virtualization/svelte-virtualizer.svelte.ts +2 -0
- package/src/virtualization/virtualizer.ts +26 -0
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
<script lang="ts" generics="TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData">
|
|
2
|
+
import {
|
|
3
|
+
applyExcelFilter,
|
|
4
|
+
normalizeForFilter,
|
|
5
|
+
createColumnVirtualizer,
|
|
6
|
+
createCoreRowModel,
|
|
7
|
+
createExpandedRowModel,
|
|
8
|
+
createFilteredRowModel,
|
|
9
|
+
createGroupedRowModel,
|
|
10
|
+
createPaginatedRowModel,
|
|
11
|
+
createSvelteVirtualizer,
|
|
12
|
+
createSortedRowModel,
|
|
13
|
+
createSvGrid,
|
|
14
|
+
filterFns,
|
|
15
|
+
getGridCellA11yProps,
|
|
16
|
+
getGridCellDomId,
|
|
17
|
+
getGridHeaderA11yProps,
|
|
18
|
+
getGridRootA11yProps,
|
|
19
|
+
getGridRowA11yProps,
|
|
20
|
+
parseEditorValue,
|
|
21
|
+
normalizeEditorOptions,
|
|
22
|
+
sortFns,
|
|
23
|
+
tableFeatures,
|
|
24
|
+
rowSortingFeature,
|
|
25
|
+
columnFilteringFeature,
|
|
26
|
+
columnGroupingFeature,
|
|
27
|
+
type CellContext,
|
|
28
|
+
type EditorContext,
|
|
29
|
+
type CellEditorOption,
|
|
30
|
+
type CellEditorType,
|
|
31
|
+
type CellFormatter,
|
|
32
|
+
type CellFormatConfig,
|
|
33
|
+
type Column,
|
|
34
|
+
type ColumnDef,
|
|
35
|
+
type Row,
|
|
36
|
+
type RowData,
|
|
37
|
+
type SvGridApi,
|
|
38
|
+
type TableFeatures,
|
|
39
|
+
} from "./index";
|
|
40
|
+
import "./sv-grid-scrollbar";
|
|
41
|
+
import type { Snippet } from "svelte";
|
|
42
|
+
import { getKeyboardIntent, getNextActiveCell } from "./keyboard";
|
|
43
|
+
import {
|
|
44
|
+
formatNumericWithConfig,
|
|
45
|
+
getDateFormatter,
|
|
46
|
+
resolveDatePattern,
|
|
47
|
+
} from "./cell-formatting";
|
|
48
|
+
import {
|
|
49
|
+
RenderSnippetConfig,
|
|
50
|
+
RenderComponentConfig,
|
|
51
|
+
} from "./render-component";
|
|
52
|
+
import { buildFillPattern } from "./fill-patterns";
|
|
53
|
+
import { buildSparkline, toSparklineValues } from "./sparkline";
|
|
54
|
+
import {
|
|
55
|
+
resolveCellFormat,
|
|
56
|
+
computeColumnStat,
|
|
57
|
+
formatsNeedingStats,
|
|
58
|
+
type ColumnStat,
|
|
59
|
+
type ResolvedCellFormat,
|
|
60
|
+
} from "./conditional-formatting";
|
|
61
|
+
import SvGridDropdown from "./SvGridDropdown.svelte";
|
|
62
|
+
import type {
|
|
63
|
+
Props,
|
|
64
|
+
SelectionPoint,
|
|
65
|
+
SelectionRange,
|
|
66
|
+
CellEditState,
|
|
67
|
+
FilterOperator,
|
|
68
|
+
FilterOption,
|
|
69
|
+
MenuPosition,
|
|
70
|
+
} from "./SvGrid.types";
|
|
71
|
+
import {
|
|
72
|
+
cfTextStyle,
|
|
73
|
+
fmtStat,
|
|
74
|
+
getCellKey,
|
|
75
|
+
resolveClassList,
|
|
76
|
+
toDateInputValue,
|
|
77
|
+
toDateTimeLocalInputValue,
|
|
78
|
+
getEditableInputValue,
|
|
79
|
+
getEditorInputType,
|
|
80
|
+
toValueArray,
|
|
81
|
+
getOptionLabel,
|
|
82
|
+
getOptionColor,
|
|
83
|
+
colorfulChipStyle,
|
|
84
|
+
getEditorClass,
|
|
85
|
+
asDate,
|
|
86
|
+
clampMenuX,
|
|
87
|
+
cssEscape,
|
|
88
|
+
rawToNumber,
|
|
89
|
+
formatFacetNumber,
|
|
90
|
+
formatFacetDate,
|
|
91
|
+
} from "./SvGrid.helpers";
|
|
92
|
+
|
|
93
|
+
import type { SvGridController } from "./SvGrid.controller.svelte";
|
|
94
|
+
|
|
95
|
+
let { ctrl, icon }: { ctrl: SvGridController<TFeatures, TData>; icon: Snippet<[string]> } = $props();
|
|
96
|
+
|
|
97
|
+
// View facade: re-bind the controller's reactive members so the markup
|
|
98
|
+
// (moved verbatim from SvGrid.svelte) stays identical.
|
|
99
|
+
const groupingControlsEnabled = $derived(ctrl.groupingControlsEnabled);
|
|
100
|
+
const filterMenuValues = $derived(ctrl.filterMenuValues);
|
|
101
|
+
const tooltip = $derived(ctrl.tooltip);
|
|
102
|
+
const showTooltipFor = $derived(ctrl.showTooltipFor);
|
|
103
|
+
const columnMenuFor = $derived(ctrl.columnMenuFor);
|
|
104
|
+
const columnMenuPos = $derived(ctrl.columnMenuPos);
|
|
105
|
+
const filterMenuFor = $derived(ctrl.filterMenuFor);
|
|
106
|
+
const filterMenuPos = $derived(ctrl.filterMenuPos);
|
|
107
|
+
const operatorMenuFor = $derived(ctrl.operatorMenuFor);
|
|
108
|
+
const operatorMenuPos = $derived(ctrl.operatorMenuPos);
|
|
109
|
+
const chooseColumnsPos = $derived(ctrl.chooseColumnsPos);
|
|
110
|
+
const showColumnFiltersEffective = $derived(ctrl.showColumnFiltersEffective);
|
|
111
|
+
const grid = $derived(ctrl.grid);
|
|
112
|
+
const allColumns = $derived(ctrl.allColumns);
|
|
113
|
+
const isColumnPinned = $derived(ctrl.isColumnPinned);
|
|
114
|
+
const pinColumnLeft = $derived(ctrl.pinColumnLeft);
|
|
115
|
+
const pinColumnRight = $derived(ctrl.pinColumnRight);
|
|
116
|
+
const unpinColumn = $derived(ctrl.unpinColumn);
|
|
117
|
+
const sortDirectionByColumn = $derived(ctrl.sortDirectionByColumn);
|
|
118
|
+
const groupingColumns = $derived(ctrl.groupingColumns);
|
|
119
|
+
const columnVirtualizationEnabled = $derived(ctrl.columnVirtualizationEnabled);
|
|
120
|
+
const updateFilterOperator = $derived(ctrl.updateFilterOperator);
|
|
121
|
+
const updateFilterMenuValue = $derived(ctrl.updateFilterMenuValue);
|
|
122
|
+
const updateFilterMenuValueTo = $derived(ctrl.updateFilterMenuValueTo);
|
|
123
|
+
const operatorsForColumn = $derived(ctrl.operatorsForColumn);
|
|
124
|
+
const defaultOperatorFor = $derived(ctrl.defaultOperatorFor);
|
|
125
|
+
const operatorLabelFor = $derived(ctrl.operatorLabelFor);
|
|
126
|
+
const isColumnFiltered = $derived(ctrl.isColumnFiltered);
|
|
127
|
+
const closeMenus = $derived(ctrl.closeMenus);
|
|
128
|
+
const autosizeColumn = $derived(ctrl.autosizeColumn);
|
|
129
|
+
const autosizeAllColumns = $derived(ctrl.autosizeAllColumns);
|
|
130
|
+
const resetColumns = $derived(ctrl.resetColumns);
|
|
131
|
+
const openChooseColumns = $derived(ctrl.openChooseColumns);
|
|
132
|
+
const sortColumnFromMenu = $derived(ctrl.sortColumnFromMenu);
|
|
133
|
+
const clearColumnSort = $derived(ctrl.clearColumnSort);
|
|
134
|
+
const groupByColumnFromMenu = $derived(ctrl.groupByColumnFromMenu);
|
|
135
|
+
const clearGroupingFromMenu = $derived(ctrl.clearGroupingFromMenu);
|
|
136
|
+
const columnMenuFacetValues = $derived(ctrl.columnMenuFacetValues);
|
|
137
|
+
const columnMenuVisibleFacets = $derived(ctrl.columnMenuVisibleFacets);
|
|
138
|
+
const isFacetChecked = $derived(ctrl.isFacetChecked);
|
|
139
|
+
const toggleFacetValue = $derived(ctrl.toggleFacetValue);
|
|
140
|
+
const isAllFacetsChecked = $derived(ctrl.isAllFacetsChecked);
|
|
141
|
+
const toggleAllFacets = $derived(ctrl.toggleAllFacets);
|
|
142
|
+
const clearColumnFilter = $derived(ctrl.clearColumnFilter);
|
|
143
|
+
const contextMenuFor = $derived(ctrl.contextMenuFor);
|
|
144
|
+
const contextMenuPos = $derived(ctrl.contextMenuPos);
|
|
145
|
+
const contextMenuItems = $derived(ctrl.contextMenuItems);
|
|
146
|
+
const closeContextMenu = $derived(ctrl.closeContextMenu);
|
|
147
|
+
const commentEditFor = $derived(ctrl.commentEditFor);
|
|
148
|
+
const saveComment = $derived(ctrl.saveComment);
|
|
149
|
+
const removeComment = $derived(ctrl.removeComment);
|
|
150
|
+
const closeCommentEditor = $derived(ctrl.closeCommentEditor);
|
|
151
|
+
</script>
|
|
152
|
+
|
|
153
|
+
{#if tooltip}
|
|
154
|
+
<!-- Custom hover tooltip. Floats above the grid; positioned by
|
|
155
|
+
showTooltipFor(). Notes and column tooltips both surface here. -->
|
|
156
|
+
<div
|
|
157
|
+
class="sv-grid-tooltip"
|
|
158
|
+
class:sv-grid-tooltip-above={!tooltip.below}
|
|
159
|
+
style={`left: ${tooltip.x}px; top: ${tooltip.y}px; ${tooltip.below ? '' : 'transform: translateY(-100%);'}`}
|
|
160
|
+
role="tooltip"
|
|
161
|
+
>{tooltip.text}</div>
|
|
162
|
+
{/if}
|
|
163
|
+
|
|
164
|
+
{#if columnMenuFor || filterMenuFor || operatorMenuFor || chooseColumnsPos}
|
|
165
|
+
<div
|
|
166
|
+
class="sv-grid-menu-backdrop"
|
|
167
|
+
role="presentation"
|
|
168
|
+
onclick={closeMenus}
|
|
169
|
+
></div>
|
|
170
|
+
{/if}
|
|
171
|
+
|
|
172
|
+
{#if columnMenuFor}
|
|
173
|
+
{@const menuColumnId = columnMenuFor}
|
|
174
|
+
{@const menuCol = allColumns.find((c) => c.id === menuColumnId)}
|
|
175
|
+
{@const menuCanSort = menuCol?.getCanSort?.() ?? false}
|
|
176
|
+
<div
|
|
177
|
+
class="sv-grid-menu sv-grid-column-menu"
|
|
178
|
+
role="menu"
|
|
179
|
+
style={`left: ${columnMenuPos.x}px; top: ${columnMenuPos.y}px;`}
|
|
180
|
+
>
|
|
181
|
+
{#if menuCanSort}
|
|
182
|
+
<button
|
|
183
|
+
type="button"
|
|
184
|
+
class="sv-grid-menu-item"
|
|
185
|
+
role="menuitem"
|
|
186
|
+
onclick={() => sortColumnFromMenu(menuColumnId, false)}
|
|
187
|
+
>
|
|
188
|
+
<span class="sv-grid-header-icon">{@render icon("sort-asc")}</span> Sort
|
|
189
|
+
ascending
|
|
190
|
+
</button>
|
|
191
|
+
<button
|
|
192
|
+
type="button"
|
|
193
|
+
class="sv-grid-menu-item"
|
|
194
|
+
role="menuitem"
|
|
195
|
+
onclick={() => sortColumnFromMenu(menuColumnId, true)}
|
|
196
|
+
>
|
|
197
|
+
<span class="sv-grid-header-icon">{@render icon("sort-desc")}</span> Sort
|
|
198
|
+
descending
|
|
199
|
+
</button>
|
|
200
|
+
<button
|
|
201
|
+
type="button"
|
|
202
|
+
class="sv-grid-menu-item"
|
|
203
|
+
role="menuitem"
|
|
204
|
+
disabled={!sortDirectionByColumn[menuColumnId]}
|
|
205
|
+
onclick={() => clearColumnSort(menuColumnId)}
|
|
206
|
+
>
|
|
207
|
+
<span class="sv-grid-header-icon">{@render icon("x")}</span> Remove sort
|
|
208
|
+
</button>
|
|
209
|
+
{/if}
|
|
210
|
+
{#if !columnVirtualizationEnabled}
|
|
211
|
+
{@const menuPinSide = isColumnPinned(menuColumnId)}
|
|
212
|
+
<div class="sv-grid-menu-sep"></div>
|
|
213
|
+
<button
|
|
214
|
+
type="button"
|
|
215
|
+
class="sv-grid-menu-item"
|
|
216
|
+
role="menuitem"
|
|
217
|
+
disabled={menuPinSide === "left"}
|
|
218
|
+
onclick={() => pinColumnLeft(menuColumnId)}
|
|
219
|
+
>
|
|
220
|
+
<span class="sv-grid-header-icon"
|
|
221
|
+
>{@render icon("op-startsWith")}</span
|
|
222
|
+
> Pin to left
|
|
223
|
+
</button>
|
|
224
|
+
<button
|
|
225
|
+
type="button"
|
|
226
|
+
class="sv-grid-menu-item"
|
|
227
|
+
role="menuitem"
|
|
228
|
+
disabled={menuPinSide === "right"}
|
|
229
|
+
onclick={() => pinColumnRight(menuColumnId)}
|
|
230
|
+
>
|
|
231
|
+
<span class="sv-grid-header-icon"
|
|
232
|
+
>{@render icon("op-greaterThan")}</span
|
|
233
|
+
> Pin to right
|
|
234
|
+
</button>
|
|
235
|
+
<button
|
|
236
|
+
type="button"
|
|
237
|
+
class="sv-grid-menu-item"
|
|
238
|
+
role="menuitem"
|
|
239
|
+
disabled={!menuPinSide}
|
|
240
|
+
onclick={() => unpinColumn(menuColumnId)}
|
|
241
|
+
>
|
|
242
|
+
<span class="sv-grid-header-icon">{@render icon("x")}</span> Unpin column
|
|
243
|
+
</button>
|
|
244
|
+
{/if}
|
|
245
|
+
<div class="sv-grid-menu-sep"></div>
|
|
246
|
+
<button
|
|
247
|
+
type="button"
|
|
248
|
+
class="sv-grid-menu-item"
|
|
249
|
+
role="menuitem"
|
|
250
|
+
onclick={() => {
|
|
251
|
+
autosizeColumn(menuColumnId);
|
|
252
|
+
closeMenus();
|
|
253
|
+
}}
|
|
254
|
+
>
|
|
255
|
+
<span class="sv-grid-header-icon">{@render icon("autosize")}</span> Autosize
|
|
256
|
+
this column
|
|
257
|
+
</button>
|
|
258
|
+
<button
|
|
259
|
+
type="button"
|
|
260
|
+
class="sv-grid-menu-item"
|
|
261
|
+
role="menuitem"
|
|
262
|
+
onclick={() => {
|
|
263
|
+
autosizeAllColumns();
|
|
264
|
+
closeMenus();
|
|
265
|
+
}}
|
|
266
|
+
>
|
|
267
|
+
<span class="sv-grid-header-icon">{@render icon("autosize")}</span> Autosize
|
|
268
|
+
all columns
|
|
269
|
+
</button>
|
|
270
|
+
{#if groupingControlsEnabled}
|
|
271
|
+
<div class="sv-grid-menu-sep"></div>
|
|
272
|
+
<button
|
|
273
|
+
type="button"
|
|
274
|
+
class="sv-grid-menu-item"
|
|
275
|
+
role="menuitem"
|
|
276
|
+
disabled={groupingColumns.includes(menuColumnId)}
|
|
277
|
+
onclick={() => groupByColumnFromMenu(menuColumnId)}
|
|
278
|
+
>
|
|
279
|
+
<span class="sv-grid-header-icon">{@render icon("group")}</span> Group
|
|
280
|
+
by this column
|
|
281
|
+
</button>
|
|
282
|
+
<button
|
|
283
|
+
type="button"
|
|
284
|
+
class="sv-grid-menu-item"
|
|
285
|
+
role="menuitem"
|
|
286
|
+
disabled={!groupingColumns.includes(menuColumnId)}
|
|
287
|
+
onclick={() => clearGroupingFromMenu(menuColumnId)}
|
|
288
|
+
>
|
|
289
|
+
<span class="sv-grid-header-icon">{@render icon("x")}</span> Remove grouping
|
|
290
|
+
</button>
|
|
291
|
+
{/if}
|
|
292
|
+
<div class="sv-grid-menu-sep"></div>
|
|
293
|
+
<button
|
|
294
|
+
type="button"
|
|
295
|
+
class="sv-grid-menu-item"
|
|
296
|
+
class:is-open={chooseColumnsPos !== null}
|
|
297
|
+
role="menuitem"
|
|
298
|
+
aria-haspopup="menu"
|
|
299
|
+
aria-expanded={chooseColumnsPos !== null}
|
|
300
|
+
onclick={(event) => openChooseColumns(event)}
|
|
301
|
+
>
|
|
302
|
+
<span class="sv-grid-header-icon">{@render icon("columns")}</span>
|
|
303
|
+
Choose columns
|
|
304
|
+
<span class="sv-grid-header-icon sv-grid-menu-item-chevron"
|
|
305
|
+
>{@render icon("chevron-down")}</span
|
|
306
|
+
>
|
|
307
|
+
</button>
|
|
308
|
+
<button
|
|
309
|
+
type="button"
|
|
310
|
+
class="sv-grid-menu-item"
|
|
311
|
+
role="menuitem"
|
|
312
|
+
onclick={() => {
|
|
313
|
+
resetColumns();
|
|
314
|
+
closeMenus();
|
|
315
|
+
}}
|
|
316
|
+
>
|
|
317
|
+
<span class="sv-grid-header-icon">{@render icon("reset")}</span> Reset columns
|
|
318
|
+
</button>
|
|
319
|
+
</div>
|
|
320
|
+
{/if}
|
|
321
|
+
|
|
322
|
+
{#if filterMenuFor && showColumnFiltersEffective}
|
|
323
|
+
{@const menuColumnId = filterMenuFor}
|
|
324
|
+
{@const menuColumn = allColumns.find((c) => c.id === menuColumnId)}
|
|
325
|
+
{@const menuOperatorOptions = operatorsForColumn(menuColumn)}
|
|
326
|
+
{@const menuActiveOperator =
|
|
327
|
+
filterMenuValues[menuColumnId]?.operator ??
|
|
328
|
+
defaultOperatorFor(menuColumn)}
|
|
329
|
+
{@const menuInputType = getEditorInputType(
|
|
330
|
+
(menuColumn?.columnDef.editorType ?? "text") as CellEditorType,
|
|
331
|
+
)}
|
|
332
|
+
<div
|
|
333
|
+
class="sv-grid-menu sv-grid-filter-menu"
|
|
334
|
+
role="menu"
|
|
335
|
+
style={`left: ${filterMenuPos.x}px; top: ${filterMenuPos.y}px;`}
|
|
336
|
+
>
|
|
337
|
+
<div class="sv-grid-menu-filter">
|
|
338
|
+
<div class="sv-grid-menu-filter-head">
|
|
339
|
+
<span class="sv-grid-header-icon">{@render icon("filter")}</span> Filter
|
|
340
|
+
condition
|
|
341
|
+
</div>
|
|
342
|
+
<select
|
|
343
|
+
class="sv-grid-menu-operator-select"
|
|
344
|
+
aria-label="Filter condition"
|
|
345
|
+
value={menuActiveOperator}
|
|
346
|
+
onchange={(event) =>
|
|
347
|
+
updateFilterOperator(
|
|
348
|
+
menuColumnId,
|
|
349
|
+
(event.currentTarget as HTMLSelectElement)
|
|
350
|
+
.value as FilterOperator,
|
|
351
|
+
)}
|
|
352
|
+
>
|
|
353
|
+
{#each menuOperatorOptions as option (option.value)}
|
|
354
|
+
<option value={option.value}
|
|
355
|
+
>{operatorLabelFor(option, menuColumn)}</option
|
|
356
|
+
>
|
|
357
|
+
{/each}
|
|
358
|
+
</select>
|
|
359
|
+
{#if menuActiveOperator !== "isBlank"}
|
|
360
|
+
<input
|
|
361
|
+
class="sv-grid-menu-condition-value"
|
|
362
|
+
type={menuInputType}
|
|
363
|
+
value={filterMenuValues[menuColumnId]?.value ?? ""}
|
|
364
|
+
placeholder={menuActiveOperator === "between" ? "From" : "Filter value..."}
|
|
365
|
+
oninput={(event) =>
|
|
366
|
+
updateFilterMenuValue(
|
|
367
|
+
menuColumnId,
|
|
368
|
+
(event.currentTarget as HTMLInputElement).value,
|
|
369
|
+
)}
|
|
370
|
+
/>
|
|
371
|
+
{#if menuActiveOperator === "between"}
|
|
372
|
+
<input
|
|
373
|
+
class="sv-grid-menu-condition-value"
|
|
374
|
+
type={menuInputType}
|
|
375
|
+
value={filterMenuValues[menuColumnId]?.valueTo ?? ""}
|
|
376
|
+
placeholder="To"
|
|
377
|
+
oninput={(event) =>
|
|
378
|
+
updateFilterMenuValueTo(
|
|
379
|
+
menuColumnId,
|
|
380
|
+
(event.currentTarget as HTMLInputElement).value,
|
|
381
|
+
)}
|
|
382
|
+
/>
|
|
383
|
+
{/if}
|
|
384
|
+
{/if}
|
|
385
|
+
<div class="sv-grid-menu-sep"></div>
|
|
386
|
+
<div class="sv-grid-menu-filter-head">Values</div>
|
|
387
|
+
<input
|
|
388
|
+
class="sv-grid-menu-search"
|
|
389
|
+
placeholder="Search values..."
|
|
390
|
+
bind:value={ctrl.columnMenuSearch}
|
|
391
|
+
/>
|
|
392
|
+
<label class="sv-grid-facet sv-grid-facet-all">
|
|
393
|
+
<input
|
|
394
|
+
type="checkbox"
|
|
395
|
+
checked={isAllFacetsChecked(menuColumnId)}
|
|
396
|
+
onchange={() => toggleAllFacets(menuColumnId)}
|
|
397
|
+
/>
|
|
398
|
+
<span class="sv-grid-facet-label">(Select all)</span>
|
|
399
|
+
</label>
|
|
400
|
+
<div class="sv-grid-facet-list">
|
|
401
|
+
{#each columnMenuVisibleFacets as value (value)}
|
|
402
|
+
<label class="sv-grid-facet">
|
|
403
|
+
<input
|
|
404
|
+
type="checkbox"
|
|
405
|
+
checked={isFacetChecked(menuColumnId, value)}
|
|
406
|
+
onchange={() => toggleFacetValue(menuColumnId, value)}
|
|
407
|
+
/>
|
|
408
|
+
<span class="sv-grid-facet-label"
|
|
409
|
+
>{value === "" ? "(Blanks)" : value}</span
|
|
410
|
+
>
|
|
411
|
+
</label>
|
|
412
|
+
{:else}
|
|
413
|
+
<div class="sv-grid-facet-empty">No values</div>
|
|
414
|
+
{/each}
|
|
415
|
+
</div>
|
|
416
|
+
{#if columnMenuFacetValues.length > columnMenuVisibleFacets.length}
|
|
417
|
+
<div class="sv-grid-facet-note">
|
|
418
|
+
Showing {columnMenuVisibleFacets.length} of {columnMenuFacetValues.length}
|
|
419
|
+
</div>
|
|
420
|
+
{/if}
|
|
421
|
+
<div class="sv-grid-menu-actions">
|
|
422
|
+
<button
|
|
423
|
+
type="button"
|
|
424
|
+
class="sv-grid-menu-btn"
|
|
425
|
+
disabled={!isColumnFiltered(menuColumnId)}
|
|
426
|
+
onclick={() => clearColumnFilter(menuColumnId)}
|
|
427
|
+
>
|
|
428
|
+
Clear filter
|
|
429
|
+
</button>
|
|
430
|
+
<button
|
|
431
|
+
type="button"
|
|
432
|
+
class="sv-grid-menu-btn sv-grid-menu-btn-primary"
|
|
433
|
+
onclick={closeMenus}
|
|
434
|
+
>
|
|
435
|
+
Done
|
|
436
|
+
</button>
|
|
437
|
+
</div>
|
|
438
|
+
</div>
|
|
439
|
+
</div>
|
|
440
|
+
{/if}
|
|
441
|
+
|
|
442
|
+
{#if chooseColumnsPos}
|
|
443
|
+
{@const everyColumn = grid.getAllColumns()}
|
|
444
|
+
<div
|
|
445
|
+
class="sv-grid-menu sv-grid-choose-columns-menu"
|
|
446
|
+
role="menu"
|
|
447
|
+
style={`left: ${chooseColumnsPos.x}px; top: ${chooseColumnsPos.y}px;`}
|
|
448
|
+
>
|
|
449
|
+
<div class="sv-grid-menu-filter-head">Visible columns</div>
|
|
450
|
+
<div class="sv-grid-facet-list">
|
|
451
|
+
{#each everyColumn as column (column.id)}
|
|
452
|
+
<label class="sv-grid-facet">
|
|
453
|
+
<input
|
|
454
|
+
type="checkbox"
|
|
455
|
+
checked={!ctrl.hiddenColumns[column.id]}
|
|
456
|
+
onchange={(event) => {
|
|
457
|
+
const visible = (event.currentTarget as HTMLInputElement)
|
|
458
|
+
.checked;
|
|
459
|
+
if (visible) {
|
|
460
|
+
const next = { ...ctrl.hiddenColumns };
|
|
461
|
+
delete next[column.id];
|
|
462
|
+
ctrl.hiddenColumns = next;
|
|
463
|
+
} else {
|
|
464
|
+
ctrl.hiddenColumns = { ...ctrl.hiddenColumns, [column.id]: true };
|
|
465
|
+
}
|
|
466
|
+
}}
|
|
467
|
+
/>
|
|
468
|
+
<span class="sv-grid-facet-label"
|
|
469
|
+
>{typeof column.columnDef.header === "string"
|
|
470
|
+
? column.columnDef.header
|
|
471
|
+
: column.id}</span
|
|
472
|
+
>
|
|
473
|
+
</label>
|
|
474
|
+
{/each}
|
|
475
|
+
</div>
|
|
476
|
+
</div>
|
|
477
|
+
{/if}
|
|
478
|
+
|
|
479
|
+
{#if operatorMenuFor}
|
|
480
|
+
{@const opColumnId = operatorMenuFor}
|
|
481
|
+
{@const opColumn = allColumns.find((c) => c.id === opColumnId)}
|
|
482
|
+
{@const opOptions = operatorsForColumn(opColumn)}
|
|
483
|
+
{@const opActive =
|
|
484
|
+
filterMenuValues[opColumnId]?.operator ?? defaultOperatorFor(opColumn)}
|
|
485
|
+
<div
|
|
486
|
+
class="sv-grid-menu sv-grid-operator-menu"
|
|
487
|
+
role="menu"
|
|
488
|
+
style={`left: ${operatorMenuPos.x}px; top: ${operatorMenuPos.y}px;`}
|
|
489
|
+
>
|
|
490
|
+
{#each opOptions as option (option.value)}
|
|
491
|
+
<button
|
|
492
|
+
type="button"
|
|
493
|
+
class="sv-grid-menu-item"
|
|
494
|
+
role="menuitemradio"
|
|
495
|
+
aria-checked={opActive === option.value}
|
|
496
|
+
onclick={() => {
|
|
497
|
+
updateFilterOperator(opColumnId, option.value);
|
|
498
|
+
closeMenus();
|
|
499
|
+
}}
|
|
500
|
+
>
|
|
501
|
+
<span class="sv-grid-header-icon"
|
|
502
|
+
>{@render icon(option.iconName)}</span
|
|
503
|
+
>
|
|
504
|
+
{operatorLabelFor(option, opColumn)}
|
|
505
|
+
</button>
|
|
506
|
+
{/each}
|
|
507
|
+
</div>
|
|
508
|
+
{/if}
|
|
509
|
+
|
|
510
|
+
{#if contextMenuFor}
|
|
511
|
+
<div
|
|
512
|
+
class="sv-grid-menu-backdrop"
|
|
513
|
+
role="presentation"
|
|
514
|
+
oncontextmenu={(e) => { e.preventDefault(); closeContextMenu(); }}
|
|
515
|
+
onclick={closeContextMenu}
|
|
516
|
+
></div>
|
|
517
|
+
<div
|
|
518
|
+
class="sv-grid-menu sv-grid-context-menu"
|
|
519
|
+
role="menu"
|
|
520
|
+
style={`left: ${contextMenuPos.x}px; top: ${contextMenuPos.y}px;`}
|
|
521
|
+
>
|
|
522
|
+
{#each contextMenuItems() as item (item.key)}
|
|
523
|
+
{#if item.separator}
|
|
524
|
+
<div class="sv-grid-menu-sep"></div>
|
|
525
|
+
{:else}
|
|
526
|
+
<button
|
|
527
|
+
type="button"
|
|
528
|
+
class="sv-grid-menu-item"
|
|
529
|
+
role="menuitem"
|
|
530
|
+
disabled={item.disabled}
|
|
531
|
+
onclick={() => { item.run?.(); closeContextMenu(); }}
|
|
532
|
+
>{item.label}</button>
|
|
533
|
+
{/if}
|
|
534
|
+
{/each}
|
|
535
|
+
</div>
|
|
536
|
+
{/if}
|
|
537
|
+
|
|
538
|
+
{#if commentEditFor}
|
|
539
|
+
<div
|
|
540
|
+
class="sv-grid-menu-backdrop"
|
|
541
|
+
role="presentation"
|
|
542
|
+
onclick={closeCommentEditor}
|
|
543
|
+
></div>
|
|
544
|
+
<div
|
|
545
|
+
class="sv-grid-menu sv-grid-comment-editor"
|
|
546
|
+
role="dialog"
|
|
547
|
+
aria-label="Edit comment"
|
|
548
|
+
style={`left: ${commentEditFor.x}px; top: ${commentEditFor.y}px;`}
|
|
549
|
+
>
|
|
550
|
+
<!-- svelte-ignore a11y_autofocus -->
|
|
551
|
+
<textarea
|
|
552
|
+
class="sv-grid-comment-textarea"
|
|
553
|
+
rows="3"
|
|
554
|
+
placeholder="Add a comment…"
|
|
555
|
+
autofocus
|
|
556
|
+
bind:value={ctrl.commentDraft}
|
|
557
|
+
onkeydown={(e) => {
|
|
558
|
+
e.stopPropagation();
|
|
559
|
+
if (e.key === "Escape") { e.preventDefault(); closeCommentEditor(); }
|
|
560
|
+
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) { e.preventDefault(); saveComment(); }
|
|
561
|
+
}}
|
|
562
|
+
></textarea>
|
|
563
|
+
<div class="sv-grid-comment-actions">
|
|
564
|
+
<button type="button" class="sv-grid-comment-remove" onclick={removeComment}>Remove</button>
|
|
565
|
+
<span class="sv-grid-comment-spacer"></span>
|
|
566
|
+
<button type="button" class="sv-grid-comment-cancel" onclick={closeCommentEditor}>Cancel</button>
|
|
567
|
+
<button type="button" class="sv-grid-comment-save" onclick={saveComment}>Save</button>
|
|
568
|
+
</div>
|
|
569
|
+
</div>
|
|
570
|
+
{/if}
|