UNPKG

alinea

Version:

[![npm](https://img.shields.io/npm/v/alinea.svg)](https://npmjs.org/package/alinea) [![install size](https://packagephobia.com/badge?p=alinea)](https://packagephobia.com/result?p=alinea)

1,061 lines (1,048 loc) 44.6 kB
import { useAtomValue } from "../../chunks/chunk-WF77DMLN.js"; import "../../chunks/chunk-OBOPLPUQ.js"; import "../../chunks/chunk-U5RRZUYZ.js"; // node_modules/@headless-tree/core/lib/esm/utils.js var memo = (fn, deps) => { let value; let oldDeps = null; return () => { const newDeps = deps(); if (!value) { value = fn(...newDeps); oldDeps = newDeps; return value; } const match = oldDeps && oldDeps.length === newDeps.length && !oldDeps.some((dep, i) => dep !== newDeps[i]); if (match) { return value; } value = fn(...newDeps); oldDeps = newDeps; return value; }; }; function functionalUpdate(updater, input) { return typeof updater === "function" ? updater(input) : updater; } function makeStateUpdater(key, instance) { return (updater) => { instance.setState((old) => { return Object.assign(Object.assign({}, old), { [key]: functionalUpdate(updater, old[key]) }); }); }; } var poll = (fn, interval = 100, timeout = 1e3) => new Promise((resolve) => { let clear; const i = setInterval(() => { if (fn()) { resolve(); clearInterval(i); clearTimeout(clear); } }, interval); clear = setTimeout(() => { clearInterval(i); }, timeout); }); // node_modules/@headless-tree/core/lib/esm/features/tree/feature.js var __awaiter = function(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function(resolve) { resolve(value); }); } return new (P || (P = Promise))(function(resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var treeFeature = { key: "tree", getInitialState: (initialState) => Object.assign({ expandedItems: [], focusedItem: null }, initialState), getDefaultConfig: (defaultConfig, tree) => Object.assign({ setExpandedItems: makeStateUpdater("expandedItems", tree), setFocusedItem: makeStateUpdater("focusedItem", tree) }, defaultConfig), stateHandlerNames: { expandedItems: "setExpandedItems", focusedItem: "setFocusedItem" }, createTreeInstance: (prev, instance) => Object.assign(Object.assign({}, prev), { retrieveItemData: () => { throw new Error("No data-loader registered"); }, retrieveChildrenIds: () => { throw new Error("No data-loader registered"); }, isItemExpanded: (itemId) => instance.getState().expandedItems.includes(itemId), getItemsMeta: () => { const { rootItemId } = instance.getConfig(); const { expandedItems } = instance.getState(); const flatItems = []; const recursiveAdd = (itemId, parentId, level, setSize, posInSet) => { var _a; flatItems.push({ itemId, level, index: flatItems.length, parentId, setSize, posInSet }); if (expandedItems.includes(itemId)) { const children2 = (_a = instance.retrieveChildrenIds(itemId)) !== null && _a !== void 0 ? _a : []; let i2 = 0; for (const childId of children2) { recursiveAdd(childId, itemId, level + 1, children2.length, i2++); } } }; const children = instance.retrieveChildrenIds(rootItemId); let i = 0; for (const itemId of children) { recursiveAdd(itemId, rootItemId, 0, children.length, i++); } return flatItems; }, expandItem: (itemId) => { var _a; if (!instance.getItemInstance(itemId).isFolder()) { return; } if ((_a = instance.getState().loadingItems) === null || _a === void 0 ? void 0 : _a.includes(itemId)) { return; } instance.applySubStateUpdate("expandedItems", (expandedItems) => [ ...expandedItems, itemId ]); instance.rebuildTree(); }, collapseItem: (itemId) => { if (!instance.getItemInstance(itemId).isFolder()) { return; } instance.applySubStateUpdate("expandedItems", (expandedItems) => expandedItems.filter((id) => id !== itemId)); instance.rebuildTree(); }, // TODO memo getFocusedItem: () => { var _a, _b; return (_b = instance.getItemInstance((_a = instance.getState().focusedItem) !== null && _a !== void 0 ? _a : "")) !== null && _b !== void 0 ? _b : instance.getItems()[0]; }, focusItem: (itemId) => { instance.applySubStateUpdate("focusedItem", itemId); }, focusNextItem: () => { const { index } = instance.getFocusedItem().getItemMeta(); const nextIndex = Math.min(index + 1, instance.getItems().length - 1); instance.focusItem(instance.getItems()[nextIndex].getId()); }, focusPreviousItem: () => { const { index } = instance.getFocusedItem().getItemMeta(); const nextIndex = Math.max(index - 1, 0); instance.focusItem(instance.getItems()[nextIndex].getId()); }, updateDomFocus: () => { setTimeout(() => __awaiter(void 0, void 0, void 0, function* () { var _a, _b; const focusedItem = instance.getFocusedItem(); (_b = (_a = instance.getConfig()).scrollToItem) === null || _b === void 0 ? void 0 : _b.call(_a, focusedItem); yield poll(() => focusedItem.getElement() !== null, 20); const focusedElement = focusedItem.getElement(); if (!focusedElement) return; focusedElement.focus(); })); }, getContainerProps: () => { var _a; return Object.assign(Object.assign({}, (_a = prev.getContainerProps) === null || _a === void 0 ? void 0 : _a.call(prev)), { role: "tree", ariaLabel: "", ariaActivedescendant: "" }); } }), createItemInstance: (prev, item, tree) => Object.assign(Object.assign({}, prev), { isLoading: () => { throw new Error("No data-loader registered"); }, scrollTo: (scrollIntoViewArg) => __awaiter(void 0, void 0, void 0, function* () { var _a, _b; (_b = (_a = tree.getConfig()).scrollToItem) === null || _b === void 0 ? void 0 : _b.call(_a, item); yield poll(() => item.getElement() !== null, 20); item.getElement().scrollIntoView(scrollIntoViewArg); }), getId: () => item.getItemMeta().itemId, getProps: () => { var _a; const itemMeta = item.getItemMeta(); return Object.assign(Object.assign({}, (_a = prev.getProps) === null || _a === void 0 ? void 0 : _a.call(prev)), { role: "treeitem", "aria-setsize": itemMeta.setSize, "aria-posinset": itemMeta.posInSet, "aria-selected": "false", "aria-label": item.getItemName(), "aria-level": itemMeta.level, tabIndex: item.isFocused() ? 0 : -1, onClick: item.getMemoizedProp("tree/onClick", () => (e) => { item.setFocused(); item.primaryAction(); if (e.ctrlKey || e.shiftKey || e.metaKey) { return; } if (!item.isFolder()) { return; } if (item.isExpanded()) { item.collapse(); } else { item.expand(); } }) }); }, expand: () => tree.expandItem(item.getItemMeta().itemId), collapse: () => tree.collapseItem(item.getItemMeta().itemId), getItemData: () => tree.retrieveItemData(item.getItemMeta().itemId), isExpanded: () => tree.getState().expandedItems.includes(item.getItemMeta().itemId), isFocused: () => tree.getState().focusedItem === item.getItemMeta().itemId || tree.getState().focusedItem === null && item.getItemMeta().index === 0, isFolder: () => item.getItemMeta().level === -1 || tree.getConfig().isItemFolder(item), getItemName: () => { const config = tree.getConfig(); return config.getItemName(item); }, setFocused: () => tree.focusItem(item.getItemMeta().itemId), primaryAction: () => { var _a, _b; return (_b = (_a = tree.getConfig()).onPrimaryAction) === null || _b === void 0 ? void 0 : _b.call(_a, item); }, getParent: memo((itemMeta) => { for (let i = itemMeta.index - 1; i >= 0; i--) { const potentialParent = tree.getItems()[i]; if (potentialParent.getItemMeta().level < itemMeta.level) { return potentialParent; } } return tree.getItemInstance(tree.getConfig().rootItemId); }, () => [item.getItemMeta()]), // TODO remove getIndexInParent: () => item.getItemMeta().posInSet, getChildren: () => tree.retrieveChildrenIds(item.getItemMeta().itemId).map((id) => tree.getItemInstance(id)), getTree: () => tree, getItemAbove: () => tree.getItems()[item.getItemMeta().index - 1], getItemBelow: () => tree.getItems()[item.getItemMeta().index + 1], getMemoizedProp: (name, create, deps) => { var _a, _b, _c, _d, _e; var _f, _g; const data = item.getDataRef(); const memoizedValue = (_a = data.current.memoizedValues) === null || _a === void 0 ? void 0 : _a[name]; if (memoizedValue && (!deps || ((_c = (_b = data.current.memoizedDeps) === null || _b === void 0 ? void 0 : _b[name]) === null || _c === void 0 ? void 0 : _c.every((d, i) => d === deps[i])))) { return memoizedValue; } (_d = (_f = data.current).memoizedDeps) !== null && _d !== void 0 ? _d : _f.memoizedDeps = {}; (_e = (_g = data.current).memoizedValues) !== null && _e !== void 0 ? _e : _g.memoizedValues = {}; const value = create(); data.current.memoizedDeps[name] = deps; data.current.memoizedValues[name] = value; return value; } }), hotkeys: { focusNextItem: { hotkey: "ArrowDown", canRepeat: true, preventDefault: true, isEnabled: (tree) => { var _a, _b; return !((_b = (_a = tree.isSearchOpen) === null || _a === void 0 ? void 0 : _a.call(tree)) !== null && _b !== void 0 ? _b : false) && !tree.getState().dnd; }, handler: (e, tree) => { tree.focusNextItem(); tree.updateDomFocus(); } }, focusPreviousItem: { hotkey: "ArrowUp", canRepeat: true, preventDefault: true, isEnabled: (tree) => { var _a, _b; return !((_b = (_a = tree.isSearchOpen) === null || _a === void 0 ? void 0 : _a.call(tree)) !== null && _b !== void 0 ? _b : false) && !tree.getState().dnd; }, handler: (e, tree) => { tree.focusPreviousItem(); tree.updateDomFocus(); } }, expandOrDown: { hotkey: "ArrowRight", canRepeat: true, handler: (e, tree) => { const item = tree.getFocusedItem(); if (item.isExpanded() || !item.isFolder()) { tree.focusNextItem(); tree.updateDomFocus(); } else { item.expand(); } } }, collapseOrUp: { hotkey: "ArrowLeft", canRepeat: true, handler: (e, tree) => { var _a; const item = tree.getFocusedItem(); if ((!item.isExpanded() || !item.isFolder()) && item.getItemMeta().level !== 0) { (_a = item.getParent()) === null || _a === void 0 ? void 0 : _a.setFocused(); tree.updateDomFocus(); } else { item.collapse(); } } }, focusFirstItem: { hotkey: "Home", handler: (e, tree) => { tree.focusItem(tree.getItems()[0].getId()); tree.updateDomFocus(); } }, focusLastItem: { hotkey: "End", handler: (e, tree) => { tree.focusItem(tree.getItems()[tree.getItems().length - 1].getId()); tree.updateDomFocus(); } } } }; // node_modules/@headless-tree/core/lib/esm/core/create-tree.js var buildItemInstance = (features, tree, itemId) => { var _a, _b; const itemInstance = {}; for (const feature of features) { Object.assign(itemInstance, (_b = (_a = feature.createItemInstance) === null || _a === void 0 ? void 0 : _a.call(feature, Object.assign({}, itemInstance), itemInstance, tree, itemId)) !== null && _b !== void 0 ? _b : {}); } return itemInstance; }; var verifyFeatures = (features) => { var _a; const loadedFeatures = features === null || features === void 0 ? void 0 : features.map((feature) => feature.key); for (const feature of features !== null && features !== void 0 ? features : []) { const missingDependency = (_a = feature.deps) === null || _a === void 0 ? void 0 : _a.find((dep) => !(loadedFeatures === null || loadedFeatures === void 0 ? void 0 : loadedFeatures.includes(dep))); if (missingDependency) { throw new Error(`${feature.key} needs ${missingDependency}`); } } }; var compareFeatures = (feature1, feature2) => { var _a; if (feature2.key && ((_a = feature1.overwrites) === null || _a === void 0 ? void 0 : _a.includes(feature2.key))) { return 1; } return -1; }; var sortFeatures = (features = []) => features.sort(compareFeatures); var createTree = (initialConfig) => { var _a, _b, _c, _d, _e; const treeInstance = {}; const additionalFeatures = [ treeFeature, ...sortFeatures(initialConfig.features) ]; verifyFeatures(additionalFeatures); let state = additionalFeatures.reduce((acc, feature) => { var _a2, _b2; return (_b2 = (_a2 = feature.getInitialState) === null || _a2 === void 0 ? void 0 : _a2.call(feature, acc, treeInstance)) !== null && _b2 !== void 0 ? _b2 : acc; }, (_b = (_a = initialConfig.initialState) !== null && _a !== void 0 ? _a : initialConfig.state) !== null && _b !== void 0 ? _b : {}); let config = additionalFeatures.reduce((acc, feature) => { var _a2, _b2; return (_b2 = (_a2 = feature.getDefaultConfig) === null || _a2 === void 0 ? void 0 : _a2.call(feature, acc, treeInstance)) !== null && _b2 !== void 0 ? _b2 : acc; }, initialConfig); const stateHandlerNames = additionalFeatures.reduce((acc, feature) => Object.assign(Object.assign({}, acc), feature.stateHandlerNames), {}); let treeElement; const treeDataRef = { current: {} }; const itemInstancesMap = {}; let itemInstances = []; const itemElementsMap = {}; const itemDataRefs = {}; let itemMetaMap = {}; const hotkeyPresets = {}; const rebuildItemMeta = (main) => { itemInstances = []; itemMetaMap = {}; const rootInstance = buildItemInstance([main, ...additionalFeatures], treeInstance, config.rootItemId); itemInstancesMap[config.rootItemId] = rootInstance; itemMetaMap[config.rootItemId] = { itemId: config.rootItemId, index: -1, parentId: null, level: -1, posInSet: 0, setSize: 1 }; for (const item of treeInstance.getItemsMeta()) { itemMetaMap[item.itemId] = item; if (!itemInstancesMap[item.itemId]) { const instance = buildItemInstance([main, ...additionalFeatures], treeInstance, item.itemId); itemInstancesMap[item.itemId] = instance; itemInstances.push(instance); } else { itemInstances.push(itemInstancesMap[item.itemId]); } } console.log("REBUILT"); }; const eachFeature = (fn) => { for (const feature of additionalFeatures) { fn(feature); } }; const mainFeature = { key: "main", createTreeInstance: (prev) => Object.assign(Object.assign({}, prev), { getState: () => state, setState: (updater) => { var _a2; (_a2 = config.setState) === null || _a2 === void 0 ? void 0 : _a2.call(config, state); }, applySubStateUpdate: (stateName, updater) => { state[stateName] = typeof updater === "function" ? updater(state[stateName]) : updater; config[stateHandlerNames[stateName]](state[stateName]); }, rebuildTree: () => { var _a2; rebuildItemMeta(mainFeature); (_a2 = config.setState) === null || _a2 === void 0 ? void 0 : _a2.call(config, state); }, getConfig: () => config, setConfig: (updater) => { config = typeof updater === "function" ? updater(config) : updater; if (config.state) { state = Object.assign(Object.assign({}, state), config.state); } }, getItemInstance: (itemId) => itemInstancesMap[itemId], getItems: () => itemInstances, registerElement: (element) => { if (treeElement === element) { return; } if (treeElement && !element) { eachFeature((feature) => { var _a2; return (_a2 = feature.onTreeUnmount) === null || _a2 === void 0 ? void 0 : _a2.call(feature, treeInstance, treeElement); }); } else if (!treeElement && element) { eachFeature((feature) => { var _a2; return (_a2 = feature.onTreeMount) === null || _a2 === void 0 ? void 0 : _a2.call(feature, treeInstance, element); }); } treeElement = element; }, getElement: () => treeElement, getDataRef: () => treeDataRef, getHotkeyPresets: () => hotkeyPresets }), createItemInstance: (prev, instance, _, itemId) => Object.assign(Object.assign({}, prev), { registerElement: (element) => { if (itemElementsMap[itemId] === element) { return; } const oldElement = itemElementsMap[itemId]; if (oldElement && !element) { eachFeature((feature) => { var _a2; return (_a2 = feature.onItemUnmount) === null || _a2 === void 0 ? void 0 : _a2.call(feature, instance, oldElement, treeInstance); }); } else if (!oldElement && element) { eachFeature((feature) => { var _a2; return (_a2 = feature.onItemMount) === null || _a2 === void 0 ? void 0 : _a2.call(feature, instance, element, treeInstance); }); } itemElementsMap[itemId] = element; }, getElement: () => itemElementsMap[itemId], // eslint-disable-next-line no-return-assign getDataRef: () => { var _a2; return (_a2 = itemDataRefs[itemId]) !== null && _a2 !== void 0 ? _a2 : itemDataRefs[itemId] = { current: {} }; }, getItemMeta: () => itemMetaMap[itemId] }) }; const features = [mainFeature, ...additionalFeatures]; for (const feature of features) { Object.assign(treeInstance, (_d = (_c = feature.createTreeInstance) === null || _c === void 0 ? void 0 : _c.call(feature, Object.assign({}, treeInstance), treeInstance)) !== null && _d !== void 0 ? _d : {}); Object.assign(hotkeyPresets, (_e = feature.hotkeys) !== null && _e !== void 0 ? _e : {}); } rebuildItemMeta(mainFeature); return treeInstance; }; // node_modules/@headless-tree/core/lib/esm/features/drag-and-drop/types.js var DropTargetPosition; (function(DropTargetPosition2) { DropTargetPosition2["Top"] = "top"; DropTargetPosition2["Bottom"] = "bottom"; DropTargetPosition2["Item"] = "item"; })(DropTargetPosition || (DropTargetPosition = {})); // node_modules/@headless-tree/core/lib/esm/features/selection/feature.js var selectionFeature = { key: "selection", getInitialState: (initialState) => Object.assign({ selectedItems: [] }, initialState), getDefaultConfig: (defaultConfig, tree) => Object.assign({ setSelectedItems: makeStateUpdater("selectedItems", tree) }, defaultConfig), stateHandlerNames: { selectedItems: "setSelectedItems" }, createTreeInstance: (prev, instance) => Object.assign(Object.assign({}, prev), { setSelectedItems: (selectedItems) => { instance.applySubStateUpdate("selectedItems", selectedItems); }, // TODO memo getSelectedItems: () => { return instance.getState().selectedItems.map(instance.getItemInstance); } }), createItemInstance: (prev, item, tree) => Object.assign(Object.assign({}, prev), { select: () => { const { selectedItems } = tree.getState(); tree.setSelectedItems(selectedItems.includes(item.getItemMeta().itemId) ? selectedItems : [...selectedItems, item.getItemMeta().itemId]); }, deselect: () => { const { selectedItems } = tree.getState(); tree.setSelectedItems(selectedItems.filter((id) => id !== item.getItemMeta().itemId)); }, isSelected: () => { const { selectedItems } = tree.getState(); return selectedItems.includes(item.getItemMeta().itemId); }, selectUpTo: (ctrl) => { const indexA = item.getItemMeta().index; const indexB = tree.getFocusedItem().getItemMeta().index; const [a, b] = indexA < indexB ? [indexA, indexB] : [indexB, indexA]; const newSelectedItems = tree.getItems().slice(a, b + 1).map((treeItem) => treeItem.getItemMeta().itemId); if (!ctrl) { tree.setSelectedItems(newSelectedItems); return; } const { selectedItems } = tree.getState(); const uniqueSelectedItems = [ .../* @__PURE__ */ new Set([...selectedItems, ...newSelectedItems]) ]; tree.setSelectedItems(uniqueSelectedItems); }, toggleSelect: () => { if (item.isSelected()) { item.deselect(); } else { item.select(); } }, getProps: () => Object.assign(Object.assign({}, prev.getProps()), { "aria-selected": item.isSelected() ? "true" : "false", onClick: item.getMemoizedProp("selection/onClick", () => (e) => { var _a, _b; if (e.shiftKey) { item.selectUpTo(e.ctrlKey || e.metaKey); } else if (e.ctrlKey || e.metaKey) { item.toggleSelect(); } else { tree.setSelectedItems([item.getItemMeta().itemId]); } (_b = (_a = prev.getProps()).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, e); }) }) }), hotkeys: { // setSelectedItem: { // hotkey: "space", // handler: (e, tree) => { // tree.setSelectedItems([tree.getFocusedItem().getId()]); // }, // }, toggleSelectItem: { hotkey: "ctrl+space", handler: (e, tree) => { tree.getFocusedItem().toggleSelect(); } }, selectUpwards: { hotkey: "shift+ArrowUp", handler: () => { } }, selectDownwards: { hotkey: "shift+ArrowDown", handler: () => { } }, selectUpwardsCtrl: { hotkey: "shift+ctrl+ArrowUp", handler: () => { } }, selectDownwardsCtrl: { hotkey: "shift+ctrl+ArrowUp", handler: () => { } }, selectAll: { hotkey: "Control+a", preventDefault: true, handler: (e, tree) => { tree.setSelectedItems(tree.getItems().map((item) => item.getId())); } } } }; // node_modules/@headless-tree/core/lib/esm/features/async-data-loader/feature.js var asyncDataLoaderFeature = { key: "async-data-loader", getInitialState: (initialState) => Object.assign({ loadingItems: [] }, initialState), getDefaultConfig: (defaultConfig, tree) => Object.assign({ setLoadingItems: makeStateUpdater("loadingItems", tree) }, defaultConfig), stateHandlerNames: { loadingItems: "setLoadingItems" }, createTreeInstance: (prev, instance) => Object.assign(Object.assign({}, prev), { retrieveItemData: (itemId) => { var _a, _b, _c, _d, _e; var _f, _g; const config = instance.getConfig(); const dataRef = instance.getDataRef(); (_a = (_f = dataRef.current).itemData) !== null && _a !== void 0 ? _a : _f.itemData = {}; (_b = (_g = dataRef.current).childrenIds) !== null && _b !== void 0 ? _b : _g.childrenIds = {}; if (dataRef.current.itemData[itemId]) { return dataRef.current.itemData[itemId]; } if (!instance.getState().loadingItems.includes(itemId)) { instance.applySubStateUpdate("loadingItems", (loadingItems) => [ ...loadingItems, itemId ]); (_c = config.asyncDataLoader) === null || _c === void 0 ? void 0 : _c.getItem(itemId).then((item) => { var _a2; dataRef.current.itemData[itemId] = item; (_a2 = config.onLoadedItem) === null || _a2 === void 0 ? void 0 : _a2.call(config, itemId, item); instance.applySubStateUpdate("loadingItems", (loadingItems) => loadingItems.filter((id) => id !== itemId)); }); } return (_e = (_d = config.createLoadingItemData) === null || _d === void 0 ? void 0 : _d.call(config)) !== null && _e !== void 0 ? _e : null; }, retrieveChildrenIds: (itemId) => { var _a, _b, _c, _d, _e; var _f, _g; const config = instance.getConfig(); const dataRef = instance.getDataRef(); (_a = (_f = dataRef.current).itemData) !== null && _a !== void 0 ? _a : _f.itemData = {}; (_b = (_g = dataRef.current).childrenIds) !== null && _b !== void 0 ? _b : _g.childrenIds = {}; if (dataRef.current.childrenIds[itemId]) { return dataRef.current.childrenIds[itemId]; } if (instance.getState().loadingItems.includes(itemId)) { return []; } instance.applySubStateUpdate("loadingItems", (loadingItems) => [ ...loadingItems, itemId ]); if ((_c = config.asyncDataLoader) === null || _c === void 0 ? void 0 : _c.getChildrenWithData) { (_d = config.asyncDataLoader) === null || _d === void 0 ? void 0 : _d.getChildrenWithData(itemId).then((children) => { var _a2, _b2; for (const { id, data } of children) { dataRef.current.itemData[id] = data; (_a2 = config.onLoadedItem) === null || _a2 === void 0 ? void 0 : _a2.call(config, id, data); } const childrenIds = children.map(({ id }) => id); dataRef.current.childrenIds[itemId] = childrenIds; (_b2 = config.onLoadedChildren) === null || _b2 === void 0 ? void 0 : _b2.call(config, itemId, childrenIds); instance.applySubStateUpdate("loadingItems", (loadingItems) => loadingItems.filter((id) => id !== itemId)); instance.rebuildTree(); }); } else { (_e = config.asyncDataLoader) === null || _e === void 0 ? void 0 : _e.getChildren(itemId).then((childrenIds) => { var _a2; dataRef.current.childrenIds[itemId] = childrenIds; (_a2 = config.onLoadedChildren) === null || _a2 === void 0 ? void 0 : _a2.call(config, itemId, childrenIds); instance.applySubStateUpdate("loadingItems", (loadingItems) => loadingItems.filter((id) => id !== itemId)); instance.rebuildTree(); }); } return []; }, invalidateItemData: (itemId) => { var _a; const dataRef = instance.getDataRef(); (_a = dataRef.current.itemData) === null || _a === void 0 ? true : delete _a[itemId]; instance.retrieveItemData(itemId); }, invalidateChildrenIds: (itemId) => { var _a; const dataRef = instance.getDataRef(); (_a = dataRef.current.childrenIds) === null || _a === void 0 ? true : delete _a[itemId]; instance.retrieveChildrenIds(itemId); } }), createItemInstance: (prev, item, tree) => Object.assign(Object.assign({}, prev), { isLoading: () => tree.getState().loadingItems.includes(item.getItemMeta().itemId), invalidateItemData: () => tree.invalidateItemData(item.getItemMeta().itemId), invalidateChildrenIds: () => tree.invalidateChildrenIds(item.getItemMeta().itemId) }) }; // node_modules/@headless-tree/core/lib/esm/features/drag-and-drop/utils.js var getDragCode = ({ item, childIndex }) => `${item.getId()}__${childIndex !== null && childIndex !== void 0 ? childIndex : "none"}`; var getDropOffset = (e, item) => { var _a; const bb = (_a = item.getElement()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect(); return bb ? (e.pageY - bb.top) / bb.height : 0.5; }; var canDrop = (dataTransfer, target, tree) => { var _a, _b, _c, _d; const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems; const config = tree.getConfig(); if (draggedItems && !((_c = (_b = config.canDrop) === null || _b === void 0 ? void 0 : _b.call(config, draggedItems, target)) !== null && _c !== void 0 ? _c : true)) { return false; } if (!draggedItems && dataTransfer && !((_d = config.canDropForeignDragObject) === null || _d === void 0 ? void 0 : _d.call(config, dataTransfer, target))) { return false; } return true; }; var getDropTargetPosition = (offset, topLinePercentage, bottomLinePercentage) => { if (offset < topLinePercentage) { return DropTargetPosition.Top; } if (offset > bottomLinePercentage) { return DropTargetPosition.Bottom; } return DropTargetPosition.Item; }; var getDropTarget = (e, item, tree, canDropInbetween = tree.getConfig().canDropInbetween) => { var _a, _b, _c, _d; const config = tree.getConfig(); const draggedItems = (_b = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems) !== null && _b !== void 0 ? _b : []; const itemTarget = { item, childIndex: null, insertionIndex: null }; const parentTarget = { item: item.getParent(), childIndex: null, insertionIndex: null }; if (!canDropInbetween) { if (!canDrop(e.dataTransfer, parentTarget, tree)) { return getDropTarget(e, item.getParent(), tree, false); } return itemTarget; } const canDropInside = canDrop(e.dataTransfer, itemTarget, tree); const offset = getDropOffset(e, item); const pos = canDropInside ? getDropTargetPosition(offset, (_c = config.topLinePercentage) !== null && _c !== void 0 ? _c : 0.3, (_d = config.bottomLinePercentage) !== null && _d !== void 0 ? _d : 0.7) : getDropTargetPosition(offset, 0.5, 0.5); if (pos === DropTargetPosition.Item) { return itemTarget; } if (!canDrop(e.dataTransfer, parentTarget, tree)) { return getDropTarget(e, item.getParent(), tree, false); } const childIndex = item.getIndexInParent() + (pos === DropTargetPosition.Top ? 0 : 1); const numberOfDragItemsBeforeTarget = item.getParent().getChildren().slice(0, childIndex).reduce((counter, child) => child && (draggedItems === null || draggedItems === void 0 ? void 0 : draggedItems.some((i) => i.getId() === child.getId())) ? ++counter : counter, 0); return { item: item.getParent(), childIndex, // TODO performance could be improved by computing this only when dragcode changed insertionIndex: childIndex - numberOfDragItemsBeforeTarget }; }; // node_modules/@headless-tree/core/lib/esm/features/drag-and-drop/feature.js var dragAndDropFeature = { key: "dragAndDrop", deps: ["selection"], getDefaultConfig: (defaultConfig, tree) => Object.assign({ canDrop: (_, target) => target.item.isFolder(), canDropForeignDragObject: () => false, setDndState: makeStateUpdater("dnd", tree) }, defaultConfig), stateHandlerNames: { dnd: "setDndState" }, createTreeInstance: (prev, tree) => Object.assign(Object.assign({}, prev), { getDropTarget: () => { var _a, _b; return (_b = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.dragTarget) !== null && _b !== void 0 ? _b : null; }, getDragLineData: () => { var _a, _b, _c, _d, _e; const target = tree.getDropTarget(); const intend = ((_a = target === null || target === void 0 ? void 0 : target.item.getItemMeta().level) !== null && _a !== void 0 ? _a : 0) + 1; if (!target || target.childIndex === null) return null; const children = target.item.getChildren(); if (target.childIndex === children.length) { const bb2 = (_c = (_b = children[target.childIndex - 1]) === null || _b === void 0 ? void 0 : _b.getElement()) === null || _c === void 0 ? void 0 : _c.getBoundingClientRect(); if (bb2) { return { intend, top: bb2.bottom, left: bb2.left, right: bb2.right }; } } const bb = (_e = (_d = children[target.childIndex]) === null || _d === void 0 ? void 0 : _d.getElement()) === null || _e === void 0 ? void 0 : _e.getBoundingClientRect(); if (bb) { return { intend, top: bb.top, left: bb.left, right: bb.right }; } return null; } }), createItemInstance: (prev, item, tree) => Object.assign(Object.assign({}, prev), { getProps: () => { var _a, _b, _c; return Object.assign(Object.assign({}, prev.getProps()), { draggable: (_c = (_b = (_a = tree.getConfig()).isItemDraggable) === null || _b === void 0 ? void 0 : _b.call(_a, item)) !== null && _c !== void 0 ? _c : true, onDragStart: item.getMemoizedProp("dnd/onDragStart", () => (e) => { var _a2, _b2, _c2; const selectedItems = tree.getSelectedItems(); const items = selectedItems.includes(item) ? selectedItems : [item]; const config = tree.getConfig(); if (!selectedItems.includes(item)) { tree.setSelectedItems([item.getItemMeta().itemId]); } if (!((_b2 = (_a2 = config.canDrag) === null || _a2 === void 0 ? void 0 : _a2.call(config, items)) !== null && _b2 !== void 0 ? _b2 : true)) { e.preventDefault(); return; } if (config.createForeignDragObject) { const { format, data } = config.createForeignDragObject(items); (_c2 = e.dataTransfer) === null || _c2 === void 0 ? void 0 : _c2.setData(format, data); } tree.applySubStateUpdate("dnd", { draggedItems: items, draggingOverItem: tree.getFocusedItem() }); }), onDragOver: item.getMemoizedProp("dnd/onDragOver", () => (e) => { var _a2, _b2, _c2; const target = getDropTarget(e, item, tree); const dataRef = tree.getDataRef(); if (!((_a2 = tree.getState().dnd) === null || _a2 === void 0 ? void 0 : _a2.draggedItems) && !((_c2 = (_b2 = tree.getConfig()).canDropForeignDragObject) === null || _c2 === void 0 ? void 0 : _c2.call(_b2, e.dataTransfer, target))) { return; } if (!canDrop(e.dataTransfer, target, tree)) { return; } e.preventDefault(); const nextDragCode = getDragCode(target); if (nextDragCode === dataRef.current.lastDragCode) { return; } dataRef.current.lastDragCode = nextDragCode; tree.applySubStateUpdate("dnd", (state) => Object.assign(Object.assign({}, state), { dragTarget: target, draggingOverItem: item })); }), onDragLeave: item.getMemoizedProp("dnd/onDragLeave", () => () => { const dataRef = tree.getDataRef(); dataRef.current.lastDragCode = "no-drag"; tree.applySubStateUpdate("dnd", (state) => Object.assign(Object.assign({}, state), { draggingOverItem: void 0, dragTarget: void 0 })); }), onDragEnd: item.getMemoizedProp("dnd/onDragEnd", () => (e) => { var _a2, _b2, _c2; const draggedItems = (_a2 = tree.getState().dnd) === null || _a2 === void 0 ? void 0 : _a2.draggedItems; tree.applySubStateUpdate("dnd", null); if (e.dataTransfer.dropEffect === "none" || !draggedItems) { return; } (_c2 = (_b2 = tree.getConfig()).onCompleteForeignDrop) === null || _c2 === void 0 ? void 0 : _c2.call(_b2, draggedItems); }), onDrop: item.getMemoizedProp("dnd/onDrop", () => (e) => { var _a2, _b2, _c2; const dataRef = tree.getDataRef(); const target = getDropTarget(e, item, tree); if (!canDrop(e.dataTransfer, target, tree)) { return; } e.preventDefault(); const config = tree.getConfig(); const draggedItems = (_a2 = tree.getState().dnd) === null || _a2 === void 0 ? void 0 : _a2.draggedItems; dataRef.current.lastDragCode = void 0; tree.applySubStateUpdate("dnd", null); if (draggedItems) { (_b2 = config.onDrop) === null || _b2 === void 0 ? void 0 : _b2.call(config, draggedItems, target); } else { (_c2 = config.onDropForeignDragObject) === null || _c2 === void 0 ? void 0 : _c2.call(config, e.dataTransfer, target); } }) }); }, isDropTarget: () => { const target = tree.getDropTarget(); return target ? target.item.getId() === item.getId() : false; }, isDropTargetAbove: () => { const target = tree.getDropTarget(); if (!target || target.childIndex === null || target.item !== item.getParent()) return false; return target.childIndex === item.getItemMeta().posInSet; }, isDropTargetBelow: () => { const target = tree.getDropTarget(); if (!target || target.childIndex === null || target.item !== item.getParent()) return false; return target.childIndex - 1 === item.getItemMeta().posInSet; }, isDraggingOver: () => { var _a, _b; return ((_b = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggingOverItem) === null || _b === void 0 ? void 0 : _b.getId()) === item.getId(); } }) }; // node_modules/@headless-tree/react/lib/esm/index.js import { useState } from "react"; var useTree = (config) => { const [tree] = useState(() => ({ current: createTree(config) })); const [state, setState] = useState(() => tree.current.getState()); tree.current.setConfig((prev) => Object.assign(Object.assign(Object.assign({}, prev), config), { state: Object.assign(Object.assign({}, state), config.state), setState: (state2) => { var _a; setState(state2); (_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state2); } })); return tree.current; }; // src/dashboard/view/EntryTree.tsx import { EntryPhase, Type } from "alinea/core"; import { Icon, fromModule, px } from "alinea/ui"; import { IcOutlineDescription } from "alinea/ui/icons/IcOutlineDescription"; import { IcRoundArchive } from "alinea/ui/icons/IcRoundArchive"; import { IcRoundEdit } from "alinea/ui/icons/IcRoundEdit"; import { IcRoundKeyboardArrowDown } from "alinea/ui/icons/IcRoundKeyboardArrowDown"; import { IcRoundKeyboardArrowRight } from "alinea/ui/icons/IcRoundKeyboardArrowRight"; import { IcRoundTranslate } from "alinea/ui/icons/IcRoundTranslate"; import { useEffect, useRef } from "react"; import { changedEntriesAtom, graphAtom } from "../atoms/DbAtoms.js"; import { rootId, useEntryTreeProvider } from "../atoms/EntryAtoms.js"; import { entryLocationAtom } from "../atoms/NavigationAtoms.js"; import { useConfig } from "../hook/UseConfig.js"; import { useLocale } from "../hook/UseLocale.js"; import { useNav } from "../hook/UseNav.js"; import { useRoot } from "../hook/UseRoot.js"; import { useNavigate } from "../util/HashRouter.js"; // src/dashboard/view/EntryTree.module.scss var EntryTree_module_default = { "tree": "alinea-EntryTree-tree", "tree-item": "alinea-EntryTree-tree-item", "treeItem": "alinea-EntryTree-tree-item", "tree-item-icon": "alinea-EntryTree-tree-item-icon", "treeItemIcon": "alinea-EntryTree-tree-item-icon", "is-selected": "alinea-EntryTree-is-selected", "isSelected": "alinea-EntryTree-is-selected", "is-drop": "alinea-EntryTree-is-drop", "isDrop": "alinea-EntryTree-is-drop", "is-dropAbove": "alinea-EntryTree-is-dropAbove", "isDropAbove": "alinea-EntryTree-is-dropAbove", "is-dropBelow": "alinea-EntryTree-is-dropBelow", "isDropBelow": "alinea-EntryTree-is-dropBelow", "tree-item-label": "alinea-EntryTree-tree-item-label", "treeItemLabel": "alinea-EntryTree-tree-item-label", "tree-item-label-itemName": "alinea-EntryTree-tree-item-label-itemName", "treeItemLabelItemName": "alinea-EntryTree-tree-item-label-itemName", "is-untranslated": "alinea-EntryTree-is-untranslated", "isUntranslated": "alinea-EntryTree-is-untranslated", "tree-item-arrow": "alinea-EntryTree-tree-item-arrow", "treeItemArrow": "alinea-EntryTree-tree-item-arrow", "tree-title": "alinea-EntryTree-tree-title", "treeTitle": "alinea-EntryTree-tree-title", "tree-status": "alinea-EntryTree-tree-status", "treeStatus": "alinea-EntryTree-tree-status", "is-draft": "alinea-EntryTree-is-draft", "isDraft": "alinea-EntryTree-is-draft" }; // src/dashboard/view/EntryTree.tsx import { Fragment, jsx, jsxs } from "react/jsx-runtime"; import { createElement } from "react"; var styles = fromModule(EntryTree_module_default); function selectedEntry(locale, item) { return item.entries.find((entry) => entry.locale === locale) ?? item.entries[0]; } function EntryTreeItem({ item, data }) { const { entryId } = useAtomValue(entryLocationAtom); const locale = useLocale(); const { schema } = useConfig(); const currentData = useRef(data); const itemData = data ?? currentData.current; if (!itemData) return null; currentData.current = itemData; const selected = selectedEntry(locale, itemData); const { icon } = Type.meta(schema[selected.type]); const isDraft = selected.phase === EntryPhase.Draft; const isUntranslated = locale && selected.locale !== locale; const isArchived = selected.phase === EntryPhase.Archived; const isSelected = entryId && itemData.id === entryId; return /* @__PURE__ */ createElement( "div", { ...item.getProps(), ref: item.registerElement, className: styles.tree.item({ untranslated: isUntranslated, selected: isSelected, drop: item.isDropTarget() && item.isDraggingOver(), dropAbove: item.isDropTargetAbove() && item.isDraggingOver(), dropBelow: item.isDropTargetBelow() && item.isDraggingOver() }), key: item.getId(), "data-id": item.getId() }, /* @__PURE__ */ jsxs( "button", { className: styles.tree.item.label(), title: selectedEntry(locale, itemData).title, style: { paddingLeft: px((item.getItemMeta().level + 1) * 12) }, children: [ /* @__PURE__ */ jsx("span", { className: styles.tree.item.icon(), children: /* @__PURE__ */ jsx( Icon, { icon: isUntranslated ? IcRoundTranslate : icon ?? IcOutlineDescription } ) }), /* @__PURE__ */ jsx("span", { className: styles.tree.item.label.itemName(), children: selectedEntry(locale, itemData).title }), item.isFolder() && /* @__PURE__ */ jsx("span", { className: styles.tree.item.arrow(), children: item.isExpanded() ? /* @__PURE__ */ jsx(Icon, { icon: IcRoundKeyboardArrowDown, size: 18 }) : /* @__PURE__ */ jsx(Icon, { icon: IcRoundKeyboardArrowRight, size: 18 }) }), !isUntranslated && isDraft && /* @__PURE__ */ jsx("span", { className: styles.tree.status({ draft: true }), children: /* @__PURE__ */ jsx(Icon, { icon: IcRoundEdit }) }), !isUntranslated && isArchived && /* @__PURE__ */ jsx("span", { className: styles.tree.status({ archived: true }), children: /* @__PURE__ */ jsx(Icon, { icon: IcRoundArchive, size: 18 }) }) ] } ) ); } function EntryTree({ i18nId: entryId, selected = [] }) { const graph = useAtomValue(graphAtom); const root = useRoot(); const treeProvider = useEntryTreeProvider(); const navigate = useNavigate(); const nav = useNav(); const locale = useLocale(); const tree = useTree({ rootItemId: rootId(root.name), canDropInbetween: true, onDrop(items, target) { return treeProvider.onDrop(items, target); }, asyncDataLoader: treeProvider, getItemName: (item) => item.getItemData() && selectedEntry(locale, item.getItemData()).title, isItemFolder: (item) => item.getItemData() && Boolean(item.getItemData().isFolder), onPrimaryAction: (item) => { navigate(nav.entry({ entryId: item.getId() })); }, initialState: { expandedItems: selected }, state: { selectedItems: entryId ? [entryId] : [] }, features: [ asyncDataLoaderFeature, selectionFeature, dragAndDropFeature // hotkeysCoreFeature ] }); const changed = useAtomValue(changedEntriesAtom); useEffect(() => { ; (async () => { for (const id of selected) { await treeProvider.getChildren(id).then(() => new Promise(requestAnimationFrame)); tree.expandItem(id); } })(); }, [selected.join()]); useEffect(() => { tree.invalidateChildrenIds(rootId(root.name)); }, [treeProvider]); useEffect(() => { for (const i18nId of changed) { try { const item = tree.getItemInstance(i18nId); if (!item) { tree.invalidateChildrenIds(rootId(root.name)); continue; } const parent = item.getParent(); const parentId = parent?.getId(); if (parentId) tree.invalidateChildrenIds(parentId); tree.invalidateChildrenIds(i18nId); tree.invalidateItemData(i18nId); } catch (e) { console.error(e); } } }, [changed]); return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("div", { ref: tree.registerElement, className: styles.tree(), children: tree.getItems().map((item, i) => { const data = item.getItemData(); return /* @__PURE__ */ jsx(EntryTreeItem, { item, data }, item.getId()); }) }) }); } export { EntryTree };