UNPKG

@frontify/fondue

Version:
389 lines (388 loc) 11.7 kB
import { jsx as S, jsxs as me } from "react/jsx-runtime"; import { useSensors as Ie, useSensor as V, PointerSensor as Ne, KeyboardSensor as Se, DndContext as ge, closestCorners as Re, MeasuringStrategy as he, DragOverlay as we } from "@dnd-kit/core"; import { restrictToWindowEdges as De } from "@dnd-kit/modifiers"; import { SortableContext as Ce, verticalListSortingStrategy as Te } from "@dnd-kit/sortable"; import { produce as Oe, enableMapSet as fe } from "immer"; import { isEqual as Y } from "lodash-es"; import { memo as _e, useMemo as D, useReducer as xe, useTransition as ve, useState as g, useEffect as C, useCallback as c, useRef as Le, cloneElement as be } from "react"; import { createPortal as Ae } from "react-dom"; import { TreeContext as Pe } from "./TreeContext.es.js"; import { getTreeNodesWithoutElements as Me, getNodesToRender as je, getReactNodeIdsInFlatArray as Ge, removeReactNodesFromFlatArray as ke } from "./helpers/nodes.es.js"; import { handleKeyDownEvent as He } from "./helpers/treeHandleKeyDown.es.js"; import { sortableTreeKeyboardCoordinates as Ke } from "./utils/keyboardCoordinates.es.js"; import { sensorsActivationConstraint as Fe } from "./helpers/sensorsActivationConstraint.es.js"; import { getAnnouncements as Ue } from "./helpers/getMovementAnnouncements.es.js"; import { TreeItemOverlay as We } from "./TreeItem/TreeItemOverlay.es.js"; import { findIndexById as Be, getNodeChildrenIds as Xe, currentNodesChanged as Ve, getCurrentChildrenForNewNodesIfExpanded as J, updateNodeWithNewChildren as Ye, shouldUpdateTreeState as $ } from "./helpers/reducer.es.js"; import { recursivelyRemoveFragmentsAndEnrichChildren as Je } from "./utils/removeFragmentsAndEnrichChildren.es.js"; import { useDeepCompareEffect as v } from "./utils/useDeepCompareEffect.es.js"; import { getProjection as $e } from "./helpers/projection.es.js"; import { ROOT_ID as qe } from "./helpers/constants.es.js"; const ze = { droppable: { strategy: he.Always } }; fe(); const Qe = Oe((o, n) => { switch (n.type) { case "EXPAND_NODE": { o.expandedIds = new Set(o.expandedIds).add(n.payload); return; } case "SHRINK_NODE": { const d = new Set(o.expandedIds); d.delete(n.payload), o.expandedIds = d; return; } case "SET_SELECTION_MODE": o.selectionMode = n.payload.selectionMode; return; case "SET_PROJECTION": { Y(o.projection, n.payload) || (o.projection = n.payload); return; } case "REGISTER_OVERLAY_ITEM": { o.overlay = n.payload; return; } case "REGISTER_ROOT_NODES": { o.rootNodes = J( o.rootNodes, o.expandedIds, n.payload ); return; } case "REGISTER_NODE_CHILDREN": { const { id: d, children: p } = n.payload; if (Be(o.rootNodes, d) === -1) { console.warn(`Parent element with ID "${d}" not found when registering children.`); return; } const E = Xe(o.rootNodes, d), I = p.map((l) => l.props.id); if (!Y(E, I) || Ve(E, o.rootNodes, p)) { const l = J( o.rootNodes, o.expandedIds, p ); o.rootNodes = Ye(o.rootNodes, d, l); } return; } case "UNREGISTER_NODE_CHILDREN": { const d = Ge(o.rootNodes, n.payload); d.length > 0 && (o.rootNodes = ke(o.rootNodes, d)); return; } case "REGISTER_NODES": { o.nodes = n.payload; return; } case "REPLACE_EXPANDED": { o.expandedIds = new Set(n.payload); return; } case "REPLACE_SELECTED": { o.selectedIds = new Set(n.payload); return; } case "REPLACE_STATE": { o.rootNodes = n.payload.rootNodes, o.overlay = n.payload.overlay, o.projection = n.payload.projection, o.selectedIds = n.payload.selectedIds, o.expandedIds = n.payload.expandedIds, o.selectionMode = n.payload.selectionMode; return; } default: { console.warn(`Updated tree with action "${n.type}" but it has not effect.`); return; } } }), Ze = _e( ({ id: o, onDrop: n, onSelect: d = () => { }, onExpand: p, onShrink: E, children: I, selectedIds: l, expandedIds: R, draggable: L = !1, multiselect: i = !1, dragHandlerPosition: h = "left", enableDragDelay: q = !0, showDragHandlerOnHoverOnly: b = !0, showContentWhileDragging: A = !1, itemStyle: P, "data-test-id": z = "fondue-tree" }) => { var W; const Q = D( () => ({ selectionMode: i ? "multiselect" : "single", selectedIds: new Set(l ?? []), expandedIds: new Set(R ?? []), rootNodes: [], expandedNodes: [], nodes: [], nodesReady: !1, projection: null }), [R, i, l] ), [t, a] = xe(Qe, Q), [, Z] = ve(), [N, M] = g(null), [T, O] = g(null), [f, j] = g(null), [G, _] = g(null); C(() => { const e = (r) => { $(r, i) && a({ type: "SET_SELECTION_MODE", payload: { selectionMode: "multiselect" } }); }, s = (r) => { $(r, i) && a({ type: "SET_SELECTION_MODE", payload: { selectionMode: "single" } }); }; return i && (window.addEventListener("keydown", e), window.addEventListener("keyup", s)), () => { window.removeEventListener("keydown", e), window.removeEventListener("keyup", s); }; }, [i]); const k = c((e) => { a({ type: "REGISTER_OVERLAY_ITEM", payload: e }); }, []), H = c((e) => { a({ type: "REGISTER_NODE_CHILDREN", payload: e }); }, []), K = c((e) => { a({ type: "UNREGISTER_NODE_CHILDREN", payload: e }); }, []), u = c( (e, s = !1) => { d(e, s, Me(t.nodes)); }, [d, t.nodes] ), y = c( (e) => { if (p) return p(e); a({ type: "EXPAND_NODE", payload: e }); }, [p] ), m = c( (e) => { if (E) return E(e); a({ type: "SHRINK_NODE", payload: e }); }, [E] ), ee = (e) => { var B, X; F(); const { over: s, active: r } = e; if (!(s != null && s.id) || !(r != null && r.id) || !((B = t.projection) != null && B.parentId)) return; const x = t.nodes.find((ye) => ye.props.id === r.id), ue = (X = x == null ? void 0 : x.props) == null ? void 0 : X.contentComponent; n == null || n({ id: r.id.toString(), parentId: t.projection.parentId, sort: t.projection.position, contentComponent: ue }); }, oe = ({ active: { id: e, data: s } }) => { j(e), O(e), e && s.current && _({ parentId: s.current.parentId, overId: e }), document.body.style.setProperty("cursor", "grabbing"); }, te = ({ over: e }) => { O((e == null ? void 0 : e.id) ?? null); }, ne = ({ delta: e }) => { M(e.x); }, re = () => { F(); }, F = () => { O(null), j(null), M(0), _(null), document.body.style.setProperty("cursor", "default"); }, se = c( (e) => He( e, t.expandedIds, t.nodes, u, m, y ), [y, m, u, t.expandedIds, t.nodes] ), U = Le({ nodes: t.nodes, offset: N ?? 0 }), [de] = g(() => Ke(U)), ae = Fe({ dragHandlerPosition: h, enableDragDelay: q }), le = Ie( V(Ne, { activationConstraint: ae }), V(Se, { coordinateGetter: de }) ), ie = D(() => Ue(t, G, _), [G, t]); v(() => { I && a({ type: "REGISTER_ROOT_NODES", payload: Je(I, { parentId: qe, level: 0 }) }); }, [I]), v(() => { t.rootNodes.length !== 0 && Z(() => { const e = je(t.rootNodes, t.expandedIds); a({ type: "REGISTER_NODES", payload: e }); }); }, [t.rootNodes, t.expandedIds]), C(() => { a({ type: "REPLACE_EXPANDED", payload: R ?? [] }); }, [R]), C(() => { a({ type: "REPLACE_SELECTED", payload: l ?? [] }); }, [l]), v(() => { U.current = { nodes: t.nodes, offset: N ?? 0 }; }, [N, t.nodes]), C(() => { const e = f && T ? $e({ nodes: t.nodes, activeId: f, overId: T, dragOffset: N ?? 0 }) : null; a({ type: "SET_PROJECTION", payload: e }); }, [f, N, T, t.nodes]); const w = (e, s) => e || s, { nodes: pe, items: ce } = D(() => { const e = { spacingY: "none", contentHight: "single-line", shadow: "none", borderRadius: "small", borderWidth: "none", borderStyle: "none", activeColorStyle: "neutral", ...P }, s = (r) => i ? { checkBoxPosition: w( r.checkBoxPosition, h ) } : { draggable: r.draggable ? !0 : L, dragHandlerPosition: w( r.dragHandlerPosition, h ), showDragHandlerOnHoverOnly: w( r.showDragHandlerOnHoverOnly, b ), showContentWhileDragging: w( r.showContentWhileDragging, A ) }; return { items: t.nodes.map((r) => r.props.id), nodes: t.nodes.map( (r) => be(r, { ...s(r.props), itemStyle: { ...e, ...r.props.itemStyle }, registerOverlay: k, onExpand: y, onShrink: m, onSelect: u, registerNodeChildren: H, unregisterNodeChildren: K }) ) }; }, [ P, t.nodes, L, i, h, b, A, k, y, m, u, H, K ]), Ee = D( () => ({ treeState: t, onSelect: u, onExpand: y, onShrink: m }), [t, u, y, m] ); return /* @__PURE__ */ S(Pe.Provider, { value: Ee, children: /* @__PURE__ */ S( "ul", { id: o, role: "tree", "data-test-id": z, onKeyDown: se, "aria-multiselectable": t.selectionMode === "multiselect", className: "tw-p-0 tw-m-0 tw-font-sans tw-font-normal tw-list-none tw-text-left tw-text-sm tw-select-none", children: /* @__PURE__ */ me( ge, { sensors: le, measuring: ze, onDragEnd: ee, onDragOver: te, onDragMove: ne, onDragStart: oe, onDragCancel: re, accessibility: { announcements: ie, container: ((W = document.getElementById(o)) == null ? void 0 : W.parentElement) ?? document.body }, collisionDetection: Re, children: [ /* @__PURE__ */ S(Ce, { items: ce, strategy: Te, children: pe }), Ae( /* @__PURE__ */ S( we, { zIndex: 1500, wrapperElement: "ul", dropAnimation: null, modifiers: [De], children: t.overlay && /* @__PURE__ */ S( We, { ...t.overlay, isSelected: t.selectedIds.has(t.overlay.id) } ) } ), document.body ) ] } ) } ) }); } ); Ze.displayName = "FondueTree"; export { Ze as Tree }; //# sourceMappingURL=Tree.es.js.map