@1771technologies/lytenyte-pro 1.0.7 → 1.0.8

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.
@@ -0,0 +1,13 @@
1
+ import type { ColumnPin } from "../+types";
2
+ export interface Cell {
3
+ readonly rowIndex: number;
4
+ readonly colIndex: number;
5
+ readonly colSpan: number;
6
+ readonly rowSpan: number;
7
+ readonly rowLastPinTop?: boolean;
8
+ readonly rowFirstPinBottom?: boolean;
9
+ readonly colLastStartPin?: boolean;
10
+ readonly colFirstEndPin?: boolean;
11
+ readonly colPin?: ColumnPin;
12
+ readonly rowPin?: "top" | "bottom" | null;
13
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,9 @@
1
- export declare function CellSpacePinStart(): import("react/jsx-runtime").JSX.Element | null;
2
- export declare function CellSpacerPinEnd(): import("react/jsx-runtime").JSX.Element | null;
3
- export declare function CellSpacerNoPin(): import("react/jsx-runtime").JSX.Element | null;
1
+ export declare function CellSpacePinStart({ xPositions: x }: {
2
+ xPositions: Uint32Array;
3
+ }): import("react/jsx-runtime").JSX.Element | null;
4
+ export declare function CellSpacerPinEnd({ xPositions: x }: {
5
+ xPositions: Uint32Array;
6
+ }): import("react/jsx-runtime").JSX.Element | null;
7
+ export declare function CellSpacerNoPin({ xPositions: x }: {
8
+ xPositions: Uint32Array;
9
+ }): import("react/jsx-runtime").JSX.Element | null;
@@ -1,35 +1,32 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useGridRoot } from "../context";
3
- export function CellSpacePinStart() {
3
+ export function CellSpacePinStart({ xPositions: x }) {
4
4
  const ctx = useGridRoot().grid;
5
- const xPos = ctx.state.xPositions.useValue();
6
5
  const bounds = ctx.state.viewBounds.useValue();
7
- const offset = xPos[bounds.colCenterStart] - xPos[bounds.colStartEnd];
6
+ const offset = x[bounds.colCenterStart] - x[bounds.colStartEnd];
8
7
  const meta = ctx.state.columnMeta.useValue();
9
8
  if (meta.columnVisibleStartCount === 0)
10
9
  return null;
11
10
  return _jsx("div", { style: { display: "inline-block", width: offset, height: 0 } });
12
11
  }
13
- export function CellSpacerPinEnd() {
12
+ export function CellSpacerPinEnd({ xPositions: x }) {
14
13
  const ctx = useGridRoot().grid;
15
- const xPos = ctx.state.xPositions.useValue();
16
14
  const bounds = ctx.state.viewBounds.useValue();
17
- const startOffset = xPos[bounds.colCenterEnd];
18
- let offset = xPos[bounds.colEndStart] - startOffset;
15
+ const startOffset = x[bounds.colCenterEnd];
16
+ let offset = x[bounds.colEndStart] - startOffset;
19
17
  const viewWidth = ctx.state.viewportWidthInner.useValue();
20
- if (xPos.at(-1) < viewWidth) {
21
- offset = viewWidth - xPos.at(-1);
18
+ if (x.at(-1) < viewWidth) {
19
+ offset = viewWidth - x.at(-1);
22
20
  }
23
21
  const meta = ctx.state.columnMeta.useValue();
24
22
  if (meta.columnVisibleEndCount === 0)
25
23
  return null;
26
24
  return _jsx("div", { style: { display: "inline-block", width: offset, height: 0 } });
27
25
  }
28
- export function CellSpacerNoPin() {
26
+ export function CellSpacerNoPin({ xPositions: x }) {
29
27
  const ctx = useGridRoot().grid;
30
- const xPos = ctx.state.xPositions.useValue();
31
28
  const bounds = ctx.state.viewBounds.useValue();
32
- const offset = xPos[bounds.colCenterStart - bounds.colStartEnd];
29
+ const offset = x[bounds.colCenterStart - bounds.colStartEnd];
33
30
  const meta = ctx.state.columnMeta.useValue();
34
31
  if (meta.columnVisibleStartCount > 0)
35
32
  return null;
@@ -1,17 +1,22 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { forwardRef, useEffect, useState } from "react";
2
+ import { forwardRef, memo, useEffect, useState } from "react";
3
3
  import { useGridRoot } from "../context";
4
- import { CellReact, sizeFromCoord } from "@1771technologies/lytenyte-shared";
4
+ import { sizeFromCoord } from "@1771technologies/lytenyte-shared";
5
5
  import { CellDefault } from "./cell-default";
6
6
  import { CellEditor } from "./cell-editor";
7
7
  import { useRowMeta } from "../rows/row/context";
8
8
  import { CellSpacePinStart, CellSpacerPinEnd } from "./cell-spacer";
9
- export const Cell = forwardRef(function Cell({ cell, ...props }, forwarded) {
9
+ import { useCellStyle } from "./use-cell-style";
10
+ export const Cell = forwardRef(function Cell(props, forwarded) {
11
+ const { colBounds: [start, end], ...rowMeta } = useRowMeta();
12
+ // This enforces our column virtualization.
13
+ if (props.cell.colPin == null && (props.cell.colIndex >= end || props.cell.colIndex < start)) {
14
+ return null;
15
+ }
16
+ return _jsx(CellImpl, { ...props, ref: forwarded, ...rowMeta });
17
+ });
18
+ const CellImpl = memo(forwardRef(function Cell({ cell, row, selected, indeterminate, xPositions, yPositions, base, renderers, rtl, ...props }, forwarded) {
10
19
  const grid = useGridRoot().grid;
11
- const cx = grid.state;
12
- const base = grid.state.columnBase.useValue();
13
- const row = cell.row.useValue();
14
- const renderers = cx.cellRenderers.useValue();
15
20
  const providedRenderer = cell.column.cellRenderer ?? base.cellRenderer;
16
21
  const Renderer = providedRenderer
17
22
  ? typeof providedRenderer === "string"
@@ -29,12 +34,10 @@ export const Cell = forwardRef(function Cell({ cell, ...props }, forwarded) {
29
34
  pos.rowIndex < cell.rowIndex + cell.rowSpan);
30
35
  });
31
36
  }, [cell.column, cell.rowIndex, cell.rowSpan, grid.internal.editActivePos]);
32
- const xPositions = cx.xPositions.useValue();
33
- const yPositions = cx.yPositions.useValue();
34
- const rowMeta = useRowMeta();
37
+ const style = useCellStyle(xPositions, yPositions, cell, rtl, grid.api.rowDetailRenderedHeight(row ?? ""), undefined);
35
38
  if (cell.isDeadRow)
36
39
  return _jsx("div", { style: { width: sizeFromCoord(cell.colIndex, xPositions) } });
37
40
  if (!row || cell.isDeadCol)
38
41
  return null;
39
- return (_jsxs(_Fragment, { children: [cell.colFirstEndPin && _jsx(CellSpacerPinEnd, {}), _jsxs(CellReact, { ...props, ref: forwarded, cell: cell, isEditing: isEditing, detailHeight: grid.api.rowDetailRenderedHeight(row ?? ""), rtl: cx.rtl.useValue(), xPosition: xPositions, yPosition: yPositions, children: [isEditing && _jsx(CellEditor, { cell: cell }), !isEditing && (_jsx(Renderer, { column: cell.column, rowSelected: rowMeta.selected, rowIndeterminate: rowMeta.indeterminate, row: row, grid: grid, rowIndex: cell.rowIndex, colIndex: cell.colIndex, rowPin: cell.rowPin }))] }), cell.colLastStartPin && _jsx(CellSpacePinStart, {})] }));
40
- });
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
+ }));
@@ -0,0 +1,3 @@
1
+ import { type CSSProperties } from "react";
2
+ import type { Cell } from "./+types.cell";
3
+ export declare function useCellStyle(xPositions: Uint32Array, yPositions: Uint32Array, cell: Cell, rtl: boolean, detailHeight: number, additional: CSSProperties | undefined): CSSProperties;
@@ -0,0 +1,51 @@
1
+ import { useMemo } from "react";
2
+ import { sizeFromCoord } from "@1771technologies/lytenyte-shared";
3
+ export function useCellStyle(xPositions, yPositions, cell, rtl, detailHeight, additional) {
4
+ const width = sizeFromCoord(cell.colIndex, xPositions, cell.colSpan);
5
+ const height = sizeFromCoord(cell.rowIndex, yPositions, cell.rowSpan) - detailHeight;
6
+ const isSticky = !!cell.colPin;
7
+ const isRowPinned = !!cell.rowPin;
8
+ const styles = useMemo(() => {
9
+ const styles = {
10
+ height,
11
+ width,
12
+ minWidth: width,
13
+ maxWidth: width,
14
+ boxSizing: "border-box",
15
+ pointerEvents: "all",
16
+ display: "inline-block",
17
+ overflow: "hidden",
18
+ };
19
+ if (cell.colPin === "end") {
20
+ styles.position = "sticky";
21
+ const x = xPositions.at(-1) - xPositions[cell.colIndex + cell.colSpan];
22
+ if (rtl)
23
+ styles.left = x;
24
+ else
25
+ styles.right = x;
26
+ styles.zIndex = isRowPinned ? 5 : 2;
27
+ }
28
+ else if (isSticky) {
29
+ styles.position = "sticky";
30
+ const x = xPositions[cell.colIndex];
31
+ if (rtl)
32
+ styles.right = x;
33
+ else
34
+ styles.left = x;
35
+ styles.zIndex = isRowPinned ? 5 : 2;
36
+ }
37
+ return { ...additional, ...styles };
38
+ }, [
39
+ additional,
40
+ cell.colIndex,
41
+ cell.colPin,
42
+ cell.colSpan,
43
+ height,
44
+ isRowPinned,
45
+ isSticky,
46
+ rtl,
47
+ width,
48
+ xPositions,
49
+ ]);
50
+ return styles;
51
+ }
@@ -333,6 +333,7 @@ export function makeClientDataSourcePaginated(p) {
333
333
  continue;
334
334
  }
335
335
  d[source] = next;
336
+ cache.delete(source);
336
337
  }
337
338
  }
