@particle-academy/fancy-cms-ui 0.0.1-dev.14 → 0.0.1-dev.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/editor.js CHANGED
@@ -878,7 +878,7 @@ function EditablePage({
878
878
  },
879
879
  [ed, selNode]
880
880
  );
881
- const addNodeAt = useCallback(
881
+ useCallback(
882
882
  (kind, targetId) => {
883
883
  const doc2 = ed.state.doc;
884
884
  const target = targetId ? doc2.nodes[targetId] : null;
@@ -907,12 +907,48 @@ function EditablePage({
907
907
  window.addEventListener("mousemove", onMove);
908
908
  return () => window.removeEventListener("mousemove", onMove);
909
909
  }, [editing, draggingEl]);
910
+ const [dropHint, setDropHint] = useState(null);
911
+ const computeDropTarget = (clientX, clientY) => {
912
+ const el = document.elementFromPoint(clientX, clientY)?.closest("[data-cms]");
913
+ if (!el) return { id: null, edge: "inside", rect: null };
914
+ const id = el.getAttribute("data-cms");
915
+ const node = ed.state.doc.nodes[id];
916
+ const r = el.getBoundingClientRect();
917
+ const rect = { x: r.left, y: r.top, w: r.width, h: r.height };
918
+ if (node && CONTAINER_TYPES2.has(node.type)) return { id, edge: "inside", rect };
919
+ return { id, edge: clientY < r.top + r.height / 2 ? "before" : "after", rect };
920
+ };
921
+ const onPageDragOver = (e) => {
922
+ e.preventDefault();
923
+ e.dataTransfer.dropEffect = "copy";
924
+ setDropHint(computeDropTarget(e.clientX, e.clientY));
925
+ };
926
+ const insertRelative = (kind, hint) => {
927
+ const doc2 = ed.state.doc;
928
+ let parent;
929
+ let order;
930
+ if (!hint.id || hint.edge === "inside") {
931
+ parent = hint.id ?? (doc2.sections[doc2.sections.length - 1] ?? null);
932
+ const sib = childrenOf(doc2, parent);
933
+ order = keyBetween(sib.length ? sib[sib.length - 1].order : null, null);
934
+ } else {
935
+ const target = doc2.nodes[hint.id];
936
+ parent = target.parent;
937
+ const sib = childrenOf(doc2, parent);
938
+ const idx = sib.findIndex((n) => n.id === hint.id);
939
+ order = hint.edge === "before" ? keyBetween(idx > 0 ? sib[idx - 1].order : null, target.order) : keyBetween(target.order, idx < sib.length - 1 ? sib[idx + 1].order : null);
940
+ }
941
+ const id = `n${doc2.seq + 1}-${Math.floor(performance.now())}`;
942
+ const def = ADD_DEFAULTS[kind];
943
+ ed.apply({ t: "insert_node", node: { id, type: def.type, parent, order, layout: def.layout, props: { ...def.props }, style: { base: { ...def.style } } } });
944
+ ed.select(id);
945
+ };
910
946
  const onPageDrop = (e) => {
911
947
  const kind = e.dataTransfer.getData("application/x-cms-element");
912
948
  if (!kind) return;
913
949
  e.preventDefault();
914
- const el = document.elementFromPoint(e.clientX, e.clientY)?.closest("[data-cms]");
915
- addNodeAt(kind, el?.getAttribute("data-cms") ?? null);
950
+ insertRelative(kind, computeDropTarget(e.clientX, e.clientY));
951
+ setDropHint(null);
916
952
  setDraggingEl(false);
917
953
  };
918
954
  const setStyle = (patch) => selection && ed.apply({ t: "set_style", id: selection, breakpoint: "base", patch });
@@ -988,7 +1024,8 @@ function EditablePage({
988
1024
  ref: pageRef,
989
1025
  onClickCapture,
990
1026
  onContextMenu: onContextMenuSelect,
991
- onDragOver: editing ? (e) => e.preventDefault() : void 0,
1027
+ onDragOver: editing ? onPageDragOver : void 0,
1028
+ onDragLeave: editing ? () => setDropHint(null) : void 0,
992
1029
  onDrop: editing ? onPageDrop : void 0,
993
1030
  children: /* @__PURE__ */ jsx(CmsPage, { doc: ed.state.doc, registry, data })
994
1031
  }
@@ -1059,10 +1096,23 @@ function EditablePage({
1059
1096
  onAdd: addNode
1060
1097
  }
1061
1098
  ) : null,
1099
+ editing && dropHint?.rect ? /* @__PURE__ */ jsx(DropIndicator, { hint: dropHint }) : null,
1062
1100
  editing ? /* @__PURE__ */ jsx(ElementPalette, { open: paletteOpen, onDragChange: setDraggingEl }) : null,
1063
1101
  editing && timelineDock ? /* @__PURE__ */ jsx("div", { style: { position: "fixed", left: 0, right: 0, bottom: 0, zIndex: Z2 }, children: timelineDock }) : null
1064
1102
  ] });
1065
1103
  }
1104
+ function DropIndicator({
1105
+ hint
1106
+ }) {
1107
+ const r = hint.rect;
1108
+ if (!r) return null;
1109
+ const color = "#ec4899";
1110
+ if (hint.edge === "inside") {
1111
+ return /* @__PURE__ */ jsx("div", { style: { position: "fixed", left: r.x, top: r.y, width: r.w, height: r.h, outline: `2px dashed ${color}`, outlineOffset: -2, borderRadius: 6, pointerEvents: "none", zIndex: Z2 + 4 } });
1112
+ }
1113
+ const y = hint.edge === "before" ? r.y : r.y + r.h;
1114
+ return /* @__PURE__ */ jsx("div", { style: { position: "fixed", left: r.x, top: y - 1.5, width: r.w, height: 3, background: color, borderRadius: 2, boxShadow: "0 0 0 1px #fff", pointerEvents: "none", zIndex: Z2 + 4 } });
1115
+ }
1066
1116
  function ElementPalette({ open, onDragChange }) {
1067
1117
  return /* @__PURE__ */ jsxs(
1068
1118
  "div",