@1771technologies/lytenyte-pro 1.0.0-beta.3 → 1.0.0-beta.31

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.
Files changed (103) hide show
  1. package/dist/+types.d.ts +88 -14
  2. package/dist/cell-selection/cell-selection-driver.js +9 -1
  3. package/dist/cell-selection/update-additive-cell-selection.js +0 -2
  4. package/dist/cells/cell-editor.js +11 -4
  5. package/dist/cells/cell.js +6 -3
  6. package/dist/column-manager/branch.d.ts +9 -3
  7. package/dist/column-manager/branch.js +20 -4
  8. package/dist/column-manager/column-manager.d.ts +3 -5
  9. package/dist/column-manager/column-manager.js +6 -8
  10. package/dist/column-manager/context.d.ts +2 -2
  11. package/dist/column-manager/label.d.ts +1 -1
  12. package/dist/column-manager/label.js +5 -5
  13. package/dist/column-manager/leaf.d.ts +2 -2
  14. package/dist/column-manager/leaf.js +22 -4
  15. package/dist/column-manager/move-handle.d.ts +3 -3
  16. package/dist/column-manager/move-handle.js +3 -5
  17. package/dist/column-manager/panel.d.ts +1 -0
  18. package/dist/column-manager/panel.js +2 -0
  19. package/dist/column-manager/root.d.ts +6 -7
  20. package/dist/column-manager/root.js +2 -15
  21. package/dist/column-manager/use-column-manager.d.ts +8 -18
  22. package/dist/column-manager/use-column-manager.js +18 -22
  23. package/dist/column-manager/use-columns-from-context.d.ts +2 -2
  24. package/dist/column-manager/use-columns-from-context.js +2 -2
  25. package/dist/column-manager/visibility-checkbox.d.ts +1 -1
  26. package/dist/column-manager/visibility-checkbox.js +2 -2
  27. package/dist/filter-tree/branch.js +1 -1
  28. package/dist/filter-tree/inclusion-checkbox.d.ts +1 -1
  29. package/dist/filter-tree/inclusion-checkbox.js +2 -2
  30. package/dist/filter-tree/label.d.ts +1 -1
  31. package/dist/filter-tree/label.js +2 -2
  32. package/dist/filter-tree/root.d.ts +3 -3
  33. package/dist/filter-tree/root.js +4 -4
  34. package/dist/grid-box/+types.d.ts +4 -2
  35. package/dist/grid-box/item.d.ts +4 -1
  36. package/dist/grid-box/item.js +39 -9
  37. package/dist/grid-box/use-aggregation-box-items.js +3 -1
  38. package/dist/grid-box/use-column-box-items.d.ts +6 -2
  39. package/dist/grid-box/use-column-box-items.js +11 -14
  40. package/dist/grid-box/use-row-group-box-items.d.ts +2 -2
  41. package/dist/grid-box/use-row-group-box-items.js +14 -15
  42. package/dist/grid.d.ts +0 -12
  43. package/dist/grid.js +0 -12
  44. package/dist/header/header-cell.d.ts +1 -1
  45. package/dist/header/header-cell.js +2 -2
  46. package/dist/header/header-group-cell.js +3 -1
  47. package/dist/header/resize-handler.d.ts +2 -2
  48. package/dist/header/resize-handler.js +8 -3
  49. package/dist/header/use-drag-move.js +9 -2
  50. package/dist/header/use-header-cell-renderer.js +4 -4
  51. package/dist/icons/index.d.ts +1 -0
  52. package/dist/icons/index.js +1 -0
  53. package/dist/index.d.ts +7 -0
  54. package/dist/index.js +7 -0
  55. package/dist/listbox/item.js +1 -1
  56. package/dist/row-data-source-client/filter/compute-filtered-rows.js +1 -1
  57. package/dist/row-data-source-client/use-client-data-source-paginated.d.ts +3 -3
  58. package/dist/row-data-source-client/use-client-data-source-paginated.js +66 -24
  59. package/dist/row-data-source-client/use-client-data-source.js +50 -20
  60. package/dist/row-data-source-client/use-client-tree-data-source.js +49 -20
  61. package/dist/row-data-source-server/use-server-data-source.js +20 -0
  62. package/dist/sort-manager/sort-add.d.ts +1 -1
  63. package/dist/sort-manager/sort-add.js +3 -3
  64. package/dist/sort-manager/sort-apply.d.ts +1 -1
  65. package/dist/sort-manager/sort-apply.js +3 -3
  66. package/dist/sort-manager/sort-cancel.d.ts +1 -1
  67. package/dist/sort-manager/sort-cancel.js +3 -3
  68. package/dist/sort-manager/sort-clear.d.ts +1 -1
  69. package/dist/sort-manager/sort-clear.js +3 -3
  70. package/dist/sort-manager/sort-column-select.d.ts +1 -1
  71. package/dist/sort-manager/sort-column-select.js +2 -2
  72. package/dist/sort-manager/sort-direction-select.d.ts +1 -1
  73. package/dist/sort-manager/sort-direction-select.js +2 -2
  74. package/dist/sort-manager/sort-remove.d.ts +1 -1
  75. package/dist/sort-manager/sort-remove.js +3 -3
  76. package/dist/sort-manager/sort-value-select.d.ts +1 -1
  77. package/dist/sort-manager/sort-value-select.js +2 -2
  78. package/dist/state/+types.d.ts +2 -1
  79. package/dist/state/api/column-autosize.js +1 -1
  80. package/dist/state/api/column-from-index.d.ts +1 -1
  81. package/dist/state/api/column-from-index.js +1 -1
  82. package/dist/state/api/column-update.d.ts +4 -1
  83. package/dist/state/api/column-update.js +13 -0
  84. package/dist/state/api/edit-end.js +1 -1
  85. package/dist/state/api/export-data-rect.js +1 -1
  86. package/dist/state/helpers/column-add-row-group.d.ts +2 -1
  87. package/dist/state/helpers/column-add-row-group.js +9 -1
  88. package/dist/state/helpers/column-marker.js +1 -1
  89. package/dist/state/helpers/edit-on-change.js +1 -0
  90. package/dist/state/helpers/empty-row-data-source.js +1 -0
  91. package/dist/state/helpers/resolve-column.d.ts +1 -1
  92. package/dist/state/helpers/resolve-column.js +7 -0
  93. package/dist/state/use-lytenyte.js +16 -4
  94. package/dist/tree-view/branch/branch.d.ts +4 -1
  95. package/dist/tree-view/branch/branch.js +4 -2
  96. package/dist/tree-view/hooks/use-tree-view-paths.d.ts +1 -1
  97. package/dist/tree-view/hooks/use-tree-view-paths.js +3 -3
  98. package/dist/tree-view/leaf.js +1 -0
  99. package/dist/viewport/begin-editing.js +1 -1
  100. package/main.css +4 -0
  101. package/package.json +12 -6
  102. package/dist/column-manager/passive-scroll.d.ts +0 -2
  103. package/dist/column-manager/passive-scroll.js +0 -2
