@1771technologies/lytenyte-pro
Version:
1,229 lines (1,228 loc) • 44.1 kB
JavaScript
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
import { IsoResizeObserver, getPreciseElementDimensions, clsx } from "@1771technologies/js-utils";
import { u as useDragStore, a as useDrag, C as Checkbox, I as Input, D as DragProvider } from "./drag-store-BF4ad65L.js";
import "@1771technologies/react-sizer";
import { useCombinedRefs, useEvent } from "@1771technologies/react-utils";
import "@1771technologies/grid-provider";
import { useRef, useState, useEffect, useCallback, useMemo, createContext, useContext, forwardRef, useId } from "react";
import "@1771technologies/react-dragon";
import "@1771technologies/grid-core";
import { c as useGrid, G as GridProvider } from "./useScrollLock-D4UY33Sb.js";
import { g as useEdgeScroll, h as useDraggable, c as canAgg, a as canMeasure, f as useDroppable, u as useAggregationSource, b as useMeasuresSource, d as useRowGroupsSource, e as useColumnPivotSource, P as Pill, M as MenuTrigger, i as PillManagerAggMenu, j as PillManagerMeasureMenu } from "./pill-B_ah-_Qz.js";
import { A as ArrowRightIcon } from "./tickmark-icon-CoogRMoO.js";
import { A as ArrowDownIcon } from "./arrow-down-icon-B-3ldODD.js";
import { D as DragIcon, M as MeasuresIcon, C as ColumnPivotIcon, R as RowGroupIcon } from "./row-group-icon-DFUMye0v.js";
import { createPortal } from "react-dom";
import { D as DragGroupIcon, S as SearchIcon } from "./search-icon-CcG1lqsn.js";
import { S as Separator } from "./separator-BnPPeAk8.js";
import { M as MoreDotsIcon } from "./more-dots-icon-CzAH3xHG.js";
import { C as CrossIcon } from "./cross-icon-CEMLAlFX.js";
import { M as MenuRoot, a as MenuPortal } from "./column-menu-driver-cG-EZgLa.js";
import { M as MenuPositioner } from "./menu-C49unLOk.js";
function Sizer({
children,
onSizeChange,
onInit,
elRef,
...props
}) {
const ref = useRef(null);
const [size, setSize] = useState(null);
useEffect(() => {
return () => ref.current?.disconnect();
}, []);
const init = useCallback((el) => {
if (!el) return;
const resize = new IsoResizeObserver(() => {
const dims2 = getPreciseElementDimensions(el);
setSize(dims2);
});
const dims = getPreciseElementDimensions(el);
setSize(dims);
resize.observe(el);
ref.current = resize;
}, []);
const [inner, setInner] = useState(null);
const combined = useCombinedRefs(elRef, setInner);
useEffect(() => {
if (!inner) return;
let raf = null;
const resizer = new IsoResizeObserver(() => {
if (raf) return;
raf = setTimeout(() => {
const dims2 = getPreciseElementDimensions(inner);
onSizeChange?.(dims2);
raf = null;
}, 20);
});
resizer.observe(inner);
const dims = getPreciseElementDimensions(inner);
onSizeChange?.(dims);
return () => resizer.disconnect();
}, [inner, onInit, onSizeChange]);
return /* @__PURE__ */ jsxs(
"div",
{
style: {
minHeight: "inherit",
maxHeight: "inherit",
height: "100%",
width: "100%",
minWidth: "inherit",
maxWidth: "inherit",
position: "relative"
},
children: [
/* @__PURE__ */ jsx(
"div",
{
ref: init,
style: {
position: "absolute",
minHeight: "inherit",
maxHeight: "inherit",
height: "100%",
width: "100%",
minWidth: "inherit",
maxWidth: "inherit",
pointerEvents: "none"
}
}
),
size && /* @__PURE__ */ jsx(
"div",
{
...props,
ref: combined,
style: {
width: size.innerWidth,
height: size.innerHeight,
position: "absolute",
overflow: "auto",
scrollbarWidth: "thin",
...props.style
},
children
}
)
]
}
);
}
function Virtualized({
data,
focusedIndex,
itemHeight,
renderer: Row,
preventFlash,
elRef,
scrollIntoViewIndex,
...props
}) {
const [size, setSize] = useState(null);
const init = useCallback((_, size2) => {
setSize(size2);
}, []);
const [rowStart, setRowStart] = useState(0);
const [rowEnd, setRowEnd] = useState(0);
const [vp, setVp] = useState(null);
const [y, setY] = useState(0);
const handleScroll = useEvent(() => {
if (!vp || !size) return;
const scrollTop = vp.scrollTop;
const rowStart2 = Math.floor(scrollTop / itemHeight);
const rowEnd2 = Math.ceil(size.innerHeight / itemHeight) + rowStart2;
setY(scrollTop);
setRowStart(Math.max(0, rowStart2 - 5));
setRowEnd(Math.min(rowEnd2 + 5, data.length));
});
const rows = useMemo(() => {
const safeRowStart = Math.max(0, rowStart);
const safeRowEnd = Math.min(data.length, rowEnd);
const rows2 = [];
if (focusedIndex != null && focusedIndex < safeRowStart) {
rows2.push(
/* @__PURE__ */ jsx(
Row,
{
rowIndex: focusedIndex,
data: data[focusedIndex],
y: focusedIndex * itemHeight,
height: itemHeight
},
focusedIndex
)
);
}
for (let i = safeRowStart; i < safeRowEnd; i++) {
rows2.push(/* @__PURE__ */ jsx(Row, { rowIndex: i, data: data[i], y: i * itemHeight, height: itemHeight }, i));
}
if (focusedIndex != null && focusedIndex >= rowEnd)
rows2.push(
/* @__PURE__ */ jsx(
Row,
{
rowIndex: focusedIndex,
data: data[focusedIndex],
y: focusedIndex * itemHeight,
height: itemHeight
}
)
);
return rows2;
}, [Row, data, focusedIndex, itemHeight, rowEnd, rowStart]);
useEffect(() => {
handleScroll();
}, [handleScroll, vp, size, data.length]);
const scrolled = useRef(false);
useEffect(() => {
if (!vp || scrollIntoViewIndex == null || scrolled.current) return;
const t = setTimeout(() => {
vp.scrollBy({ top: scrollIntoViewIndex * itemHeight });
scrolled.current = true;
setTimeout(() => {
const child = vp.querySelector(`[data-rowindex="${scrollIntoViewIndex}"]`);
if (child) {
child.focus();
}
}, 30);
}, 10);
return () => clearTimeout(t);
}, [itemHeight, scrollIntoViewIndex, vp]);
const combinedRef = useCombinedRefs(setVp, elRef);
return /* @__PURE__ */ jsxs(
Sizer,
{
onInit: init,
onSizeChange: setSize,
...props,
onScroll: handleScroll,
elRef: combinedRef,
children: [
preventFlash && /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(
"div",
{
style: {
position: "sticky",
top: 0,
height: 0,
width: "100%",
transform: `translate3d(0px, ${-y}px, 0px)`
},
children: rows
}
),
/* @__PURE__ */ jsx(
"div",
{
style: {
height: data.length * itemHeight,
width: "100%",
position: "relative",
pointerEvents: "none"
}
}
)
] }),
!preventFlash && /* @__PURE__ */ jsx("div", { style: { height: data.length * itemHeight, width: "100%", position: "relative" }, children: rows })
]
}
);
}
const context$3 = createContext(null);
const ColumnStateProvider = (props) => {
const [query, setQuery] = useState("");
const value = useMemo(() => {
return {
query,
setQuery
};
}, [query]);
return /* @__PURE__ */ jsx(context$3.Provider, { value, children: props.children });
};
const useColumnManagerState = () => useContext(context$3);
function createPathTree(items, config = {}) {
const roots = [];
const pathOccurrences = /* @__PURE__ */ new Map();
const pathToParentMap = /* @__PURE__ */ new Map();
const separator = config.pathSeparator ?? "/";
const considerAdjacency = config.considerAdjacency ?? false;
function getOccurrenceKey(path) {
const pathKey = path.join(separator);
const count = pathOccurrences.get(pathKey) ?? 0;
pathOccurrences.set(pathKey, count + 1);
return `${pathKey}#${count}`;
}
function isAdjacentPath(existingParent, pathSegment, level) {
const lastChild = existingParent.children[existingParent.children.length - 1];
if (!lastChild) return false;
return lastChild.path.length === level + 1 && lastChild.path[level] === pathSegment;
}
function findOrCreateParent(path, currentLevel, currentParent) {
if (considerAdjacency && !currentParent && path.length === 1) {
const lastRoot = roots[roots.length - 1];
if (lastRoot?.type === "parent" && lastRoot.path[0] === path[0]) {
return lastRoot;
}
}
if (currentLevel === path.length - 1) {
if (!considerAdjacency) {
const pathKey = path.slice(0, currentLevel + 1).join(separator);
const existingParent = pathToParentMap.get(pathKey);
if (existingParent) {
return existingParent;
}
}
if (considerAdjacency && currentParent) {
const lastChild = currentParent.children[currentParent.children.length - 1];
if (lastChild?.type === "parent" && isAdjacentPath(currentParent, path[currentLevel], currentLevel)) {
return lastChild;
}
}
const newParent2 = {
type: "parent",
path: path.slice(0, currentLevel + 1),
parent: currentParent,
children: [],
occurrence: getOccurrenceKey(path.slice(0, currentLevel + 1))
};
if (currentParent) {
currentParent.children.push(newParent2);
} else {
roots.push(newParent2);
}
if (!considerAdjacency) {
pathToParentMap.set(path.slice(0, currentLevel + 1).join(separator), newParent2);
}
return newParent2;
}
if (considerAdjacency && !currentParent) {
const lastRoot = roots[roots.length - 1];
if (lastRoot?.type === "parent" && lastRoot.path[currentLevel] === path[currentLevel]) {
return findOrCreateParent(path, currentLevel + 1, lastRoot);
}
} else if (considerAdjacency && currentParent) {
if (isAdjacentPath(currentParent, path[currentLevel], currentLevel)) {
const lastChild = currentParent.children[currentParent.children.length - 1];
return findOrCreateParent(path, currentLevel + 1, lastChild);
}
} else if (!considerAdjacency) {
const pathKey = path.slice(0, currentLevel + 1).join(separator);
const existingParent = pathToParentMap.get(pathKey);
if (existingParent) {
return findOrCreateParent(path, currentLevel + 1, existingParent);
}
}
const newParent = {
type: "parent",
path: path.slice(0, currentLevel + 1),
parent: currentParent,
children: [],
occurrence: getOccurrenceKey(path.slice(0, currentLevel + 1))
};
if (currentParent) {
currentParent.children.push(newParent);
} else {
roots.push(newParent);
}
if (!considerAdjacency) {
pathToParentMap.set(path.slice(0, currentLevel + 1).join(separator), newParent);
}
return findOrCreateParent(path, currentLevel + 1, newParent);
}
for (const item of items) {
const { path, data } = item;
if (path.length === 0) {
const leafNode2 = {
type: "leaf",
path: [],
parent: null,
data
};
roots.push(leafNode2);
continue;
}
const parentNode = findOrCreateParent(path, 0, null);
const leafNode = {
type: "leaf",
path,
parent: parentNode,
data
};
parentNode.children.push(leafNode);
}
return roots;
}
const context$2 = createContext({
count: 0,
expansions: {},
renderer: () => null,
focused: null,
setFocused: () => {
},
rtl: false,
onExpansionChange: () => {
},
onAction: () => {
}
});
function ListViewProvider(props) {
return /* @__PURE__ */ jsx(context$2.Provider, { value: props.value, children: props.children });
}
const useListView = () => useContext(context$2);
function ListView({
paths,
expansions,
onExpansionChange,
onKeydown,
onAction,
renderer,
itemClassName,
itemStyle,
edgeScrollActive,
className,
style,
rtl = false,
itemHeight = 24,
scrollIntoViewIndex
}) {
const tree = useMemo(() => {
return createPathTree(paths, { considerAdjacency: true });
}, [paths]);
const flattenedTree = useMemo(() => {
const stack = [...tree];
const flattened = [];
while (stack.length) {
const item = stack.shift();
if (item.type === "leaf") {
flattened.push(item);
} else {
if (expansions[item.occurrence] ?? true) {
stack.unshift(...item.children);
}
flattened.push(item);
}
}
return flattened;
}, [expansions, tree]);
const [focused, setFocused] = useState(null);
const context2 = useMemo(() => {
return {
count: flattenedTree.length,
onExpansionChange,
expansions,
renderer,
setFocused,
onKeydown,
focused,
onAction,
itemClassName,
itemStyle,
rtl
};
}, [
expansions,
flattenedTree.length,
focused,
itemClassName,
itemStyle,
onAction,
onExpansionChange,
onKeydown,
renderer,
rtl
]);
const ref = useRef(null);
const r = useEdgeScroll({
isActive: !!edgeScrollActive,
direction: "vertical"
});
const combined = useCombinedRefs(r, ref);
return /* @__PURE__ */ jsx(ListViewProvider, { value: context2, children: /* @__PURE__ */ jsx(
Virtualized,
{
elRef: combined,
className,
style,
tabIndex: 0,
role: "tree",
onKeyDown: (ev) => {
if (document.activeElement === ref.current && ev.key === "ArrowDown") {
setFocused(0);
const firstChild = ref.current?.firstElementChild?.firstElementChild;
if (firstChild?.getAttribute("data-rowindex") !== "0")
ref.current?.scrollTo({ top: 0 });
setTimeout(() => {
const child = ref.current?.firstElementChild?.firstElementChild;
if (child) child.focus();
}, 20);
ev.preventDefault();
ev.stopPropagation();
}
if (focused == null) return;
if (ev.key === "ArrowDown") {
const next = ref.current?.querySelector(
`[data-rowindex="${focused + 1}"]`
);
ev.preventDefault();
ev.stopPropagation();
if (!next) {
document.activeElement?.scrollIntoView();
setTimeout(() => {
const next2 = ref.current?.querySelector(
`[data-rowindex=${focused + 1}]`
);
if (!next2) return;
next2.focus();
}, 20);
return;
}
const bb = ref.current.getBoundingClientRect();
const n = next.getBoundingClientRect();
next.focus({ preventScroll: true });
if (bb.bottom - (n.top + n.height) < 0) {
next.scrollIntoView({ behavior: "instant", block: "end" });
}
}
if (ev.key === "ArrowUp") {
const next = ref.current?.querySelector(
`[data-rowindex="${focused - 1}"]`
);
ev.preventDefault();
ev.stopPropagation();
if (!next) {
document.activeElement?.scrollIntoView();
setTimeout(() => {
const next2 = ref.current?.querySelector(
`[data-rowindex=${focused - 1}]`
);
if (!next2) return;
next2.focus();
}, 20);
return;
}
const bb = ref.current.getBoundingClientRect();
const n = next.getBoundingClientRect();
next.focus({ preventScroll: true });
if (bb.top - n.top > 0) {
next.scrollIntoView({ behavior: "instant" });
}
}
},
data: flattenedTree,
itemHeight,
renderer: ListItemRenderer,
focusedIndex: focused,
scrollIntoViewIndex,
preventFlash: true
}
) });
}
function ListItemRenderer(p) {
let depth = 1;
let current = p.data?.parent;
while (current) {
current = current?.parent;
depth++;
}
const ctx = useListView();
const isExpanded = p.data?.type === "parent" ? ctx.expansions[p.data.occurrence] ?? true : void 0;
return /* @__PURE__ */ jsx(
"div",
{
tabIndex: -1,
"data-rowindex": p.rowIndex,
onFocus: () => ctx.setFocused(p.rowIndex),
onBlur: () => ctx.setFocused(null),
onClick: () => ctx.onAction(p.data),
onKeyDown: (ev) => {
const open = ctx.rtl ? "ArrowLeft" : "ArrowRight";
const close = ctx.rtl ? "ArrowRight" : "ArrowLeft";
if (ev.key === " " && p.data.type === "parent") {
ctx.onExpansionChange(p.data.occurrence, !isExpanded);
ev.preventDefault();
return;
}
if (ev.key === open && p.data.type === "parent") {
ctx.onExpansionChange(p.data.occurrence, true);
ev.preventDefault();
return;
}
if (ev.key === close && p.data.type === "parent") {
ctx.onExpansionChange(p.data.occurrence, false);
ev.preventDefault();
return;
}
if (ev.key === "Enter") {
ctx.onAction(p.data);
ev.preventDefault();
return;
}
ctx.onKeydown?.(ev.nativeEvent, p.data);
},
role: "treeitem",
style: {
...ctx.itemStyle,
position: "absolute",
top: p.y,
height: p.height,
width: "100%",
boxSizing: "border-box"
},
className: ctx.itemClassName,
"aria-posinset": p.rowIndex + 1,
"aria-level": depth,
"aria-setsize": ctx.count,
"aria-expanded": p.data.type === "parent" ? ctx.expansions[p.data.occurrence] : void 0,
children: /* @__PURE__ */ jsx(
ctx.renderer,
{
data: p.data,
depth: depth - 1,
expanded: !!isExpanded,
parent: p.data.type === "parent",
treeFlatIndex: p.rowIndex
}
)
}
);
}
function allLeafs(c) {
const leafs = [];
const stack = [...c.children];
while (stack.length) {
const item = stack.pop();
if (item.type === "leaf") {
leafs.push(item.data);
} else {
stack.push(...item.children);
}
}
return leafs;
}
function canHideItem(item, api) {
if (item.type === "parent") {
const leafs = allLeafs(item);
return leafs.every((leaf) => api.columnIsHidable(leaf));
} else {
return api.columnIsHidable(item.data);
}
}
function handleItemHide(item, api) {
const state = api.getState();
const base = state.columnBase.peek();
if (canHideItem(item, api)) {
if (item.type === "parent") {
const columns = allLeafs(item);
const allVisible = columns.every((c) => !(c.hide ?? base.hide));
const nextState = allVisible ? true : false;
const update = Object.fromEntries(columns.map((c) => [c.id, { hide: nextState }]));
api.columnUpdateMany(update);
} else {
const column = item.data;
const next = !(column.hide ?? base.hide);
api.columnUpdate(column, { hide: next });
}
}
}
function ColumnManagerTree({
className,
itemClassName,
children,
itemHeight = 30
}) {
const { api, state } = useGrid();
const columns = state.columns.use();
const expansions = state.internal.columnManagerTreeExpansions.use();
const { query } = useColumnManagerState();
const paths = useMemo(() => {
const paths2 = columns.filter((c) => {
if (api.columnIsGridGenerated(c) && !api.columnIsGroupAutoColumn(c)) return false;
if (!query) return true;
const searchLabel = [c.headerName ?? c.id, ...c.groupPath ?? []].join(" ");
return searchLabel.toLowerCase().includes(query.toLocaleLowerCase());
}).map((c) => ({ path: c.groupPath ?? [], data: c }));
return paths2;
}, [api, columns, query]);
const dragStore = useDragStore();
const edgeScroll = useDrag(dragStore, (d) => !!d.active);
return /* @__PURE__ */ jsx(
ListView,
{
edgeScrollActive: edgeScroll,
expansions,
className: clsx("lng1771-column-manager__tree", className),
itemClassName: clsx("lng1771-column-manager__tree-item-wrapper", itemClassName),
paths,
itemHeight,
renderer: children,
onAction: (item) => handleItemHide(item, api),
onExpansionChange: (id, s) => {
state.internal.columnManagerTreeExpansions.set((prev) => ({ ...prev, [id]: s }));
}
}
);
}
const ColumnManagerTreeItem = forwardRef(function TreeItem({ className, depthPadding = 12, style, columnItem: ci, ...props }, ref) {
const { api, state } = useGrid();
const base = state.columnBase.use();
const columns = state.internal.columnLookup.use();
const pivotMode = state.columnPivotModeIsOn.use();
const labelId = useId();
const pivotModel = state.columnPivotModel.use();
const aggModel = state.aggModel.use();
const groupModel = state.rowGroupModel.use();
const measureModel = state.measureModel.use();
const dropData = useMemo(() => {
const ids = ci.data.type === "leaf" ? [ci.data.data.id] : allLeafs(ci.data).map((c) => c.id);
return { target: "columns", ids, isGroup: ci.data.type === "parent" };
}, [ci.data]);
const { setDrag } = useDraggable({
id: ci.data.type === "leaf" ? ci.data.data.id : ci.data.occurrence,
getData: () => {
const columns2 = ci.data.type === "leaf" ? [ci.data.data] : allLeafs(ci.data);
return { target: "columns", columns: columns2 };
},
getTags: () => {
const columns2 = ci.data.type === "leaf" ? [ci.data.data] : allLeafs(ci.data);
const isPivotable = columns2.every((c) => api.columnIsPivotable(c)) && columns2.some((c) => !pivotModel.includes(c.id));
const isGroupable = columns2.every((c) => api.columnIsRowGroupable(c)) && columns2.some((c) => !groupModel.includes(c.id));
const isAggregable = columns2.every((c) => canAgg(c, base)) && columns2.some((c) => !aggModel[c.id]);
const isMeasurable = columns2.every((c) => canMeasure(c, base)) && columns2.some((c) => !measureModel[c.id]);
const dragTags = ["columns"];
if (isPivotable) dragTags.push("column-pivot");
if (isGroupable) dragTags.push("row-group");
if (isAggregable) dragTags.push("aggregations");
if (isMeasurable) dragTags.push("measures");
return dragTags;
},
onDragEnd: (p) => {
const data = p.data;
const over = p.over.at(-1);
if (!over) return;
if (over.data.target === "columns") {
const ids = over.data.ids;
const isGroup = over.data.isGroup;
const srcIds = data.columns.map((c) => c.id);
if (srcIds.some((c) => ids.includes(c))) return;
if (isGroup || over.yHalf === "top") api.columnMoveBefore(srcIds, ids[0]);
else api.columnMoveAfter(srcIds, ids[0]);
return;
}
if (over.id === "row-groups-pills") {
const columns2 = data.columns.filter((c) => !groupModel.includes(c.id));
state.rowGroupModel.set((prev) => [...prev, ...columns2.map((c) => c.id)]);
return;
}
if (over.id === "column-pivots-pills") {
const columns2 = data.columns.filter((c) => !pivotModel.includes(c.id));
state.columnPivotModel.set((prev) => [...prev, ...columns2.map((c) => c.id)]);
return;
}
if (over.id === "aggregations-pills") {
const columns2 = Object.fromEntries(
data.columns.filter((c) => !aggModel[c.id]).map((c) => {
const aggFn = c.aggFnDefault ?? c.aggFnsAllowed?.at(0) ?? base.aggFnsAllowed?.at(0);
return [c.id, { fn: aggFn }];
})
);
state.aggModel.set((prev) => ({ ...prev, ...columns2 }));
return;
}
if (over.id === "measures-pills") {
const columns2 = Object.fromEntries(
data.columns.filter((c) => !measureModel[c.id]).map((c) => {
const measureFn = c.measureFnDefault ?? c.measureFnsAllowed?.at(0) ?? base.measureFnsAllowed?.at(0);
return [c.id, { fn: measureFn }];
})
);
state.measureModel.set((prev) => ({ ...prev, ...columns2 }));
return;
}
}
});
const {
ref: dropRef,
canDrop,
yHalf
} = useDroppable({
id: ci.data.type === "leaf" ? ci.data.data.id : ci.data.occurrence,
accepted: ["columns"],
data: dropData
});
const combinedRefs = useCombinedRefs(ref, dropRef);
if (ci.data.type === "leaf") {
const data = ci.data.data;
const column = columns.get(data.id);
if (!column) return null;
const hidden = column.hide ?? base.hide;
const hidable = !pivotMode && api.columnIsHidable(column);
return /* @__PURE__ */ jsxs(
"div",
{
...props,
className: clsx("lng1771-column-manager__tree-item", className),
ref: combinedRefs,
"data-can-drop": canDrop,
style: {
paddingInlineStart: `calc(${depthPadding}px + ${ci.depth > 0 ? ci.depth + 1 : 0} * ${depthPadding}px + 22px)`,
...style
},
children: [
canDrop && yHalf === "top" && /* @__PURE__ */ jsx("div", { className: "lng1771-column-manager__tree-item-drop-indicator-top" }),
canDrop && yHalf === "bottom" && /* @__PURE__ */ jsx("div", { className: "lng1771-column-manager__tree-item-drop-indicator-bottom" }),
/* @__PURE__ */ jsx(DragIcon, { width: 16, height: 16, dragRef: setDrag }),
/* @__PURE__ */ jsx(
Checkbox,
{
htmlFor: labelId,
"aria-labelledby": labelId,
isDisabled: !hidable,
tabIndex: -1,
isChecked: !hidden,
disabled: !hidable
}
),
/* @__PURE__ */ jsx("label", { id: labelId, children: data.headerName ?? data.id })
]
}
);
} else {
const id = ci.data.occurrence;
const path = ci.data.path.at(-1);
const columns2 = allLeafs(ci.data);
const checked = columns2.every((c) => !(c.hide ?? base.hide));
const isIndeterminate = columns2.some((c) => !(c.hide ?? base.hide)) && !checked;
const hidable = !pivotMode && columns2.every((c) => api.columnIsHidable(c));
return /* @__PURE__ */ jsxs(
"div",
{
...props,
style: {
paddingInlineStart: `calc(${depthPadding}px + ${ci.depth} * ${depthPadding}px)`,
...style
},
ref: combinedRefs,
className: clsx("lng1771-column-manager__tree-item", className),
children: [
canDrop && yHalf === "top" && /* @__PURE__ */ jsx("div", { className: "lng1771-column-manager__tree-item-drop-indicator-top" }),
canDrop && yHalf === "bottom" && /* @__PURE__ */ jsx("div", { className: "lng1771-column-manager__tree-item-drop-indicator-bottom" }),
/* @__PURE__ */ jsx(
"button",
{
className: "lng1771-column-manager__tree-item-expander",
onFocus: (ev) => ev.currentTarget.blur(),
onClick: (ev) => {
ev.stopPropagation();
state.internal.columnManagerTreeExpansions.set((prev) => ({
...prev,
[id]: !ci.expanded
}));
},
children: ci.expanded ? /* @__PURE__ */ jsx(ArrowDownIcon, { width: 16, height: 16, id }) : /* @__PURE__ */ jsx(ArrowRightIcon, { id, width: 16, height: 16 })
}
),
/* @__PURE__ */ jsx(DragIcon, { width: 16, height: 16, dragRef: setDrag }),
/* @__PURE__ */ jsx(
Checkbox,
{
htmlFor: labelId,
"aria-labelledby": labelId,
tabIndex: -1,
isDisabled: !hidable,
isChecked: checked || isIndeterminate,
isDeterminate: isIndeterminate
}
),
/* @__PURE__ */ jsx("label", { id: labelId, children: path })
]
}
);
}
});
function ColumnManagerDragPlaceholder(props) {
const store = useDragStore();
const s = useDrag(store, (s2) => s2.active);
if (!s) return null;
const c = props.children ?? DefaultPlaceholder;
return createPortal(
/* @__PURE__ */ jsx(
"div",
{
className: "lng1771-column-manager__drag-placeholder",
style: { transform: `translate3d(${s.x}px, ${s.y}px, 0px)` },
children: c(s)
}
),
document.body
);
}
function DefaultPlaceholder(p) {
return /* @__PURE__ */ jsx(Placeholder, { ...p });
}
function Placeholder(p) {
const c = useMemo(() => {
return p.id.split("/").join(" / ").replaceAll("#0", "");
}, [p.id]);
return /* @__PURE__ */ jsxs("div", { className: "lng1771-column-manager__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 })
] });
}
const context$1 = createContext({});
const ColumnManagerDragBox = forwardRef(function ColumnManagerDragBox2({ source, className, children, ...props }, ref) {
const aggs = useAggregationSource(source);
const measures = useMeasuresSource(source);
const rowGroups = useRowGroupsSource(source, "vertical");
const pivots = useColumnPivotSource(source, "vertical");
const sourceItems = useMemo(() => {
if (source === "aggregations") return aggs.filter((c) => c.active);
if (source === "column-pivots") return pivots.filter((c) => c.active);
if (source === "measures") return measures.filter((c) => c.active);
if (source === "row-groups") return rowGroups.filter((c) => c.active);
return [];
}, [aggs, measures, pivots, rowGroups, source]);
const dropTags = useMemo(() => {
if (source === "aggregations") return ["aggregations"];
if (source === "column-pivots") return ["column-pivot"];
if (source === "measures") return ["measures"];
if (source === "row-groups") return ["row-group"];
return [];
}, [source]);
const dropData = useMemo(() => {
return { target: source, sourceItems };
}, [source, sourceItems]);
const value = useMemo(() => {
return { dropData, dropTags, pillSource: source };
}, [dropData, dropTags, source]);
return /* @__PURE__ */ jsx(context$1.Provider, { value, children: /* @__PURE__ */ jsx(
"div",
{
...props,
tabIndex: 0,
className: clsx("lng1771-column-manager__drag-box", className),
ref,
children
}
) });
});
const useDragBox = () => useContext(context$1);
const ColumnManagerDragBoxControls = forwardRef(function ColumnManagerDragBoxControls2({ className, children, ...props }, ref) {
return /* @__PURE__ */ jsx(
"div",
{
...props,
className: clsx("lng1771-column-manager__drag-box-controls", className),
ref,
children
}
);
});
const ColumnManagerDragBoxLabel = forwardRef(function ColumnManagerDragBoxLabel2({ className, children, icon, ...props }, ref) {
const { pillSource: source } = useDragBox();
const I = useMemo(() => {
if (icon) return icon;
if (source === "aggregations") return /* @__PURE__ */ jsx(MeasuresIcon, {});
if (source === "measures") return /* @__PURE__ */ jsx(MeasuresIcon, {});
if (source === "column-pivots") return /* @__PURE__ */ jsx(ColumnPivotIcon, {});
if (source === "row-groups") return /* @__PURE__ */ jsx(RowGroupIcon, {});
}, [icon, source]);
return /* @__PURE__ */ jsxs("div", { ...props, className: clsx("lng1771-column-manager__drag-box-label", className), ref, children: [
I,
children
] });
});
const ColumnManagerDragBoxExpander = forwardRef(function ColumnManagerDragBoxExpander2({ className, ...props }, ref) {
const { pillSource } = useDragBox();
const { state: sx } = useGrid();
const key = pillSource === "row-groups" ? "rowGroups" : pillSource === "aggregations" ? "values" : pillSource === "column-pivots" ? "columnPivots" : "measures";
const expansions = sx.internal.columnManagerBoxExpansions.use();
const expanded = expansions[key];
return /* @__PURE__ */ jsx(
"button",
{
...props,
className: clsx("lng1771-column-manager__drag-box-expander", className),
onClick: () => {
const current = sx.internal.columnManagerBoxExpansions.peek();
const next = current[key] == null ? false : !current[key];
sx.internal.columnManagerBoxExpansions.set({
...current,
[key]: next
});
},
ref,
children: expanded ? /* @__PURE__ */ jsx(ArrowDownIcon, {}) : /* @__PURE__ */ jsx(ArrowRightIcon, {})
}
);
});
const ColumnManagerDropZoneVisibility = forwardRef(function ColumnManagerDropZoneVisibility2(props, ref) {
const { pillSource } = useDragBox();
const { state: sx } = useGrid();
const key = pillSource === "row-groups" ? "rowGroups" : pillSource === "aggregations" ? "values" : pillSource === "column-pivots" ? "columnPivots" : "measures";
const expansions = sx.internal.columnManagerBoxExpansions.use();
const expanded = expansions[key];
if (!expanded) return null;
return /* @__PURE__ */ jsx("div", { ...props, ref });
});
const ColumnManagerDropZone = forwardRef(function ColumnManagerDropZone2({ className, children, ...props }, ref) {
const { pillSource, dropTags, dropData } = useDragBox();
const {
canDrop,
isTarget,
isNearestOver,
ref: dropRef
} = useDroppable({
id: `${pillSource}-pills`,
accepted: dropTags,
data: dropData
});
const combined = useCombinedRefs(dropRef, ref);
return /* @__PURE__ */ jsxs(
"div",
{
...props,
className: clsx("lng1771-column-manager__drop-zone", className),
"data-is-drop-target": isTarget,
ref: combined,
"data-pill-source": pillSource,
"data-drop-visible": canDrop && dropData.sourceItems.filter((c) => c.active).length === 0,
tabIndex: -1,
children: [
children({ pills: dropData.sourceItems }),
dropData.sourceItems.length === 0 && /* @__PURE__ */ jsx(EmtpyDefault, { source: pillSource }),
canDrop && isNearestOver && dropData.sourceItems.filter((c) => c.active).length > 0 && /* @__PURE__ */ jsx("div", { className: "lng1771-column-manager__drop-zone-indicator" })
]
}
);
});
function EmtpyDefault({ source }) {
const label = useMemo(() => {
if (source === "aggregations") return "Drag here to aggregate";
if (source === "measures") return "Drag here to measure";
if (source === "column-pivots") return "Drag here to pivot";
if (source === "row-groups") return "Drag here to group";
return "";
}, [source]);
return /* @__PURE__ */ jsxs("div", { className: "lng1771-column-manager__empty-default-container", children: [
/* @__PURE__ */ jsx("div", { className: "lng1771-column-manager__empty-default-icon", children: /* @__PURE__ */ jsx(DragGroupIcon, {}) }),
/* @__PURE__ */ jsx("div", { className: "lng1771-column-manager__empty-default-label", children: label })
] });
}
const context = createContext({});
const useComponents = () => useContext(context);
const ColumnMangerContextProvider = context.Provider;
const ColumnManagerPill = forwardRef(function ColumnManagerPill2({ item, ...props }, ref) {
const {
ref: dropRef,
isTarget,
canDrop,
yHalf
} = useDroppable({
id: item.dropId,
accepted: item.dropTags,
data: item.dropData,
active: item.active
});
const grid = useGrid();
const combinedRefs = useCombinedRefs(ref, dropRef);
const [isDragging, setIsDragging] = useState(false);
const {
aggMenuRenderer: AggMenu,
measureMenuRenderer: MeasureMenu,
menuTriggerIcon: TriggerIcon
} = useComponents();
return /* @__PURE__ */ jsxs(
"div",
{
...props,
role: "button",
ref: combinedRefs,
"data-pill-key": item.dropId,
"data-pill-active": item.active,
"data-is-droppable": isTarget && canDrop,
className: "lng1771-column-manager__pill-outer",
children: [
/* @__PURE__ */ jsxs(
Pill,
{
kind: item.kind,
className: "lng1771-column-manager__pill-inner",
interactive: true,
"data-draggable": item.draggable,
"data-drag-active": isDragging,
children: [
item.draggable && /* @__PURE__ */ jsx(DragHandle, { item, setIsDragging }),
/* @__PURE__ */ jsxs("div", { className: "lng1771-column-manager__pill-labels", children: [
/* @__PURE__ */ jsx("span", { children: item.label }),
item.secondaryLabel && /* @__PURE__ */ jsx("span", { className: "lng1771-column-manager__pill-inner--secondary-label", children: item.secondaryLabel })
] }),
/* @__PURE__ */ jsxs("div", { className: "lng1771-column-manager__pill-buttons", children: [
(item.isAggregation || item.isMeasure) && /* @__PURE__ */ jsxs(MenuRoot, { children: [
/* @__PURE__ */ jsx(
MenuTrigger,
{
className: "lng1771-column-manager__pill-button",
"data-pill-menu-trigger": "true",
onClick: (e) => e.stopPropagation(),
children: /* @__PURE__ */ jsx(TriggerIcon, { width: 16, height: 16 })
}
),
/* @__PURE__ */ jsx(MenuPortal, { children: /* @__PURE__ */ jsxs(
MenuPositioner,
{
onClick: (ev) => ev.stopPropagation(),
className: "lng1771-column-manager__agg-menu",
children: [
item.isAggregation && /* @__PURE__ */ jsx(AggMenu, { grid, column: item.column }),
item.isMeasure && /* @__PURE__ */ jsx(MeasureMenu, { grid, column: item.column })
]
}
) })
] }),
(item.isRowGroup || item.isColumnPivot || item.isAggregation || item.isMeasure) && /* @__PURE__ */ jsx("button", { className: "lng1771-column-manager__pill-button", onClick: item.onClick, children: /* @__PURE__ */ jsx(CrossIcon, { width: 16, height: 16 }) })
] })
]
}
),
canDrop && "bottom" === yHalf && /* @__PURE__ */ jsx("div", { className: "lng1771-column-manager__drop-indicator-end" }),
canDrop && "top" === yHalf && /* @__PURE__ */ jsx("div", { className: "lng1771-column-manager__drop-indicator-start" })
]
}
);
});
function DragHandle({
item,
setIsDragging
}) {
const { setDrag, isActive } = useDraggable({
id: item.label,
getTags: () => item.dragTags.filter((c) => c !== "columns"),
getData: () => item?.dragData,
onDragStart: () => {
document.body.classList.add("lng1771-drag-on");
},
onDragCancel: () => {
document.body.classList.remove("lng1771-drag-on");
},
onDragEnd: (p) => {
item.dragEnd?.(p);
document.body.classList.remove("lng1771-drag-on");
}
});
useEffect(() => {
setIsDragging(isActive);
}, [isActive, setIsDragging]);
return /* @__PURE__ */ jsx("button", { tabIndex: -1, className: "lng1771-column-manager__pill-dragger", ref: setDrag, children: /* @__PURE__ */ jsx(DragIcon, { width: 16, height: 16 }) });
}
const ColumnManagerSearch = forwardRef(function ColumnManagerSearch2({ className, ...props }, ref) {
const { query, setQuery } = useColumnManagerState();
return /* @__PURE__ */ jsx(
Input,
{
...props,
ref,
small: true,
className: clsx("lng1771-column-manager__search-input", className),
icon: SearchIcon,
value: query,
onChange: (e) => {
setQuery(e.target.value);
props.onChange?.(e);
}
}
);
});
function Toggle({ on, onChange, disabled, id }) {
const ref = useRef(null);
return /* @__PURE__ */ jsxs(
"div",
{
className: clsx(
"lng1771-toggle",
on && !disabled && "lng1771-toggle--on",
disabled && "lng1771-toggle--disabled"
),
onClick: () => {
if (disabled) return;
onChange(!on);
ref.current?.focus();
},
children: [
/* @__PURE__ */ jsx(
"div",
{
className: clsx(
on && "lng1771-toggle__thumb--on",
!on && "lng1771-toggle__thumb--off",
disabled && "lng1771-toggle__thumb--disabled"
)
}
),
/* @__PURE__ */ jsx(
"input",
{
ref,
id,
type: "checkbox",
checked: on,
onChange: (e) => onChange(e.target.checked),
disabled
}
)
]
}
);
}
const PivotModeToggle = forwardRef(
function PivotModeToggle2({ children, className, ...props }, ref) {
const grid = useGrid();
const state = grid.state;
const id = useId();
const pivotMode = state.columnPivotModeIsOn.use();
return /* @__PURE__ */ jsxs("div", { ...props, className: clsx("lng1771-column-manager__pivot-toggle", className), ref, children: [
/* @__PURE__ */ jsx(Toggle, { id, on: pivotMode, onChange: (b) => state.columnPivotModeIsOn.set(b) }),
/* @__PURE__ */ jsx("label", { htmlFor: id, className: "lng1771-column-manager__pivot-toggle-label", children: children ?? "Pivot Mode" })
] });
}
);
const Root = forwardRef(function Root2({ children, className, grid, aggMenuRenderer, measureMenuRenderer, menuTriggerIcon, ...props }, ref) {
const components = useMemo(() => {
return {
aggMenuRenderer: aggMenuRenderer ?? PillManagerAggMenu,
measureMenuRenderer: measureMenuRenderer ?? PillManagerMeasureMenu,
menuTriggerIcon: menuTriggerIcon ?? MoreDotsIcon
};
}, [aggMenuRenderer, measureMenuRenderer, menuTriggerIcon]);
return /* @__PURE__ */ jsx(ColumnStateProvider, { children: /* @__PURE__ */ jsx(ColumnMangerContextProvider, { value: components, children: /* @__PURE__ */ jsx(GridProvider, { value: grid, children: /* @__PURE__ */ jsx(DragProvider, { children: /* @__PURE__ */ jsx("div", { ...props, className: clsx("lng1771-column-manager", className), ref, children }) }) }) }) });
});
const ColumnManager = {
Root,
Tree: ColumnManagerTree,
TreeItem: ColumnManagerTreeItem,
PivotModeToggle,
Separator,
Search: ColumnManagerSearch,
DragBox: ColumnManagerDragBox,
DragBoxControls: ColumnManagerDragBoxControls,
DragBoxLabel: ColumnManagerDragBoxLabel,
DragBoxExpander: ColumnManagerDragBoxExpander,
DropZoneVisibility: ColumnManagerDropZoneVisibility,
DropZone: ColumnManagerDropZone,
Pill: ColumnManagerPill,
DragPlaceholder: ColumnManagerDragPlaceholder
};
export {
ColumnManager
};