338
339
  data.set([...d]);
@@ -459,6 +460,7 @@ export function makeClientDataSourcePaginated(p) {
459
460
  data.set(d);
460
461
  const grid = grid$();
461
462
  grid?.state.rowDataStore.rowClearCache();
463
+ cache.clear();
462
464
  },
463
465
  rowData: (section) => {
464
466
  const d = [];
@@ -428,6 +428,7 @@ export function makeClientDataSource(p) {
428
428
  continue;
429
429
  }
430
430
  d[source] = next;
431
+ cache.delete(source);
431
432
  }
432
433
  }
433
434
  data.set([...d]);
@@ -534,6 +535,7 @@ export function makeClientDataSource(p) {
534
535
  data.set(d);
535
536
  const grid = peek(grid$);
536
537
  grid?.state.rowDataStore.rowClearCache();
538
+ cache.clear();
537
539
  },
538
540
  rowData: (section) => {
539
541
  const d = [];
@@ -277,6 +277,7 @@ export function makeClientTreeDataSource(p) {
277
277
  continue;
278
278
  }
279
279
  d[source] = next;
280
+ cache.delete(source);
280
281
  }
281
282
  }
282
283
  data.set([...d]);
@@ -383,6 +384,7 @@ export function makeClientTreeDataSource(p) {
383
384
  data.set(d);
384
385
  const grid = peek(grid$);
385
386
  grid?.state.rowDataStore.rowClearCache();
387
+ cache.clear();
386
388
  },
