@frontify/fondue
Version:
Design system of Frontify
389 lines (388 loc) • 11.7 kB
JavaScript
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