UNPKG

@asup/tree-of-nodes

Version:
539 lines (498 loc) 25.3 kB
import "./main.css"; import {jsxs as $duWW8$jsxs, Fragment as $duWW8$Fragment, jsx as $duWW8$jsx} from "react/jsx-runtime"; import {ContextMenuHandler as $duWW8$ContextMenuHandler} from "@asup/context-menu"; import $duWW8$react, {useContext as $duWW8$useContext, useMemo as $duWW8$useMemo, useState as $duWW8$useState, useEffect as $duWW8$useEffect, useRef as $duWW8$useRef, useCallback as $duWW8$useCallback, createContext as $duWW8$createContext} from "react"; import {ExclamationCircleFill as $duWW8$ExclamationCircleFill, CaretRightFill as $duWW8$CaretRightFill, CaretDownFill as $duWW8$CaretDownFill, CaretRight as $duWW8$CaretRight} from "react-bootstrap-icons"; import {Spinner as $duWW8$Spinner} from "react-bootstrap"; function $parcel$export(e, n, v, s) { Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true}); } var $b65191f6d0a0a991$exports = {}; $parcel$export($b65191f6d0a0a991$exports, "TreeNode", function () { return $47c36cf4281201f5$export$2eba8ec3a333fdbb; }); $parcel$export($b65191f6d0a0a991$exports, "TreeOfNodes", function () { return $ba47aaf387735a90$export$5580fff3e08a8be5; }); $parcel$export($b65191f6d0a0a991$exports, "WordEntry", function () { return $84765747a8c6bfe2$export$14f190ac910bde69; }); const $6303f0814ed0ce8b$export$c6fd3ab3f44300d0 = (id, included, hierarchyNodes)=>{ const processIds = Array.isArray(id) ? id : [ id ]; const current = processIds.map((i)=>hierarchyNodes.find((h)=>h.id === i)).filter((h)=>h !== undefined); if (current.length === 0) return included; const parents = current.map((h)=>h.parentId).map((pid)=>hierarchyNodes.find((h)=>pid === h.id)).filter((p)=>p !== undefined); if (parents.length === 0) return included; else return $6303f0814ed0ce8b$export$c6fd3ab3f44300d0(parents.map((p)=>p.id), [ ...included, ...parents.filter((p)=>!included.includes(p)) ], hierarchyNodes); }; const $33abc00b1ca5c55c$export$bd923365b402cb04 = (id, hierarchyNodes)=>{ const processIds = Array.isArray(id) ? id : [ id ]; const newChildren = hierarchyNodes.filter((h)=>h.parentId !== undefined && processIds.includes(h.parentId) && !processIds.includes(h.id)).map((h)=>h.id); return newChildren.length === 0 ? processIds : $33abc00b1ca5c55c$export$bd923365b402cb04([ ...processIds, ...newChildren ], hierarchyNodes); }; const $886f402bccb0fd30$export$29ec378200e05207 = (0, $duWW8$createContext)(undefined); const $84765747a8c6bfe2$export$14f190ac910bde69 = /*#__PURE__*/ (0, $duWW8$react).forwardRef(({ id: id, value: value, editing: editing, saving: saving, setValue: setValue, sendEscape: sendEscape, style: style, spellCheck: spellCheck = "true" }, ref)=>{ const [currentValue, setCurrentValue] = (0, $duWW8$useState)(value !== null && value !== void 0 ? value : ""); (0, $duWW8$useEffect)(()=>{ setCurrentValue(value !== null && value !== void 0 ? value : ""); }, [ value ]); const returnData = (0, $duWW8$useCallback)(()=>{ setValue === null || setValue === void 0 ? void 0 : setValue(currentValue); }, [ currentValue, setValue ]); const keyPress = (0, $duWW8$useCallback)((e)=>{ if (e.code === "Escape") { setCurrentValue(value !== null && value !== void 0 ? value : ""); sendEscape === null || sendEscape === void 0 ? void 0 : sendEscape(); } else if (e.code === "Enter") returnData(); }, [ returnData, sendEscape, value ]); // Add window onMouseDown event to stop events when editing (0, $duWW8$useEffect)(()=>{ const handleMouseDown = (e)=>{ const target = e.target; if (editing && target.id !== `${id}` && target.id !== `${id}-holder` && target.id !== `${id}-spinner` && target.className !== "ton-rename") { e.preventDefault(); e.stopPropagation(); returnData(); } }; window.addEventListener("mousedown", handleMouseDown); return ()=>{ window.removeEventListener("mousedown", handleMouseDown); }; }, [ editing, id, returnData ]); return !editing ? /*#__PURE__*/ (0, $duWW8$jsx)("span", { className: "ton-label-span", style: style, id: `${id}`, children: value ? value : /*#__PURE__*/ (0, $duWW8$jsx)((0, $duWW8$Fragment), { children: "\xa0" }) }) : /*#__PURE__*/ (0, $duWW8$jsxs)("div", { style: style, id: `${id}-holder`, className: "ton-rename-holder", children: [ saving && /*#__PURE__*/ (0, $duWW8$jsx)((0, $duWW8$Spinner), { id: `${id}-spinner`, size: "sm", animation: "border" }), /*#__PURE__*/ (0, $duWW8$jsx)("input", { autoFocus: true, spellCheck: spellCheck, id: String(id), ref: ref, type: "text", className: "ton-rename", value: currentValue, disabled: saving, onChange: (e)=>setCurrentValue(e.currentTarget.value), onBlur: returnData, onKeyDownCapture: keyPress }) ] }); }); $84765747a8c6bfe2$export$14f190ac910bde69.displayName = "WordEntry"; const $47c36cf4281201f5$export$2eba8ec3a333fdbb = ({ id: id, canRemove: canRemove, canRename: canRename, canAddChildren: canAddChildren, canRemoveChildren: canRemoveChildren, canRenameChildren: canRenameChildren })=>{ // Contexts const treeContext = (0, $duWW8$useContext)((0, $886f402bccb0fd30$export$29ec378200e05207)); // Node information const thisNode = (0, $duWW8$useMemo)(()=>treeContext === null || treeContext === void 0 ? void 0 : treeContext.nodeList.find((n)=>n.id === id), [ id, treeContext === null || treeContext === void 0 ? void 0 : treeContext.nodeList ]); const childNodes = (0, $duWW8$useMemo)(()=>treeContext === null || treeContext === void 0 ? void 0 : treeContext.nodeList.filter((n)=>n.parentId === id), [ id, treeContext === null || treeContext === void 0 ? void 0 : treeContext.nodeList ]); const descendents = (0, $duWW8$useMemo)(()=>{ var _treeContext_nodeList; return (0, $33abc00b1ca5c55c$export$bd923365b402cb04)(id, (_treeContext_nodeList = treeContext === null || treeContext === void 0 ? void 0 : treeContext.nodeList) !== null && _treeContext_nodeList !== void 0 ? _treeContext_nodeList : []); }, [ id, treeContext ]); // State const [error, setError] = (0, $duWW8$useState)(false); const [errorText, setErrorText] = (0, $duWW8$useState)(""); const expanded = (0, $duWW8$useMemo)(()=>{ var _treeContext_expandedNodes_findIndex; return ((_treeContext_expandedNodes_findIndex = treeContext === null || treeContext === void 0 ? void 0 : treeContext.expandedNodes.findIndex((e)=>e === id)) !== null && _treeContext_expandedNodes_findIndex !== void 0 ? _treeContext_expandedNodes_findIndex : -1) > -1; }, [ id, treeContext === null || treeContext === void 0 ? void 0 : treeContext.expandedNodes ]); // Ensures that child nodes are drawn before they are expanded const [hasRenderedClosed, setHasRenderedClosed] = (0, $duWW8$useState)(childNodes !== undefined && childNodes.length > 0); (0, $duWW8$useEffect)(()=>{ if (childNodes && childNodes.length > 0 && !hasRenderedClosed) setHasRenderedClosed(true); }, [ childNodes, hasRenderedClosed ]); // Checkbox const checkRef = (0, $duWW8$useRef)(null); (0, $duWW8$useEffect)(()=>{ if (checkRef.current) { if (treeContext === null || treeContext === void 0 ? void 0 : treeContext.selected.includes(id)) { checkRef.current.checked = true; checkRef.current.indeterminate = false; } else if (descendents.some((d)=>treeContext === null || treeContext === void 0 ? void 0 : treeContext.selected.includes(d))) { checkRef.current.checked = false; checkRef.current.indeterminate = true; } else { checkRef.current.checked = false; checkRef.current.indeterminate = false; } } }, [ descendents, id, treeContext === null || treeContext === void 0 ? void 0 : treeContext.selected ]); // Apply selected border const currentBorder = (0, $duWW8$useMemo)(()=>{ return (treeContext === null || treeContext === void 0 ? void 0 : treeContext.selected.includes(id)) ? "1px solid black" : ""; }, [ id, treeContext === null || treeContext === void 0 ? void 0 : treeContext.selected ]); const nodeColour = (0, $duWW8$useMemo)(()=>{ if (treeContext && treeContext.selected) { const anc = (0, $6303f0814ed0ce8b$export$c6fd3ab3f44300d0)(treeContext.selected, [], treeContext === null || treeContext === void 0 ? void 0 : treeContext.nodeList).map((n)=>n.id); if ([ ...anc, treeContext.selected ].includes(id)) return treeContext.nodeHighlight; } return; }, [ id, treeContext ]); // New node parameters const newNameRef = (0, $duWW8$useRef)(null); const [showNewNode, setShowNewNode] = (0, $duWW8$useState)(false); const [savingNewNode, setSavingNewNode] = (0, $duWW8$useState)(false); // Rename parameters const currentNameRef = (0, $duWW8$useRef)(null); const [renaming, setRenaming] = (0, $duWW8$useState)(false); const [updatingNode, setUpdatingNode] = (0, $duWW8$useState)(false); // Context functions const handleReturn = (0, $duWW8$useCallback)((ret)=>{ if (!ret.success) { setError(true); var _ret_ErrorText; setErrorText((_ret_ErrorText = ret.ErrorText) !== null && _ret_ErrorText !== void 0 ? _ret_ErrorText : "An unknown error has occured"); } else { setError(false); setErrorText(""); } }, []); const confirmNewNode = (0, $duWW8$useCallback)(async (label)=>{ setSavingNewNode(true); if (treeContext === null || treeContext === void 0 ? void 0 : treeContext.onAddChild) handleReturn(await treeContext.onAddChild(id, label)); setSavingNewNode(false); setShowNewNode(false); }, [ handleReturn, id, treeContext ]); const renameNode = (0, $duWW8$useCallback)(async (newLabel)=>{ setRenaming(false); if (treeContext === null || treeContext === void 0 ? void 0 : treeContext.onRename) { setUpdatingNode(true); handleReturn(await treeContext.onRename(id, newLabel)); setUpdatingNode(false); } }, [ handleReturn, id, treeContext ]); const deleteThis = (0, $duWW8$useCallback)(async ()=>{ if (treeContext === null || treeContext === void 0 ? void 0 : treeContext.onRemove) { setUpdatingNode(true); handleReturn(await treeContext.onRemove(id)); setUpdatingNode(false); } }, [ handleReturn, id, treeContext ]); // Context actions const addChild = (0, $duWW8$useCallback)(()=>{ var _treeContext_handleExpandClick; setShowNewNode(true); treeContext === null || treeContext === void 0 ? void 0 : (_treeContext_handleExpandClick = treeContext.handleExpandClick) === null || _treeContext_handleExpandClick === void 0 ? void 0 : _treeContext_handleExpandClick.call(treeContext, id, true); }, [ id, treeContext ]); (0, $duWW8$useEffect)(()=>{ if (showNewNode === true && newNameRef.current) newNameRef.current.focus(); }, [ showNewNode ]); const renameThis = (0, $duWW8$useCallback)(()=>{ var _treeContext_handleSelect; setRenaming(true); treeContext === null || treeContext === void 0 ? void 0 : (_treeContext_handleSelect = treeContext.handleSelect) === null || _treeContext_handleSelect === void 0 ? void 0 : _treeContext_handleSelect.call(treeContext, id); }, [ id, treeContext ]); // Context menu const menuItems = (0, $duWW8$useMemo)(()=>{ const menuItems = []; if (canAddChildren) menuItems.push({ label: "Add", action: addChild }); if (canRename) menuItems.push({ label: "Rename", action: renameThis }); if (canRemove && (childNodes === undefined || childNodes.length === 0)) menuItems.push({ label: "Delete", action: deleteThis }); return menuItems; }, [ addChild, canAddChildren, canRemove, canRename, childNodes, deleteThis, renameThis ]); // Return node return !treeContext ? null : /*#__PURE__*/ (0, $duWW8$jsxs)((0, $duWW8$Fragment), { children: [ /*#__PURE__*/ (0, $duWW8$jsx)((0, $duWW8$ContextMenuHandler), { menuItems: menuItems, style: { display: "inline-block", width: "100%" }, children: /*#__PURE__*/ (0, $duWW8$jsx)("div", { id: `${treeContext.id}-treenode-${id}`, className: "treenode", children: error ? /*#__PURE__*/ (0, $duWW8$jsxs)((0, $duWW8$Fragment), { children: [ /*#__PURE__*/ (0, $duWW8$jsx)((0, $duWW8$ExclamationCircleFill), { color: "var(--bs-danger)" }), " ", errorText ] }) : /*#__PURE__*/ (0, $duWW8$jsxs)("div", { className: "ton-node", children: [ treeContext.showCheckBox && /*#__PURE__*/ (0, $duWW8$jsx)("input", { ref: checkRef, type: "checkbox", role: "checkbox", className: "ton-checkbox", id: `${treeContext.id}-treenode-checkbox-${id}`, onClick: ()=>{ var _treeContext_handleSelect; return (_treeContext_handleSelect = treeContext.handleSelect) === null || _treeContext_handleSelect === void 0 ? void 0 : _treeContext_handleSelect.call(treeContext, descendents); } }), childNodes && childNodes.length > 0 ? !expanded ? /*#__PURE__*/ (0, $duWW8$jsx)((0, $duWW8$CaretRightFill), { id: `${treeContext.id}-treenode-caret-${id}`, style: { width: "16px", height: "16px" }, className: "ton-expander", role: "button", color: nodeColour, "aria-expanded": false, "aria-label": "Expander", onClick: ()=>treeContext.handleExpandClick(id) }) : /*#__PURE__*/ (0, $duWW8$jsx)((0, $duWW8$CaretDownFill), { id: `${treeContext.id}-treenode-caret-${id}`, className: "ton-expander", role: "button", "aria-expanded": true, "aria-label": "Expander", color: nodeColour, onClick: ()=>treeContext.handleExpandClick(id) }) : /*#__PURE__*/ (0, $duWW8$jsx)((0, $duWW8$CaretRight), { id: `${treeContext.id}-treenode-caret-${id}`, className: "ton-expander", role: "button", color: nodeColour, "aria-expanded": false, "aria-label": "Disabled expander", onClick: ()=>{ var _treeContext_handleSelect; return (_treeContext_handleSelect = treeContext.handleSelect) === null || _treeContext_handleSelect === void 0 ? void 0 : _treeContext_handleSelect.call(treeContext, id); } }), thisNode && /*#__PURE__*/ (0, $duWW8$jsx)("div", { className: "ton-label", style: { width: `calc(100% - ${treeContext.showCheckBox ? "32px" : "16px"})` }, onContextMenuCapture: ()=>{ var _treeContext_handleSelect; return (_treeContext_handleSelect = treeContext.handleSelect) === null || _treeContext_handleSelect === void 0 ? void 0 : _treeContext_handleSelect.call(treeContext, id); }, onClickCapture: ()=>{ var _treeContext_handleSelect; if (!treeContext.expandedNodes.includes(id)) treeContext.handleExpandClick(id); (_treeContext_handleSelect = treeContext.handleSelect) === null || _treeContext_handleSelect === void 0 ? void 0 : _treeContext_handleSelect.call(treeContext, id); }, onFocusCapture: ()=>{ var _treeContext_handleSelect; return (_treeContext_handleSelect = treeContext.handleSelect) === null || _treeContext_handleSelect === void 0 ? void 0 : _treeContext_handleSelect.call(treeContext, id); }, children: /*#__PURE__*/ (0, $duWW8$jsx)((0, $84765747a8c6bfe2$export$14f190ac910bde69), { id: `${treeContext.id}-treenode-entry-${id}`, ref: currentNameRef, value: thisNode.label, editing: renaming, saving: updatingNode, setValue: (ret)=>renameNode(ret), sendEscape: ()=>setRenaming(false), style: { border: currentBorder, margin: currentBorder === "" ? "1px" : "", backgroundColor: currentBorder === "" ? "" : treeContext.textHighlight }, spellCheck: treeContext.spellCheck }) }) ] }) }) }), childNodes && /*#__PURE__*/ (0, $duWW8$jsx)("div", { className: `ton-collapsible-wrapper ${expanded && hasRenderedClosed && childNodes.length > 0 ? "" : "collapsed"}`, children: childNodes.length > 0 && /*#__PURE__*/ (0, $duWW8$jsx)("div", { className: "ton-collapsible", children: childNodes.map((h)=>/*#__PURE__*/ (0, $duWW8$jsx)("span", { id: `${treeContext.id}-treenode-child-${h.id}`, className: "ton-child", children: /*#__PURE__*/ (0, $duWW8$jsx)($47c36cf4281201f5$export$2eba8ec3a333fdbb, { id: h.id, canRemove: canRemoveChildren, canRename: canRenameChildren, canAddChildren: canAddChildren, canRemoveChildren: canRemoveChildren, canRenameChildren: canRenameChildren }) }, h.id)) }) }), showNewNode && /*#__PURE__*/ (0, $duWW8$jsx)((0, $84765747a8c6bfe2$export$14f190ac910bde69), { style: { marginLeft: "14px" }, id: `treenode-new-${id}`, ref: newNameRef, editing: true, setValue: (ret)=>confirmNewNode(ret), saving: savingNewNode, sendEscape: ()=>setShowNewNode(false), spellCheck: treeContext.spellCheck }) ] }); }; $47c36cf4281201f5$export$2eba8ec3a333fdbb.displayName = "TreeNode"; const $c7008d808d3e1c7a$export$40c47a7ac5f85aba = (nodeList, selected, expandedNodes)=>{ return [ ...expandedNodes, ...(0, $6303f0814ed0ce8b$export$c6fd3ab3f44300d0)(selected, [], nodeList).map((n)=>n.id).filter((k)=>!expandedNodes.includes(k)) ].sort((a, b)=>`${a}`.localeCompare(`${b}`)); }; const $ba47aaf387735a90$export$5580fff3e08a8be5 = ({ id: id, nodeList: nodeList, roots: roots, selected: selected = [], showCheckBox: showCheckBox = false, handleSelect: handleSelect, onAdd: onAdd, onRename: onRename, onRemove: onRemove, canRemoveRoot: canRemoveRoot = false, canRenameRoot: canRenameRoot = false, canAddChildren: canAddChildren = false, canRemoveChildren: canRemoveChildren = false, canRenameChildren: canRenameChildren = false, nodeHighlight: nodeHighlight = "red", textHighlight: textHighlight = "rgba(255, 0, 0, 0.2)", spellCheck: spellCheck = "true" })=>{ const [expandedNodes, setExpandedNodes] = (0, $duWW8$useState)([]); const selectedArray = (0, $duWW8$useMemo)(()=>Array.isArray(selected) ? selected : [ selected ], [ selected ]); (0, $duWW8$useEffect)(()=>{ if (selectedArray.length > 0) { // Check all nodes are showing that should be const shouldExpand = (0, $c7008d808d3e1c7a$export$40c47a7ac5f85aba)(nodeList, selectedArray, expandedNodes); if (shouldExpand.filter((n)=>!expandedNodes.includes(n)).length > 0) setExpandedNodes(shouldExpand); } }, [ expandedNodes, nodeList, selectedArray ]); // Change expansion and update contexts const changeExpand = (0, $duWW8$useCallback)((eKey, force)=>{ const newExpandedNodes = [ ...expandedNodes ]; const ix = newExpandedNodes.findIndex((nKey)=>nKey === eKey); if (ix === -1 && force === undefined || force === true) newExpandedNodes.push(eKey); else newExpandedNodes.splice(ix, 1); setExpandedNodes(newExpandedNodes); }, [ expandedNodes ]); return /*#__PURE__*/ (0, $duWW8$jsx)("div", { id: id, className: "tree-of-nodes", children: /*#__PURE__*/ (0, $duWW8$jsx)((0, $886f402bccb0fd30$export$29ec378200e05207).Provider, { value: { id: id, nodeList: nodeList, selected: selectedArray, showCheckBox: showCheckBox, handleSelect: handleSelect, expandedNodes: expandedNodes, handleExpandClick: (r, f)=>changeExpand(r, f), onAddChild: onAdd, onRename: onRename, onRemove: onRemove, nodeHighlight: nodeHighlight, textHighlight: textHighlight, spellCheck: spellCheck }, children: roots.map((r)=>/*#__PURE__*/ (0, $duWW8$jsx)((0, $47c36cf4281201f5$export$2eba8ec3a333fdbb), { id: r, canRemove: canRemoveRoot, canAddChildren: canAddChildren, canRename: canRenameRoot, canRemoveChildren: canRemoveChildren, canRenameChildren: canRenameChildren }, r)) }) }); }; $ba47aaf387735a90$export$5580fff3e08a8be5.displayName = "TreeOfNodes"; var $3d005c8713d7dfb7$exports = {}; $parcel$export($3d005c8713d7dfb7$exports, "getParents", function () { return $6303f0814ed0ce8b$export$c6fd3ab3f44300d0; }); export {$47c36cf4281201f5$export$2eba8ec3a333fdbb as TreeNode, $ba47aaf387735a90$export$5580fff3e08a8be5 as TreeOfNodes, $84765747a8c6bfe2$export$14f190ac910bde69 as WordEntry, $6303f0814ed0ce8b$export$c6fd3ab3f44300d0 as getAncestors}; //# sourceMappingURL=main.js.map