387
389
  rowExpand: (expansions) => {
388
390
  const grid = peek(grid$);
@@ -1,6 +1,14 @@
1
+ import type { CellRendererFn, ColumnBase, RowNode } from "../../+types";
1
2
  export interface RowMetaData {
2
3
  readonly selected: boolean;
3
4
  readonly indeterminate: boolean;
5
+ readonly colBounds: [number, number];
6
+ readonly row: RowNode<any> | null;
7
+ readonly xPositions: Uint32Array;
8
+ readonly yPositions: Uint32Array;
9
+ readonly base: ColumnBase<any>;
10
+ readonly renderers: Record<string, CellRendererFn<any>>;
11
+ readonly rtl: boolean;
4
12
  }
5
13
  export declare const RowContext: import("react").Context<RowMetaData>;
6
14
  export declare const useRowMeta: () => RowMetaData;
@@ -1,3 +1,13 @@
1
1
  import { createContext, useContext } from "react";
2
- export const RowContext = createContext({ selected: false, indeterminate: false });
2
+ export const RowContext = createContext({
3
+ selected: false,
4
+ indeterminate: false,
5
+ colBounds: [0, 0],
6
+ row: null,
7
+ xPositions: new Uint32Array(),
8
+ yPositions: new Uint32Array(),
9
+ base: null,
10
+ renderers: null,
11
+ rtl: false,
12
+ });
3
13
  export const useRowMeta = () => useContext(RowContext);
@@ -10,9 +10,11 @@ import { CellSpacerNoPin } from "../../cells/cell-spacer";
10
10
  const empty = [];
11
11
  const RowImpl = forwardRef(function Rows({ row, ...props }, forwarded) {
12
12
  const ctx = useGridRoot().grid;
13
- const rowMeta = useRowContextValue(ctx, row.row);
13
+ const yPos = ctx.state.yPositions.useValue();
14
+ const rowMeta = useRowContextValue(ctx, row.row, yPos);
15
+ const hasSpans = ctx.internal.hasSpans.useValue();
14
16
  const accepted = props.accepted ?? empty;
15
- 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, yPositions: ctx.state.yPositions.useValue(), "data-ln-row-selected": rowMeta.selected, children: [_jsx(CellSpacerNoPin, {}), props.children, _jsx(RowDetailRow, { layout: row })] }) }));
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 })] }) }));
16
18
  });
