@1771technologies/lytenyte-pro 1.0.12 → 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/+types.d.ts +21 -2
- package/dist/__play__/grid-navigation/cell-spans-large.play.d.ts +3 -0
- package/dist/__play__/grid-navigation/cell-spans-large.play.js +26 -0
- package/dist/__play__/grid-navigation/cell-spans-with-pins.play.d.ts +3 -0
- package/dist/__play__/grid-navigation/cell-spans-with-pins.play.js +27 -0
- package/dist/__play__/grid-navigation/cell-spans.play.d.ts +3 -0
- package/dist/__play__/grid-navigation/cell-spans.play.js +52 -0
- package/dist/__play__/grid-navigation/cell-with-tabbables.play.d.ts +3 -0
- package/dist/__play__/grid-navigation/cell-with-tabbables.play.js +47 -0
- package/dist/__play__/grid-navigation/column-groups.play.d.ts +3 -0
- package/dist/__play__/grid-navigation/column-groups.play.js +24 -0
- package/dist/__play__/grid-navigation/full-width-rows.play.d.ts +6 -0
- package/dist/__play__/grid-navigation/full-width-rows.play.js +67 -0
- package/dist/__play__/grid-navigation/horizontal-navigation.pt.d.ts +1 -0
- package/dist/__play__/grid-navigation/horizontal-navigation.pt.js +877 -0
- package/dist/__play__/grid-navigation/normal-layout.play.d.ts +10 -0
- package/dist/__play__/grid-navigation/normal-layout.play.js +72 -0
- package/dist/__play__/grid-navigation/pinned-gap-layout.play.d.ts +3 -0
- package/dist/__play__/grid-navigation/pinned-gap-layout.play.js +11 -0
- package/dist/__play__/grid-navigation/row-detail-with-spans.play.d.ts +6 -0
- package/dist/__play__/grid-navigation/row-detail-with-spans.play.js +79 -0
- package/dist/__play__/grid-navigation/row-detail.play.d.ts +6 -0
- package/dist/__play__/grid-navigation/row-detail.play.js +78 -0
- package/dist/__play__/grid-navigation/row-detail.pt.d.ts +1 -0
- package/dist/__play__/grid-navigation/row-detail.pt.js +68 -0
- package/dist/__play__/grid-navigation/vertical-navigation.pt.d.ts +1 -0
- package/dist/__play__/grid-navigation/vertical-navigation.pt.js +176 -0
- package/dist/__play__/test-utils/bank-data-smaller.d.ts +19 -0
- package/dist/__play__/test-utils/bank-data-smaller.js +252 -0
- package/dist/__play__/test-utils/row-handler.d.ts +6 -0
- package/dist/__play__/test-utils/row-handler.js +33 -0
- package/dist/cells/+types.cell.d.ts +1 -1
- package/dist/cells/cell-default.d.ts +1 -1
- package/dist/cells/cell-editor.js +19 -12
- package/dist/cells/cell-spacer.js +9 -4
- package/dist/cells/cell.js +4 -3
- package/dist/context.d.ts +3 -3
- package/dist/header/use-header-cell-renderer.js +1 -0
- package/dist/icons/index.js +1 -3
- package/dist/root/root.js +39 -56
- package/dist/rows/row/context.d.ts +2 -1
- package/dist/rows/row/context.js +1 -0
- package/dist/rows/row/row.d.ts +1 -1
- package/dist/rows/row/row.js +1 -1
- package/dist/rows/row/use-row-context-value.d.ts +2 -2
- package/dist/rows/row/use-row-context-value.js +3 -2
- package/dist/rows/row-detail-row.js +4 -87
- package/dist/rows/row-full-width.js +1 -1
- package/dist/state/api/cell-root.js +4 -3
- package/dist/state/api/focus-cell.d.ts +1 -1
- package/dist/state/api/focus-cell.js +19 -12
- package/dist/state/helpers/column-marker.js +2 -0
- package/dist/state/helpers/get-span-callback.js +1 -1
- package/dist/state/helpers/row-layout/row-layout.js +3 -22
- package/dist/state/use-lytenyte.js +3 -1
- package/dist/viewport/viewport.js +22 -15
- package/package.json +7 -7
|
@@ -3,7 +3,7 @@ import { useCallback, useEffect, useState } from "react";
|
|
|
3
3
|
import { getTabbables } from "@1771technologies/lytenyte-dom-utils";
|
|
4
4
|
import { useGridRoot } from "../context.js";
|
|
5
5
|
import { editOnChange } from "../state/helpers/edit-on-change.js";
|
|
6
|
-
import {
|
|
6
|
+
import { handleNavigation } from "@1771technologies/lytenyte-shared";
|
|
7
7
|
export function CellEditor({ cell }) {
|
|
8
8
|
const [el, setEl] = useState(null);
|
|
9
9
|
const grid = useGridRoot().grid;
|
|
@@ -41,20 +41,27 @@ export function CellEditor({ cell }) {
|
|
|
41
41
|
: Object.keys(editValidation).length >= 1) {
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
handleNavigation({
|
|
45
|
+
event: {
|
|
46
|
+
key: "ArrowDown",
|
|
47
|
+
ctrlKey: false,
|
|
48
|
+
metaKey: false,
|
|
49
|
+
preventDefault: () => { },
|
|
50
|
+
stopPropagation: () => { },
|
|
51
|
+
},
|
|
52
|
+
topCount: grid.state.rowDataStore.rowTopCount.get(),
|
|
53
|
+
centerCount: grid.state.rowDataStore.rowCenterCount.get(),
|
|
54
|
+
isRowDetailExpanded: (r) => {
|
|
55
|
+
const row = grid.api.rowByIndex(r);
|
|
56
|
+
if (!row)
|
|
57
|
+
return false;
|
|
58
|
+
return grid.api.rowDetailIsExpanded(row);
|
|
59
|
+
},
|
|
60
|
+
viewport: grid.state.viewport.get(),
|
|
52
61
|
rowCount: ds.rowCount.get(),
|
|
53
|
-
topCount: ds.rowTopCount.get(),
|
|
54
|
-
centerCount: ds.rowCenterCount.get(),
|
|
55
62
|
columnCount: grid.state.columnMeta.get().columnsVisible.length,
|
|
56
63
|
focusActive: grid.internal.focusActive,
|
|
57
|
-
|
|
64
|
+
gridId: grid.state.gridId.get(),
|
|
58
65
|
getRootCell: grid.api.cellRoot,
|
|
59
66
|
rtl: grid.state.rtl.get(),
|
|
60
67
|
scrollIntoView: grid.api.scrollIntoView,
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useGridRoot } from "../context.js";
|
|
3
|
+
import { useRowMeta } from "../rows/row/context.js";
|
|
3
4
|
export function CellSpacePinStart({ xPositions: x }) {
|
|
5
|
+
const { layout, colBounds } = useRowMeta();
|
|
4
6
|
const ctx = useGridRoot().grid;
|
|
5
7
|
const bounds = ctx.state.viewBounds.useValue();
|
|
6
|
-
const offset = x[bounds.colCenterStart] - x[bounds.colStartEnd];
|
|
7
8
|
const meta = ctx.state.columnMeta.useValue();
|
|
8
|
-
if (meta.columnVisibleStartCount === 0)
|
|
9
|
+
if (meta.columnVisibleStartCount === 0 || layout.kind === "full-width")
|
|
9
10
|
return null;
|
|
11
|
+
const colOffset = layout.cells.findIndex((c) => !c.colPin && c.colIndex + c.colSpan - 1 >= colBounds[0] && !c.isDeadCol);
|
|
12
|
+
const offset = x[colOffset] - x[bounds.colStartEnd];
|
|
10
13
|
return _jsx("div", { style: { display: "inline-block", width: offset, height: 0 } });
|
|
11
14
|
}
|
|
12
15
|
export function CellSpacerPinEnd({ xPositions: x }) {
|
|
@@ -24,11 +27,13 @@ export function CellSpacerPinEnd({ xPositions: x }) {
|
|
|
24
27
|
return _jsx("div", { style: { display: "inline-block", width: offset, height: 0 } });
|
|
25
28
|
}
|
|
26
29
|
export function CellSpacerNoPin({ xPositions: x }) {
|
|
30
|
+
const { layout, colBounds } = useRowMeta();
|
|
27
31
|
const ctx = useGridRoot().grid;
|
|
28
32
|
const bounds = ctx.state.viewBounds.useValue();
|
|
29
|
-
const offset = x[bounds.colCenterStart - bounds.colStartEnd];
|
|
30
33
|
const meta = ctx.state.columnMeta.useValue();
|
|
31
|
-
if (meta.columnVisibleStartCount > 0)
|
|
34
|
+
if (meta.columnVisibleStartCount > 0 || layout.kind === "full-width")
|
|
32
35
|
return null;
|
|
36
|
+
const colOffset = layout.cells.findIndex((c) => c.colIndex + c.colSpan - 1 >= colBounds[0] && !c.isDeadCol);
|
|
37
|
+
const offset = x[colOffset - bounds.colStartEnd];
|
|
33
38
|
return _jsx("div", { style: { display: "inline-block", width: offset, height: 0 } });
|
|
34
39
|
}
|
package/dist/cells/cell.js
CHANGED
|
@@ -10,12 +10,13 @@ import { useCellStyle } from "./use-cell-style.js";
|
|
|
10
10
|
export const Cell = forwardRef(function Cell(props, forwarded) {
|
|
11
11
|
const { colBounds: [start, end], ...rowMeta } = useRowMeta();
|
|
12
12
|
// This enforces our column virtualization.
|
|
13
|
-
if (props.cell.colPin == null &&
|
|
13
|
+
if (props.cell.colPin == null &&
|
|
14
|
+
(props.cell.colIndex >= end || props.cell.colIndex + props.cell.colSpan - 1 < start)) {
|
|
14
15
|
return null;
|
|
15
16
|
}
|
|
16
17
|
return _jsx(CellImpl, { ...props, ref: forwarded, ...rowMeta });
|
|
17
18
|
});
|
|
18
|
-
const CellImpl = memo(forwardRef(function Cell({ cell, row, selected, indeterminate, xPositions, yPositions, base, renderers, rtl, ...props }, forwarded) {
|
|
19
|
+
const CellImpl = memo(forwardRef(function Cell({ cell, row, selected, indeterminate, xPositions, yPositions, base, renderers, rtl, layout: _, ...props }, forwarded) {
|
|
19
20
|
const grid = useGridRoot().grid;
|
|
20
21
|
const providedRenderer = cell.column.cellRenderer ?? base.cellRenderer;
|
|
21
22
|
const Renderer = providedRenderer
|
|
@@ -39,5 +40,5 @@ const CellImpl = memo(forwardRef(function Cell({ cell, row, selected, indetermin
|
|
|
39
40
|
return _jsx("div", { style: { width: sizeFromCoord(cell.colIndex, xPositions) } });
|
|
40
41
|
if (!row || cell.isDeadCol)
|
|
41
42
|
return null;
|
|
42
|
-
return (_jsxs(_Fragment, { children: [cell.colFirstEndPin && _jsx(CellSpacerPinEnd, { xPositions: xPositions }), _jsxs("div", { ...props, ref: forwarded, role: "gridcell", "data-ln-rowindex": cell.rowIndex, "data-ln-colindex": cell.colIndex, "data-ln-colspan": cell.colSpan, "data-ln-rowspan": cell.rowSpan, "data-ln-pin": cell.colPin ?? "center", "data-ln-cell": true, "data-ln-last-top-pin": cell.rowLastPinTop, "data-ln-first-bottom-pin": cell.rowFirstPinBottom, "data-ln-last-start-pin": cell.colLastStartPin, "data-ln-first-end-pin": cell.colFirstEndPin, tabIndex: isEditing ? -1 : 0, style: style, children: [isEditing && _jsx(CellEditor, { cell: cell }), !isEditing && (_jsx(Renderer, { column: cell.column, rowSelected: selected, rowIndeterminate: indeterminate, row: row, grid: grid, rowIndex: cell.rowIndex, colIndex: cell.colIndex, rowPin: cell.rowPin }))] }), cell.colLastStartPin && _jsx(CellSpacePinStart, { xPositions: xPositions })] }));
|
|
43
|
+
return (_jsxs(_Fragment, { children: [cell.colFirstEndPin && _jsx(CellSpacerPinEnd, { xPositions: xPositions }), _jsxs("div", { ...props, ref: forwarded, role: "gridcell", "data-ln-rowindex": cell.rowIndex, "data-ln-colindex": cell.colIndex, "data-ln-colspan": cell.colSpan, "data-ln-rowspan": cell.rowSpan, "data-ln-pin": cell.colPin ?? "center", "data-ln-cell": true, "data-ln-last-top-pin": cell.rowLastPinTop, "data-ln-first-bottom-pin": cell.rowFirstPinBottom, "data-ln-last-start-pin": cell.colLastStartPin, "data-ln-first-end-pin": cell.colFirstEndPin, tabIndex: isEditing ? -1 : 0, style: { ...style, ...props.style }, children: [isEditing && _jsx(CellEditor, { cell: cell }), !isEditing && (_jsx(Renderer, { column: cell.column, rowSelected: selected, rowIndeterminate: indeterminate, row: row, grid: grid, rowIndex: cell.rowIndex, colIndex: cell.colIndex, rowPin: cell.rowPin }))] }), cell.colLastStartPin && _jsx(CellSpacePinStart, { xPositions: xPositions })] }));
|
|
43
44
|
}));
|
package/dist/context.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Grid } from "./+types";
|
|
2
|
-
import type { InternalAtoms } from "./state/+types";
|
|
1
|
+
import type { Grid } from "./+types.js";
|
|
2
|
+
import type { InternalAtoms } from "./state/+types.js";
|
|
3
3
|
export interface GridRootContext {
|
|
4
|
-
readonly ref: (el: HTMLElement |
|
|
4
|
+
readonly ref: (el: HTMLElement | null) => void;
|
|
5
5
|
readonly grid: Grid<any> & {
|
|
6
6
|
internal: InternalAtoms;
|
|
7
7
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo } from "react";
|
|
3
3
|
import { useGridRoot } from "../context.js";
|
|
4
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
4
5
|
function DefaultRenderer(p) {
|
|
5
6
|
return _jsx(_Fragment, { children: p.column.name ?? p.column.id });
|
|
6
7
|
}
|
package/dist/icons/index.js
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
|
-
export { AddIcon, AddSmallIcon, AggregateIcon, AggregationIcon, ArchiveIcon, ArrowDownIcon, ArrowLeftIcon, ArrowRightCurvedIcon, ArrowRightIcon, ArrowUpIcon, AutosizeIcon, BackIcon, BookmarkIcon, BooleanIcon, CalendarIcon, ChartIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, Close2Icon, CloseIcon, CollapseGroupIcon, Columns2Icon, ColumnsIcon, CopyIcon, CornerRadiusIcon, CustomizeThemeIcon, CutIcon, CsvIcon, DeleteIcon, DocsIcon, DownloadIcon, Drag2Icon, DragDotsIcon, DragDotsSmallIcon, DragIcon, DuplicateIcon, EditIcon, EmailIcon, ExcelIcon, ExpandGroupIcon, ExpandIcon, Expression2Icon, ExpressionIcon, ExternalLinkIcon, File2Icon, FileIcon, FilterIcon, FolderIcon, GlobeIcon, GridViewIcon, GroupByColIcon, HamburgerIcon, HelpIcon, HiddenIcon, HistoryIcon, ImportIcon, LinkIcon, ListViewIcon, LoadingIcon, LocationIcon, ModalIcon, MoreIcon, MoreVerticalIcon, MultilineIcon, NumberIcon, PasteIcon, PieIcon, PinColumnIcon, RefreshIcon, SearchIcon, SettingsIcon, ShareIcon, SingleLineIcon, Sort2Icon, SortIcon, SpacingHIcon, SpacingIcon, StickColumnIcon, SwapIcon, TagIcon, TaskIcon, TextIcon, ThemesIcon, Tickmark2Icon, TickmarkIcon, TimeIcon, UploadIcon, UserIcon, ViewIcon,
|
|
2
|
-
// eslint-disable-next-line import/extensions
|
|
3
|
-
} from "@1771technologies/lytenyte-core/icons";
|
|
1
|
+
export { AddIcon, AddSmallIcon, AggregateIcon, AggregationIcon, ArchiveIcon, ArrowDownIcon, ArrowLeftIcon, ArrowRightCurvedIcon, ArrowRightIcon, ArrowUpIcon, AutosizeIcon, BackIcon, BookmarkIcon, BooleanIcon, CalendarIcon, ChartIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, Close2Icon, CloseIcon, CollapseGroupIcon, Columns2Icon, ColumnsIcon, CopyIcon, CornerRadiusIcon, CustomizeThemeIcon, CutIcon, CsvIcon, DeleteIcon, DocsIcon, DownloadIcon, Drag2Icon, DragDotsIcon, DragDotsSmallIcon, DragIcon, DuplicateIcon, EditIcon, EmailIcon, ExcelIcon, ExpandGroupIcon, ExpandIcon, Expression2Icon, ExpressionIcon, ExternalLinkIcon, File2Icon, FileIcon, FilterIcon, FolderIcon, GlobeIcon, GridViewIcon, GroupByColIcon, HamburgerIcon, HelpIcon, HiddenIcon, HistoryIcon, ImportIcon, LinkIcon, ListViewIcon, LoadingIcon, LocationIcon, ModalIcon, MoreIcon, MoreVerticalIcon, MultilineIcon, NumberIcon, PasteIcon, PieIcon, PinColumnIcon, RefreshIcon, SearchIcon, SettingsIcon, ShareIcon, SingleLineIcon, Sort2Icon, SortIcon, SpacingHIcon, SpacingIcon, StickColumnIcon, SwapIcon, TagIcon, TaskIcon, TextIcon, ThemesIcon, Tickmark2Icon, TickmarkIcon, TimeIcon, UploadIcon, UserIcon, ViewIcon, } from "@1771technologies/lytenyte-core/icons";
|
package/dist/root/root.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect,
|
|
3
|
-
import { useEvent, useMeasure } from "@1771technologies/lytenyte-react-hooks";
|
|
2
|
+
import { useEffect, useMemo, useState } from "react";
|
|
4
3
|
import { RootProvider } from "../context.js";
|
|
5
4
|
import { DialogDriver } from "./dialog-driver.js";
|
|
6
5
|
import { PopoverDriver } from "./popover-driver.js";
|
|
@@ -33,13 +32,6 @@ export function Root({ grid, children, ...events }) {
|
|
|
33
32
|
document.body.appendChild(invalidLicenseWatermark);
|
|
34
33
|
return () => invalidLicenseWatermark.remove();
|
|
35
34
|
}, []);
|
|
36
|
-
const onViewportChange = useEvent((bounds) => {
|
|
37
|
-
grid.state.viewport.set(element ?? null);
|
|
38
|
-
grid.state.viewportHeightOuter.set(bounds.height);
|
|
39
|
-
grid.state.viewportWidthOuter.set(bounds.width);
|
|
40
|
-
grid.state.viewportWidthInner.set(element?.clientWidth ?? 0);
|
|
41
|
-
grid.state.viewportHeightInner.set(element?.clientHeight ?? 0);
|
|
42
|
-
});
|
|
43
35
|
// Add event listeners in the standard react way
|
|
44
36
|
useEffect(() => {
|
|
45
37
|
const ev = Object.entries(events).map(([onName, fn]) => {
|
|
@@ -51,53 +43,7 @@ export function Root({ grid, children, ...events }) {
|
|
|
51
43
|
return () => ev.forEach((c) => c?.());
|
|
52
44
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
53
45
|
}, [Object.values(events)]);
|
|
54
|
-
const [ref, bounds, , element] = useMeasure({
|
|
55
|
-
onChange: onViewportChange,
|
|
56
|
-
});
|
|
57
|
-
// Add css variables so that we can avoid re-renders
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
return grid.state.widthTotal.watch(() => {
|
|
60
|
-
const vp = grid.state.viewport.get();
|
|
61
|
-
const width = grid.state.widthTotal.get();
|
|
62
|
-
if (!vp)
|
|
63
|
-
return;
|
|
64
|
-
vp.style.setProperty("--lng-vp-total-width", `${width}px`);
|
|
65
|
-
});
|
|
66
|
-
}, [grid]);
|
|
67
46
|
const internal = grid.internal;
|
|
68
|
-
// Listen to size changes of the window
|
|
69
|
-
useLayoutEffect(() => {
|
|
70
|
-
if (!element)
|
|
71
|
-
return;
|
|
72
|
-
const obs = new ResizeObserver(() => {
|
|
73
|
-
grid.state.viewport.set(element ?? null);
|
|
74
|
-
grid.state.viewportHeightOuter.set(bounds.height);
|
|
75
|
-
grid.state.viewportWidthOuter.set(bounds.width);
|
|
76
|
-
grid.state.viewportWidthInner.set(element?.clientWidth ?? 0);
|
|
77
|
-
grid.state.viewportHeightInner.set(element?.clientHeight ?? 0);
|
|
78
|
-
});
|
|
79
|
-
obs.observe(element);
|
|
80
|
-
const controller = new AbortController();
|
|
81
|
-
element.addEventListener("scroll", () => {
|
|
82
|
-
internal.xScroll.set(Math.abs(element.scrollLeft));
|
|
83
|
-
internal.yScroll.set(element.scrollTop);
|
|
84
|
-
}, { signal: controller.signal });
|
|
85
|
-
return () => {
|
|
86
|
-
obs.disconnect();
|
|
87
|
-
controller.abort();
|
|
88
|
-
};
|
|
89
|
-
}, [
|
|
90
|
-
bounds.height,
|
|
91
|
-
bounds.width,
|
|
92
|
-
element,
|
|
93
|
-
grid.state.viewport,
|
|
94
|
-
grid.state.viewportHeightInner,
|
|
95
|
-
grid.state.viewportHeightOuter,
|
|
96
|
-
grid.state.viewportWidthInner,
|
|
97
|
-
grid.state.viewportWidthOuter,
|
|
98
|
-
internal.xScroll,
|
|
99
|
-
internal.yScroll,
|
|
100
|
-
]);
|
|
101
47
|
useEffect(() => {
|
|
102
48
|
return internal.focusActive.watch(() => {
|
|
103
49
|
const editActive = internal.editActivePos.get();
|
|
@@ -114,12 +60,49 @@ export function Root({ grid, children, ...events }) {
|
|
|
114
60
|
}
|
|
115
61
|
});
|
|
116
62
|
}, [grid.api, internal.editActivePos, internal.focusActive]);
|
|
63
|
+
const [vp, ref] = useState(null);
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (!vp)
|
|
66
|
+
return;
|
|
67
|
+
const controller = new AbortController();
|
|
68
|
+
vp.addEventListener("scroll", () => {
|
|
69
|
+
internal.xScroll.set(Math.abs(vp.scrollLeft));
|
|
70
|
+
internal.yScroll.set(vp.scrollTop);
|
|
71
|
+
}, { signal: controller.signal });
|
|
72
|
+
return () => controller.abort();
|
|
73
|
+
}, [internal.xScroll, internal.yScroll, vp]);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
grid.state.viewport.set(vp);
|
|
76
|
+
if (!vp)
|
|
77
|
+
return;
|
|
78
|
+
const obs = new ResizeObserver(() => {
|
|
79
|
+
grid.state.viewportHeightOuter.set(vp.offsetHeight);
|
|
80
|
+
grid.state.viewportWidthOuter.set(vp.offsetWidth);
|
|
81
|
+
grid.state.viewportWidthInner.set(vp.clientWidth);
|
|
82
|
+
grid.state.viewportHeightInner.set(vp.clientHeight);
|
|
83
|
+
});
|
|
84
|
+
grid.state.viewportHeightOuter.set(vp.offsetHeight);
|
|
85
|
+
grid.state.viewportWidthOuter.set(vp.offsetWidth);
|
|
86
|
+
grid.state.viewportWidthInner.set(vp.clientWidth);
|
|
87
|
+
grid.state.viewportHeightInner.set(vp.clientHeight);
|
|
88
|
+
obs.observe(vp);
|
|
89
|
+
return () => {
|
|
90
|
+
obs.disconnect();
|
|
91
|
+
};
|
|
92
|
+
}, [
|
|
93
|
+
grid.state.viewport,
|
|
94
|
+
grid.state.viewportHeightInner,
|
|
95
|
+
grid.state.viewportHeightOuter,
|
|
96
|
+
grid.state.viewportWidthInner,
|
|
97
|
+
grid.state.viewportWidthOuter,
|
|
98
|
+
vp,
|
|
99
|
+
]);
|
|
117
100
|
const value = useMemo(() => {
|
|
118
101
|
return {
|
|
119
102
|
ref,
|
|
120
103
|
grid: grid,
|
|
121
104
|
};
|
|
122
|
-
}, [grid
|
|
105
|
+
}, [grid]);
|
|
123
106
|
const cellSelectionMode = grid.state.cellSelectionMode.useValue();
|
|
124
107
|
return (_jsxs(RootProvider, { value: value, children: [_jsx(DialogDriver, {}), _jsx(PopoverDriver, {}), cellSelectionMode !== "none" && _jsx(CellSelectionDriver, {}), children] }));
|
|
125
108
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { CellRendererFn, ColumnBase, RowNode } from "../../+types";
|
|
1
|
+
import type { CellRendererFn, ColumnBase, RowLayout, RowNode } from "../../+types";
|
|
2
2
|
export interface RowMetaData {
|
|
3
3
|
readonly selected: boolean;
|
|
4
4
|
readonly indeterminate: boolean;
|
|
5
5
|
readonly colBounds: [number, number];
|
|
6
6
|
readonly row: RowNode<any> | null;
|
|
7
|
+
readonly layout: RowLayout<any>;
|
|
7
8
|
readonly xPositions: Uint32Array;
|
|
8
9
|
readonly yPositions: Uint32Array;
|
|
9
10
|
readonly base: ColumnBase<any>;
|
package/dist/rows/row/context.js
CHANGED
package/dist/rows/row/row.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RowNormalRowLayout } from "../../+types
|
|
1
|
+
import type { RowNormalRowLayout } from "../../+types";
|
|
2
2
|
import { type DropWrapProps } from "@1771technologies/lytenyte-shared";
|
|
3
3
|
export interface RowProps extends Omit<DropWrapProps, "accepted"> {
|
|
4
4
|
readonly row: RowNormalRowLayout<any>;
|
package/dist/rows/row/row.js
CHANGED
|
@@ -11,7 +11,7 @@ const empty = [];
|
|
|
11
11
|
const RowImpl = forwardRef(function Rows({ row, ...props }, forwarded) {
|
|
12
12
|
const ctx = useGridRoot().grid;
|
|
13
13
|
const yPos = ctx.state.yPositions.useValue();
|
|
14
|
-
const rowMeta = useRowContextValue(ctx, row
|
|
14
|
+
const rowMeta = useRowContextValue(ctx, row, yPos);
|
|
15
15
|
const hasSpans = ctx.internal.hasSpans.useValue();
|
|
16
16
|
const accepted = props.accepted ?? empty;
|
|
17
17
|
return (_jsx(RowContext.Provider, { value: rowMeta, children: _jsxs(RowReact, { ...props, ref: forwarded, accepted: accepted, gridId: ctx.state.gridId.useValue(), rowIndex: row.rowIndex, rowFirstPinBottom: row.rowFirstPinBottom, rowLastPinTop: row.rowLastPinTop, rowIsFocusRow: row.rowIsFocusRow ?? false, rowPin: row.rowPin, topOffset: ctx.view.useValue().rows.rowTopTotalHeight, yPositions: yPos, hasSpans: hasSpans, "data-ln-row-selected": rowMeta.selected, children: [_jsx(CellSpacerNoPin, { xPositions: rowMeta.xPositions }), props.children, _jsx(RowDetailRow, { layout: row })] }) }));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Grid,
|
|
1
|
+
import type { Grid, RowLayout } from "../../+types.js";
|
|
2
2
|
import type { InternalAtoms } from "../../state/+types.js";
|
|
3
3
|
import type { RowMetaData } from "./context.js";
|
|
4
4
|
export declare function useRowContextValue(grid: Grid<any> & {
|
|
5
5
|
internal: InternalAtoms;
|
|
6
|
-
}, row:
|
|
6
|
+
}, row: RowLayout<any>, yPositions: Uint32Array): RowMetaData;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEffect, useMemo, useState } from "react";
|
|
2
2
|
export function useRowContextValue(grid, row, yPositions) {
|
|
3
|
-
const r = row.useValue();
|
|
3
|
+
const r = row.row.useValue();
|
|
4
4
|
const xPositions = grid.state.xPositions.useValue();
|
|
5
5
|
const [indeterminate, setIndeterminate] = useState(false);
|
|
6
6
|
const [selected, setSelected] = useState(false);
|
|
@@ -33,12 +33,13 @@ export function useRowContextValue(grid, row, yPositions) {
|
|
|
33
33
|
indeterminate,
|
|
34
34
|
colBounds,
|
|
35
35
|
row: r,
|
|
36
|
+
layout: row,
|
|
36
37
|
xPositions,
|
|
37
38
|
yPositions,
|
|
38
39
|
rtl,
|
|
39
40
|
base,
|
|
40
41
|
renderers,
|
|
41
42
|
};
|
|
42
|
-
}, [base, colBounds, indeterminate, r, renderers, rtl, selected, xPositions, yPositions]);
|
|
43
|
+
}, [base, colBounds, indeterminate, r, renderers, row, rtl, selected, xPositions, yPositions]);
|
|
43
44
|
return value;
|
|
44
45
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { SCROLL_WIDTH_VARIABLE_USE, sizeFromCoord } from "@1771technologies/lytenyte-shared";
|
|
3
3
|
import { useGridRoot } from "../context.js";
|
|
4
4
|
import { useEffect, useState } from "react";
|
|
5
|
-
import { getTabbables, isHTMLElement } from "@1771technologies/lytenyte-dom-utils";
|
|
6
5
|
export function RowDetailRow({ layout, }) {
|
|
7
6
|
const cx = useGridRoot();
|
|
8
7
|
const row = layout.row.useValue();
|
|
@@ -17,89 +16,6 @@ function RowDetailImpl({ row, rowIndex }) {
|
|
|
17
16
|
const rowHeight = sizeFromCoord(rowIndex, cx.grid.state.yPositions.get()) - height;
|
|
18
17
|
const Renderer = cx.grid.state.rowDetailRenderer.useValue().fn;
|
|
19
18
|
const [ref, setRef] = useState(null);
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
const parent = ref?.parentElement;
|
|
22
|
-
const first = ref?.firstElementChild;
|
|
23
|
-
if (!parent || !first)
|
|
24
|
-
return;
|
|
25
|
-
const controller = new AbortController();
|
|
26
|
-
let focusTime = false;
|
|
27
|
-
const vp = cx.grid.state.viewport.get();
|
|
28
|
-
vp?.addEventListener("keydown", () => {
|
|
29
|
-
focusTime = true;
|
|
30
|
-
setTimeout(() => {
|
|
31
|
-
focusTime = false;
|
|
32
|
-
}, 20);
|
|
33
|
-
}, { capture: true, signal: controller.signal });
|
|
34
|
-
parent.addEventListener("focusin", (e) => {
|
|
35
|
-
if (focusTime && e.relatedTarget && isHTMLElement(e.relatedTarget)) {
|
|
36
|
-
const row = getNearestRow(e.relatedTarget);
|
|
37
|
-
const gridId = cx.grid.state.gridId.get();
|
|
38
|
-
if (gridId !== row?.getAttribute("data-ln-gridid"))
|
|
39
|
-
return;
|
|
40
|
-
const prevIndex = getRowIndexFromEl(row);
|
|
41
|
-
if (prevIndex - 1 === rowIndex) {
|
|
42
|
-
first.focus();
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}, { signal: controller.signal });
|
|
46
|
-
parent.addEventListener("keydown", (e) => {
|
|
47
|
-
if (e.key === "ArrowDown" && document.activeElement !== first) {
|
|
48
|
-
e.stopPropagation();
|
|
49
|
-
e.preventDefault();
|
|
50
|
-
first.focus();
|
|
51
|
-
}
|
|
52
|
-
}, { signal: controller.signal });
|
|
53
|
-
first.addEventListener("keydown", (e) => {
|
|
54
|
-
const next = rtl ? "ArrowLeft" : "ArrowRight";
|
|
55
|
-
const prev = rtl ? "ArrowRight" : "ArrowLeft";
|
|
56
|
-
if (e.key === "Escape") {
|
|
57
|
-
first.focus();
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
if (e.key === "ArrowUp") {
|
|
61
|
-
e.stopPropagation();
|
|
62
|
-
e.preventDefault();
|
|
63
|
-
cx.grid.api.focusCell({
|
|
64
|
-
row: rowIndex,
|
|
65
|
-
column: cx.grid.internal.focusActive.get()?.colIndex ?? 0,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
if (e.key === next) {
|
|
69
|
-
e.preventDefault();
|
|
70
|
-
e.stopPropagation();
|
|
71
|
-
const focusables = getTabbables(first);
|
|
72
|
-
const index = focusables.indexOf(document.activeElement);
|
|
73
|
-
if (index === -1)
|
|
74
|
-
focusables.at(0)?.focus();
|
|
75
|
-
else
|
|
76
|
-
focusables.at(index + 1)?.focus();
|
|
77
|
-
}
|
|
78
|
-
if (e.key === prev) {
|
|
79
|
-
e.preventDefault();
|
|
80
|
-
e.stopPropagation();
|
|
81
|
-
const focusables = getTabbables(first);
|
|
82
|
-
const index = focusables.indexOf(document.activeElement);
|
|
83
|
-
if (index === -1)
|
|
84
|
-
focusables.at(-1)?.focus();
|
|
85
|
-
else
|
|
86
|
-
focusables[index - 1]?.focus();
|
|
87
|
-
}
|
|
88
|
-
}, { signal: controller.signal });
|
|
89
|
-
return () => {
|
|
90
|
-
controller.abort();
|
|
91
|
-
};
|
|
92
|
-
}, [
|
|
93
|
-
cx.grid.api,
|
|
94
|
-
cx.grid.internal.focusActive,
|
|
95
|
-
cx.grid.internal.focusPrevRowIndex,
|
|
96
|
-
cx.grid.state.gridId,
|
|
97
|
-
cx.grid.state.rtl,
|
|
98
|
-
cx.grid.state.viewport,
|
|
99
|
-
ref,
|
|
100
|
-
rowIndex,
|
|
101
|
-
rtl,
|
|
102
|
-
]);
|
|
103
19
|
useEffect(() => {
|
|
104
20
|
const first = ref?.firstElementChild;
|
|
105
21
|
if (!first)
|
|
@@ -115,12 +31,13 @@ function RowDetailImpl({ row, rowIndex }) {
|
|
|
115
31
|
}, [cx.grid.internal.rowDetailAutoHeightCache, ref?.firstElementChild, rowIndex]);
|
|
116
32
|
const isAuto = cx.grid.state.rowDetailHeight.useValue() === "auto";
|
|
117
33
|
return (_jsx("div", { ref: setRef, role: "gridcell", style: {
|
|
118
|
-
pointerEvents: "
|
|
34
|
+
pointerEvents: "none",
|
|
119
35
|
position: "absolute",
|
|
120
36
|
left: 0,
|
|
121
37
|
width: SCROLL_WIDTH_VARIABLE_USE,
|
|
122
|
-
}, children: _jsx("div", { tabIndex: -
|
|
38
|
+
}, children: _jsx("div", { tabIndex: 0, "data-ln-gridid": cx.grid.state.gridId.get(), "data-ln-row-detail": true, "data-ln-rowindex": rowIndex, style: {
|
|
123
39
|
position: "sticky",
|
|
40
|
+
pointerEvents: "all",
|
|
124
41
|
right: rtl ? "0px" : undefined,
|
|
125
42
|
left: rtl ? undefined : "0px",
|
|
126
43
|
marginTop: rowHeight,
|
|
@@ -12,7 +12,7 @@ const RowFullWidthImpl = forwardRef(function RowFullWidth({ row: layout, space,
|
|
|
12
12
|
const row = layout.row.useValue();
|
|
13
13
|
const yPositions = grid.state.yPositions.useValue();
|
|
14
14
|
const hasSpans = grid.internal.hasSpans.useValue();
|
|
15
|
-
const meta = useRowContextValue(grid, layout
|
|
15
|
+
const meta = useRowContextValue(grid, layout, yPositions);
|
|
16
16
|
return (_jsx(RowFullWidthReact, { ...props, ref: forwarded, accepted: props.accepted ?? empty, detail: _jsx(RowDetailRow, { layout: layout }), detailHeight: grid.api.rowDetailRenderedHeight(row ?? ""), gridId: grid.state.gridId.useValue(), rtl: meta.rtl, hasSpans: hasSpans, rowFirstPinBottom: layout.rowFirstPinBottom, rowLastPinTop: layout.rowLastPinTop, rowIndex: layout.rowIndex, rowIsFocusRow: layout.rowIsFocusRow ?? false, rowPin: layout.rowPin, topOffset: grid.view.useValue().rows.rowTopTotalHeight, yPositions: yPositions, space: space, "data-ln-row-selected": meta.selected, children: children ??
|
|
17
17
|
(row ? (_jsx(Renderer, { grid: grid, row: row, rowIndex: layout.rowIndex, rowSelected: meta.selected, rowIndeterminate: meta.indeterminate })) : null) }));
|
|
18
18
|
});
|
|
@@ -45,13 +45,14 @@ export const makeCellRoot = (grid) => {
|
|
|
45
45
|
if (status === CONTAINS_DEAD_CELLS) {
|
|
46
46
|
const spec = l.lookup.get(row);
|
|
47
47
|
// This cell is not covered
|
|
48
|
-
if (!spec || spec[column * 4]
|
|
48
|
+
if (!spec || spec[column * 4] > 0) {
|
|
49
49
|
return { kind: "cell", rowIndex: row, colIndex: column, root: null };
|
|
50
50
|
}
|
|
51
|
-
const rowSpan = spec[column * 4];
|
|
52
|
-
const colSpan = spec[column * 4 + 1];
|
|
53
51
|
const rowIndex = spec[column * 4 + 2];
|
|
54
52
|
const colIndex = spec[column * 4 + 3];
|
|
53
|
+
const rootSpec = l.lookup.get(rowIndex);
|
|
54
|
+
const rowSpan = rootSpec[colIndex * 4];
|
|
55
|
+
const colSpan = rootSpec[colIndex * 4 + 1];
|
|
55
56
|
return {
|
|
56
57
|
kind: "cell",
|
|
57
58
|
rowIndex: row,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Grid, GridApi } from "../../+types";
|
|
2
|
-
import type { InternalAtoms } from "../+types
|
|
2
|
+
import type { InternalAtoms } from "../+types";
|
|
3
3
|
export declare const makeFocusCell: (grid: Grid<any> & {
|
|
4
4
|
internal: InternalAtoms;
|
|
5
5
|
}) => GridApi<any>["focusCell"];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { focusCell, getHeaderRows,
|
|
1
|
+
import { focusCell, getHeaderRows, handleNavigation, isColumnFloatingHeader, } from "@1771technologies/lytenyte-shared";
|
|
2
2
|
import { clamp } from "@1771technologies/lytenyte-js-utils";
|
|
3
3
|
export const makeFocusCell = (grid) => {
|
|
4
4
|
return (position) => {
|
|
@@ -18,20 +18,27 @@ export const makeFocusCell = (grid) => {
|
|
|
18
18
|
if (!key)
|
|
19
19
|
return false;
|
|
20
20
|
const ds = grid.state.rowDataStore;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
handleNavigation({
|
|
22
|
+
event: {
|
|
23
|
+
key,
|
|
24
|
+
ctrlKey: false,
|
|
25
|
+
metaKey: false,
|
|
26
|
+
preventDefault: () => { },
|
|
27
|
+
stopPropagation: () => { },
|
|
28
|
+
},
|
|
29
|
+
topCount: grid.state.rowDataStore.rowTopCount.get(),
|
|
30
|
+
centerCount: grid.state.rowDataStore.rowCenterCount.get(),
|
|
31
|
+
isRowDetailExpanded: (r) => {
|
|
32
|
+
const row = grid.api.rowByIndex(r);
|
|
33
|
+
if (!row)
|
|
34
|
+
return false;
|
|
35
|
+
return grid.api.rowDetailIsExpanded(row);
|
|
36
|
+
},
|
|
37
|
+
viewport: vp,
|
|
29
38
|
rowCount: ds.rowCount.get(),
|
|
30
|
-
topCount: ds.rowTopCount.get(),
|
|
31
|
-
centerCount: ds.rowCenterCount.get(),
|
|
32
39
|
columnCount: grid.state.columnMeta.get().columnsVisible.length,
|
|
33
40
|
focusActive: grid.internal.focusActive,
|
|
34
|
-
|
|
41
|
+
gridId: grid.state.gridId.get(),
|
|
35
42
|
getRootCell: grid.api.cellRoot,
|
|
36
43
|
rtl: grid.state.rtl.get(),
|
|
37
44
|
scrollIntoView: grid.api.scrollIntoView,
|
|
@@ -35,9 +35,11 @@ export function columnHandleMarker({ columns, marker, markerEnabled, }) {
|
|
|
35
35
|
}
|
|
36
36
|
return columns;
|
|
37
37
|
}
|
|
38
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
38
39
|
function HeaderRenderer() {
|
|
39
40
|
return (_jsx(_Fragment, { children: _jsx("div", { style: { overflow: "hidden", opacity: 0, width: "100%", height: "100%" }, children: "Marker column default" }) }));
|
|
40
41
|
}
|
|
42
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
41
43
|
function FloatingRenderer() {
|
|
42
44
|
return _jsx(_Fragment, {});
|
|
43
45
|
}
|
|
@@ -44,30 +44,11 @@ export function makeRowLayout({ view: n, viewCache, layout, rds, columns }) {
|
|
|
44
44
|
* BOTTOM ROW LAYOUT END
|
|
45
45
|
*/
|
|
46
46
|
return {
|
|
47
|
-
top: top
|
|
48
|
-
center: center
|
|
49
|
-
bottom: bottom
|
|
47
|
+
top: top,
|
|
48
|
+
center: center,
|
|
49
|
+
bottom: bottom,
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
-
const partition = (n, row) => {
|
|
53
|
-
if (row.kind === "full-width")
|
|
54
|
-
return row;
|
|
55
|
-
let found = false;
|
|
56
|
-
const cells = [
|
|
57
|
-
...row.cells.slice(0, n.colStartEnd),
|
|
58
|
-
...row.cells.slice(n.colCenterStart, n.colCenterEnd).map((c) => {
|
|
59
|
-
if (!found && c.isDeadCol && !c.isDeadRow)
|
|
60
|
-
return { ...c, isDeadCol: false, isDeadRow: true };
|
|
61
|
-
found = true;
|
|
62
|
-
return c;
|
|
63
|
-
}),
|
|
64
|
-
...row.cells.slice(n.colEndStart, n.colEndEnd),
|
|
65
|
-
];
|
|
66
|
-
return {
|
|
67
|
-
...row,
|
|
68
|
-
cells,
|
|
69
|
-
};
|
|
70
|
-
};
|
|
71
52
|
function handleViewLayout({ columns, spanLayout: n, rowStart, rowEnd, rowPin, layout, viewCache, container, rowForIndex, }) {
|
|
72
53
|
for (let r = rowStart; r < rowEnd; r++) {
|
|
73
54
|
const status = layout.special[r];
|
|
@@ -194,6 +194,7 @@ export function makeLyteNyte(p) {
|
|
|
194
194
|
rowDataStore.rowCenterCount.$();
|
|
195
195
|
rowDataStore.rowTopCount.$();
|
|
196
196
|
rowDataSource();
|
|
197
|
+
rowDetailExpansions();
|
|
197
198
|
rowGroupModel();
|
|
198
199
|
sortModel();
|
|
199
200
|
filterModel();
|
|
@@ -430,6 +431,7 @@ export function makeLyteNyte(p) {
|
|
|
430
431
|
const topCount = rowDataStore.rowTopCount.$();
|
|
431
432
|
const botCount = rowDataStore.rowBottomCount.$();
|
|
432
433
|
const rowCount = rowDataStore.rowCount.$();
|
|
434
|
+
const expansions = rowDetailExpansions();
|
|
433
435
|
const fullWidthPredicate = rowFullWidthPredicate().fn;
|
|
434
436
|
updateFull({
|
|
435
437
|
topCount,
|
|
@@ -442,7 +444,7 @@ export function makeLyteNyte(p) {
|
|
|
442
444
|
isFullWidth: fullWidthPredicate ? getFullWidthCallback(rds, fullWidthPredicate, grid) : null,
|
|
443
445
|
isRowCutoff: (r) => {
|
|
444
446
|
const row = rds.rowByIndex(r);
|
|
445
|
-
return !row || row.kind === "branch";
|
|
447
|
+
return !row || row.kind === "branch" || expansions.has(row.id);
|
|
446
448
|
},
|
|
447
449
|
rowScanDistance: rowScan,
|
|
448
450
|
rowStart: n.rowCenterStart,
|