@nitrogenbuilder/core
Version:
CMS Agnostic Page Builder for React projects
1 lines • 5.21 kB
JavaScript
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{useEffect,useMemo,useRef,useState}from"react";import{createPortal}from"react-dom";import{DndContext,DragOverlay,KeyboardSensor,MeasuringStrategy,PointerSensor,closestCenter,defaultDropAnimation,useSensor,useSensors}from"@dnd-kit/core";import{SortableContext,arrayMove,verticalListSortingStrategy}from"@dnd-kit/sortable";import{CSS}from"@dnd-kit/utilities";import{SortableTreeItem}from"./components/index.js";import{sortableTreeKeyboardCoordinates}from"./keyboardCoordinates.js";import{buildTree,flattenTree,getChildCount,getProjection,removeChildrenOf,removeItem}from"./utilities.js";const measuring={droppable:{strategy:MeasuringStrategy.Always}},dropAnimationConfig={keyframes:({transform:e})=>[{opacity:1,transform:CSS.Transform.toString(e.initial)},{opacity:0,transform:CSS.Transform.toString({...e.final,x:e.final.x+5,y:e.final.y+5})}],easing:"ease-out",sideEffects({active:e}){e.node.animate([{opacity:0},{opacity:1}],{duration:defaultDropAnimation.duration,easing:defaultDropAnimation.easing})}};function mapTreeItemsToItems(e){let t=[];if("object"==typeof e.module.options?.children&&e.module.options?.children?.slots){t={};("function"==typeof e.module.options.children.slots?e.module.options.children.slots(e.props):e.module.options.children.slots).forEach(((o,n)=>{const r=o.id,i=e.props.children?.[r]||[];t[r]=[],t[r].push({id:`${e.id}_${r}_slot`,module:{name:o.label,options:{children:!0}},props:{...e.props,children:i.map(mapTreeItemsToItems)}})}))}return e.props?.children&&Array.isArray(e.props.children)&&(t=e.props.children.map(mapTreeItemsToItems)),{id:e.id,module:{name:e.module.name,options:e.module.options},props:{...e.props,children:t}}}export function SortableTree({collapsible:e,treeItems:t=[],currItemId:o="",indicator:n=!1,indentationWidth:r=24,removable:i,onSelect:a,onDelete:d,reorderModules:s}){const[l,c]=useState(t),[p,m]=useState(new Set),[u,f]=useState(null),[g,h]=useState(null),[S,v]=useState(0),[y,I]=useState(null);useEffect((()=>{const e=t.map((e=>mapTreeItemsToItems(e)));c(e)}),[t]);const b=useMemo((()=>{const e=flattenTree(l),t=e.reduce(((e,{props:{children:t},id:o})=>p.has(o)&&t&&t.length?[...e,o]:e),[]);return removeChildrenOf(e,u?[u,...t]:t)}),[u,l,p]),x=u&&g?getProjection(b,u,g,S,r):null,C=useRef({items:b,offset:S}),[D]=useState((()=>sortableTreeKeyboardCoordinates(C,n,r))),T=useSensors(useSensor(PointerSensor),useSensor(KeyboardSensor,{coordinateGetter:D})),j=useMemo((()=>b.map((({id:e})=>e))),[b]),M=u?b.find((({id:e})=>e===u)):null;useEffect((()=>{C.current={items:b,offset:S}}),[b,S]);return _jsx(DndContext,{accessibility:{announcements:{onDragStart:({active:e})=>`Picked up ${e.id}.`,onDragMove:({active:e,over:t})=>E("onDragMove",e.id,t?.id),onDragOver:({active:e,over:t})=>E("onDragOver",e.id,t?.id),onDragEnd:({active:e,over:t})=>E("onDragEnd",e.id,t?.id),onDragCancel:({active:e})=>`Moving was cancelled. ${e.id} was dropped in its original position.`}},sensors:T,collisionDetection:closestCenter,measuring:measuring,onDragStart:function({active:{id:e}}){f(e),h(e);const t=b.find((({id:t})=>t===e));t&&I({parentId:t.parentId,overId:e});document.body.style.setProperty("cursor","grabbing")},onDragMove:function({delta:e}){v(e.x)},onDragOver:function({over:e}){h(e?.id??null)},onDragEnd:function({active:e,over:t}){if($(),x&&t){const{depth:o,parentId:n}=x,r=JSON.parse(JSON.stringify(flattenTree(l))),i=r.findIndex((({id:e})=>e===t.id)),a=r.findIndex((({id:t})=>t===e.id)),d=r[a];r[a]={...d,depth:o,parentId:n};const p=arrayMove(r,a,i),m=buildTree(p);if(s)return void s(p);c(m)}},onDragCancel:function(){$()},children:_jsxs(SortableContext,{items:j,strategy:verticalListSortingStrategy,children:[b.map((({id:t,props:{children:s},depth:l,module:{name:f}},g)=>_jsx(SortableTreeItem,{id:t,index:g,value:f,depth:t===u&&x?x.depth:l,indentationWidth:r,indicator:n,highlighted:t===o,collapsed:Boolean(p.has(t)&&s&&s.length),onClickName:a,onCollapse:e&&s&&s.length?()=>function(e){const t=new Set(p);p.has(e)?t.delete(e):t.add(e);m(t)}(t):void 0,onRemove:i?()=>function(e){if(d)return void d(e);c((t=>removeItem(t,e)))}(t):void 0},t))),createPortal(_jsx(DragOverlay,{dropAnimation:dropAnimationConfig,zIndex:9999,modifiers:n?[adjustTranslate]:void 0,children:u&&M?_jsx(SortableTreeItem,{id:u,depth:M.depth,clone:!0,childCount:getChildCount(l,u)+1,value:b.find((({id:e})=>e===u))?.module.name??"",indentationWidth:r}):null}),document.body)]})});function $(){h(null),f(null),v(0),I(null),document.body.style.setProperty("cursor","")}function E(e,t,o){if(o&&x){if("onDragEnd"!==e){if(y&&x.parentId===y.parentId&&o===y.overId)return;I({parentId:x.parentId,overId:o})}const n=JSON.parse(JSON.stringify(flattenTree(l))),r=n.findIndex((({id:e})=>e===o)),i=n.findIndex((({id:e})=>e===t)),a=arrayMove(n,i,r),d=a[r-1];let s;const c="onDragEnd"===e?"dropped":"moved",p="onDragEnd"===e?"dropped":"nested";if(d)if(x.depth>d.depth)s=`${t} was ${p} under ${d.id}.`;else{let e=d;for(;e&&x.depth<e.depth;){const t=e.parentId;e=a.find((({id:e})=>e===t))}e&&(s=`${t} was ${c} after ${e.id}.`)}else{const e=a[r+1];s=`${t} was ${c} before ${e.id}.`}return s}}}const adjustTranslate=({transform:e})=>({...e,y:e.y-25});