17
19
  export const Row = memo(RowImpl, (prev, next) => {
18
20
  const { row: rowP, ...propsP } = prev;
@@ -3,4 +3,4 @@ import type { InternalAtoms } from "../../state/+types";
3
3
  import type { RowMetaData } from "./context";
4
4
  export declare function useRowContextValue(grid: Grid<any> & {
5
5
  internal: InternalAtoms;
6
- }, row: GridAtomReadonlyUnwatchable<RowNode<any> | null>): RowMetaData;
6
+ }, row: GridAtomReadonlyUnwatchable<RowNode<any> | null>, yPositions: Uint32Array): RowMetaData;
@@ -1,8 +1,13 @@
1
1
  import { useEffect, useMemo, useState } from "react";
2
- export function useRowContextValue(grid, row) {
2
+ export function useRowContextValue(grid, row, yPositions) {
3
3
  const r = row.useValue();
4
+ const xPositions = grid.state.xPositions.useValue();
4
5
  const [indeterminate, setIndeterminate] = useState(false);
5
6
  const [selected, setSelected] = useState(false);
7
+ const colBounds = grid.internal.colBounds.useValue();
8
+ const rtl = grid.state.rtl.useValue();
9
+ const base = grid.state.columnBase.useValue();
10
+ const renderers = grid.state.cellRenderers.useValue();
6
11
  useEffect(() => {
7
12
  function handleSelection() {
8
13
  if (!r)
@@ -23,7 +28,17 @@ export function useRowContextValue(grid, row) {
23
28
  return grid.state.rowSelectedIds.watch(() => handleSelection());
24
29
  }, [grid.state.rowDataSource, grid.state.rowSelectedIds, r]);
25
30
  const value = useMemo(() => {
26
- return { selected, indeterminate };
27
- }, [indeterminate, selected]);
31
+ return {
32
+ selected,
33
+ indeterminate,
34
+ colBounds,
35
+ row: r,
36
+ xPositions,
37
+ yPositions,
38
+ rtl,
39
+ base,
40
+ renderers,
41
+ };
42
+ }, [base, colBounds, indeterminate, r, renderers, rtl, selected, xPositions, yPositions]);
28
43
  return value;
29
44
  }
@@ -10,8 +10,10 @@ const RowFullWidthImpl = forwardRef(function RowFullWidth({ row: layout, space,
10
10
  const grid = useGridRoot().grid;
11
11
  const Renderer = grid.state.rowFullWidthRenderer.useValue().fn;
12
12
  const row = layout.row.useValue();
13
- const meta = useRowContextValue(grid, layout.row);
14
- 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: grid.state.rtl.useValue(), rowFirstPinBottom: layout.rowFirstPinBottom, rowLastPinTop: layout.rowLastPinTop, rowIndex: layout.rowIndex, rowIsFocusRow: layout.rowIsFocusRow ?? false, yPositions: grid.state.yPositions.useValue(), space: space, "data-ln-row-selected": meta.selected, children: children ??
13
+ const yPositions = grid.state.yPositions.useValue();
14
+ const hasSpans = grid.internal.hasSpans.useValue();
15
+ const meta = useRowContextValue(grid, layout.row, yPositions);
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 ??
15
17
  (row ? (_jsx(Renderer, { grid: grid, row: row, rowIndex: layout.rowIndex, rowSelected: meta.selected, rowIndeterminate: meta.indeterminate })) : null) }));
16
18
  });