@@ -6,7 +6,7 @@ import { fastDeepMemo, useCombinedRefs, } from "@1771technologies/lytenyte-react
6
6
  import { useHeaderCellRenderer } from "./use-header-cell-renderer";
7
7
  import { ResizeHandler } from "./resize-handler";
8
8
  import { useDragMove } from "./use-drag-move";
9
- const HeaderCellImpl = forwardRef(function HeaderCell({ cell, resizerSlot, resizerStyle, resizerClassName, children, ...props }, forwarded) {
9
+ const HeaderCellImpl = forwardRef(function HeaderCell({ cell, resizerAs, resizerStyle, resizerClassName, children, ...props }, forwarded) {
10
10
  const grid = useGridRoot().grid;
11
11
  const ctx = grid.state;
12
12
  const xPositions = ctx.xPositions.useValue();
@@ -19,6 +19,6 @@ const HeaderCellImpl = forwardRef(function HeaderCell({ cell, resizerSlot, resiz
19
19
  : (cell.column.uiHints?.resizable ?? base.uiHints?.resizable ?? false);
20
20
  const { ref, ...dragProps } = useDragMove(grid, cell, props.onDragStart);
21
21
  const combined = useCombinedRefs(forwarded, ref);
22
- return (_jsxs(HeaderCellReact, { ...props, ...dragProps, ref: combined, cell: cell, columnId: cell.column.id, viewportWidth: viewport, isFloating: cell.kind === "floating", rtl: rtl, xPositions: xPositions, children: [children == undefined ? _jsx(Renderer, { column: cell.column, grid: grid }) : children, resizable && cell.kind === "cell" && (_jsx(ResizeHandler, { cell: cell, xPositions: xPositions, slot: resizerSlot, className: resizerClassName, style: resizerStyle }))] }));
22
+ return (_jsxs(HeaderCellReact, { ...props, ...dragProps, ref: combined, cell: cell, columnId: cell.column.id, viewportWidth: viewport, isFloating: cell.kind === "floating", rtl: rtl, xPositions: xPositions, children: [children == undefined ? _jsx(Renderer, { column: cell.column, grid: grid }) : children, resizable && cell.kind === "cell" && (_jsx(ResizeHandler, { cell: cell, xPositions: xPositions, as: resizerAs, className: resizerClassName, style: resizerStyle }))] }));
23
23
  });
24
24
  export const HeaderCell = fastDeepMemo(HeaderCellImpl);
@@ -9,6 +9,8 @@ const HeaderGroupCellImpl = forwardRef(function HeaderCell({ cell, children, ...
9
9
  const ctx = grid.state;
10
10
  const { ref, ...dragProps } = useDragMove(grid, cell, props.onDragStart);
11
11
  const combined = useCombinedRefs(ref, forwarded);
12
- return (_jsx(HeaderGroupCellReact, { ...props, ...dragProps, ref: combined, cell: cell, cellId: cell.id, height: ctx.headerGroupHeight.useValue(), rtl: ctx.rtl.useValue(), viewportWidth: ctx.viewportWidthInner.useValue(), xPositions: ctx.xPositions.useValue(), isHiddenMove: cell.isHiddenMove ?? false, children: children == undefined ? cell.id : children }));
12
+ const isExpanded = grid.state.columnGroupExpansions.useValue()[cell.id] ??
13
+ grid.state.columnGroupDefaultExpansion.get();
14
+ return (_jsx(HeaderGroupCellReact, { ...props, ...dragProps, ref: combined, cell: cell, cellId: cell.id, height: ctx.headerGroupHeight.useValue(), rtl: ctx.rtl.useValue(), viewportWidth: ctx.viewportWidthInner.useValue(), xPositions: ctx.xPositions.useValue(), isHiddenMove: cell.isHiddenMove ?? false, "data-ln-collapsible": cell.isCollapsible, "data-ln-collapsed": !isExpanded, children: children == undefined ? cell.id : children }));
13
15
  });
14
16
  export const HeaderGroupCell = fastDeepMemo(HeaderGroupCellImpl);
@@ -2,11 +2,11 @@ import { type SlotComponent } from "@1771technologies/lytenyte-react-hooks";
2
2
  import type { HeaderCellLayout } from "../+types";
3
3
  import { type CSSProperties } from "react";
4
4
  interface ResizeHandlerProps<T> {
5
- readonly slot?: SlotComponent;
5
+ readonly as?: SlotComponent;
6
6
  readonly cell: HeaderCellLayout<T>;
7
7
  readonly xPositions: Uint32Array;
8
8
  readonly className?: string;
9
9
  readonly style?: CSSProperties;
10
10
  }
11
- export declare function ResizeHandler<T>({ slot, cell, xPositions, style, className, }: ResizeHandlerProps<T>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
11
+ export declare function ResizeHandler<T>({ as, cell, xPositions, style, className, }: ResizeHandlerProps<T>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
12
12
  export {};
@@ -5,12 +5,13 @@ import { DEFAULT_COLUMN_WIDTH_MAX, DEFAULT_COLUMN_WIDTH_MIN, getColIndexFromEl,
5
5
  import { useGridRoot } from "../context";
6
6
  import { getComputedStyle, isHTMLElement } from "@1771technologies/lytenyte-dom-utils";
7
7
  import { clamp, getClientX } from "@1771technologies/lytenyte-js-utils";
8
- export function ResizeHandler({ slot, cell, xPositions, style, className, }) {
8
+ export function ResizeHandler({ as, cell, xPositions, style, className, }) {
9
9
  const width = sizeFromCoord(cell.colStart, xPositions, cell.colSpan);
10
10
  const sx = useGridRoot().grid;
11
11
  const double = sx.state.columnDoubleClickToAutosize.useValue();
12
12
  const defaultProps = {
13
13
  role: "button",
14
+ "data-ln-header-resizer": "true",
14
15
  "aria-label": `Resize ${cell.column.name ?? cell.column.id}`,
15
16
  tabIndex: -1,
16
17
  onDoubleClick: () => {
@@ -56,7 +57,9 @@ export function ResizeHandler({ slot, cell, xPositions, style, className, }) {
56
57
  const id = sx.state.gridId.get();
57
58
  const query = `[data-ln-row][data-ln-gridid="${id}"] [data-ln-cell="true"][data-ln-colindex="${cell.colStart}"]`;
58
59
  const headerQuery = `[data-ln-header-row] [data-ln-header-cell="true"][data-ln-header-id="${cell.id}"]`;
60
+ const floatingQuery = `[data-ln-header-row] [data-ln-header-cell="true"][data-ln-header-id="${cell.id}"][data-ln-header-floating="true"]`;
59
61
  const header = vp.querySelector(headerQuery);
62
+ const floating = vp.querySelector(floatingQuery);
60
63
  if (!header)
61
64
  return;
62
65
  const pin = header.getAttribute("data-ln-pin");
@@ -71,6 +74,8 @@ export function ResizeHandler({ slot, cell, xPositions, style, className, }) {
71
74
  }
72
75
  const q = Array.from(vp.querySelectorAll(query));
73
76
  q.push(header);
77
+ if (floating)
78
+ q.push(floating);
74
79
  q.forEach((c) => {
75
80
  if (!isHTMLElement(c))
76
81
  return;
@@ -112,7 +117,7 @@ export function ResizeHandler({ slot, cell, xPositions, style, className, }) {
112
117
  className,
113
118
  style: {
114
119
  height: "100%",
115
- width: "8px",
120
+ width: "6px",
116
121
  ...style,
117
122
  top: "0px",
118
123
  insetInlineEnd: cell.colPin !== "end" ? "0px" : undefined,
@@ -122,7 +127,7 @@ export function ResizeHandler({ slot, cell, xPositions, style, className, }) {
122
127
  };
123
128
  const edge = useSlot({
124
129
  props: [defaultProps],
125
- slot: slot ?? _jsx("div", {}),
130
+ slot: as ?? _jsx("div", {}),
126
131
  });
127
132
  return edge;
128
133
  }
@@ -1,4 +1,4 @@
1
- import { getHoveredColumnIndex, getNearestFocusable, useDraggable, } from "@1771technologies/lytenyte-shared";
1
+ import { COLUMN_MARKER_ID, getHoveredColumnIndex, getNearestFocusable, GROUP_COLUMN_PREFIX, useDraggable, } from "@1771technologies/lytenyte-shared";
2
2
  import { useMemo, useRef } from "react";
3
3
  export function useDragMove(grid, cell, onDragStart) {
4
4
  const ctx = grid.state;
@@ -12,7 +12,9 @@ export function useDragMove(grid, cell, onDragStart) {
12
12
  return columns;
13
13
  }, [cell.colEnd, cell.colStart, meta.columnsVisible]);
14
14
  const isMovable = useMemo(() => {
15
- return columns.every((c) => c.uiHints?.movable ?? base.uiHints?.movable ?? false);
15
+ return columns.every((c) => !c.id.startsWith(GROUP_COLUMN_PREFIX) &&
16
+ c.id !== COLUMN_MARKER_ID &&
17
+ (c.uiHints?.movable ?? base.uiHints?.movable ?? false));
16
18
  }, [base.uiHints?.movable, columns]);
17
19
  const swapDirection = useRef(null);
18
20
  const swapIndex = useRef(-1);
@@ -53,6 +55,11 @@ export function useDragMove(grid, cell, onDragStart) {
53
55
  });
54
56
  if (index == null)
55
57
  return;
58
+ const columnTarget = grid.api.columnByIndex(index);
59
+ if (columnTarget) {
60
+ if (columnTarget.id === COLUMN_MARKER_ID || columnTarget.id.startsWith(GROUP_COLUMN_PREFIX))
61
+ return;
62
+ }
56
63
  const first = columns[0];
57
64
  const currentIndex = grid.api.columnIndex(first);
58
65
  const columnIndices = columns.map((c) => grid.api.columnIndex(c));
@@ -2,7 +2,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useMemo } from "react";
3
3
  import { useGridRoot } from "../context";
4
4
  function DefaultRenderer(p) {
5
- return _jsx(_Fragment, { children: p.column.id });
5
+ return _jsx(_Fragment, { children: p.column.name ?? p.column.id });
6
6
  }
7
7
  export function useHeaderCellRenderer(cell) {
8
8
  const ctx = useGridRoot().grid;
@@ -18,16 +18,16 @@ export function useHeaderCellRenderer(cell) {
18
18
  return renderer;
19
19
  }
20
20
  else {
21
- const renderer = cell.column.floatingRenderer ?? base.floatingRenderer ?? DefaultRenderer;
21
+ const renderer = cell.column.floatingCellRenderer ?? base.floatingCellRenderer ?? DefaultRenderer;
22
22
  if (typeof renderer === "string")
23
23
  return floatingRenderers[renderer] ?? DefaultRenderer;
24
24
  else
25
25
  return renderer;
26
26
  }
27
27
  }, [
28
- base.floatingRenderer,
28
+ base.floatingCellRenderer,
29
29
  base.headerRenderer,
30
- cell.column.floatingRenderer,
30
+ cell.column.floatingCellRenderer,
31
31
  cell.column.headerRenderer,
32
32
  cell.kind,
33
33
  floatingRenderers,
@@ -0,0 +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, } from "@1771technologies/lytenyte-core/icons";
@@ -0,0 +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, } from "@1771technologies/lytenyte-core/icons";
package/dist/index.d.ts CHANGED
@@ -1,6 +1,13 @@
1
+ export { GROUP_COLUMN_PREFIX, COLUMN_MARKER_ID, GROUP_COLUMN_SINGLE_ID, GROUP_COLUMN_MULTI_PREFIX, } from "@1771technologies/lytenyte-shared";
1
2
  export { Grid } from "./grid.js";
2
3
  export { SortManager } from "./sort-manager/sort-manager.js";
3
4
  export { FilterTree } from "./filter-tree/filter-tree.js";
4
5
  export { ColumnManager } from "./column-manager/column-manager.js";
5
6
  export { GridBox } from "./grid-box/grid-box.js";
7
+ export { DropWrap } from "@1771technologies/lytenyte-dragon";
6
8
  export { activateLicense } from "./license.js";
9
+ export { measureText } from "@1771technologies/lytenyte-shared";
10
+ export { makeClientDataSource, useClientRowDataSource, } from "./row-data-source-client/use-client-data-source";
11
+ export { makeClientDataSourcePaginated, useClientRowDataSourcePaginated, } from "./row-data-source-client/use-client-data-source-paginated";
12
+ export { makeClientTreeDataSource, useClientTreeDataSource, } from "./row-data-source-client/use-client-tree-data-source";
13
+ export { makeServerDataSource, useServerDataSource, } from "./row-data-source-server/use-server-data-source";
package/dist/index.js CHANGED
@@ -1,6 +1,13 @@
1
+ export { GROUP_COLUMN_PREFIX, COLUMN_MARKER_ID, GROUP_COLUMN_SINGLE_ID, GROUP_COLUMN_MULTI_PREFIX, } from "@1771technologies/lytenyte-shared";
1
2
  export { Grid } from "./grid.js";
2
3
  export { SortManager } from "./sort-manager/sort-manager.js";
3
4
  export { FilterTree } from "./filter-tree/filter-tree.js";
4
5
  export { ColumnManager } from "./column-manager/column-manager.js";
5
6
  export { GridBox } from "./grid-box/grid-box.js";
7
+ export { DropWrap } from "@1771technologies/lytenyte-dragon";
6
8
  export { activateLicense } from "./license.js";
9
+ export { measureText } from "@1771technologies/lytenyte-shared";
10
+ export { makeClientDataSource, useClientRowDataSource, } from "./row-data-source-client/use-client-data-source";
11
+ export { makeClientDataSourcePaginated, useClientRowDataSourcePaginated, } from "./row-data-source-client/use-client-data-source-paginated";
12
+ export { makeClientTreeDataSource, useClientTreeDataSource, } from "./row-data-source-client/use-client-tree-data-source";
13
+ export { makeServerDataSource, useServerDataSource, } from "./row-data-source-server/use-server-data-source";
@@ -9,6 +9,7 @@ export const Item = forwardRef(function Item(props, forwarded) {
9
9
  const prev = ctx.rtl ? "ArrowRight" : "ArrowLeft";
10
10
  if (ev.key !== next && ev.key !== prev)
11
11
  return;
12
+ ev.preventDefault();
12
13
  const items = getTabbables(ev.currentTarget);
13
14
  if (!items.length)
14
15
  return;
@@ -18,7 +19,6 @@ export const Item = forwardRef(function Item(props, forwarded) {
18
19
  const itemToFocus = items[nextIndex];
19
20
  if (!itemToFocus)
20
21
  return;
21
- ev.preventDefault();
22
22
  ev.stopPropagation();
23
23
  itemToFocus.focus();
24
24
  }, ref: forwarded, tabIndex: 0, "data-ln-listbox-item": true }));
@@ -22,7 +22,7 @@ export function computeFilteredRows(rows, grid, filterModel, filterInModel, quic
22
22
  const pass = nonIgnored.some((c) => {
23
23
  const field = `${grid.api.columnField(c, { data: row.data, kind: "leaf" })}`;
24
24
  if (sensitivity === "case-insensitive")
25
- field.toLowerCase().includes(quickSearch.toLowerCase());
25
+ return field.toLowerCase().includes(quickSearch.toLowerCase());
26
26
  return field.includes(quickSearch);
27
27
  });
28
28
  if (!pass)
@@ -1,10 +1,10 @@
1
1
  import type { GridAtom, RowDataSourceClientPaginated } from "../+types.js";
2
- import { type ClientRowDataSourceParams } from "../+types.js";
2
+ import { type ClientRowDataSourcePaginatedParams } from "../+types.js";
3
3
  interface DataAtoms<T> {
4
4
  readonly top: GridAtom<T[]>;
5
5
  readonly center: GridAtom<T[]>;
6
6
  readonly bottom: GridAtom<T[]>;
7
7
  }
8
- export declare function makeClientDataSourcePaginated<T>(p: ClientRowDataSourceParams<T>): [RowDataSourceClientPaginated<T>, DataAtoms<T>];
9
- export declare function useClientRowDataSourcePaginated<T>(p: ClientRowDataSourceParams<T>): RowDataSourceClientPaginated<T>;
8
+ export declare function makeClientDataSourcePaginated<T>(p: ClientRowDataSourcePaginatedParams<T>): [RowDataSourceClientPaginated<T>, DataAtoms<T>];
9
+ export declare function useClientRowDataSourcePaginated<T>(p: ClientRowDataSourcePaginatedParams<T>): RowDataSourceClientPaginated<T>;
10
10
  export {};
@@ -10,7 +10,7 @@ import { builtIns } from "./built-ins/built-ins.js";
10
10
  export function makeClientDataSourcePaginated(p) {
11
11
  const rdsStore = createStore();
12
12
  const pageInternal = atom(0);
13
- const rowsPerPage = atom(50);
13
+ const rowsPerPage = atom(p.rowsPerPage ?? 50);
14
14
  const pageCount = atom((g) => Math.max(Math.ceil(g(flatLength) / g(rowsPerPage)), 1));
15
15
  const page = atom((g) => clamp(0, g(pageInternal), g(pageCount) - 1), (g, s, n) => {
16
16
  const res = typeof n === "function" ? n(g(pageInternal)) : n;
@@ -19,6 +19,9 @@ export function makeClientDataSourcePaginated(p) {
19
19
  const data = atom(p.data);
20
20
  const topData = atom(p.topData ?? []);
21
21
  const bottomData = atom(p.bottomData ?? []);
22
+ const dataToSrc$ = atom((g) => {
23
+ return new Map(g(data).map((c, i) => [c, i]));
24
+ });
22
25
  const cache = new Map();
23
26
  const centerNodes = atom((g) => {
24
27
  const nodes = [];
@@ -149,6 +152,13 @@ export function makeClientDataSourcePaginated(p) {
149
152
  };
150
153
  return comparator;
151
154
  });
155
+ const idToNode = atom((g) => {
156
+ const map = new Map();
157
+ traverse(g(tree).root, (node) => {
158
+ map.set(node.id, node);
159
+ });
160
+ return map;
161
+ });
152
162
  const initialized = atom(false);
153
163
  const flat = atom((g) => {
154
164
  if (!g(initialized))
@@ -200,14 +210,27 @@ export function makeClientDataSourcePaginated(p) {
200
210
  const currentPage = rdsStore.get(pageInternal);
201
211
  const center = clamp(0, rowCount - currentPage * perPage, perPage);
202
212
  store.rowCenterCount.set(center);
203
- cleanup.push(rdsStore.sub(flatLength, () => {
204
- grid.state.rowDataStore.rowClearCache();
213
+ const updateCounts = () => {
205
214
  const rowCount = rdsStore.get(flatLength);
206
215
  const perPage = rdsStore.get(rowsPerPage);
207
216
  const currentPage = rdsStore.get(pageInternal);
208
217
  const center = clamp(0, rowCount - currentPage * perPage, perPage);
218
+ // Move to the last page if we are past the boundary
219
+ if (center === 0 && currentPage !== 0) {
220
+ const currentPage = rdsStore.get(pageCount) - 1;
221
+ rdsStore.set(page, currentPage);
222
+ rdsStore.set(snapshot, (prev) => prev + 1);
223
+ const center = clamp(0, rowCount - currentPage * perPage, perPage);
224
+ store.rowCenterCount.set(center);
225
+ grid.state.rowDataStore.rowClearCache();
226
+ return;
227
+ }
209
228
  store.rowCenterCount.set(center);
210
- }));
229
+ grid.state.rowDataStore.rowClearCache();
230
+ };
231
+ cleanup.push(rdsStore.sub(flatLength, updateCounts));
232
+ cleanup.push(rdsStore.sub(page, updateCounts));
233
+ cleanup.push(rdsStore.sub(rowsPerPage, updateCounts));
211
234
  cleanup.push(rdsStore.sub(pageInternal, () => {
212
235
  grid.state.rowDataStore.rowClearCache();
213
236
  }));
@@ -299,30 +322,32 @@ export function makeClientDataSourcePaginated(p) {
299
322
  };
300
323
  const rowUpdate = (updates) => {
301
324
  const grid = rdsStore.get(grid$);
302
- const t = rdsStore.get(tree);
303
325
  const d = rdsStore.get(data);
304
- for (const [key, data] of updates.entries()) {
305
- const rowIndex = typeof key === "number" ? key : rowToIndex(key);
306
- const row = rowByIndex(rowIndex);
307
- if (!row || !grid) {
308
- console.error(`Failed to find the row at index ${rowIndex} which is being updated.`);
326
+ const idMap = rdsStore.get(idToNode);
327
+ const dataToSrc = rdsStore.get(dataToSrc$);
328
+ for (const [key, next] of updates.entries()) {
329
+ const row = typeof key === "string" ? rowById(key) : rowByIndex(key);
330
+ const treeNode = typeof key === "string" ? idMap.get(key) : null;
331
+ if ((!row && !treeNode) || !grid) {
332
+ console.error(`Failed to find the row with identifier ${key} which is being updated.`);
309
333
  continue;
310
334
  }
311
- if (row.kind === "branch") {
312
- row.data = data;
335
+ if (row?.kind === "branch") {
336
+ row.data = next;
313
337
  }
314
338
  else {
315
- const source = t.idToSourceIndex.get(row.id);
339
+ const data = row?.kind === "leaf" ? row.data : treeNode?.data.data;
340
+ const source = dataToSrc.get(data);
316
341
  if (source == null) {
317
- console.error(`Failed to find the row at index ${rowIndex} which is being updated.`);
342
+ console.error(`Failed to find the row with identifier ${key} which is being updated.`);
318
343
  continue;
319
344
  }
320
- d[source] = data;
345
+ d[source] = next;
321
346
  }
322
- grid.state.rowDataStore.rowInvalidateIndex(rowIndex);
323
347
  }
324
348
  rdsStore.set(data, [...d]);
325
349
  rdsStore.set(snapshot, (prev) => prev + 1);
350
+ grid.state.rowDataStore.rowClearCache();
326
351
  };
327
352
  const rowToIndex = (rowId) => {
328
353
  const f = rdsStore.get(flat);
@@ -375,11 +400,10 @@ export function makeClientDataSourcePaginated(p) {
375
400
  const field = grid.api.columnField(c, row);
376
401
  return field;
377
402
  }));
378
- return [...values].map((x) => {
379
- if (!p.transformInFilterItem)
380
- return { id: `${x}`, label: `${x}`, value: x };
381
- return p.transformInFilterItem({ field: x, column: c });
382
- });
403
+ if (p.transformInFilterItem) {
404
+ return p.transformInFilterItem({ column: c, values: [...values] });
405
+ }
406
+ return [...values].map((x) => ({ id: `${x}`, label: `${x}`, value: x }));
383
407
  },
384
408
  rowAreAllSelected: (rowId) => {
385
409
  const g = rdsStore.get(grid$);
@@ -436,11 +460,29 @@ export function makeClientDataSourcePaginated(p) {
436
460
  const grid = rdsStore.get(grid$);
437
461
  grid?.state.rowDataStore.rowClearCache();
438
462
  },
463
+ rowSetCenterData: (d) => {
464
+ rdsStore.set(data, d);
465
+ const grid = rdsStore.get(grid$);
466
+ grid?.state.rowDataStore.rowClearCache();
467
+ },
439
468
  rowSetTopData: (data) => {
440
469
  rdsStore.set(topData, data);
441
470
  const grid = rdsStore.get(grid$);
442
471
  grid?.state.rowDataStore.rowClearCache();
443
472
  },
473
+ rowData: (section) => {
474
+ const d = [];
475
+ if (section === "top" || section === "flat") {
476
+ d.push(...rdsStore.get(topData));
477
+ }
478
+ if (section === "center" || section === "flat") {
479
+ d.push(...rdsStore.get(data));
480
+ }
481
+ if (section === "bottom" || section === "flat") {
482
+ d.push(...rdsStore.get(bottomData));
483
+ }
484
+ return d;
485
+ },
444
486
  rowExpand: (expansions) => {
445
487
  const grid = rdsStore.get(grid$);
446
488
  if (!grid)
@@ -527,12 +569,12 @@ export function useClientRowDataSourcePaginated(p) {
527
569
  if (p.reflectData) {
528
570
  // Need to queue the microtask since it we cannot update state during render.
529
571
  if (p.data !== da.center.get())
530
- queueMicrotask(() => da.center.set(p.data));
572
+ queueMicrotask(() => ds.current.rowSetCenterData(p.data));
531
573
  if (!equal(p.topData ?? [], da.top.get())) {
532
- queueMicrotask(() => da.top.set(p.topData ?? []));
574
+ queueMicrotask(() => ds.current.rowSetTopData(p.topData ?? []));
533
575
  }
534
576
  if (!equal(p.bottomData ?? [], da.bottom.get()))
535
- queueMicrotask(() => da.bottom.set(p.bottomData ?? []));
577
+ queueMicrotask(() => ds.current.rowSetBotData(p.bottomData ?? []));
536
578
  }
537
579
  return ds.current;
538
580
  }
@@ -14,6 +14,9 @@ export function makeClientDataSource(p) {
14
14
  const data = atom(p.data);
15
15
  const topData = atom(p.topData ?? []);
16
16
  const bottomData = atom(p.bottomData ?? []);
17
+ const dataToSrc$ = atom((g) => {
18
+ return new Map(g(data).map((c, i) => [c, i]));
19
+ });
17
20
  const cache = new Map();
18
21
  const centerNodes = atom((g) => {
19
22
  const nodes = [];
@@ -199,6 +202,13 @@ export function makeClientDataSource(p) {
199
202
  };
200
203
  return comparator;
201
204
  });
205
+ const idToNode = atom((g) => {
206
+ const map = new Map();
207
+ traverse(g(tree).root, (node) => {
208
+ map.set(node.id, node);
209
+ });
210
+ return map;
211
+ });
202
212
  const tree = atom((g) => (g(columnPivotMode) ? g(pivotTree) : g(normalTree)));
203
213
  const initialized = atom(false);
204
214
  const flatPivot = atom((g) => {
@@ -318,6 +328,7 @@ export function makeClientDataSource(p) {
318
328
  let prevPivotColumnValues = pivotModel.values;
319
329
  const updatePivotColumns = (model, ignoreEqualCheck = false) => {
320
330
  if (!ignoreEqualCheck &&
331
+ rdsStore.get(initialized) &&
321
332
  equal(prevPivotColumnModel, model.columns) &&
322
333
  equal(prevPivotColumnValues, model.values))
323
334
  return;
@@ -429,30 +440,32 @@ export function makeClientDataSource(p) {
429
440
  };
430
441
  const rowUpdate = (updates) => {
431
442
  const grid = rdsStore.get(grid$);
432
- const t = rdsStore.get(normalTree);
433
443
  const d = rdsStore.get(data);
434
- for (const [key, data] of updates.entries()) {
435
- const rowIndex = typeof key === "number" ? key : rowToIndex(key);
436
- const row = rowByIndex(rowIndex);
437
- if (!row || !grid) {
438
- console.error(`Failed to find the row at index ${rowIndex} which is being updated.`);
444
+ const idMap = rdsStore.get(idToNode);
445
+ const dataToSrc = rdsStore.get(dataToSrc$);
446
+ for (const [key, next] of updates.entries()) {
447
+ const row = typeof key === "string" ? rowById(key) : rowByIndex(key);
448
+ const treeNode = typeof key === "string" ? idMap.get(key) : null;
449
+ if ((!row && !treeNode) || !grid) {
450
+ console.error(`Failed to find the row with identifier ${key} which is being updated.`);
439
451
  continue;
440
452
  }
441
- if (row.kind === "branch") {
442
- row.data = data;
453
+ if (row?.kind === "branch") {
454
+ row.data = next;
443
455
  }
444
456
  else {
445
- const source = t.idToSourceIndex.get(row.id);
457
+ const data = row?.kind === "leaf" ? row.data : treeNode?.data.data;
458
+ const source = dataToSrc.get(data);
446
459
  if (source == null) {
447
- console.error(`Failed to find the row at index ${rowIndex} which is being updated.`);
460
+ console.error(`Failed to find the row with identifier ${key} which is being updated.`);
448
461
  continue;
449
462
  }
450
- d[source] = data;
463
+ d[source] = next;
451
464
  }
452
- grid.state.rowDataStore.rowInvalidateIndex(rowIndex);
453
465
  }
454
466
  rdsStore.set(data, [...d]);
455
467
  rdsStore.set(snapshot, (prev) => prev + 1);
468
+ grid.state.rowDataStore.rowClearCache();
456
469
  };
457
470
  const rowToIndex = (rowId) => {
458
471
  const f = rdsStore.get(flat);
@@ -500,11 +513,10 @@ export function makeClientDataSource(p) {
500
513
  const field = grid.api.columnField(c, row);
501
514
  return field;
502
515
  }));
503
- return [...values].map((x) => {
504
- if (!p.transformInFilterItem)
505
- return { id: `${x}`, label: `${x}`, value: x };
506
- return p.transformInFilterItem({ field: x, column: c });
507
- });
516
+ if (p.transformInFilterItem) {
517
+ return p.transformInFilterItem({ column: c, values: [...values] });
518
+ }
519
+ return [...values].map((x) => ({ id: `${x}`, label: `${x}`, value: x }));
508
520
  },
509
521
  rowAdd: (newRows, place = "end") => {
510
522
  rdsStore.set(data, (prev) => {
@@ -546,11 +558,29 @@ export function makeClientDataSource(p) {
546
558
  const grid = rdsStore.get(grid$);
547
559
  grid?.state.rowDataStore.rowClearCache();
548
560
  },
561
+ rowSetCenterData: (d) => {
562
+ rdsStore.set(data, d);
563
+ const grid = rdsStore.get(grid$);
564
+ grid?.state.rowDataStore.rowClearCache();
565
+ },
549
566
  rowSetTopData: (data) => {
550
567
  rdsStore.set(topData, data);
551
568
  const grid = rdsStore.get(grid$);
552
569
  grid?.state.rowDataStore.rowClearCache();
553
570
  },
571
+ rowData: (section) => {
572
+ const d = [];
573
+ if (section === "top" || section === "flat") {
574
+ d.push(...rdsStore.get(topData));
575
+ }
576
+ if (section === "center" || section === "flat") {
577
+ d.push(...rdsStore.get(data));
578
+ }
579
+ if (section === "bottom" || section === "flat") {
580
+ d.push(...rdsStore.get(bottomData));
581
+ }
582
+ return d;
583
+ },
554
584
  rowExpand: (expansions) => {
555
585
  const grid = rdsStore.get(grid$);
556
586
  if (!grid)
@@ -656,12 +686,12 @@ export function useClientRowDataSource(p) {
656
686
  if (p.reflectData) {
657
687
  // Need to queue the microtask since it we cannot update state during render.
658
688
  if (p.data !== da.center.get())
659
- queueMicrotask(() => da.center.set(p.data));
689
+ queueMicrotask(() => ds.current.rowSetCenterData(p.data));
660
690
  if (!equal(p.topData ?? [], da.top.get())) {
661
- queueMicrotask(() => da.top.set(p.topData ?? []));
691
+ queueMicrotask(() => ds.current.rowSetTopData(p.topData ?? []));
662
692
  }
663
693
  if (!equal(p.bottomData ?? [], da.bottom.get()))
664
- queueMicrotask(() => da.bottom.set(p.bottomData ?? []));
694
+ queueMicrotask(() => ds.current.rowSetBotData(p.bottomData ?? []));
665
695
  }
666
696
  return ds.current;
667
697
  }