@1771technologies/lytenyte-pro
Version:
1,456 lines (1,455 loc) • 134 kB
JavaScript
import { C as Checkbox, d as COLUMN_MARKER_ID, H as HEADER_CELL_POSITION, g as getTransform, e as COLUMN_EMPTY_PREFIX, f as HEADER_GROUP_CELL_POSITION, h as CollapseButton, F as FLOATING_CELL_POSITION, i as FULL_ENCODING, j as CellFullWidth, E as END_ENCODING, k as Cell, I as Input, G as GRID_CELL_POSITION, l as GridButton } from "./drag-store-BF4ad65L.js";
import { t, n, v, w, B, J, L, K, M, q, p, r, s, P, x, o, z, m, y, R, A } from "./drag-store-BF4ad65L.js";
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
import { Sizer } from "@1771technologies/react-sizer";
import { useEvent, useIsoEffect } from "@1771technologies/react-utils";
import { context } from "@1771technologies/grid-provider";
import * as React from "react";
import { useContext, useMemo, useEffect, useRef, useState, useCallback, memo } from "react";
import { sizeFromCoord, clsx, getClientX, IsoResizeObserver, getPreciseElementDimensions, getClientY, getFocusableElements, clamp, equal, getRelativeXPosition, getRelativeYPosition } from "@1771technologies/js-utils";
import { useDraggable, useDroppable, dragState } from "@1771technologies/react-dragon";
import { getHoveredRowIndex, getHoveredColumnIndex, getRootCell } from "@1771technologies/grid-core";
import { c as useGrid$1, u as useControlled, a as useTransitionStatus, b as useScrollLock, G as GridProvider } from "./useScrollLock-D4UY33Sb.js";
import * as ReactDOM from "react-dom";
import { createPortal } from "react-dom";
import { cascada, signal } from "@1771technologies/react-cascada";
import { M as MenuRoot, a as MenuPortal, t as translateOpenChangeReason, P as PATIENT_CLICK_THRESHOLD, C as ColumnMenuDriver } from "./column-menu-driver-cG-EZgLa.js";
import { SplitPane, splitPaneAxe } from "@1771technologies/react-split-pane";
import { A as AnchorProvider } from "./anchor-context-Cqr_oiJt.js";
import { F as FloatingPortal, P as PropTypes, H as HTMLElementType, r as refType, j as useEventCallback, n as useOpenChangeComplete, p as useFloatingRootContext, x as useRole, v as useClick, w as useDismiss, L as getTarget, A as useInteractions, m as mergeProps, q as useHover, t as safePolygon } from "./proptypes-BjYr2nFr.js";
import { u as useDialogRootContext, D as DialogPortalContext, b as useOptionalDialogRootContext, c as DialogContext, d as DialogRootContext } from "./DialogPortalContext-C2WZTqJ3.js";
import { P as PopoverRootContext, u as usePopoverRootContext, b as PopoverPortalContext } from "./PopoverPortalContext-BdsDjihw.js";
import { makeGridPro } from "@1771technologies/grid-store-pro";
import { M as MoreDotsIcon } from "./more-dots-icon-CzAH3xHG.js";
import { S as SortAscending, a as SortDescending } from "./sort-descending-BMtfaa2L.js";
import { createClientDataSource } from "@1771technologies/grid-client-data-source-pro";
import { createTreeDataSource } from "@1771technologies/grid-tree-data-source";
function useGrid() {
return useContext(context);
}
function useHeaderDisplayGridTemplate(levelsCount, headerHeight, groupHeaderHeight, floatingRowEnabled, floatingRowHeight) {
const gridTemplateRows = useMemo(() => {
const groupHeight = typeof groupHeaderHeight === "number" ? `${groupHeaderHeight}px` : "auto";
const height = typeof headerHeight === "number" ? `${headerHeight}px` : "auto";
const template = Array.from({ length: levelsCount }, () => groupHeight);
template.push(height);
if (floatingRowEnabled) {
const floatingHeight = typeof floatingRowHeight === "number" ? `${floatingRowHeight}px` : "auto";
template.push(floatingHeight);
}
return template.join(" ");
}, [floatingRowEnabled, floatingRowHeight, groupHeaderHeight, headerHeight, levelsCount]);
return gridTemplateRows;
}
function HeaderCellMarker({ api }) {
const supportsSelectedAll = api.rowSelectionSelectAllSupported();
const allSelected = api.rowSelectionAllRowsSelected();
const selected = api.getState().rowSelectionSelectedIds.use();
const someSelected = useMemo(() => {
for (const c of selected) {
if (api.rowById(c)) return true;
}
return false;
}, [api, selected]);
if (!supportsSelectedAll) return null;
return /* @__PURE__ */ jsx(
"div",
{
style: {
display: "flex",
alignItems: "center",
justifyContent: "center",
width: "100%",
height: "100%"
},
children: /* @__PURE__ */ jsx(
Checkbox,
{
tabIndex: -1,
isChecked: allSelected || someSelected,
isDeterminate: !allSelected && someSelected,
onClick: () => {
if (allSelected) api.rowSelectionClear();
else api.rowSelectionSelectAll();
}
}
)
}
);
}
function useHeaderCellRenderer(api, column) {
const sx = api.getState();
const renderers = sx.columnHeaderRenderers.use();
const base = sx.columnBase.use();
const defaultRenderer = sx.internal.columnHeaderDefaultRenderer.peek();
const Renderer = useMemo(() => {
if (column.id === COLUMN_MARKER_ID) return HeaderCellMarker;
const fn = column.headerRenderer ?? base.headerRenderer;
if (!fn) return defaultRenderer;
if (typeof fn === "string") {
const cell = renderers[fn];
if (!cell) throw new Error(`Header cell renderer with name ${fn} does not exist.`);
return cell;
}
return fn;
}, [base.headerRenderer, column.headerRenderer, column.id, defaultRenderer, renderers]);
return Renderer;
}
function useHeaderMove(api, column, columnIndex, ref) {
const gridId = api.getState().gridId.use();
const dragProps = useDraggable({
onDragStart: () => {
document.body.classList.add("lng1771-drag-on");
},
onDragEnd: () => {
document.body.classList.remove("lng1771-drag-on");
},
onDragCancel: () => {
document.body.classList.remove("lng1771-drag-on");
},
dragData: () => ({ columns: [column], columnIndex }),
dragTags: () => {
const c = [`${gridId}:grid:${column.pin ?? "none"}`];
const groupable = api.columnIsRowGroupable(column);
const isGrouped = api.getState().rowGroupModel.peek().includes(column.id);
if (groupable && !isGrouped) c.push(`${gridId}:grid:groupable`);
return c;
},
placeholder: () => /* @__PURE__ */ jsx(DragPlaceholder$1, { column })
});
const { canDrop, isOver, ...dropProps } = useDroppable({
tags: [`${gridId}:grid:${column.pin ?? "none"}`],
onDrop: (p2) => {
const data2 = p2.getData();
const dragIndex2 = data2.columnIndex;
const isBefore2 = columnIndex < dragIndex2;
const src = data2.columns.map((c) => c.id);
const target = column.id;
if (src.includes(target)) return;
if (isBefore2) api.columnMoveBefore(src, target);
else api.columnMoveAfter(src, target);
setTimeout(() => {
if (!ref.current) return;
const parent = ref.current.parentElement;
const movedEl = parent?.querySelector(
`[data-lng1771-column-id="${src[0]}"]`
);
movedEl?.focus();
}, 10);
}
});
const dragData = dragState.dragData.use();
const data = dragData?.();
const dragIndex = data?.columnIndex ?? -1;
const isBefore = columnIndex < dragIndex;
const moveProps = api.columnIsMovable(column) ? dragProps : {};
return { moveProps, dropProps, isBefore, canDrop, isOver, dragIndex };
}
function DragPlaceholder$1(c) {
return /* @__PURE__ */ jsxs("div", { className: "lng1771-header-drag-placeholder--default", children: [
/* @__PURE__ */ jsx(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
width: "20px",
height: "20px",
fill: "currentcolor",
viewBox: "0 0 256 256",
children: /* @__PURE__ */ jsx("path", { d: "M90.34,61.66a8,8,0,0,1,0-11.32l32-32a8,8,0,0,1,11.32,0l32,32a8,8,0,0,1-11.32,11.32L136,43.31V96a8,8,0,0,1-16,0V43.31L101.66,61.66A8,8,0,0,1,90.34,61.66Zm64,132.68L136,212.69V160a8,8,0,0,0-16,0v52.69l-18.34-18.35a8,8,0,0,0-11.32,11.32l32,32a8,8,0,0,0,11.32,0l32-32a8,8,0,0,0-11.32-11.32Zm83.32-72-32-32a8,8,0,0,0-11.32,11.32L212.69,120H160a8,8,0,0,0,0,16h52.69l-18.35,18.34a8,8,0,0,0,11.32,11.32l32-32A8,8,0,0,0,237.66,122.34ZM43.31,136H96a8,8,0,0,0,0-16H43.31l18.35-18.34A8,8,0,0,0,50.34,90.34l-32,32a8,8,0,0,0,0,11.32l32,32a8,8,0,0,0,11.32-11.32Z" })
}
),
/* @__PURE__ */ jsx("span", { children: c.column.headerName ?? c.column.id })
] });
}
function useHeaderFocus(api, ref, columnIndex) {
useEffect(() => {
const sx = api.getState();
const unsub = sx.internal.navigatePosition.watch(() => {
const position = sx.internal.navigatePosition.peek();
if (!ref.current || !position || position.kind !== HEADER_CELL_POSITION) return;
if (position.columnIndex === columnIndex && !ref.current.contains(document.activeElement)) {
api.navigateScrollIntoView(null, columnIndex);
ref.current.focus();
}
});
return () => unsub();
}, [api, columnIndex, ref]);
const onFocus = useEvent(() => {
api.getState().internal.navigatePosition.set({ kind: HEADER_CELL_POSITION, columnIndex });
});
return { onFocus };
}
function HeaderCell({
api,
column,
columnIndex,
viewportWidth,
rowStart,
rowEnd,
xPositions
}) {
const isStart = column.pin === "start";
const isEnd = column.pin === "end";
const rtl = api.getState().rtl.use();
const style = useMemo(() => {
const x2 = isEnd ? xPositions[columnIndex] - xPositions.at(-1) + viewportWidth : xPositions[columnIndex];
const width = sizeFromCoord(columnIndex, xPositions);
const style2 = {
transform: getTransform(x2 * (rtl ? -1 : 1), 0),
gridRowStart: rowStart,
gridRowEnd: rowEnd,
width
};
if (isStart || isEnd) {
style2.insetInlineStart = "0px";
style2.position = "sticky";
style2.zIndex = 2;
}
return style2;
}, [columnIndex, isEnd, isStart, rowEnd, rowStart, rtl, viewportWidth, xPositions]);
const Renderer = useHeaderCellRenderer(api, column);
const ref = useRef(null);
const { moveProps, dropProps, isBefore, isOver, canDrop, dragIndex } = useHeaderMove(
api,
column,
columnIndex,
ref
);
const sx = api.getState();
sx.sortModel.use();
const events = useHeaderFocus(api, ref, columnIndex);
if (api.columnIsEmpty(column)) {
return /* @__PURE__ */ jsx(
"button",
{
...events,
ref,
onClick: () => {
const id = column.id.replace(COLUMN_EMPTY_PREFIX, "").split("|>").slice(0, -1);
api.columnGroupToggle(id.join(api.getState().columnGroupIdDelimiter.peek()));
},
style,
className: "lng1771-header__cell-expand",
children: "+"
}
);
}
const sortDir = api.columnSortDirection(column);
return /* @__PURE__ */ jsx(
"div",
{
style,
ref,
role: "columnheader",
"data-lng1771-column-id": column.id,
"data-lng1771-kind": "header",
"aria-colindex": columnIndex + 1,
"aria-colspan": 1,
"aria-sort": sortDir === "asc" ? "ascending" : sortDir === "desc" ? "descending" : "none",
tabIndex: -1,
...moveProps,
...dropProps,
...events,
className: clsx(
"lng1771-header__cell",
isOver && columnIndex !== dragIndex && "lng1771-header__cell--over",
isOver && isBefore && "lng1771-header__cell--over-before",
isOver && !isBefore && "lng1771-header__cell--over-after",
isOver && !canDrop && "lng1771-header__cell--over-not-allowed"
),
children: /* @__PURE__ */ jsx(Renderer, { api, column })
}
);
}
function useHeaderCells(api) {
const sx = api.getState();
const visibleColumns = sx.columnsVisible.use();
const xPositions = sx.columnPositions.use();
const bounds = sx.internal.virtBounds.use();
const hierarchy = sx.columnGroupLevels.use();
const startCount = sx.columnVisibleStartCount.use();
const centerCount = sx.columnVisibleCenterCount.use();
const endCount = sx.columnVisibleEndCount.use();
const viewportWidth = sx.internal.viewportInnerWidth.use();
return useMemo(() => {
const cells = [];
const columnRowCount = hierarchy.length + 1;
function handleCell(i) {
const column = visibleColumns[i];
let rowStart = columnRowCount;
let level = columnRowCount - 2;
while (hierarchy[level]?.[i] === null) {
rowStart--;
level--;
}
cells.push(
/* @__PURE__ */ jsx(
HeaderCell,
{
api,
column,
columnIndex: i,
viewportWidth,
xPositions,
rowStart,
rowEnd: columnRowCount + 1,
startCount,
centerCount,
endCount
},
column.id
)
);
}
for (let i = 0; i < startCount; i++) {
handleCell(i);
}
for (let i = bounds.columnStart; i < bounds.columnEnd; i++) {
handleCell(i);
}
const first = startCount + centerCount;
for (let i = first; i < visibleColumns.length; i++) {
handleCell(i);
}
return cells;
}, [
api,
bounds.columnEnd,
bounds.columnStart,
centerCount,
endCount,
hierarchy,
startCount,
viewportWidth,
visibleColumns,
xPositions
]);
}
function useResizeDivider(api, column) {
const isResizable = api.columnIsResizable(column);
const [active, setActive] = useState(false);
const resizeProps = useMemo(() => {
if (!isResizable) return {};
const onPointerDown = (e) => {
if (e.pointerType === "mouse" && e.button !== 0) return;
const startWidth = api.columnVisualWidth(column);
const isRtl = api.getState().rtl.peek();
let startX = null;
let anim = null;
let delta = 0;
e.preventDefault();
e.stopPropagation();
document.body.classList.add("lng1771-column-resize-active");
setActive(true);
const controller = new AbortController();
document.addEventListener(
"pointermove",
(ev) => {
if (startX === null) {
startX = getClientX(ev);
return;
}
const endAdjust = column.pin === "end" ? -1 : 1;
const rtlAdjust = isRtl ? -1 : 1;
delta = (getClientX(ev) - startX) * endAdjust * rtlAdjust;
if (anim) cancelAnimationFrame(anim);
anim = requestAnimationFrame(() => {
api.getState().internal.columnWidthDeltas.set({ [column.id]: delta });
});
},
{ signal: controller.signal }
);
window.addEventListener(
"pointerup",
() => {
if (anim) cancelAnimationFrame(anim);
setActive(false);
document.body.classList.remove("lng1771-column-resize-active");
const newWidth = startWidth + delta;
api.columnResize(column, newWidth);
api.getState().internal.columnWidthDeltas.set(null);
controller.abort();
},
{ signal: controller.signal }
);
};
return { onPointerDown };
}, [api, column, isResizable]);
return { ...resizeProps, active };
}
function HeaderDivider({
api,
columnIndex,
xPositions,
viewportWidth,
rowStart,
rowEnd,
column,
startCount,
centerCount,
endCount
}) {
const isResizable = api.columnIsResizable(column);
const isLastStart = startCount > 0 && columnIndex === startCount - 1;
const isFirstEnd = endCount > 0 && startCount + centerCount === columnIndex;
const isLast = startCount + centerCount + endCount - 1 === columnIndex;
const { onPointerDown, active: resizeActive } = useResizeDivider(api, column);
const rtl = api.getState().rtl.use();
const style = useMemo(() => {
const isStart = column.pin === "start";
const isEnd = column.pin == "end";
const endAdjustment = centerCount + startCount - 1 === columnIndex && endCount > 0 ? 2 : 0;
const x2 = isEnd ? xPositions[columnIndex] - xPositions.at(-1) + viewportWidth - 2 : xPositions[columnIndex] + sizeFromCoord(columnIndex, xPositions) - 3 - endAdjustment;
const xAdjustment = isLastStart ? 1 : isFirstEnd ? 0 : isLast ? 1 : 0;
const style2 = {
transform: getTransform((x2 - xAdjustment) * (rtl ? -1 : 1), 0),
gridRowStart: rowStart,
gridRowEnd: rowEnd
};
if (isStart || isEnd) {
style2.insetInlineStart = "0px";
style2.position = "sticky";
style2.zIndex = 2;
}
if (isLast && !isResizable) style2.opacity = 0;
return style2;
}, [
centerCount,
column.pin,
columnIndex,
endCount,
isFirstEnd,
isLast,
isLastStart,
isResizable,
rowEnd,
rowStart,
rtl,
startCount,
viewportWidth,
xPositions
]);
return /* @__PURE__ */ jsx(
"div",
{
onPointerDown,
"data-resize-active": resizeActive,
onDoubleClick: () => {
const autosize = api.getState().autosizeDoubleClickHeader.peek();
if (autosize) api.autosizeColumn(column, { includeHeader: true });
},
className: clsx(
"lng1771-header__cell-divider",
isResizable && "lng1771-header__cell-divider--resizable"
),
style,
children: /* @__PURE__ */ jsx("div", {})
}
);
}
function useHeaderDividers(api) {
const sx = api.getState();
const xPositions = sx.columnPositions.use();
const hierarchy = sx.columnGroupLevels.use();
const viewportWidth = sx.internal.viewportInnerWidth.use();
const bounds = sx.internal.virtBounds.use();
const startCount = sx.columnVisibleStartCount.use();
const centerCount = sx.columnVisibleCenterCount.use();
const endCount = sx.columnVisibleEndCount.use();
const columns = sx.columnsVisible.use();
return useMemo(() => {
const firstEndIndex = xPositions.length - 1 - endCount;
const columnRowCount = hierarchy.length + 1;
const dividers = [];
const indices = Array.from(
{ length: bounds.columnEnd - bounds.columnStart },
(_, i) => i + bounds.columnStart
);
for (let i = startCount - 1; i >= 0; i--) indices.unshift(i);
const first = startCount + centerCount;
for (let j = first; j < centerCount + startCount + endCount; j++) indices.push(j);
for (let i = 0; i < indices.length - endCount; i++) {
const columnIndex = indices[i];
const rowStart = getRowStart(hierarchy, startCount, firstEndIndex, columnIndex);
const column = columns[columnIndex];
dividers.push(
/* @__PURE__ */ jsx(
HeaderDivider,
{
api,
column,
xPositions,
viewportWidth,
rowStart,
rowEnd: columnRowCount + 1,
columnIndex,
startCount,
centerCount,
endCount
},
column.id
)
);
}
for (let i = indices.length - endCount; i < indices.length; i++) {
const columnIndex = indices[i];
const rowStart = getRowStart(hierarchy, startCount, firstEndIndex, columnIndex);
const column = columns[columnIndex];
dividers.push(
/* @__PURE__ */ jsx(
HeaderDivider,
{
api,
column,
xPositions,
viewportWidth,
rowStart,
rowEnd: columnRowCount + 1,
columnIndex,
startCount,
centerCount,
endCount
},
column.id
)
);
}
return dividers;
}, [
api,
bounds.columnEnd,
bounds.columnStart,
centerCount,
columns,
endCount,
hierarchy,
startCount,
viewportWidth,
xPositions
]);
}
function isPartOfGroup(columnIndex, hierarchy) {
if (!hierarchy.length) return false;
return hierarchy.length > 0 && hierarchy[0][columnIndex] != null;
}
function getRowStart(hierarchy, startCount, firstEndIndex, columnIndex) {
const isFirstEndIndex = columnIndex === firstEndIndex;
const isLastStartIndex = columnIndex === startCount - 1 && startCount > 0;
const hasGroup = isPartOfGroup(columnIndex, hierarchy);
if (isFirstEndIndex || isLastStartIndex || !hasGroup) return 1;
let level = 0;
while (level < hierarchy.length && hierarchy[level][columnIndex] != null) {
level++;
}
while (hierarchy[level - 1]?.[columnIndex] && hierarchy[level - 1][columnIndex].end - 1 === columnIndex) {
level--;
}
return level + 1;
}
function useHeaderGroupMove(api, item, pin) {
const sx = api.getState();
const gridId = sx.gridId.use();
const visible = sx.columnsVisible.use();
const columns = useMemo(() => {
return visible.slice(item.start, item.end);
}, [item.end, item.start, visible]);
const move = useDraggable({
dragTags: () => [`${gridId}:grid:${pin ?? "none"}`],
dragData: () => ({ columns, columnIndex: item.start }),
placeholder: () => /* @__PURE__ */ jsx(
DragPlaceholder,
{
cnt: item.end - item.start,
label: item.id.split(sx.columnGroupIdDelimiter.peek()).at(-1)
}
)
});
const isMovable = columns.every((c) => api.columnIsMovable(c));
return { moveProps: isMovable ? move : {} };
}
function DragPlaceholder(c) {
return /* @__PURE__ */ jsxs("div", { className: "lng1771-drag-placeholder", children: [
c.label,
" | moving ",
c.cnt,
" columns"
] });
}
function HeaderGroupCell({
api,
groupItem,
pin,
viewportWidth,
rowStart,
xPositions
}) {
const rtl = api.getState().rtl.use();
const style = useMemo(() => {
const isStart = pin === "start";
const isEnd = pin == "end";
const width = sizeFromCoord(groupItem.start, xPositions, groupItem.end - groupItem.start);
const columnIndex = groupItem.start;
const x2 = isEnd ? xPositions[columnIndex] - xPositions.at(-1) + viewportWidth : xPositions[columnIndex];
const style2 = {
transform: getTransform(x2 * (rtl ? -1 : 1), 0),
gridRowStart: rowStart,
gridRowEnd: rowStart + 1,
width
};
if (isStart || isEnd) {
style2.insetInlineStart = "0px";
style2.position = "sticky";
style2.zIndex = 2;
}
return style2;
}, [groupItem.end, groupItem.start, pin, rowStart, rtl, viewportWidth, xPositions]);
const headerMove = useHeaderGroupMove(api, groupItem, pin);
const ref = useRef(null);
const skipRef = useRef(false);
useEffect(() => {
const sx = api.getState();
const position = sx.internal.navigatePosition;
const unsub = position.watch(() => {
const pos = position.peek();
if (!pos || !ref.current || pos.kind !== HEADER_GROUP_CELL_POSITION) return;
if (groupItem.start === pos.columnStartIndex && groupItem.end === pos.columnEndIndex && pos.hierarchyRowIndex === rowStart - 1 && !ref.current.contains(document.activeElement) && ref.current !== document.activeElement) {
api.navigateScrollIntoView(null, pos.columnIndex);
skipRef.current = true;
ref.current.focus();
}
});
return () => unsub();
}, [api, groupItem.end, groupItem.start, rowStart]);
const onFocus = useEvent(() => {
if (skipRef.current) {
skipRef.current = false;
return;
}
api.getState().internal.navigatePosition.set({
kind: HEADER_GROUP_CELL_POSITION,
columnStartIndex: groupItem.start,
columnEndIndex: groupItem.end,
columnIndex: groupItem.start,
hierarchyRowIndex: rowStart - 1
});
});
const Renderer = api.getState().columnGroupHeaderRenderer.use() ?? HeaderGroupDefault;
return /* @__PURE__ */ jsx(
"div",
{
ref,
onFocus,
style,
"data-lng1771-group-id": groupItem.id,
"data-lng1771-kind": "header-group",
"aria-colindex": groupItem.start + 1,
"aria-colspan": groupItem.end - groupItem.start,
role: "columnheader",
tabIndex: -1,
...headerMove.moveProps,
className: "lng1771-header__group",
children: /* @__PURE__ */ jsx(Renderer, { group: groupItem, api })
}
);
}
function HeaderGroupDefault({ group, api }) {
const label = useMemo(() => {
const delimiter = api.getState().columnGroupIdDelimiter.peek();
return group.id.split(delimiter).at(-1);
}, [api, group.id]);
return /* @__PURE__ */ jsxs(
"div",
{
style: {
width: "100%",
height: "100%",
display: "flex",
alignItems: "center",
boxSizing: "border-box",
justifyContent: "space-between",
paddingInline: 12
},
children: [
label,
group.isCollapsible && /* @__PURE__ */ jsx(CollapseButton, { onClick: () => api.columnGroupToggle(group.id), children: "-" })
]
}
);
}
function useHeaderGroupCells(api) {
const sx = api.getState();
const bounds = sx.internal.virtBounds.use();
const hierarchy = sx.columnGroupLevels.use();
const xPositions = sx.columnPositions.use();
const startCount = sx.columnVisibleStartCount.use();
const centerCount = sx.columnVisibleCenterCount.use();
const endCount = sx.columnVisibleEndCount.use();
const viewportWidth = sx.internal.viewportInnerWidth.use();
return useMemo(() => {
const cells = [];
function handleCell(groupItem, levelIndex, pin) {
cells.push(
/* @__PURE__ */ jsx(
HeaderGroupCell,
{
api,
groupItem,
pin,
rowStart: levelIndex + 1,
viewportWidth,
centerCount,
startCount,
endCount,
xPositions
},
groupItem.occurrenceKey
)
);
}
for (let level = 0; level < hierarchy.length; level++) {
const processedIndices = /* @__PURE__ */ new Set();
const row = hierarchy[level];
for (let i = 0; i < startCount; i++) {
const groupItem = row[i];
if (!groupItem) continue;
if (!processedIndices.has(i)) handleCell(groupItem, level, "start");
for (let j = groupItem.start; j < groupItem.end; j++) processedIndices.add(j);
}
for (let i = bounds.columnStart; i < bounds.columnEnd; i++) {
const groupItem = row[i];
if (!groupItem) continue;
if (!processedIndices.has(i)) handleCell(groupItem, level, null);
for (let j = groupItem.start; j < groupItem.end; j++) processedIndices.add(j);
}
const first = startCount + centerCount;
for (let i = first; i < row.length; i++) {
const groupItem = row[i];
if (!groupItem) continue;
if (!processedIndices.has(i)) handleCell(groupItem, level, "end");
for (let j = groupItem.start; j < groupItem.end; j++) processedIndices.add(j);
}
}
return cells;
}, [
api,
bounds.columnEnd,
bounds.columnStart,
centerCount,
endCount,
hierarchy,
startCount,
viewportWidth,
xPositions
]);
}
function useFloatingFocus(api, ref, columnIndex) {
useEffect(() => {
const sx = api.getState();
const unsub = sx.internal.navigatePosition.watch(() => {
const position = sx.internal.navigatePosition.peek();
if (!ref.current || !position || position.kind !== FLOATING_CELL_POSITION) return;
if (position.columnIndex === columnIndex && !ref.current.contains(document.activeElement)) {
api.navigateScrollIntoView(null, columnIndex);
ref.current.focus();
}
});
return () => unsub();
}, [api, columnIndex, ref]);
const onFocus = useEvent(() => {
api.getState().internal.navigatePosition.set({ kind: FLOATING_CELL_POSITION, columnIndex });
});
return { onFocus };
}
function FloatingCell({
api,
viewportWidth,
column,
xPositions,
columnIndex,
rowStart,
startCount
}) {
const isStart = column.pin === "start";
const isEnd = column.pin === "end";
const isLastStart = columnIndex === startCount - 1;
const rtl = api.getState().rtl.use();
const style = useMemo(() => {
const x2 = isEnd ? xPositions[columnIndex] - xPositions.at(-1) + viewportWidth : xPositions[columnIndex];
const width = sizeFromCoord(columnIndex, xPositions);
const style2 = {
transform: getTransform(x2 * (rtl ? -1 : 1), 0),
gridRowStart: rowStart,
gridRowEnd: rowStart + 1,
width
};
if (isStart || isEnd) {
style2.insetInlineStart = "0px";
style2.position = "sticky";
style2.zIndex = 2;
}
return style2;
}, [columnIndex, isEnd, isStart, rowStart, rtl, viewportWidth, xPositions]);
const sx = api.getState();
const base = sx.columnBase.use();
const rendererKey = column.floatingCellRenderer ?? base.floatingCellRenderer;
const renderers = sx.floatingCellRenderers.use();
const Component = useMemo(() => {
if (typeof rendererKey === "string") {
if (renderers[rendererKey])
throw new Error(`Failed to find floating renderer: ${rendererKey}`);
return renderers[rendererKey];
}
if (!rendererKey) return () => /* @__PURE__ */ jsx(Fragment, {});
return rendererKey;
}, [rendererKey, renderers]);
const ref = useRef(null);
const events = useFloatingFocus(api, ref, columnIndex);
const hide = api.columnIsGridGenerated(column) && !api.columnIsGroupAutoColumn(column);
return /* @__PURE__ */ jsx(
"div",
{
ref,
style,
...events,
role: "columnheader",
"data-lng1771-kind": "floating",
"data-lng1771-pin": column.pin ?? "center",
"data-lng1771-last-start": isLastStart ? true : void 0,
"data-lng1771-column-id": column.id,
"aria-colindex": columnIndex,
"aria-colspan": 1,
tabIndex: -1,
className: "lng1771-header__cell-floating",
children: !hide && /* @__PURE__ */ jsx(Component, { api, column })
}
);
}
function useFloatingCells(api, enabled) {
const sx = api.getState();
const visibleColumns = sx.columnsVisible.use();
const xPositions = sx.columnPositions.use();
const bounds = sx.internal.virtBounds.use();
const hierarchy = sx.columnGroupLevels.use();
const startCount = sx.columnVisibleStartCount.use();
const centerCount = sx.columnVisibleCenterCount.use();
const endCount = sx.columnVisibleEndCount.use();
const viewportWidth = sx.internal.viewportInnerWidth.use();
return useMemo(() => {
if (!enabled) return [];
const cells = [];
const columnRowCount = hierarchy.length + 1;
function handleCell(i) {
const column = visibleColumns[i];
const rowStart = columnRowCount + 1;
cells.push(
/* @__PURE__ */ jsx(
FloatingCell,
{
api,
column,
columnIndex: i,
viewportWidth,
xPositions,
rowStart,
startCount,
centerCount,
endCount
},
column.id
)
);
}
for (let i = 0; i < startCount; i++) {
handleCell(i);
}
for (let i = bounds.columnStart; i < bounds.columnEnd; i++) {
handleCell(i);
}
const first = startCount + centerCount;
for (let i = first; i < visibleColumns.length; i++) {
handleCell(i);
}
return cells;
}, [
api,
bounds.columnEnd,
bounds.columnStart,
centerCount,
enabled,
endCount,
hierarchy.length,
startCount,
viewportWidth,
visibleColumns,
xPositions
]);
}
function Header() {
const { state, api } = useGrid();
const columnHeaderHeight = state.columnHeaderHeight.use();
const columnGroupHeaderHeight = state.columnGroupHeaderHeight.use();
const floatingRowHeight = state.floatingRowHeight.use();
const floatingRowEnabled = state.floatingRowEnabled.use();
const hierarchy = state.columnGroupLevels.use();
const headerGroupCells = useHeaderGroupCells(api);
const headerCells = useHeaderCells(api);
const headerDividers = useHeaderDividers(api);
const floatingCells = useFloatingCells(api, floatingRowEnabled);
const gridTemplateRows = useHeaderDisplayGridTemplate(
hierarchy.length,
columnHeaderHeight,
columnGroupHeaderHeight,
floatingRowEnabled,
floatingRowHeight
);
const headerHeightSetting = state.internal.viewportHeaderHeight.use();
const headerHeight = useMemo(() => {
return `${headerHeightSetting - (floatingRowEnabled ? floatingRowHeight : 0)}px`;
}, [floatingRowEnabled, floatingRowHeight, headerHeightSetting]);
return /* @__PURE__ */ jsxs(
"div",
{
role: "row",
className: "lng1771-header",
style: { gridTemplateRows, "--lng1771-header-height": headerHeight },
children: [
headerGroupCells,
headerCells,
headerDividers,
floatingCells
]
}
);
}
function HeaderContainer({ style }) {
const { state } = useGrid();
const [header, setHeader] = useState(null);
useIsoEffect(() => {
if (!header) return;
const resize = new IsoResizeObserver(() => {
if (!header) return;
const prec = getPreciseElementDimensions(header);
state.internal.viewportHeaderHeight.set(prec.outerHeight);
});
resize.observe(header);
return () => resize.disconnect();
}, [header]);
return /* @__PURE__ */ jsx("div", { ref: setHeader, className: "lng1771-header-container", style, children: /* @__PURE__ */ jsx(Header, {}) });
}
function RowDetail({ api, row, rowPin, yPositions, rowIndex, height }) {
const sx = api.getState();
const width = sx.internal.viewportInnerWidth.use();
const Renderer = sx.rowDetailRenderer.use() ?? RowDetailDefault;
const style = useMemo(() => {
const isTop = rowPin === "top";
const isBot = rowPin === "bottom";
const rowCount = sx.internal.rowCount.peek();
const rowTopCount = sx.internal.rowTopCount.peek();
const rowBotCount = sx.internal.rowBottomCount.peek();
const firstBotIndex = rowCount - rowBotCount;
const offset = sizeFromCoord(rowIndex, yPositions) - height;
const y2 = isBot ? yPositions[rowIndex] - yPositions[firstBotIndex] : isTop ? yPositions[rowIndex] : yPositions[rowIndex] - yPositions[rowTopCount];
const transform = getTransform(0, y2 + offset);
return { width, height, transform };
}, [
height,
rowIndex,
rowPin,
sx.internal.rowBottomCount,
sx.internal.rowCount,
sx.internal.rowTopCount,
width,
yPositions
]);
return /* @__PURE__ */ jsx("div", { style, className: "lng1771-row-detail", children: /* @__PURE__ */ jsx(Renderer, { api, row }) });
}
function RowDetailDefault() {
return /* @__PURE__ */ jsx("div", { children: "Not Implemented" });
}
function RowDragIndicator({ section }) {
const { state } = useGrid();
const rowIndex = state.internal.rowDragOverIndex.use();
const dragIndex = state.internal.rowDragStartIndex.use();
const yPositions = state.internal.rowPositions.use();
const width = state.internal.viewportInnerWidth.use();
const topCount = state.internal.rowTopCount.use();
const bottomCount = state.internal.rowBottomCount.use();
const rowCount = state.internal.rowCount.use();
const isBefore = rowIndex < dragIndex;
if (rowIndex === -1 || rowIndex == null) return null;
if (section === "top" && rowIndex > topCount) return null;
if (section === "center" && rowIndex < topCount || rowIndex >= rowCount - bottomCount)
return null;
if (section === "bottom" && rowIndex < rowCount - bottomCount) return null;
const firstBotIndex = rowCount - bottomCount;
const height = sizeFromCoord(rowIndex, yPositions);
const y2 = section === "bottom" ? yPositions[rowIndex] - yPositions[firstBotIndex] : section === "top" ? yPositions[rowIndex] : yPositions[rowIndex] - yPositions[topCount];
return /* @__PURE__ */ jsx(
"div",
{
style: { transform: getTransform(0, y2 + (isBefore ? 0 : height)), width },
className: "lng1771-row-drag-indicator"
}
);
}
function Rows({
width,
...els
}) {
const { state, api } = useGrid();
const layout = state.internal.virtLayout.use();
const xPositions = state.columnPositions.use();
const yPositions = state.internal.rowPositions.use();
const columns = state.columnsVisible.use();
const refreshKey = state.internal.rowRefreshCount.use();
const headerHeight = state.internal.viewportHeaderHeight.use();
const rowCount = state.internal.rowCount.use();
const topCount = state.internal.rowTopCount.use();
const botCount = state.internal.rowBottomCount.use();
const topHeight = yPositions[topCount];
const botHeight = yPositions.at(-1) - yPositions[rowCount - botCount];
const detailHeight = state.internal.rowDetailHeight.use();
const [fullWidthCache, cellCache] = useMemo(() => {
return [{}, {}];
}, [botCount, columns, headerHeight, refreshKey, rowCount, topCount, xPositions, yPositions]);
const firstBotIndex = rowCount - botCount;
const paginate = state.paginate.use();
const currentPage = state.paginateCurrentPage.use();
const [top, center, bottom] = useMemo(() => {
const top2 = [];
const center2 = [];
const bottom2 = [];
let paginateOffset = 0;
if (paginate) {
const [rowStart] = api.paginateRowStartAndEndForPage(currentPage);
paginateOffset = yPositions[rowStart];
}
for (const [rowIndex, cells] of layout) {
if (rowIndex >= rowCount) continue;
const isTop = rowIndex < topCount;
const isBot = rowIndex >= firstBotIndex;
const isCenter = !isTop && !isBot;
const place = isCenter ? center2 : isTop ? top2 : bottom2;
const row = api.rowByIndex(rowIndex);
if (!row) continue;
let i = 0;
while (i < cells.length) {
const encoding = cells[i];
if (encoding === FULL_ENCODING) {
fullWidthCache[rowIndex] ??= /* @__PURE__ */ jsx(
CellFullWidth,
{
api,
row,
colCount: columns.length,
rowPin: rowIndex < topCount ? "top" : rowIndex >= firstBotIndex ? "bottom" : null,
rowIndex,
yPositions,
paginateOffset
},
`${rowIndex}-full`
);
place.push(fullWidthCache[rowIndex]);
i++;
} else if (encoding === END_ENCODING) {
break;
} else {
const rowIndex2 = cells[i++];
const rowSpan = cells[i++];
const colIndex = cells[i++];
const colSpan = cells[i++];
cellCache[rowIndex2] ??= {};
cellCache[rowIndex2][colIndex] = /* @__PURE__ */ jsx(
Cell,
{
api,
column: columns[colIndex],
rowIndex: rowIndex2,
rowSpan,
colSpan,
rowPin: rowIndex2 < topCount ? "top" : rowIndex2 >= firstBotIndex ? "bottom" : null,
rowNode: row,
columnIndex: colIndex,
yPositions,
xPositions,
paginateOffset
},
`r${rowIndex2}-c${colIndex}`
);
place.push(cellCache[rowIndex2][colIndex]);
}
}
const rowDetailHeight = detailHeight(rowIndex);
if (rowDetailHeight > 0) {
place.push(
/* @__PURE__ */ jsx(
RowDetail,
{
api,
height: rowDetailHeight,
row,
rowPin: rowIndex < topCount ? "top" : rowIndex >= firstBotIndex ? "bottom" : null,
rowIndex,
yPositions
}
)
);
}
}
return [top2, center2, bottom2];
}, [
api,
cellCache,
columns,
currentPage,
detailHeight,
firstBotIndex,
fullWidthCache,
layout,
paginate,
rowCount,
topCount,
xPositions,
yPositions
]);
const viewportWidth = state.internal.viewportInnerWidth.use();
const endCount = state.columnVisibleEndCount.use();
const minWidth = Math.max(endCount > 0 ? viewportWidth : 0, width);
return /* @__PURE__ */ jsxs(Fragment, { children: [
topHeight > 0 && /* @__PURE__ */ jsxs(
"div",
{
style: {
width,
minWidth,
top: headerHeight,
height: topHeight,
minHeight: topHeight,
maxHeight: topHeight
},
className: "lng1771-rows__top-section",
children: [
top,
/* @__PURE__ */ jsx(RowDragIndicator, { section: "top" }),
/* @__PURE__ */ jsx(els.top, {})
]
}
),
/* @__PURE__ */ jsxs(
"div",
{
style: {
width,
minWidth
},
className: "lng1771-rows__center-section",
children: [
center,
/* @__PURE__ */ jsx(RowDragIndicator, { section: "center" }),
/* @__PURE__ */ jsx(els.center, {})
]
}
),
botHeight > 0 && /* @__PURE__ */ jsxs(
"div",
{
style: {
bottom: 0,
width,
minWidth,
height: botHeight,
minHeight: botHeight,
maxHeight: botHeight
},
className: "lng1771-rows__bottom-section",
children: [
bottom,
/* @__PURE__ */ jsx(RowDragIndicator, { section: "bottom" }),
/* @__PURE__ */ jsx(els.bottom, {})
]
}
)
] });
}
function RowContainer({
totalHeight,
totalWidth,
children
}) {
const { api, state } = useGrid();
const gridId = state.gridId.use();
const { onDragOver, onDrop } = useDroppable({
tags: [`${gridId}:row-drag`],
onDrop: (p2) => {
const overIndex = state.internal.rowDragOverIndex.peek();
const data = p2.getData();
if (!data?.rows || !data?.api) return;
const isExternal = data.api !== api;
const additional = isExternal ? { externalGridApi: data.api, isExternal: true } : {};
api.eventFire("onRowDragDrop", {
api,
event: p2.event,
overIndex,
rows: data.rows,
...additional
});
}
});
const columns = state.columnsVisible.use();
if (columns.length === 0) return /* @__PURE__ */ jsx(Fragment, {});
return /* @__PURE__ */ jsx(
"div",
{
style: { width: totalWidth, minHeight: totalHeight },
onDrop,
onDragOver,
className: "lng1771-row-container",
children
}
);
}
function NavigationDriver() {
const { state, api } = useGrid();
const viewport = state.internal.viewport.use();
const rtl = state.rtl.use();
useEffect(() => {
if (!viewport) return;
const controller = new AbortController();
viewport.addEventListener(
"keydown",
(ev) => {
const key = ev.key;
const startDir = rtl ? "ArrowRight" : "ArrowLeft";
const endDir = rtl ? "ArrowLeft" : "ArrowRight";
const position = state.internal.navigatePosition.peek();
const activeEdit = state.internal.cellEditActiveLocation.peek();
if (activeEdit || ev.shiftKey) return;
if (document.activeElement === viewport && (key === "ArrowDown" || key === endDir)) {
if (state.columnsVisible.peek().length) {
state.internal.navigatePosition.set({ kind: HEADER_CELL_POSITION, columnIndex: 0 });
}
ev.preventDefault();
ev.stopPropagation();
}
if (!position) return;
let handled = false;
const meta = ev.ctrlKey || ev.metaKey;
if (key === "PageUp") {
api.navigatePageUp();
handled = true;
} else if (key === "PageDown") {
api.navigatePageDown();
handled = true;
} else if (key === "Home") {
api.navigateToTop();
handled = true;
} else if (key === "End") {
api.navigateToBottom();
handled = true;
} else if (key === "ArrowUp") {
if (meta) {
api.navigateToTop();
} else {
api.navigateUp();
}
handled = true;
} else if (key === "ArrowDown") {
if (meta) {
api.navigateToBottom();
} else {
api.navigateDown();
}
handled = true;
} else if (key === startDir) {
if (meta) {
api.navigateToStart();
} else {
api.navigatePrev();
}
handled = true;
} else if (key === endDir) {
if (meta) {
api.navigateToEnd();
} else {
api.navigateNext();
}
handled = true;
}
if (handled) {
ev.preventDefault();
ev.stopPropagation();
}
},
{ signal: controller.signal }
);
const unsub = state.internal.navigatePosition.watch(() => {
const position = state.internal.navigatePosition.peek();
if (!position) return;
const rowIndex = "rowIndex" in position ? position.rowIndex : null;
const columnIndex = position.columnIndex;
api.navigateScrollIntoView(rowIndex, columnIndex);
});
viewport.addEventListener(
"focusout",
() => {
setTimeout(() => {
if (viewport.contains(document.activeElement)) {
return;
}
api.getState().internal.navigatePosition.set(null);
}, 100);
},
{ signal: controller.signal }
);
return () => {
controller.abort();
unsub();
};
}, [
api,
rtl,
state.columnsVisible,
state.internal.cellEditActiveLocation,
state.internal.navigatePosition,
viewport
]);
return /* @__PURE__ */ jsx(Fragment, {});
}
function cellEditLocation(c) {
return `r${c.rowIndex}-c${c.columnIndex}`;
}
function handleBeginCellEditFromEvent(api, event) {
if (event.button !== 0) return;
const clientY = getClientY(event);
const clientX = getClientX(event);
const rowIndex = getHoveredRowIndex(api, clientY);
const columnIndex = getHoveredColumnIndex(api, clientX);
if (rowIndex == null || columnIndex == null) return;
const sx = api.getState();
const active = sx.internal.cellEditActiveEdits.peek();
const l = { rowIndex, columnIndex };
const key = cellEditLocation(l);
if (active.has(key)) return;
api.cellEditBegin(l, true);
}
function CellEditDriver() {
const { state, api } = useGrid();
const viewport = state.internal.viewport.use();
const cellEditActivator = state.cellEditPointerActivator.use();
useEffect(() => {
if (!viewport) return;
const controller = new AbortController();
const signal2 = controller.signal;
if (cellEditActivator === "single-click") {
viewport.addEventListener("pointerdown", (ev) => handleBeginCellEditFromEvent(api, ev), {
signal: signal2
});
}
if (cellEditActivator === "double-click") {
viewport.addEventListener(
"dblclick",
(ev) => {
if (state.internal.cellEditActiveEdits.peek().size > 0) return;
handleBeginCellEditFromEvent(api, ev);
},
{ signal: signal2 }
);
}
return () => controller.abort();
}, [
api,
cellEditActivator,
state.columnsVisible,
state.internal.cellEditActiveEdits,
state.internal.cellEditActiveLocation,
viewport
]);
return /* @__PURE__ */ jsx(Fragment, {});
}
function RowHoverDriver() {
const s3 = useGrid();
const gridId = s3.state.gridId.use();
const hoveredRow = s3.state.internal.hoveredRow.use();
if (hoveredRow == null) return;
return /* @__PURE__ */ jsx("style", { children: `
#${gridId} > div > div > [aria-rowindex="${hoveredRow + 1}"] {
background-color: var(--lng1771-gray-10);
}
` });
}
function Viewport({
children,
...els
}) {
const { state } = useGrid();
const onSizeChange = useEvent((size) => {
state.internal.viewportInnerHeight.set(size.innerHeight);
state.internal.viewportInnerWidth.set(size.innerWidth);
state.internal.viewportOuterWidth.set(size.outerWidth);
state.internal.viewportOuterHeight.set(size.outerHeight);
const el = state.internal.viewport.peek();
if (el) {
state.internal.viewportXScroll.set(Math.abs(el.scrollLeft));
state.internal.viewportYScroll.set(Math.abs(el.scrollTop));
state.internal.viewportInnerWidth.set(el.clientWidth);
state.internal.viewportInnerHeight.set(el.clientHeight);
}
});
const onInit = useEvent((_, size) => {
onSizeChange(size);
});
const onScroll = useEvent(() => {
const viewport = state.internal.viewport.peek();
if (!viewport) return;
state.internal.viewportXScroll.set(Math.abs(viewport.scrollLeft));
state.internal.viewportYScroll.set(Math.abs(viewport.scrollTop));
});
const ref = useEvent((el) => {
state.internal.viewport.set(el);
});
const paginate = state.paginate.use();
const totalHeight = paginate ? void 0 : state.internal.rowPositions.use().at(-1);
const totalWidth = state.columnPositions.use().at(-1);
const rtl = state.rtl.use();
const grid = state.gridId.use();
return /* @__PURE__ */ jsxs(
Sizer,
{
onInit,
onSizeChange,
onScroll,
elRef: ref,
style: { direction: rtl ? "rtl" : void 0 },
id: grid,
className: "lng1771-viewport",
children: [
/* @__PURE__ */ jsx(HeaderContainer, { style: { width: totalWidth } }),
/* @__PURE__ */ jsx(RowContainer, { totalHeight, totalWidth, children: /* @__PURE__ */ jsx(Rows, { width: totalWidth, ...els }) }),
/* @__PURE__ */ jsx(NavigationDriver, {}),
/* @__PURE__ */ jsx(CellEditDriver, {}),
/* @__PURE__ */ jsx(RowHoverDriver, {}),
children
]
}
);
}
function getEditRows(locations, predicate) {
const validLocations = Object.groupBy(
[...locations].filter(([_, l]) => predicate(l)).map(([_, l]) => l),
(l) => l.rowIndex
);
return Object.entries(validLocations);
}
function TextEditor({
value,
setValue,
isValid,
column
}) {
const opts = column.cellEditParams ?? {};
return /* @__PURE__ */ jsx(
Input,
{
error: !isValid,
maxLength: opts.maxLength,
className: "lng1771-cell__edit-input",