17
19
  export const RowFullWidth = fastDeepMemo(RowFullWidthImpl);
@@ -1,18 +1,4 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useGridRoot } from "../../context";
3
- import { sizeFromCoord } from "@1771technologies/lytenyte-shared";
4
2
  export function NativeScroller(props) {
5
- const cx = useGridRoot().grid;
6
- const view = cx.view.useValue().rows;
7
- const yPos = cx.state.yPositions.useValue();
8
- let offset = yPos[view.rowFirstCenter] - view.rowTopTotalHeight;
9
- if (view.rowFocusedIndex != null && view.rowFocusedIndex < view.rowFirstCenter) {
10
- const size = sizeFromCoord(view.rowFocusedIndex, yPos);
11
- offset -= size;
12
- }
13
- const offsetPx = `${offset}px`;
14
- return (_jsx("div", { role: "presentation", style: {
15
- transform: `translate3d(0px, ${offset}px, 0px)`,
16
- "--ln-y-offset": offsetPx,
17
- }, children: props.children }));
3
+ return _jsx("div", { role: "presentation", children: props.children });
18
4
  }
@@ -8,6 +8,8 @@ export interface InternalAtoms {
8
8
  readonly xScroll: GridAtom<number>;
9
9
  readonly yScroll: GridAtom<number>;
10
10
  readonly layout: LayoutState;
11
+ readonly hasSpans: GridAtomReadonly<boolean>;
12
+ readonly colBounds: GridAtomReadonly<[number, number]>;
11
13
  readonly focusActive: GridAtom<PositionUnion | null>;
12
14
  readonly focusPrevColIndex: GridAtom<number | null>;
13
15
  readonly focusPrevRowIndex: GridAtom<number | null>;
@@ -69,9 +69,6 @@ const partition = (n, row) => {
69
69
  };
70
70
  };
