@svgrid/grid 3.0.2 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/GridMenus.svelte +44 -2
- package/dist/SvChartMenu.svelte +69 -0
- package/dist/SvChartMenu.svelte.d.ts +11 -0
- package/dist/SvChartPanes.svelte +113 -0
- package/dist/SvChartPanes.svelte.d.ts +20 -0
- package/dist/SvGrid.controller.svelte.d.ts +110 -39
- package/dist/SvGrid.controller.svelte.js +655 -200
- package/dist/SvGrid.css +105 -2
- package/dist/SvGrid.svelte +386 -514
- package/dist/SvGrid.types.d.ts +210 -9
- package/dist/SvGridCellEditor.svelte +17 -0
- package/dist/SvGridChart.svelte +2257 -329
- package/dist/SvGridChart.svelte.d.ts +6 -106
- package/dist/SvGridChart.types.d.ts +338 -0
- package/dist/SvGridChart.types.js +1 -0
- package/dist/SvGridChartBuilder.svelte +323 -0
- package/dist/SvGridChartBuilder.svelte.d.ts +34 -0
- package/dist/SvGridChartPanel.svelte +221 -275
- package/dist/SvGridChartPickers.svelte +417 -0
- package/dist/SvGridChartPickers.svelte.d.ts +70 -0
- package/dist/SvGridChartView.svelte +13 -14
- package/dist/SvModal.svelte +7 -1
- package/dist/SvModal.svelte.d.ts +5 -0
- package/dist/ai.d.ts +40 -8
- package/dist/ai.js +135 -24
- package/dist/aria.d.ts +11 -0
- package/dist/build-api.js +108 -22
- package/dist/cdn/GridMenus-7kbpnnBW.js +635 -0
- package/dist/cdn/GridMenus-BL7ZgQvU.js +636 -0
- package/dist/cdn/SvChartMenu-Bl6PBbkT.js +58 -0
- package/dist/cdn/SvChartMenu-FBSMINA6.js +59 -0
- package/dist/cdn/{SvDateRangeInput-DMLKmGEc.js → SvDateRangeInput-BeU_TkbQ.js} +15 -14
- package/dist/cdn/{SvDateRangeInput-CaOuMs8O.js → SvDateRangeInput-yX8vzleW.js} +38 -37
- package/dist/cdn/{SvDateTimePicker-sonaH0oh.js → SvDateTimePicker-DQwt4UAs.js} +139 -180
- package/dist/cdn/SvDateTimePicker-vNU6bZ-q.js +775 -0
- package/dist/cdn/{SvGridCellEditor-CjEJMJKc.js → SvGridCellEditor-B1p-vCK5.js} +188 -178
- package/dist/cdn/{SvGridCellEditor-BWnTi2N7.js → SvGridCellEditor-D_0q4xAu.js} +98 -88
- package/dist/cdn/SvGridChart-C3EWAZaM.js +3574 -0
- package/dist/cdn/SvGridChart-DzLkSwCH.js +3572 -0
- package/dist/cdn/SvGridChartBuilder-BE2T1ykB.js +783 -0
- package/dist/cdn/SvGridChartBuilder-CfII62sZ.js +784 -0
- package/dist/cdn/SvGridChartPanel-CCX5_Wgd.js +675 -0
- package/dist/cdn/SvGridChartPanel-xf4sWVTo.js +699 -0
- package/dist/cdn/SvGridChartView-CfuXmY5I.js +48 -0
- package/dist/cdn/SvGridChartView-DYwabQWj.js +47 -0
- package/dist/cdn/SvMenuList-CLN8OuIK.js +452 -0
- package/dist/cdn/SvMenuList-DkGhNKjf.js +451 -0
- package/dist/cdn/SvModal-BAE-pjZX.js +396 -0
- package/dist/cdn/SvModal-CIZWCcad.js +397 -0
- package/dist/cdn/chart-Dz7SqMXH.js +4341 -0
- package/dist/cdn/chart-export-BXqueeWJ.js +135 -0
- package/dist/cdn/chart-export-pdf-DONFUnNY.js +110 -0
- package/dist/cdn/chart-panel-messages-CUbf2R4i.js +1052 -0
- package/dist/cdn/chart-panel-messages-CmNrMdsr.js +1053 -0
- package/dist/cdn/chart-summary-BJW_tg_X.js +138 -0
- package/dist/cdn/chart-trend-CaN9mDEV.js +50 -0
- package/dist/cdn/chart-validate-HcOVFAfJ.js +188 -0
- package/dist/cdn/{column-resize-DsfNXMom.js → column-resize-DpmOLfRp.js} +3 -3
- package/dist/cdn/{date-format-BnnHlqGw.js → date-format-CtquV-p3.js} +583 -603
- package/dist/cdn/{date-format-BNii4zeD.js → date-format-D6KFzU_W.js} +347 -367
- package/dist/cdn/dismissable-DAHetSNk.js +44 -0
- package/dist/cdn/editor-contract-LXgQJAgd.js +22 -0
- package/dist/cdn/focus-trap-BBOQYBma.js +65 -0
- package/dist/cdn/{row-resize-BRcimkUT.js → row-resize-niQCp040.js} +44 -36
- package/dist/cdn/{src-DNbz94Ct.js → src-BKhZ6eXd.js} +10227 -9787
- package/dist/cdn/{src-BJ2opd0j.js → src-V1uu8iE9.js} +6568 -6128
- package/dist/cdn/svgrid.js +26 -15
- package/dist/cdn/svgrid.svelte-external.js +26 -15
- package/dist/chart-axes.d.ts +53 -0
- package/dist/chart-axes.js +351 -0
- package/dist/chart-cartesian.d.ts +88 -0
- package/dist/chart-cartesian.js +1862 -0
- package/dist/chart-decimate.d.ts +51 -0
- package/dist/chart-decimate.js +199 -0
- package/dist/chart-export-pdf.d.ts +47 -0
- package/dist/chart-export-pdf.js +187 -0
- package/dist/chart-export.d.ts +2 -1
- package/dist/chart-export.js +18 -3
- package/dist/chart-financial.d.ts +91 -0
- package/dist/chart-financial.js +175 -0
- package/dist/chart-flow.d.ts +10 -0
- package/dist/chart-flow.js +298 -0
- package/dist/chart-format.d.ts +18 -0
- package/dist/chart-format.js +65 -0
- package/dist/chart-grid.d.ts +8 -0
- package/dist/chart-grid.js +190 -0
- package/dist/chart-hierarchy.d.ts +17 -0
- package/dist/chart-hierarchy.js +146 -0
- package/dist/chart-indicators.d.ts +115 -0
- package/dist/chart-indicators.js +389 -0
- package/dist/chart-messages.d.ts +95 -0
- package/dist/chart-messages.js +92 -0
- package/dist/chart-motion.d.ts +16 -0
- package/dist/chart-motion.js +141 -0
- package/dist/chart-panel-messages.d.ts +265 -0
- package/dist/chart-panel-messages.js +285 -0
- package/dist/chart-pivot.d.ts +87 -0
- package/dist/chart-pivot.js +156 -0
- package/dist/chart-polar.d.ts +25 -0
- package/dist/chart-polar.js +700 -0
- package/dist/chart-samples.d.ts +16 -0
- package/dist/chart-samples.js +153 -0
- package/dist/chart-scale.d.ts +113 -0
- package/dist/chart-scale.js +405 -0
- package/dist/chart-stats.d.ts +111 -0
- package/dist/chart-stats.js +419 -0
- package/dist/chart-stream.d.ts +45 -0
- package/dist/chart-stream.js +91 -0
- package/dist/chart-summary.d.ts +27 -0
- package/dist/chart-summary.js +205 -0
- package/dist/chart-sync.svelte.d.ts +32 -0
- package/dist/chart-sync.svelte.js +23 -0
- package/dist/chart-table.d.ts +35 -0
- package/dist/chart-table.js +165 -0
- package/dist/chart-trend.d.ts +19 -0
- package/dist/chart-trend.js +61 -0
- package/dist/chart-types.d.ts +1456 -0
- package/dist/chart-types.js +6 -0
- package/dist/chart-validate.d.ts +43 -0
- package/dist/chart-validate.js +272 -0
- package/dist/chart-zoom.d.ts +40 -0
- package/dist/chart-zoom.js +145 -0
- package/dist/chart.d.ts +186 -865
- package/dist/chart.js +460 -2204
- package/dist/clipboard.d.ts +1 -0
- package/dist/clipboard.js +137 -18
- package/dist/column-resize.d.ts +3 -0
- package/dist/column-resize.js +4 -1
- package/dist/columns.js +3 -0
- package/dist/command-context.d.ts +19 -0
- package/dist/command-context.js +116 -0
- package/dist/core.d.ts +7 -0
- package/dist/createPopoverSelect.svelte.d.ts +2 -2
- package/dist/editing.d.ts +2 -8
- package/dist/editing.js +262 -33
- package/dist/fill-patterns.d.ts +0 -5
- package/dist/fill-patterns.js +56 -2
- package/dist/grid-messages.d.ts +10 -3
- package/dist/grid-messages.js +5 -0
- package/dist/history.d.ts +83 -0
- package/dist/history.js +133 -0
- package/dist/index.d.ts +24 -6
- package/dist/index.js +20 -2
- package/dist/keyboard-handlers.js +88 -31
- package/dist/keyboard.d.ts +55 -0
- package/dist/keyboard.js +132 -0
- package/dist/menus.d.ts +3 -1
- package/dist/menus.js +7 -2
- package/dist/merges.d.ts +97 -0
- package/dist/merges.js +147 -0
- package/dist/row-resize.d.ts +3 -0
- package/dist/row-resize.js +14 -0
- package/dist/scroll-sync.d.ts +1 -0
- package/dist/scroll-sync.js +24 -0
- package/dist/selection.d.ts +16 -0
- package/dist/selection.js +108 -16
- package/dist/shortcut-registry.d.ts +145 -0
- package/dist/shortcut-registry.js +44 -0
- package/dist/svgrid-wrapper.types.d.ts +213 -22
- package/dist/virtualization/virtualizer.js +38 -17
- package/package.json +6 -1
- package/src/GridMenus.svelte +44 -2
- package/src/SvChartMenu.svelte +69 -0
- package/src/SvChartPanes.svelte +113 -0
- package/src/SvChartPanes.test.ts +66 -0
- package/src/SvGrid.controller.svelte.ts +629 -172
- package/src/SvGrid.css +105 -2
- package/src/SvGrid.svelte +386 -514
- package/src/SvGrid.types.ts +188 -8
- package/src/SvGridCellEditor.svelte +17 -0
- package/src/SvGridChart.svelte +2257 -329
- package/src/SvGridChart.test.ts +1419 -1
- package/src/SvGridChart.types.ts +336 -0
- package/src/SvGridChartBuilder.svelte +323 -0
- package/src/SvGridChartPanel.svelte +221 -275
- package/src/SvGridChartPickers.svelte +417 -0
- package/src/SvGridChartView.svelte +13 -14
- package/src/SvModal.svelte +7 -1
- package/src/SvModal.test.ts +9 -0
- package/src/ai.test.ts +57 -2
- package/src/ai.ts +166 -22
- package/src/aria.d.ts +11 -0
- package/src/build-api.coverage.test.ts +184 -0
- package/src/build-api.ts +107 -18
- package/src/chart-axes.test.ts +573 -0
- package/src/chart-axes.ts +342 -0
- package/src/chart-cartesian.ts +1863 -0
- package/src/chart-decimate.test.ts +249 -0
- package/src/chart-decimate.ts +186 -0
- package/src/chart-export-pdf.test.ts +91 -0
- package/src/chart-export-pdf.ts +207 -0
- package/src/chart-export.test.ts +14 -0
- package/src/chart-export.ts +13 -3
- package/src/chart-financial.ts +208 -0
- package/src/chart-flow.ts +286 -0
- package/src/chart-format.ts +67 -0
- package/src/chart-grid.ts +179 -0
- package/src/chart-hierarchy.ts +135 -0
- package/src/chart-indicators.test.ts +443 -0
- package/src/chart-indicators.ts +384 -0
- package/src/chart-messages.test.ts +21 -0
- package/src/chart-messages.ts +184 -0
- package/src/chart-motion.test.ts +71 -0
- package/src/chart-motion.ts +148 -0
- package/src/chart-panel-messages.test.ts +29 -0
- package/src/chart-panel-messages.ts +550 -0
- package/src/chart-pivot.test.ts +54 -0
- package/src/chart-pivot.ts +225 -0
- package/src/chart-polar.ts +674 -0
- package/src/chart-samples.ts +106 -0
- package/src/chart-scale.ts +394 -0
- package/src/chart-series-types.test.ts +714 -0
- package/src/chart-stats.ts +409 -0
- package/src/chart-stream.test.ts +75 -0
- package/src/chart-stream.ts +114 -0
- package/src/chart-summary.test.ts +90 -0
- package/src/chart-summary.ts +197 -0
- package/src/chart-sync.svelte.ts +41 -0
- package/src/chart-table.test.ts +76 -0
- package/src/chart-table.ts +178 -0
- package/src/chart-trend.ts +47 -0
- package/src/chart-types.ts +1309 -0
- package/src/chart-validate.test.ts +100 -0
- package/src/chart-validate.ts +247 -0
- package/src/chart-zoom.test.ts +137 -0
- package/src/chart-zoom.ts +124 -0
- package/src/chart.coverage.test.ts +81 -0
- package/src/chart.test.ts +56 -3
- package/src/chart.ts +557 -2784
- package/src/clipboard.test.ts +151 -0
- package/src/clipboard.ts +145 -16
- package/src/column-resize.ts +7 -1
- package/src/columns.ts +2 -0
- package/src/command-context.test.ts +200 -0
- package/src/command-context.ts +137 -0
- package/src/core.ts +7 -0
- package/src/editing.test.ts +281 -3
- package/src/editing.ts +256 -38
- package/src/fill-patterns.test.ts +35 -0
- package/src/fill-patterns.ts +56 -2
- package/src/grid-messages.ts +16 -3
- package/src/history.test.ts +196 -0
- package/src/history.ts +162 -0
- package/src/icon-seam.test.ts +3 -2
- package/src/index.ts +150 -2
- package/src/keyboard-handlers.coverage.test.ts +126 -6
- package/src/keyboard-handlers.ts +91 -30
- package/src/keyboard-shortcuts.seam.test.ts +200 -0
- package/src/keyboard.test.ts +124 -1
- package/src/keyboard.ts +142 -0
- package/src/menus.test.ts +26 -0
- package/src/menus.ts +10 -3
- package/src/merges.test.ts +112 -0
- package/src/merges.ts +168 -0
- package/src/pivot.grid.test.ts +40 -5
- package/src/row-resize.test.ts +44 -0
- package/src/row-resize.ts +17 -0
- package/src/scroll-sync.test.ts +42 -1
- package/src/scroll-sync.ts +25 -0
- package/src/selection.multi-range.test.ts +34 -0
- package/src/selection.test.ts +30 -2
- package/src/selection.ts +111 -19
- package/src/shortcut-registry.test.ts +97 -0
- package/src/shortcut-registry.ts +181 -0
- package/src/svgrid-wrapper.types.ts +184 -13
- package/src/svgrid.behavior.test.ts +135 -0
- package/src/svgrid.charting.test.ts +513 -3
- package/src/svgrid.context-menu.test.ts +31 -0
- package/src/svgrid.new-features.wrapper.test.ts +10 -3
- package/src/virtualization/virtualizer.ts +39 -17
- package/dist/cdn/GridMenus-DyFA-QxA.js +0 -602
- package/dist/cdn/GridMenus-M2XP9t0_.js +0 -603
- package/dist/cdn/SvDateTimePicker-CCbDZNZB.js +0 -816
- package/dist/cdn/SvGridChart-DAb9RbRs.js +0 -1480
- package/dist/cdn/SvGridChart-Yl-IXZFO.js +0 -1481
- package/dist/cdn/SvGridChartPanel-DayQpDsR.js +0 -834
- package/dist/cdn/SvGridChartPanel-aqf8n-vJ.js +0 -810
- package/dist/cdn/SvGridChartView-CxfakxR0.js +0 -56
- package/dist/cdn/SvGridChartView-Dm_YEx9L.js +0 -55
- package/dist/cdn/chart-CKJRCPOk.js +0 -1652
package/dist/SvGrid.svelte
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
generics="TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData"
|
|
4
4
|
>
|
|
5
5
|
import {
|
|
6
|
-
getGridCellA11yProps,
|
|
7
6
|
getGridCellDomId,
|
|
8
7
|
getGridHeaderA11yProps,
|
|
9
8
|
getGridRootA11yProps,
|
|
@@ -22,6 +21,7 @@
|
|
|
22
21
|
RenderComponentConfig,
|
|
23
22
|
} from "./render-component";
|
|
24
23
|
import { buildSparkline, toSparklineValues } from "./sparkline";
|
|
24
|
+
import { mergeDrawAt } from "./merges";
|
|
25
25
|
import { localizeOperatorLabel } from "./filter-operators";
|
|
26
26
|
import { GRID_ICON_GLYPHS, type GridIconName } from "./grid-icons";
|
|
27
27
|
// The whole editor UI - including the lazy SvGridDropdown / SvDateTimePicker
|
|
@@ -387,8 +387,9 @@
|
|
|
387
387
|
);
|
|
388
388
|
|
|
389
389
|
const rowSizePx = (i: number): number => {
|
|
390
|
-
// A height the user dragged
|
|
391
|
-
// where they put it across re-renders
|
|
390
|
+
// A height the user dragged, or set through the api, wins over the
|
|
391
|
+
// declared one, so the row stays where they put it across re-renders
|
|
392
|
+
// and virtualization recycling.
|
|
392
393
|
const dragged = ctrl.rowResizeHeightPx(i);
|
|
393
394
|
if (dragged != null) return dragged;
|
|
394
395
|
const rh = opt.rowHeight;
|
|
@@ -402,10 +403,47 @@
|
|
|
402
403
|
autoRowHeightOn
|
|
403
404
|
? `min-height: ${measuredRowHeightPx(i) ?? rowSizePx(i)}px;`
|
|
404
405
|
: `height: ${rowSizePx(i)}px;`;
|
|
406
|
+
const collapsedColumns = $derived(ctrl.collapsedColumns);
|
|
405
407
|
const columnVirtualizationEnabled = $derived(
|
|
406
408
|
ctrl.columnVirtualizationEnabled,
|
|
407
409
|
);
|
|
408
410
|
const virtualRows = $derived(ctrl.virtualRows);
|
|
411
|
+
const frozenRowCount = $derived(ctrl.frozenRowCount);
|
|
412
|
+
const frozenRowList = $derived(ctrl.frozenRowList);
|
|
413
|
+
// Merged cells. A merge is drawn once per band (the frozen rows, the
|
|
414
|
+
// scrolling body), by the top-left cell of the part the band shows, with
|
|
415
|
+
// its spans clamped to the rendered window: a td never spans into rows
|
|
416
|
+
// the table has not drawn.
|
|
417
|
+
const mergeIndex = $derived(ctrl.mergeIndex);
|
|
418
|
+
const mergeColumnWindow = $derived.by(() => ({
|
|
419
|
+
firstCol: renderedColumns[0]?.item.index ?? 0,
|
|
420
|
+
lastCol: renderedColumns[renderedColumns.length - 1]?.item.index ?? -1,
|
|
421
|
+
}));
|
|
422
|
+
const mergeBodyWindow = $derived.by(() => {
|
|
423
|
+
const cols = mergeColumnWindow;
|
|
424
|
+
if (!rowVirtualizationEnabled) return { firstRow: frozenRowCount, lastRow: allRows.length - 1, ...cols };
|
|
425
|
+
let firstRow = Number.POSITIVE_INFINITY;
|
|
426
|
+
let lastRow = -1;
|
|
427
|
+
for (const item of virtualRows) {
|
|
428
|
+
if (item.index < frozenRowCount) continue;
|
|
429
|
+
if (item.index < firstRow) firstRow = item.index;
|
|
430
|
+
if (item.index > lastRow) lastRow = item.index;
|
|
431
|
+
}
|
|
432
|
+
return { firstRow: Number.isFinite(firstRow) ? firstRow : frozenRowCount, lastRow, ...cols };
|
|
433
|
+
});
|
|
434
|
+
const mergeFrozenWindow = $derived.by(() => ({ firstRow: 0, lastRow: frozenRowCount - 1, ...mergeColumnWindow }));
|
|
435
|
+
/** The width a td spanning `colSpan` rendered columns from `colIndex` takes. */
|
|
436
|
+
function mergedWidth(colIndex: number, colSpan: number, own: number): number {
|
|
437
|
+
if (colSpan <= 1) return own;
|
|
438
|
+
let total = 0;
|
|
439
|
+
for (const rendered of renderedColumns) {
|
|
440
|
+
const i = rendered.item.index;
|
|
441
|
+
if (i >= colIndex && i < colIndex + colSpan) total += rendered.item.size;
|
|
442
|
+
}
|
|
443
|
+
return total || own;
|
|
444
|
+
}
|
|
445
|
+
const frozenBandHeight = $derived(ctrl.frozenBandHeight);
|
|
446
|
+
const frozenRowTop = $derived(ctrl.frozenRowTop);
|
|
409
447
|
const autoRowHeightOn = $derived(ctrl.autoRowHeightOn);
|
|
410
448
|
const measureRowHeight = $derived(ctrl.measureRowHeight);
|
|
411
449
|
const measuredRowHeightPx = $derived(ctrl.measuredRowHeightPx);
|
|
@@ -522,9 +560,8 @@
|
|
|
522
560
|
const toggleSelectAllRows = $derived(ctrl.toggleSelectAllRows);
|
|
523
561
|
const setActiveCell = $derived(ctrl.setActiveCell);
|
|
524
562
|
const scrollActiveCellIntoView = $derived(ctrl.scrollActiveCellIntoView);
|
|
563
|
+
const cellSelectionState = $derived(ctrl.cellSelectionState);
|
|
525
564
|
const getColumnWidth = $derived(ctrl.getColumnWidth);
|
|
526
|
-
const getCellRangeEdges = $derived(ctrl.getCellRangeEdges);
|
|
527
|
-
const fillHandleCell = $derived(ctrl.fillHandleCell);
|
|
528
565
|
const isInFillPreview = $derived(ctrl.isInFillPreview);
|
|
529
566
|
const fillMarqueeEdges = $derived(ctrl.fillMarqueeEdges);
|
|
530
567
|
const startFillDrag = $derived(ctrl.startFillDrag);
|
|
@@ -755,6 +792,19 @@
|
|
|
755
792
|
rotate-on-open both hang off it (SvGrid.css), and an override that
|
|
756
793
|
dropped the class would lose both silently - which is the kind of bug
|
|
757
794
|
that only shows up in someone else's app. -->
|
|
795
|
+
{#snippet chartToggle()}
|
|
796
|
+
<button
|
|
797
|
+
type="button"
|
|
798
|
+
class="sv-grid-toolbar-btn sv-grid-chart-toggle"
|
|
799
|
+
class:is-active={ctrl.chartPanelOpen}
|
|
800
|
+
aria-label={ctrl.chartPanelOpen ? "Close chart" : "Open chart"}
|
|
801
|
+
aria-expanded={ctrl.chartPanelOpen}
|
|
802
|
+
onclick={() => (ctrl.chartPanelOpen = !ctrl.chartPanelOpen)}
|
|
803
|
+
>
|
|
804
|
+
{@render icon("chart")}
|
|
805
|
+
Chart
|
|
806
|
+
</button>
|
|
807
|
+
{/snippet}
|
|
758
808
|
{#snippet icon(name: GridIconName)}
|
|
759
809
|
{@const override = opt.icons?.[name]}
|
|
760
810
|
{#if override}
|
|
@@ -1046,6 +1096,9 @@
|
|
|
1046
1096
|
</div>
|
|
1047
1097
|
</div>
|
|
1048
1098
|
{:else if pivotViewOn}
|
|
1099
|
+
<!-- The Chart panel docks here the way it docks beside the flat grid,
|
|
1100
|
+
and charts the pivot on screen: the root reserves the panel's edge and
|
|
1101
|
+
the pivot bar carries the toggle the toolbar carries in flat mode. -->
|
|
1049
1102
|
<div
|
|
1050
1103
|
class="sv-grid-root sv-grid-pivot-root"
|
|
1051
1104
|
class:sv-grid-root-fill={opt.containerHeight === "100%"}
|
|
@@ -1053,7 +1106,7 @@
|
|
|
1053
1106
|
typeof opt.containerHeight === "string"
|
|
1054
1107
|
? opt.containerHeight
|
|
1055
1108
|
: `${opt.containerHeight ?? 520}px`
|
|
1056
|
-
}; display: flex; flex-direction: column
|
|
1109
|
+
}; display: flex; flex-direction: column; ${chartDockReserveStyle}`}
|
|
1057
1110
|
>
|
|
1058
1111
|
<div class="sv-grid-pivot-bar">
|
|
1059
1112
|
<span class="sv-grid-pivot-badge">{messages.group}</span>
|
|
@@ -1063,6 +1116,9 @@
|
|
|
1063
1116
|
aria-pressed="true"
|
|
1064
1117
|
onclick={() => ctrl.togglePivotMode()}
|
|
1065
1118
|
>{messages.pivotUpsellTitle}</button>
|
|
1119
|
+
{#if ctrl.chartingEnabled}
|
|
1120
|
+
{@render chartToggle()}
|
|
1121
|
+
{/if}
|
|
1066
1122
|
</div>
|
|
1067
1123
|
<div style="flex: 1 1 auto; min-height: 0;">
|
|
1068
1124
|
{#if pivotResult}
|
|
@@ -1081,6 +1137,9 @@
|
|
|
1081
1137
|
</div>
|
|
1082
1138
|
{/if}
|
|
1083
1139
|
</div>
|
|
1140
|
+
{#if ctrl.chartingEnabled && ctrl.chartPanelOpen && ChartPanelView}
|
|
1141
|
+
<ChartPanelView {ctrl} />
|
|
1142
|
+
{/if}
|
|
1084
1143
|
</div>
|
|
1085
1144
|
{:else}
|
|
1086
1145
|
|
|
@@ -1406,6 +1465,308 @@
|
|
|
1406
1465
|
inline editing, no row-selection checkbox, no fill handle.
|
|
1407
1466
|
Position-sticky CSS keeps it anchored to the top of the body or
|
|
1408
1467
|
the bottom of the viewport while the rest scrolls. -->
|
|
1468
|
+
<!--
|
|
1469
|
+
One body row, whatever path renders it: the virtualized window, the
|
|
1470
|
+
plain full-list body, or the frozen rows pinned above the window. The
|
|
1471
|
+
two loops used to carry a copy each and had drifted apart (cell
|
|
1472
|
+
tooltips on one, the fill handle on the other), so a feature landed in
|
|
1473
|
+
one mode and not the other. `rowStyle` is the height the caller knows:
|
|
1474
|
+
the virtualizer's measured size, or the declared one.
|
|
1475
|
+
-->
|
|
1476
|
+
{#snippet bodyRow(row: Row<TData>, rowIndex: number, rowStyle: string)}
|
|
1477
|
+
{#if opt.isDetailRow?.(row.original as TData, rowIndex)}
|
|
1478
|
+
{@render detailRowMarkup(row, rowIndex)}
|
|
1479
|
+
{:else if isGroupRow(row) && !groupColumnMode}
|
|
1480
|
+
<tr
|
|
1481
|
+
class="sv-grid-row sv-grid-group-row"
|
|
1482
|
+
class:sv-grid-row-selected={isRowSelected(row.id)}
|
|
1483
|
+
class:sv-grid-row-frozen={rowIndex < frozenRowCount}
|
|
1484
|
+
class:sv-grid-row-frozen-last={frozenRowCount > 0 && rowIndex === frozenRowCount - 1}
|
|
1485
|
+
style:top={rowIndex < frozenRowCount ? `${frozenRowTop(rowIndex)}px` : undefined}
|
|
1486
|
+
aria-level={row.depth + 1}
|
|
1487
|
+
aria-expanded={row.getIsExpanded?.() ? "true" : "false"}
|
|
1488
|
+
{...getGridRowA11yProps(rowIndex + 1)}
|
|
1489
|
+
class:sv-grid-row-collapsed={ctrl.isRowCollapsed(rowIndex)}
|
|
1490
|
+
style={rowStyle}
|
|
1491
|
+
>
|
|
1492
|
+
<td
|
|
1493
|
+
class="sv-grid-cell sv-grid-group-cell"
|
|
1494
|
+
class:sv-grid-cell-active={activeCell.rowIndex ===
|
|
1495
|
+
rowIndex}
|
|
1496
|
+
colspan={allColumns.length +
|
|
1497
|
+
(showRowNumbersEffective ? 1 : 0) +
|
|
1498
|
+
(showRowSelectionEffective ? 1 : 0)}
|
|
1499
|
+
onclick={() => row.toggleExpanded?.()}
|
|
1500
|
+
>
|
|
1501
|
+
{@render groupRowContent(row)}
|
|
1502
|
+
</td>
|
|
1503
|
+
</tr>
|
|
1504
|
+
{:else}
|
|
1505
|
+
{@const userRowClass = computeRowClass(row, rowIndex)}
|
|
1506
|
+
<tr
|
|
1507
|
+
class={`sv-grid-row ${userRowClass} ${rowDropClass(rowIndex)}`}
|
|
1508
|
+
class:sv-grid-row-selected={isRowSelected(row.id)}
|
|
1509
|
+
class:sv-grid-row-alt={opt.zebraRows &&
|
|
1510
|
+
rowIndex % 2 === 1}
|
|
1511
|
+
class:sv-grid-row-draggable={rowDragManagedEffective}
|
|
1512
|
+
class:sv-grid-group-footer-row={isGroupFooterRow(row)}
|
|
1513
|
+
class:sv-grid-grand-total-row={isGrandTotalRow(row)}
|
|
1514
|
+
class:sv-grid-row-auto-height={autoRowHeightOn}
|
|
1515
|
+
class:sv-grid-row-frozen={rowIndex < frozenRowCount}
|
|
1516
|
+
class:sv-grid-row-frozen-last={frozenRowCount > 0 && rowIndex === frozenRowCount - 1}
|
|
1517
|
+
style:top={rowIndex < frozenRowCount ? `${frozenRowTop(rowIndex)}px` : undefined}
|
|
1518
|
+
{...getGridRowA11yProps(rowIndex + 1)}
|
|
1519
|
+
aria-level={sgAriaLevel(row)}
|
|
1520
|
+
aria-expanded={sgAriaExpanded(row)}
|
|
1521
|
+
{...rowDragAttrs(rowIndex)}
|
|
1522
|
+
class:sv-grid-row-collapsed={ctrl.isRowCollapsed(rowIndex)}
|
|
1523
|
+
style={rowStyle}
|
|
1524
|
+
use:measureRowHeight={rowIndex}
|
|
1525
|
+
>
|
|
1526
|
+
{#if showRowNumbersEffective}
|
|
1527
|
+
<td
|
|
1528
|
+
class="sv-grid-cell sv-grid-row-number-cell"
|
|
1529
|
+
style={`width: ${rowNumberColumnWidth}px; min-width: ${rowNumberColumnWidth}px; max-width: ${rowNumberColumnWidth}px; left: 0;`}
|
|
1530
|
+
>{rowIndex + 1}</td
|
|
1531
|
+
>
|
|
1532
|
+
{/if}
|
|
1533
|
+
{#if showRowSelectionEffective}
|
|
1534
|
+
<td
|
|
1535
|
+
class="sv-grid-cell sv-grid-selection-cell"
|
|
1536
|
+
style={`width: ${selectionColumnWidth}px; min-width: ${selectionColumnWidth}px; max-width: ${selectionColumnWidth}px; left: ${showRowNumbersEffective ? rowNumberColumnWidth : 0}px;`}
|
|
1537
|
+
onclick={() => toggleRowSelectionById(row.id)}
|
|
1538
|
+
>
|
|
1539
|
+
<button
|
|
1540
|
+
type="button"
|
|
1541
|
+
class="sv-grid-checkbox"
|
|
1542
|
+
role="checkbox"
|
|
1543
|
+
aria-checked={isRowSelected(row.id)}
|
|
1544
|
+
aria-label="Select row"
|
|
1545
|
+
onclick={(event) => {
|
|
1546
|
+
event.stopPropagation();
|
|
1547
|
+
toggleRowSelectionById(row.id);
|
|
1548
|
+
}}
|
|
1549
|
+
onkeydown={(event) =>
|
|
1550
|
+
toggleCheckboxWithKeyboard(event, () => {
|
|
1551
|
+
event.stopPropagation();
|
|
1552
|
+
toggleRowSelectionById(row.id);
|
|
1553
|
+
})}
|
|
1554
|
+
></button>
|
|
1555
|
+
</td>
|
|
1556
|
+
{/if}
|
|
1557
|
+
{#if columnVirtualizationEnabled && columnWindowStart > 0}
|
|
1558
|
+
<td
|
|
1559
|
+
class="sv-grid-cell sv-grid-cell-spacer"
|
|
1560
|
+
aria-hidden="true"
|
|
1561
|
+
style={`width: ${columnWindowStart}px; min-width: ${columnWindowStart}px; max-width: ${columnWindowStart}px;`}
|
|
1562
|
+
></td>
|
|
1563
|
+
{/if}
|
|
1564
|
+
{#each renderedColumns as rendered (rendered.column.id)}
|
|
1565
|
+
{@const colIndex = rendered.item.index}
|
|
1566
|
+
{@const draw = mergeIndex
|
|
1567
|
+
? mergeDrawAt(mergeIndex, rowIndex, colIndex, rowIndex < frozenRowCount ? mergeFrozenWindow : mergeBodyWindow)
|
|
1568
|
+
: null}
|
|
1569
|
+
{#if draw?.kind !== "skip"}
|
|
1570
|
+
{@const cellRow = draw?.kind === "continuation" ? (allRows[draw.merge.rowIndex] ?? row) : row}
|
|
1571
|
+
{@const cellColumn = draw?.kind === "continuation" ? (allColumns[draw.merge.colIndex] ?? rendered.column) : rendered.column}
|
|
1572
|
+
{@const baseValue = getColumnBaseValue(
|
|
1573
|
+
cellRow,
|
|
1574
|
+
cellColumn,
|
|
1575
|
+
)}
|
|
1576
|
+
{@const cellValue = getCellDisplayValue(
|
|
1577
|
+
cellRow.id,
|
|
1578
|
+
cellColumn.id,
|
|
1579
|
+
baseValue,
|
|
1580
|
+
)}
|
|
1581
|
+
{@const isEditing =
|
|
1582
|
+
ctrl.editingCell?.rowId === cellRow.id &&
|
|
1583
|
+
ctrl.editingCell?.columnId === cellColumn.id}
|
|
1584
|
+
{@const inRowEdit =
|
|
1585
|
+
!!fullRowEdit &&
|
|
1586
|
+
fullRowEdit.rowId === cellRow.id &&
|
|
1587
|
+
cellColumn.id in fullRowEdit.draft}
|
|
1588
|
+
{@const cellSel = cellSelectionState(rowIndex, colIndex)}
|
|
1589
|
+
{@const fillEdges = fillMarqueeEdges(rowIndex, colIndex)}
|
|
1590
|
+
{@const userCellClass = computeCellClass(
|
|
1591
|
+
cellRow,
|
|
1592
|
+
cellColumn,
|
|
1593
|
+
)}
|
|
1594
|
+
{@const cellTooltip = computeCellTooltip(
|
|
1595
|
+
cellRow,
|
|
1596
|
+
cellColumn,
|
|
1597
|
+
)}
|
|
1598
|
+
{@const cellValidity = computeCellValidity(
|
|
1599
|
+
cellRow,
|
|
1600
|
+
cellColumn,
|
|
1601
|
+
)}
|
|
1602
|
+
{@const cellNote = computeCellNote(
|
|
1603
|
+
cellRow,
|
|
1604
|
+
cellColumn,
|
|
1605
|
+
)}
|
|
1606
|
+
{@const tdWidth = draw ? mergedWidth(colIndex, draw.colSpan, rendered.item.size) : rendered.item.size}
|
|
1607
|
+
<td
|
|
1608
|
+
rowspan={draw && draw.rowSpan > 1 ? draw.rowSpan : undefined}
|
|
1609
|
+
colspan={draw && draw.colSpan > 1 ? draw.colSpan : undefined}
|
|
1610
|
+
data-merge-origin={draw ? `${draw.merge.rowIndex}:${draw.merge.colIndex}` : undefined}
|
|
1611
|
+
class:sv-grid-cell-merged={!!draw}
|
|
1612
|
+
class={`sv-grid-cell ${userCellClass}`}
|
|
1613
|
+
class:sv-grid-cell-editing={isEditing || inRowEdit}
|
|
1614
|
+
class:sv-grid-cell-collapsed={!!collapsedColumns[rendered.column.id]}
|
|
1615
|
+
class:sv-grid-cell-active={!!cellSel?.active}
|
|
1616
|
+
class:sv-grid-cell-has-fill-handle={!!cellSel?.fillHandle}
|
|
1617
|
+
class:sv-grid-cell-cf={hasConditionalFormats}
|
|
1618
|
+
class:sv-grid-cell-invalid={cellValidity.invalid}
|
|
1619
|
+
class:sv-grid-cell-has-note={cellNote != null}
|
|
1620
|
+
aria-invalid={cellValidity.invalid ? "true" : undefined}
|
|
1621
|
+
data-svgrid-row={rowIndex}
|
|
1622
|
+
data-svgrid-col={colIndex}
|
|
1623
|
+
data-col-id={rendered.column.id}
|
|
1624
|
+
data-align={getColumnAlign(rendered.column)}
|
|
1625
|
+
data-pinned={isColumnPinned(rendered.column.id) ??
|
|
1626
|
+
undefined}
|
|
1627
|
+
data-selected-range={cellSel?.edges ? "true" : undefined}
|
|
1628
|
+
data-range-top={cellSel?.edges?.top ? "true" : undefined}
|
|
1629
|
+
data-range-bottom={cellSel?.edges?.bottom
|
|
1630
|
+
? "true"
|
|
1631
|
+
: undefined}
|
|
1632
|
+
data-range-left={cellSel?.edges?.left
|
|
1633
|
+
? "true"
|
|
1634
|
+
: undefined}
|
|
1635
|
+
data-range-right={cellSel?.edges?.right
|
|
1636
|
+
? "true"
|
|
1637
|
+
: undefined}
|
|
1638
|
+
data-fill-preview={isInFillPreview(rowIndex, colIndex)
|
|
1639
|
+
? "true"
|
|
1640
|
+
: undefined}
|
|
1641
|
+
data-fill-top={fillEdges?.top ? "true" : undefined}
|
|
1642
|
+
data-fill-bottom={fillEdges?.bottom ? "true" : undefined}
|
|
1643
|
+
data-fill-left={fillEdges?.left ? "true" : undefined}
|
|
1644
|
+
data-fill-right={fillEdges?.right ? "true" : undefined}
|
|
1645
|
+
style={`width: ${tdWidth}px; min-width: ${tdWidth}px; max-width: ${tdWidth}px; ${cellPinStyle(rendered.column.id)}`}
|
|
1646
|
+
onpointerdown={(event) =>
|
|
1647
|
+
onCellPointerDown(rowIndex, colIndex, event)}
|
|
1648
|
+
onpointerenter={(event) => {
|
|
1649
|
+
onCellPointerEnter(rowIndex, colIndex);
|
|
1650
|
+
// The column tooltip fires on whole-cell hover; a
|
|
1651
|
+
// per-cell note waits for its corner below. A
|
|
1652
|
+
// validation message wins over the column's tooltip.
|
|
1653
|
+
const tip =
|
|
1654
|
+
cellValidity.invalid && cellValidity.message
|
|
1655
|
+
? cellValidity.message
|
|
1656
|
+
: cellTooltip;
|
|
1657
|
+
if (tip)
|
|
1658
|
+
showTooltipFor(
|
|
1659
|
+
event.currentTarget as HTMLElement,
|
|
1660
|
+
tip,
|
|
1661
|
+
);
|
|
1662
|
+
}}
|
|
1663
|
+
onpointerleave={hideTooltip}
|
|
1664
|
+
ondblclick={() =>
|
|
1665
|
+
emitCellDoubleClick(rowIndex, colIndex)}
|
|
1666
|
+
onclick={() => onCellClick(rowIndex, colIndex)}
|
|
1667
|
+
oncontextmenu={(event) =>
|
|
1668
|
+
openContextMenu(
|
|
1669
|
+
event,
|
|
1670
|
+
rowIndex,
|
|
1671
|
+
colIndex,
|
|
1672
|
+
rendered.column.id,
|
|
1673
|
+
)}
|
|
1674
|
+
use:cellFlashAction={{
|
|
1675
|
+
rowId: cellRow.id,
|
|
1676
|
+
value: cellValue,
|
|
1677
|
+
active: !!cellColumn.columnDef.cellFlash,
|
|
1678
|
+
className: flashClassFor(
|
|
1679
|
+
cellColumn.columnDef.cellFlash,
|
|
1680
|
+
),
|
|
1681
|
+
}}
|
|
1682
|
+
role="gridcell"
|
|
1683
|
+
id={getGridCellDomId(ctrl.gridDomId, rowIndex, colIndex)}
|
|
1684
|
+
aria-colindex={colIndex + 1}
|
|
1685
|
+
aria-rowindex={rowIndex + 1}
|
|
1686
|
+
aria-selected={isRowSelected(row.id)}
|
|
1687
|
+
>
|
|
1688
|
+
{#if inRowEdit || isEditing}
|
|
1689
|
+
<!-- The editing cell stays empty until the lazy
|
|
1690
|
+
editor chunk lands, exactly as it already did
|
|
1691
|
+
for the dropdown / date editors. Falling back
|
|
1692
|
+
to the read-only value here would flash stale
|
|
1693
|
+
content into a cell the user is editing. -->
|
|
1694
|
+
{#if CellEditor}
|
|
1695
|
+
<CellEditor {ctrl} column={cellColumn} row={cellRow} fullRow={inRowEdit} />
|
|
1696
|
+
{/if}
|
|
1697
|
+
{:else}
|
|
1698
|
+
{#if plainCellBody}
|
|
1699
|
+
{@render cellBody(cellRow, cellColumn, cellValue)}
|
|
1700
|
+
{:else}
|
|
1701
|
+
{@render cellBodyWithFormat(
|
|
1702
|
+
cellRow,
|
|
1703
|
+
cellColumn,
|
|
1704
|
+
cellValue,
|
|
1705
|
+
)}
|
|
1706
|
+
{/if}
|
|
1707
|
+
{/if}
|
|
1708
|
+
{#if !isEditing && cellSel?.fillHandle}
|
|
1709
|
+
<!-- Excel-style fill handle: drag down/right to
|
|
1710
|
+
extend the selection and pattern-fill the new
|
|
1711
|
+
cells on release. Rendered inside the bottom-
|
|
1712
|
+
right cell of the selection range (or active
|
|
1713
|
+
cell if there's no range). -->
|
|
1714
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
1715
|
+
<div
|
|
1716
|
+
class="sv-grid-fill-handle"
|
|
1717
|
+
role="button"
|
|
1718
|
+
aria-label="Fill handle"
|
|
1719
|
+
tabindex={-1}
|
|
1720
|
+
onpointerdown={(event) =>
|
|
1721
|
+
startFillDrag(event, rowIndex, colIndex)}
|
|
1722
|
+
ondblclick={(event) => {
|
|
1723
|
+
// Not the cell's double-click: this fills
|
|
1724
|
+
// down as far as the neighbour column goes.
|
|
1725
|
+
event.stopPropagation();
|
|
1726
|
+
event.preventDefault();
|
|
1727
|
+
ctrl.fillDownToNeighbour();
|
|
1728
|
+
}}
|
|
1729
|
+
></div>
|
|
1730
|
+
{/if}
|
|
1731
|
+
{#if cellValidity.invalid && cellValidity.message}
|
|
1732
|
+
<!-- The validation message, for assistive tech: the
|
|
1733
|
+
tooltip above is mouse-only, and unlike a title
|
|
1734
|
+
a visually-hidden span adds no second native
|
|
1735
|
+
tooltip competing with the custom one. -->
|
|
1736
|
+
<span class="sv-grid-sr-only"
|
|
1737
|
+
>{cellValidity.message}</span
|
|
1738
|
+
>
|
|
1739
|
+
{/if}
|
|
1740
|
+
{#if cellNote != null && !isEditing}
|
|
1741
|
+
<span
|
|
1742
|
+
class="sv-grid-cell-note-corner"
|
|
1743
|
+
aria-label="Note"
|
|
1744
|
+
onpointerenter={(event) => {
|
|
1745
|
+
event.stopPropagation();
|
|
1746
|
+
showTooltipFor(
|
|
1747
|
+
event.currentTarget as HTMLElement,
|
|
1748
|
+
cellNote,
|
|
1749
|
+
);
|
|
1750
|
+
}}
|
|
1751
|
+
onpointerleave={(event) => {
|
|
1752
|
+
event.stopPropagation();
|
|
1753
|
+
hideTooltip();
|
|
1754
|
+
}}
|
|
1755
|
+
></span>
|
|
1756
|
+
{/if}
|
|
1757
|
+
</td>
|
|
1758
|
+
{/if}
|
|
1759
|
+
{/each}
|
|
1760
|
+
{#if columnVirtualizationEnabled && columnWindowRightSpacer > 0}
|
|
1761
|
+
<td
|
|
1762
|
+
class="sv-grid-cell sv-grid-cell-spacer"
|
|
1763
|
+
aria-hidden="true"
|
|
1764
|
+
style={`width: ${columnWindowRightSpacer}px; min-width: ${columnWindowRightSpacer}px; max-width: ${columnWindowRightSpacer}px;`}
|
|
1765
|
+
></td>
|
|
1766
|
+
{/if}
|
|
1767
|
+
</tr>
|
|
1768
|
+
{/if}
|
|
1769
|
+
{/snippet}
|
|
1409
1770
|
{#snippet pinnedRowBody(
|
|
1410
1771
|
rowData: TData,
|
|
1411
1772
|
where: "top" | "bottom",
|
|
@@ -1475,7 +1836,8 @@
|
|
|
1475
1836
|
// No gutter column on most grids, so fall back to the first body cell -
|
|
1476
1837
|
// otherwise `rowResize` would be a prop that silently does nothing.
|
|
1477
1838
|
anchor: "row",
|
|
1478
|
-
onResize: (index, height) => ctrl.
|
|
1839
|
+
onResize: (index, height) => ctrl.resizeRowByUser(index, height),
|
|
1840
|
+
onAutosize: (index) => ctrl.resizeRowByUser(index, null),
|
|
1479
1841
|
}}
|
|
1480
1842
|
use:lazyColumnResize={{
|
|
1481
1843
|
disabled: !columnResizeEnabled,
|
|
@@ -1483,12 +1845,13 @@
|
|
|
1483
1845
|
onResize: (columnId, width) => {
|
|
1484
1846
|
ctrl.columnWidths = { ...ctrl.columnWidths, [columnId]: width };
|
|
1485
1847
|
},
|
|
1848
|
+
onResizeEnd: (columnId, width, startWidth) => ctrl.resizeColumnByUser(columnId, width, startWidth),
|
|
1486
1849
|
label: (columnId) => {
|
|
1487
1850
|
const col = ctrl.findColumnById(columnId);
|
|
1488
1851
|
return col ? toolPanelHeaderLabel(col) : columnId;
|
|
1489
1852
|
},
|
|
1490
1853
|
canResize: (columnId) => ctrl.columnResizable(columnId),
|
|
1491
|
-
onAutosize: (columnId) => ctrl.
|
|
1854
|
+
onAutosize: (columnId) => ctrl.autosizeColumnByUser(columnId),
|
|
1492
1855
|
}}
|
|
1493
1856
|
>
|
|
1494
1857
|
{#if showGlobalFilterEffective}
|
|
@@ -1535,17 +1898,7 @@
|
|
|
1535
1898
|
</button>
|
|
1536
1899
|
{/if}
|
|
1537
1900
|
{#if ctrl.chartingEnabled}
|
|
1538
|
-
|
|
1539
|
-
type="button"
|
|
1540
|
-
class="sv-grid-toolbar-btn sv-grid-chart-toggle"
|
|
1541
|
-
class:is-active={ctrl.chartPanelOpen}
|
|
1542
|
-
aria-label={ctrl.chartPanelOpen ? "Close chart" : "Open chart"}
|
|
1543
|
-
aria-expanded={ctrl.chartPanelOpen}
|
|
1544
|
-
onclick={() => (ctrl.chartPanelOpen = !ctrl.chartPanelOpen)}
|
|
1545
|
-
>
|
|
1546
|
-
{@render icon("chart")}
|
|
1547
|
-
Chart
|
|
1548
|
-
</button>
|
|
1901
|
+
{@render chartToggle()}
|
|
1549
1902
|
{/if}
|
|
1550
1903
|
</div>
|
|
1551
1904
|
{/if}
|
|
@@ -1560,7 +1913,7 @@
|
|
|
1560
1913
|
typeof opt.containerHeight === "string"
|
|
1561
1914
|
? opt.containerHeight
|
|
1562
1915
|
: `${opt.containerHeight ?? 520}px`
|
|
1563
|
-
}; --sg-thead-h: ${headerHeight}px; --sg-pinned-row-h: ${typeof opt.rowHeight === "number" ? opt.rowHeight : 30}px;`}
|
|
1916
|
+
}; --sg-thead-h: ${headerHeight}px; --sg-frozen-h: ${frozenBandHeight}px; --sg-pinned-row-h: ${typeof opt.rowHeight === "number" ? opt.rowHeight : 30}px;`}
|
|
1564
1917
|
>
|
|
1565
1918
|
<div
|
|
1566
1919
|
class="sv-grid-container sv-grid-container-custom-scrollbars"
|
|
@@ -1723,6 +2076,7 @@
|
|
|
1723
2076
|
)}
|
|
1724
2077
|
<th
|
|
1725
2078
|
class="sv-grid-column"
|
|
2079
|
+
class:sv-grid-column-collapsed={!!collapsedColumns[header.column.id]}
|
|
1726
2080
|
class:is-drag-target-before={colDropOnId ===
|
|
1727
2081
|
header.column.id && colDropSide === "before"}
|
|
1728
2082
|
class:is-drag-target-after={colDropOnId ===
|
|
@@ -2180,6 +2534,9 @@
|
|
|
2180
2534
|
</td>
|
|
2181
2535
|
</tr>
|
|
2182
2536
|
{:else if rowVirtualizationEnabled}
|
|
2537
|
+
{#each frozenRowList as row, rowIndex (row.id)}
|
|
2538
|
+
{@render bodyRow(row, rowIndex, rowStyleFor(rowIndex))}
|
|
2539
|
+
{/each}
|
|
2183
2540
|
{#if rowTopSpacer > 0}
|
|
2184
2541
|
<tr class="sv-grid-row sv-grid-row-spacer" aria-hidden="true">
|
|
2185
2542
|
<td
|
|
@@ -2191,256 +2548,17 @@
|
|
|
2191
2548
|
></td>
|
|
2192
2549
|
</tr>
|
|
2193
2550
|
{/if}
|
|
2551
|
+
<!-- The virtualizer counts every row, frozen ones included, so its
|
|
2552
|
+
offsets and sizes stay in row-index space; the frozen rows are
|
|
2553
|
+
rendered in the band above and SKIPPED here. Shifting the
|
|
2554
|
+
index instead (item i drawn as row i + N) sized every row with
|
|
2555
|
+
the height of the row N above it, so a row dragged taller under
|
|
2556
|
+
a freeze showed its neighbour's height. -->
|
|
2194
2557
|
{#each virtualRows as rowItem (rowItem.key)}
|
|
2195
2558
|
{@const rowIndex = rowItem.index}
|
|
2196
2559
|
{@const row = allRows[rowIndex]}
|
|
2197
|
-
{#if row}
|
|
2198
|
-
{
|
|
2199
|
-
{@render detailRowMarkup(row, rowIndex)}
|
|
2200
|
-
{:else if isGroupRow(row) && !groupColumnMode}
|
|
2201
|
-
<tr
|
|
2202
|
-
class="sv-grid-row sv-grid-group-row"
|
|
2203
|
-
class:sv-grid-row-selected={isRowSelected(row.id)}
|
|
2204
|
-
aria-level={row.depth + 1}
|
|
2205
|
-
aria-expanded={row.getIsExpanded?.() ? "true" : "false"}
|
|
2206
|
-
{...getGridRowA11yProps(rowIndex + 1)}
|
|
2207
|
-
style={rowHeightStyle(rowItem.size)}
|
|
2208
|
-
>
|
|
2209
|
-
<td
|
|
2210
|
-
class="sv-grid-cell sv-grid-group-cell"
|
|
2211
|
-
class:sv-grid-cell-active={activeCell.rowIndex ===
|
|
2212
|
-
rowIndex}
|
|
2213
|
-
colspan={allColumns.length +
|
|
2214
|
-
(showRowNumbersEffective ? 1 : 0) +
|
|
2215
|
-
(showRowSelectionEffective ? 1 : 0)}
|
|
2216
|
-
onclick={() => row.toggleExpanded?.()}
|
|
2217
|
-
>
|
|
2218
|
-
{@render groupRowContent(row)}
|
|
2219
|
-
</td>
|
|
2220
|
-
</tr>
|
|
2221
|
-
{:else}
|
|
2222
|
-
{@const userRowClass = computeRowClass(row, rowIndex)}
|
|
2223
|
-
<tr
|
|
2224
|
-
class={`sv-grid-row ${userRowClass} ${rowDropClass(rowIndex)}`}
|
|
2225
|
-
class:sv-grid-row-selected={isRowSelected(row.id)}
|
|
2226
|
-
class:sv-grid-row-alt={opt.zebraRows &&
|
|
2227
|
-
rowIndex % 2 === 1}
|
|
2228
|
-
class:sv-grid-row-draggable={rowDragManagedEffective}
|
|
2229
|
-
class:sv-grid-group-footer-row={isGroupFooterRow(row)}
|
|
2230
|
-
class:sv-grid-grand-total-row={isGrandTotalRow(row)}
|
|
2231
|
-
class:sv-grid-row-auto-height={autoRowHeightOn}
|
|
2232
|
-
{...getGridRowA11yProps(rowIndex + 1)}
|
|
2233
|
-
aria-level={sgAriaLevel(row)}
|
|
2234
|
-
aria-expanded={sgAriaExpanded(row)}
|
|
2235
|
-
{...rowDragAttrs(rowIndex)}
|
|
2236
|
-
style={rowHeightStyle(rowItem.size)}
|
|
2237
|
-
use:measureRowHeight={rowIndex}
|
|
2238
|
-
>
|
|
2239
|
-
{#if showRowNumbersEffective}
|
|
2240
|
-
<td
|
|
2241
|
-
class="sv-grid-cell sv-grid-row-number-cell"
|
|
2242
|
-
style={`width: ${rowNumberColumnWidth}px; min-width: ${rowNumberColumnWidth}px; max-width: ${rowNumberColumnWidth}px; left: 0;`}
|
|
2243
|
-
>{rowIndex + 1}</td
|
|
2244
|
-
>
|
|
2245
|
-
{/if}
|
|
2246
|
-
{#if showRowSelectionEffective}
|
|
2247
|
-
<td
|
|
2248
|
-
class="sv-grid-cell sv-grid-selection-cell"
|
|
2249
|
-
style={`width: ${selectionColumnWidth}px; min-width: ${selectionColumnWidth}px; max-width: ${selectionColumnWidth}px; left: ${showRowNumbersEffective ? rowNumberColumnWidth : 0}px;`}
|
|
2250
|
-
onclick={() => toggleRowSelectionById(row.id)}
|
|
2251
|
-
>
|
|
2252
|
-
<button
|
|
2253
|
-
type="button"
|
|
2254
|
-
class="sv-grid-checkbox"
|
|
2255
|
-
role="checkbox"
|
|
2256
|
-
aria-checked={isRowSelected(row.id)}
|
|
2257
|
-
aria-label="Select row"
|
|
2258
|
-
onclick={(event) => {
|
|
2259
|
-
event.stopPropagation();
|
|
2260
|
-
toggleRowSelectionById(row.id);
|
|
2261
|
-
}}
|
|
2262
|
-
onkeydown={(event) =>
|
|
2263
|
-
toggleCheckboxWithKeyboard(event, () => {
|
|
2264
|
-
event.stopPropagation();
|
|
2265
|
-
toggleRowSelectionById(row.id);
|
|
2266
|
-
})}
|
|
2267
|
-
></button>
|
|
2268
|
-
</td>
|
|
2269
|
-
{/if}
|
|
2270
|
-
{#if columnVirtualizationEnabled && columnWindowStart > 0}
|
|
2271
|
-
<td
|
|
2272
|
-
class="sv-grid-cell sv-grid-cell-spacer"
|
|
2273
|
-
aria-hidden="true"
|
|
2274
|
-
style={`width: ${columnWindowStart}px; min-width: ${columnWindowStart}px; max-width: ${columnWindowStart}px;`}
|
|
2275
|
-
></td>
|
|
2276
|
-
{/if}
|
|
2277
|
-
{#each renderedColumns as rendered (rendered.column.id)}
|
|
2278
|
-
{@const colIndex = rendered.item.index}
|
|
2279
|
-
{@const baseValue = getColumnBaseValue(
|
|
2280
|
-
row,
|
|
2281
|
-
rendered.column,
|
|
2282
|
-
)}
|
|
2283
|
-
{@const cellValue = getCellDisplayValue(
|
|
2284
|
-
row.id,
|
|
2285
|
-
rendered.column.id,
|
|
2286
|
-
baseValue,
|
|
2287
|
-
)}
|
|
2288
|
-
{@const isEditing =
|
|
2289
|
-
ctrl.editingCell?.rowId === row.id &&
|
|
2290
|
-
ctrl.editingCell?.columnId === rendered.column.id}
|
|
2291
|
-
{@const inRowEdit =
|
|
2292
|
-
!!fullRowEdit &&
|
|
2293
|
-
fullRowEdit.rowId === row.id &&
|
|
2294
|
-
rendered.column.id in fullRowEdit.draft}
|
|
2295
|
-
{@const rangeEdges = getCellRangeEdges(
|
|
2296
|
-
rowIndex,
|
|
2297
|
-
colIndex,
|
|
2298
|
-
)}
|
|
2299
|
-
{@const fillEdges = fillMarqueeEdges(rowIndex, colIndex)}
|
|
2300
|
-
{@const hasFillHandle =
|
|
2301
|
-
fillHandleCell &&
|
|
2302
|
-
fillHandleCell.rowIndex === rowIndex &&
|
|
2303
|
-
fillHandleCell.colIndex === colIndex}
|
|
2304
|
-
{@const userCellClass = computeCellClass(
|
|
2305
|
-
row,
|
|
2306
|
-
rendered.column,
|
|
2307
|
-
)}
|
|
2308
|
-
{@const cellValidity = computeCellValidity(
|
|
2309
|
-
row,
|
|
2310
|
-
rendered.column,
|
|
2311
|
-
)}
|
|
2312
|
-
{@const cellNote = computeCellNote(
|
|
2313
|
-
row,
|
|
2314
|
-
rendered.column,
|
|
2315
|
-
)}
|
|
2316
|
-
<td
|
|
2317
|
-
class={`sv-grid-cell ${userCellClass}`}
|
|
2318
|
-
class:sv-grid-cell-editing={isEditing || inRowEdit}
|
|
2319
|
-
class:sv-grid-cell-active={activeCell.rowIndex ===
|
|
2320
|
-
rowIndex && activeCell.colIndex === colIndex}
|
|
2321
|
-
class:sv-grid-cell-has-fill-handle={hasFillHandle}
|
|
2322
|
-
class:sv-grid-cell-cf={hasConditionalFormats}
|
|
2323
|
-
class:sv-grid-cell-invalid={cellValidity.invalid}
|
|
2324
|
-
class:sv-grid-cell-has-note={cellNote != null}
|
|
2325
|
-
aria-invalid={cellValidity.invalid ? "true" : undefined}
|
|
2326
|
-
title={cellValidity.message ?? undefined}
|
|
2327
|
-
data-svgrid-row={rowIndex}
|
|
2328
|
-
data-svgrid-col={colIndex}
|
|
2329
|
-
data-col-id={rendered.column.id}
|
|
2330
|
-
data-align={getColumnAlign(rendered.column)}
|
|
2331
|
-
data-pinned={isColumnPinned(rendered.column.id) ??
|
|
2332
|
-
undefined}
|
|
2333
|
-
data-selected-range={rangeEdges ? "true" : undefined}
|
|
2334
|
-
data-range-top={rangeEdges?.top ? "true" : undefined}
|
|
2335
|
-
data-range-bottom={rangeEdges?.bottom
|
|
2336
|
-
? "true"
|
|
2337
|
-
: undefined}
|
|
2338
|
-
data-range-left={rangeEdges?.left
|
|
2339
|
-
? "true"
|
|
2340
|
-
: undefined}
|
|
2341
|
-
data-range-right={rangeEdges?.right
|
|
2342
|
-
? "true"
|
|
2343
|
-
: undefined}
|
|
2344
|
-
data-fill-preview={isInFillPreview(rowIndex, colIndex)
|
|
2345
|
-
? "true"
|
|
2346
|
-
: undefined}
|
|
2347
|
-
data-fill-top={fillEdges?.top ? "true" : undefined}
|
|
2348
|
-
data-fill-bottom={fillEdges?.bottom ? "true" : undefined}
|
|
2349
|
-
data-fill-left={fillEdges?.left ? "true" : undefined}
|
|
2350
|
-
data-fill-right={fillEdges?.right ? "true" : undefined}
|
|
2351
|
-
style={`width: ${rendered.item.size}px; min-width: ${rendered.item.size}px; max-width: ${rendered.item.size}px; ${cellPinStyle(rendered.column.id)}`}
|
|
2352
|
-
onpointerdown={(event) =>
|
|
2353
|
-
onCellPointerDown(rowIndex, colIndex, event)}
|
|
2354
|
-
onpointerenter={() =>
|
|
2355
|
-
onCellPointerEnter(rowIndex, colIndex)}
|
|
2356
|
-
ondblclick={() =>
|
|
2357
|
-
emitCellDoubleClick(rowIndex, colIndex)}
|
|
2358
|
-
onclick={() => onCellClick(rowIndex, colIndex)}
|
|
2359
|
-
oncontextmenu={(event) =>
|
|
2360
|
-
openContextMenu(
|
|
2361
|
-
event,
|
|
2362
|
-
rowIndex,
|
|
2363
|
-
colIndex,
|
|
2364
|
-
rendered.column.id,
|
|
2365
|
-
)}
|
|
2366
|
-
use:cellFlashAction={{
|
|
2367
|
-
rowId: row.id,
|
|
2368
|
-
value: cellValue,
|
|
2369
|
-
active: !!rendered.column.columnDef.cellFlash,
|
|
2370
|
-
className: flashClassFor(
|
|
2371
|
-
rendered.column.columnDef.cellFlash,
|
|
2372
|
-
),
|
|
2373
|
-
}}
|
|
2374
|
-
role="gridcell"
|
|
2375
|
-
id={getGridCellDomId(ctrl.gridDomId, rowIndex, colIndex)}
|
|
2376
|
-
aria-colindex={colIndex + 1}
|
|
2377
|
-
aria-rowindex={rowIndex + 1}
|
|
2378
|
-
aria-selected={isRowSelected(row.id)}
|
|
2379
|
-
>
|
|
2380
|
-
{#if inRowEdit || isEditing}
|
|
2381
|
-
<!-- The editing cell stays empty until the lazy
|
|
2382
|
-
editor chunk lands, exactly as it already did
|
|
2383
|
-
for the dropdown / date editors. Falling back
|
|
2384
|
-
to the read-only value here would flash stale
|
|
2385
|
-
content into a cell the user is editing. -->
|
|
2386
|
-
{#if CellEditor}
|
|
2387
|
-
<CellEditor {ctrl} column={rendered.column} {row} fullRow={inRowEdit} />
|
|
2388
|
-
{/if}
|
|
2389
|
-
{:else}
|
|
2390
|
-
{#if plainCellBody}
|
|
2391
|
-
{@render cellBody(row, rendered.column, cellValue)}
|
|
2392
|
-
{:else}
|
|
2393
|
-
{@render cellBodyWithFormat(
|
|
2394
|
-
row,
|
|
2395
|
-
rendered.column,
|
|
2396
|
-
cellValue,
|
|
2397
|
-
)}
|
|
2398
|
-
{/if}
|
|
2399
|
-
{/if}
|
|
2400
|
-
{#if !isEditing && fillHandleCell && fillHandleCell.rowIndex === rowIndex && fillHandleCell.colIndex === colIndex}
|
|
2401
|
-
<!-- Excel-style fill handle: drag down/right to
|
|
2402
|
-
extend the selection and pattern-fill the new
|
|
2403
|
-
cells on release. Rendered inside the bottom-
|
|
2404
|
-
right cell of the selection range (or active
|
|
2405
|
-
cell if there's no range). -->
|
|
2406
|
-
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
2407
|
-
<div
|
|
2408
|
-
class="sv-grid-fill-handle"
|
|
2409
|
-
role="button"
|
|
2410
|
-
aria-label="Fill handle"
|
|
2411
|
-
tabindex={-1}
|
|
2412
|
-
onpointerdown={(event) =>
|
|
2413
|
-
startFillDrag(event, rowIndex, colIndex)}
|
|
2414
|
-
></div>
|
|
2415
|
-
{/if}
|
|
2416
|
-
{#if cellNote != null && !isEditing}
|
|
2417
|
-
<span
|
|
2418
|
-
class="sv-grid-cell-note-corner"
|
|
2419
|
-
aria-label="Note"
|
|
2420
|
-
onpointerenter={(event) => {
|
|
2421
|
-
event.stopPropagation();
|
|
2422
|
-
showTooltipFor(
|
|
2423
|
-
event.currentTarget as HTMLElement,
|
|
2424
|
-
cellNote,
|
|
2425
|
-
);
|
|
2426
|
-
}}
|
|
2427
|
-
onpointerleave={(event) => {
|
|
2428
|
-
event.stopPropagation();
|
|
2429
|
-
hideTooltip();
|
|
2430
|
-
}}
|
|
2431
|
-
></span>
|
|
2432
|
-
{/if}
|
|
2433
|
-
</td>
|
|
2434
|
-
{/each}
|
|
2435
|
-
{#if columnVirtualizationEnabled && columnWindowRightSpacer > 0}
|
|
2436
|
-
<td
|
|
2437
|
-
class="sv-grid-cell sv-grid-cell-spacer"
|
|
2438
|
-
aria-hidden="true"
|
|
2439
|
-
style={`width: ${columnWindowRightSpacer}px; min-width: ${columnWindowRightSpacer}px; max-width: ${columnWindowRightSpacer}px;`}
|
|
2440
|
-
></td>
|
|
2441
|
-
{/if}
|
|
2442
|
-
</tr>
|
|
2443
|
-
{/if}
|
|
2560
|
+
{#if row && rowIndex >= frozenRowCount}
|
|
2561
|
+
{@render bodyRow(row, rowIndex, rowHeightStyle(rowItem.size))}
|
|
2444
2562
|
{/if}
|
|
2445
2563
|
{/each}
|
|
2446
2564
|
{#if rowBottomSpacer > 0}
|
|
@@ -2456,253 +2574,7 @@
|
|
|
2456
2574
|
{/if}
|
|
2457
2575
|
{:else}
|
|
2458
2576
|
{#each allRows as row, rowIndex (row.id)}
|
|
2459
|
-
{
|
|
2460
|
-
{@render detailRowMarkup(row, rowIndex)}
|
|
2461
|
-
{:else if isGroupRow(row) && !groupColumnMode}
|
|
2462
|
-
<tr
|
|
2463
|
-
class="sv-grid-row sv-grid-group-row"
|
|
2464
|
-
class:sv-grid-row-selected={isRowSelected(row.id)}
|
|
2465
|
-
aria-level={row.depth + 1}
|
|
2466
|
-
aria-expanded={row.getIsExpanded?.() ? "true" : "false"}
|
|
2467
|
-
{...getGridRowA11yProps(rowIndex + 1)}
|
|
2468
|
-
style={rowStyleFor(rowIndex)}
|
|
2469
|
-
>
|
|
2470
|
-
<td
|
|
2471
|
-
class="sv-grid-cell sv-grid-group-cell"
|
|
2472
|
-
class:sv-grid-cell-active={activeCell.rowIndex ===
|
|
2473
|
-
rowIndex}
|
|
2474
|
-
colspan={allColumns.length +
|
|
2475
|
-
(showRowNumbersEffective ? 1 : 0) +
|
|
2476
|
-
(showRowSelectionEffective ? 1 : 0)}
|
|
2477
|
-
onclick={() => row.toggleExpanded?.()}
|
|
2478
|
-
>
|
|
2479
|
-
{@render groupRowContent(row)}
|
|
2480
|
-
</td>
|
|
2481
|
-
</tr>
|
|
2482
|
-
{:else}
|
|
2483
|
-
{@const userRowClass = computeRowClass(row, rowIndex)}
|
|
2484
|
-
<tr
|
|
2485
|
-
class={`sv-grid-row ${userRowClass} ${rowDropClass(rowIndex)}`}
|
|
2486
|
-
class:sv-grid-row-selected={isRowSelected(row.id)}
|
|
2487
|
-
class:sv-grid-row-alt={opt.zebraRows &&
|
|
2488
|
-
rowIndex % 2 === 1}
|
|
2489
|
-
class:sv-grid-row-draggable={rowDragManagedEffective}
|
|
2490
|
-
class:sv-grid-group-footer-row={isGroupFooterRow(row)}
|
|
2491
|
-
class:sv-grid-grand-total-row={isGrandTotalRow(row)}
|
|
2492
|
-
class:sv-grid-row-auto-height={autoRowHeightOn}
|
|
2493
|
-
{...getGridRowA11yProps(rowIndex + 1)}
|
|
2494
|
-
aria-level={sgAriaLevel(row)}
|
|
2495
|
-
aria-expanded={sgAriaExpanded(row)}
|
|
2496
|
-
{...rowDragAttrs(rowIndex)}
|
|
2497
|
-
style={rowStyleFor(rowIndex)}
|
|
2498
|
-
use:measureRowHeight={rowIndex}
|
|
2499
|
-
>
|
|
2500
|
-
{#if showRowNumbersEffective}
|
|
2501
|
-
<td
|
|
2502
|
-
class="sv-grid-cell sv-grid-row-number-cell"
|
|
2503
|
-
style={`width: ${rowNumberColumnWidth}px; min-width: ${rowNumberColumnWidth}px; max-width: ${rowNumberColumnWidth}px; left: 0;`}
|
|
2504
|
-
>{rowIndex + 1}</td
|
|
2505
|
-
>
|
|
2506
|
-
{/if}
|
|
2507
|
-
{#if showRowSelectionEffective}
|
|
2508
|
-
<td
|
|
2509
|
-
class="sv-grid-cell sv-grid-selection-cell"
|
|
2510
|
-
style={`width: ${selectionColumnWidth}px; min-width: ${selectionColumnWidth}px; max-width: ${selectionColumnWidth}px; left: ${showRowNumbersEffective ? rowNumberColumnWidth : 0}px;`}
|
|
2511
|
-
onclick={() => toggleRowSelectionById(row.id)}
|
|
2512
|
-
>
|
|
2513
|
-
<button
|
|
2514
|
-
type="button"
|
|
2515
|
-
class="sv-grid-checkbox"
|
|
2516
|
-
role="checkbox"
|
|
2517
|
-
aria-checked={isRowSelected(row.id)}
|
|
2518
|
-
aria-label="Select row"
|
|
2519
|
-
onclick={(event) => {
|
|
2520
|
-
event.stopPropagation();
|
|
2521
|
-
toggleRowSelectionById(row.id);
|
|
2522
|
-
}}
|
|
2523
|
-
onkeydown={(event) =>
|
|
2524
|
-
toggleCheckboxWithKeyboard(event, () => {
|
|
2525
|
-
event.stopPropagation();
|
|
2526
|
-
toggleRowSelectionById(row.id);
|
|
2527
|
-
})}
|
|
2528
|
-
></button>
|
|
2529
|
-
</td>
|
|
2530
|
-
{/if}
|
|
2531
|
-
{#if columnVirtualizationEnabled && columnWindowStart > 0}
|
|
2532
|
-
<td
|
|
2533
|
-
class="sv-grid-cell sv-grid-cell-spacer"
|
|
2534
|
-
aria-hidden="true"
|
|
2535
|
-
style={`width: ${columnWindowStart}px; min-width: ${columnWindowStart}px; max-width: ${columnWindowStart}px;`}
|
|
2536
|
-
></td>
|
|
2537
|
-
{/if}
|
|
2538
|
-
{#each renderedColumns as rendered (rendered.column.id)}
|
|
2539
|
-
{@const colIndex = rendered.item.index}
|
|
2540
|
-
{@const baseValue = getColumnBaseValue(
|
|
2541
|
-
row,
|
|
2542
|
-
rendered.column,
|
|
2543
|
-
)}
|
|
2544
|
-
{@const cellValue = getCellDisplayValue(
|
|
2545
|
-
row.id,
|
|
2546
|
-
rendered.column.id,
|
|
2547
|
-
baseValue,
|
|
2548
|
-
)}
|
|
2549
|
-
{@const isEditing =
|
|
2550
|
-
ctrl.editingCell?.rowId === row.id &&
|
|
2551
|
-
ctrl.editingCell?.columnId === rendered.column.id}
|
|
2552
|
-
{@const inRowEdit =
|
|
2553
|
-
!!fullRowEdit &&
|
|
2554
|
-
fullRowEdit.rowId === row.id &&
|
|
2555
|
-
rendered.column.id in fullRowEdit.draft}
|
|
2556
|
-
{@const rangeEdges = getCellRangeEdges(
|
|
2557
|
-
rowIndex,
|
|
2558
|
-
colIndex,
|
|
2559
|
-
)}
|
|
2560
|
-
{@const userCellClass = computeCellClass(
|
|
2561
|
-
row,
|
|
2562
|
-
rendered.column,
|
|
2563
|
-
)}
|
|
2564
|
-
{@const cellTooltip = computeCellTooltip(
|
|
2565
|
-
row,
|
|
2566
|
-
rendered.column,
|
|
2567
|
-
)}
|
|
2568
|
-
{@const cellValidity = computeCellValidity(
|
|
2569
|
-
row,
|
|
2570
|
-
rendered.column,
|
|
2571
|
-
)}
|
|
2572
|
-
{@const cellNote = computeCellNote(row, rendered.column)}
|
|
2573
|
-
<td
|
|
2574
|
-
class={`sv-grid-cell ${userCellClass}`}
|
|
2575
|
-
class:sv-grid-cell-editing={isEditing || inRowEdit}
|
|
2576
|
-
class:sv-grid-cell-active={activeCell.rowIndex ===
|
|
2577
|
-
rowIndex && activeCell.colIndex === colIndex}
|
|
2578
|
-
class:sv-grid-cell-cf={hasConditionalFormats}
|
|
2579
|
-
class:sv-grid-cell-invalid={cellValidity.invalid}
|
|
2580
|
-
class:sv-grid-cell-has-note={cellNote != null}
|
|
2581
|
-
aria-invalid={cellValidity.invalid ? "true" : undefined}
|
|
2582
|
-
data-svgrid-row={rowIndex}
|
|
2583
|
-
data-svgrid-col={colIndex}
|
|
2584
|
-
data-col-id={rendered.column.id}
|
|
2585
|
-
data-align={getColumnAlign(rendered.column)}
|
|
2586
|
-
data-pinned={isColumnPinned(rendered.column.id) ??
|
|
2587
|
-
undefined}
|
|
2588
|
-
data-selected-range={rangeEdges ? "true" : undefined}
|
|
2589
|
-
data-range-top={rangeEdges?.top ? "true" : undefined}
|
|
2590
|
-
data-range-bottom={rangeEdges?.bottom
|
|
2591
|
-
? "true"
|
|
2592
|
-
: undefined}
|
|
2593
|
-
data-range-left={rangeEdges?.left ? "true" : undefined}
|
|
2594
|
-
data-range-right={rangeEdges?.right
|
|
2595
|
-
? "true"
|
|
2596
|
-
: undefined}
|
|
2597
|
-
style={`width: ${rendered.item.size}px; min-width: ${rendered.item.size}px; max-width: ${rendered.item.size}px; ${cellPinStyle(rendered.column.id)}`}
|
|
2598
|
-
onpointerdown={(event) =>
|
|
2599
|
-
onCellPointerDown(rowIndex, colIndex, event)}
|
|
2600
|
-
onpointerenter={(event) => {
|
|
2601
|
-
onCellPointerEnter(rowIndex, colIndex);
|
|
2602
|
-
// Column tooltip fires on whole-cell hover.
|
|
2603
|
-
// Per-cell notes are gated on the corner hot-
|
|
2604
|
-
// zone below (Excel-style: hover the small
|
|
2605
|
-
// triangle to read the note). A validation
|
|
2606
|
-
// message (when the cell is invalid) wins over
|
|
2607
|
-
// the plain column tooltip.
|
|
2608
|
-
const tip =
|
|
2609
|
-
cellValidity.invalid && cellValidity.message
|
|
2610
|
-
? cellValidity.message
|
|
2611
|
-
: cellTooltip;
|
|
2612
|
-
if (tip)
|
|
2613
|
-
showTooltipFor(
|
|
2614
|
-
event.currentTarget as HTMLElement,
|
|
2615
|
-
tip,
|
|
2616
|
-
);
|
|
2617
|
-
}}
|
|
2618
|
-
onpointerleave={hideTooltip}
|
|
2619
|
-
ondblclick={() =>
|
|
2620
|
-
emitCellDoubleClick(rowIndex, colIndex)}
|
|
2621
|
-
onclick={() => onCellClick(rowIndex, colIndex)}
|
|
2622
|
-
oncontextmenu={(event) =>
|
|
2623
|
-
openContextMenu(
|
|
2624
|
-
event,
|
|
2625
|
-
rowIndex,
|
|
2626
|
-
colIndex,
|
|
2627
|
-
rendered.column.id,
|
|
2628
|
-
)}
|
|
2629
|
-
use:cellFlashAction={{
|
|
2630
|
-
rowId: row.id,
|
|
2631
|
-
value: cellValue,
|
|
2632
|
-
active: !!rendered.column.columnDef.cellFlash,
|
|
2633
|
-
className: flashClassFor(
|
|
2634
|
-
rendered.column.columnDef.cellFlash,
|
|
2635
|
-
),
|
|
2636
|
-
}}
|
|
2637
|
-
{...getGridCellA11yProps({
|
|
2638
|
-
id: getGridCellDomId(ctrl.gridDomId, rowIndex, colIndex),
|
|
2639
|
-
rowIndex: rowIndex + 1,
|
|
2640
|
-
colIndex: colIndex + 1,
|
|
2641
|
-
selected: isRowSelected(row.id),
|
|
2642
|
-
})}
|
|
2643
|
-
>
|
|
2644
|
-
{#if inRowEdit || isEditing}
|
|
2645
|
-
<!-- Empty until the lazy editor chunk lands - see the
|
|
2646
|
-
matching branch in the pinned-row body above. -->
|
|
2647
|
-
{#if CellEditor}
|
|
2648
|
-
<CellEditor {ctrl} column={rendered.column} {row} fullRow={inRowEdit} />
|
|
2649
|
-
{/if}
|
|
2650
|
-
{:else}
|
|
2651
|
-
{@render cellBodyWithFormat(
|
|
2652
|
-
row,
|
|
2653
|
-
rendered.column,
|
|
2654
|
-
cellValue,
|
|
2655
|
-
)}
|
|
2656
|
-
{/if}
|
|
2657
|
-
{#if cellValidity.invalid && cellValidity.message}
|
|
2658
|
-
<!-- The validation message, for assistive tech.
|
|
2659
|
-
On this path the message is shown visually by
|
|
2660
|
-
the pointerenter tooltip above, which is mouse-
|
|
2661
|
-
only - a keyboard or screen-reader user would
|
|
2662
|
-
get `aria-invalid` with no reason attached.
|
|
2663
|
-
A visually-hidden span inside the cell is read
|
|
2664
|
-
as part of the cell when focus lands on it, and
|
|
2665
|
-
unlike `title` it adds no second native tooltip
|
|
2666
|
-
competing with the custom one. -->
|
|
2667
|
-
<span class="sv-grid-sr-only"
|
|
2668
|
-
>{cellValidity.message}</span
|
|
2669
|
-
>
|
|
2670
|
-
{/if}
|
|
2671
|
-
{#if cellNote != null && !isEditing}
|
|
2672
|
-
<!-- Excel-style per-cell note indicator. The
|
|
2673
|
-
triangle itself is the hot-zone; hover
|
|
2674
|
-
just the corner to see the note (Excel
|
|
2675
|
-
red-dot behaviour). The cell-level
|
|
2676
|
-
tooltip handler only shows the column
|
|
2677
|
-
tooltip, so the two surfaces stay
|
|
2678
|
-
separate. -->
|
|
2679
|
-
<span
|
|
2680
|
-
class="sv-grid-cell-note-corner"
|
|
2681
|
-
aria-label="Note"
|
|
2682
|
-
onpointerenter={(event) => {
|
|
2683
|
-
event.stopPropagation();
|
|
2684
|
-
showTooltipFor(
|
|
2685
|
-
event.currentTarget as HTMLElement,
|
|
2686
|
-
cellNote,
|
|
2687
|
-
);
|
|
2688
|
-
}}
|
|
2689
|
-
onpointerleave={(event) => {
|
|
2690
|
-
event.stopPropagation();
|
|
2691
|
-
hideTooltip();
|
|
2692
|
-
}}
|
|
2693
|
-
></span>
|
|
2694
|
-
{/if}
|
|
2695
|
-
</td>
|
|
2696
|
-
{/each}
|
|
2697
|
-
{#if columnVirtualizationEnabled && columnWindowRightSpacer > 0}
|
|
2698
|
-
<td
|
|
2699
|
-
class="sv-grid-cell sv-grid-cell-spacer"
|
|
2700
|
-
aria-hidden="true"
|
|
2701
|
-
style={`width: ${columnWindowRightSpacer}px; min-width: ${columnWindowRightSpacer}px; max-width: ${columnWindowRightSpacer}px;`}
|
|
2702
|
-
></td>
|
|
2703
|
-
{/if}
|
|
2704
|
-
</tr>
|
|
2705
|
-
{/if}
|
|
2577
|
+
{@render bodyRow(row, rowIndex, rowStyleFor(rowIndex))}
|
|
2706
2578
|
{/each}
|
|
2707
2579
|
{/if}
|
|
2708
2580
|
</tbody>
|