71
71
  function handleViewLayout({ columns, spanLayout: n, rowStart, rowEnd, rowPin, layout, viewCache, container, rowForIndex, }) {
72
- /**
73
- * TOP ROW LAYOUT START
74
- */
75
72
  for (let r = rowStart; r < rowEnd; r++) {
76
73
  const status = layout.special[r];
77
74
  const computed = layout.computed[r];
@@ -87,7 +84,9 @@ function handleViewLayout({ columns, spanLayout: n, rowStart, rowEnd, rowPin, la
87
84
  const rowLastPinTop = n.rowTopEnd - 1 === r ? true : undefined;
88
85
  if (status === FULL_WIDTH) {
89
86
  const row = {
90
- id: node.get()?.id ?? `${r}`,
87
+ get id() {
88
+ return node.get()?.id ?? `${r}`;
89
+ },
91
90
  rowIndex: r,
92
91
  kind: "full-width",
93
92
  rowPin,
@@ -155,7 +154,7 @@ function handleViewLayout({ columns, spanLayout: n, rowStart, rowEnd, rowPin, la
155
154
  rowIndex: r,
156
155
  rowSpan: cellSpec?.[c * 4] || 1,
157
156
  colSpan: cellSpec?.[c * 4 + 1] || 1,
158
- rowPin: "top",
157
+ rowPin,
159
158
  colPin: "end",
160
159
  isDeadCol,
161
160
  isDeadRow,
@@ -166,11 +165,13 @@ function handleViewLayout({ columns, spanLayout: n, rowStart, rowEnd, rowPin, la
166
165
  });
167
166
  }
168
167
  const row = {
169
- id: node.get()?.id ?? `${r}`,
168
+ get id() {
169
+ return node.get()?.id ?? `${r}`;
170
+ },
170
171
  rowIndex: r,
171
172
  kind: "row",
172
173
  cells: cellLayout,
173
- rowPin: "top",
174
+ rowPin,
174
175
  row: node,
175
176
  rowLastPinTop,
176
177
  };
@@ -246,6 +246,10 @@ export function makeLyteNyte(p) {
246
246
  });
247
247
  return bounds;
248
248
  }, { dirty: (prev, next) => !equal(prev, next) });
249
+ const internal_colBounds = computed(() => {
250
+ const b = bounds();
251
+ return [b.colCenterStart, b.colCenterEnd];
252
+ }, { dirty: (l, r) => !equal(l, r) });
249
253
  /**
250
254
  * COLUMN VIEW
251
255
  * Compute the column layout. This impacts both the row layout and header layout. Column layout
@@ -390,6 +394,10 @@ export function makeLyteNyte(p) {
390
394
  }, innerHeight - headerHeight);
391
395
  });
392
396
  const heightTotal = computed(() => yPositions().at(-1));
397
+ const hasSpans = computed(() => {
398
+ const visible = columnMeta().columnsVisible;
399
+ return cellSelectionMode() !== "none" || !visible.every((c) => !(c.colSpan || c.rowSpan));
400
+ });
393
401
  const rowView = computed(() => {
394
402
  if (!viewport())
395
403
  return {
@@ -412,7 +420,7 @@ export function makeLyteNyte(p) {
412
420
  const rowScan = rowScanDistance();
413
421
  const columns = columnMeta().columnsVisible;
414
422
  const rds = rowDataSource();
415
- const { layout } = layoutState$();
423
+ const { layout, cache } = layoutState$();
416
424
  const topCount = rowDataStore.rowTopCount.$();
417
425
  const botCount = rowDataStore.rowBottomCount.$();
418
426
  const rowCount = rowDataStore.rowCount.$();
@@ -441,7 +449,7 @@ export function makeLyteNyte(p) {
441
449
  const focus = internal_focusActive();
442
450
  const view = makeRowLayout({
443
451
  view: n,
444
- viewCache: new Map(),
452
+ viewCache: cache,
445
453
  layout,
446
454
  rds: rowDataStore,
447
455
  columns,
@@ -609,6 +617,8 @@ export function makeLyteNyte(p) {
609
617
  xScroll: makeAtom(xScroll),
610
618
  yScroll: makeAtom(yScroll),
611
619
  layout: layoutState,
620
+ colBounds: makeAtom(internal_colBounds),
621
+ hasSpans: makeAtom(hasSpans),
612
622
  focusActive: makeAtom(internal_focusActive),
613
623
  focusPrevColIndex: makeAtom(internal_focusPrevCol),
614
624
  focusPrevRowIndex: makeAtom(internal_focusPrevRow),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@1771technologies/lytenyte-pro",
3
3
  "description": "Blazingly fast headless React data grid with 100s of features.",
4
- "version": "1.0.7",
4
+ "version": "1.0.8",
5
5
  "type": "module",
6
6
  "license": "COMMERCIAL",
7
7
  "files": [
@@ -49,12 +49,12 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@1771technologies/atom": "^1.0.2",
52
- "@1771technologies/lytenyte-core": "1.0.7",
53
- "@1771technologies/lytenyte-shared": "1.0.7",
54
- "@1771technologies/lytenyte-dom-utils": "1.0.7",
55
- "@1771technologies/lytenyte-js-utils": "1.0.7",
56
- "@1771technologies/lytenyte-dragon": "1.0.7",
57
- "@1771technologies/lytenyte-react-hooks": "1.0.7"
52
+ "@1771technologies/lytenyte-core": "1.0.8",
53
+ "@1771technologies/lytenyte-dragon": "1.0.8",
54
+ "@1771technologies/lytenyte-shared": "1.0.8",
55
+ "@1771technologies/lytenyte-dom-utils": "1.0.8",
56
+ "@1771technologies/lytenyte-react-hooks": "1.0.8",
57
+ "@1771technologies/lytenyte-js-utils": "1.0.8"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "react": "^18.0.0 || ^19.0.0",