@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.cjs CHANGED
@@ -1297,7 +1297,7 @@ function EditablePage({
1297
1297
  },
1298
1298
  [ed, selNode]
1299
1299
  );
1300
- const addNodeAt = react.useCallback(
1300
+ react.useCallback(
1301
1301
  (kind, targetId) => {
1302
1302
  const doc2 = ed.state.doc;
1303
1303
  const target = targetId ? doc2.nodes[targetId] : null;
@@ -1326,12 +1326,48 @@ function EditablePage({
1326
1326
  window.addEventListener("mousemove", onMove);
1327
1327
  return () => window.removeEventListener("mousemove", onMove);
1328
1328
  }, [editing, draggingEl]);
1329
+ const [dropHint, setDropHint] = react.useState(null);
1330
+ const computeDropTarget = (clientX, clientY) => {
1331
+ const el = document.elementFromPoint(clientX, clientY)?.closest("[data-cms]");
1332
+ if (!el) return { id: null, edge: "inside", rect: null };
1333
+ const id = el.getAttribute("data-cms");
1334
+ const node = ed.state.doc.nodes[id];
1335
+ const r = el.getBoundingClientRect();
1336
+ const rect = { x: r.left, y: r.top, w: r.width, h: r.height };
1337
+ if (node && CONTAINER_TYPES2.has(node.type)) return { id, edge: "inside", rect };
1338
+ return { id, edge: clientY < r.top + r.height / 2 ? "before" : "after", rect };
1339
+ };
1340
+ const onPageDragOver = (e) => {
1341
+ e.preventDefault();
1342
+ e.dataTransfer.dropEffect = "copy";
1343
+ setDropHint(computeDropTarget(e.clientX, e.clientY));
1344
+ };
1345
+ const insertRelative = (kind, hint) => {
1346
+ const doc2 = ed.state.doc;
1347
+ let parent;
1348
+ let order;
1349
+ if (!hint.id || hint.edge === "inside") {
1350
+ parent = hint.id ?? (doc2.sections[doc2.sections.length - 1] ?? null);
1351
+ const sib = childrenOf(doc2, parent);
1352
+ order = keyBetween(sib.length ? sib[sib.length - 1].order : null, null);
1353
+ } else {
1354
+ const target = doc2.nodes[hint.id];
1355
+ parent = target.parent;
1356
+ const sib = childrenOf(doc2, parent);
1357
+ const idx = sib.findIndex((n) => n.id === hint.id);
1358
+ 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);
1359
+ }
1360
+ const id = `n${doc2.seq + 1}-${Math.floor(performance.now())}`;
1361
+ const def = ADD_DEFAULTS[kind];
1362
+ ed.apply({ t: "insert_node", node: { id, type: def.type, parent, order, layout: def.layout, props: { ...def.props }, style: { base: { ...def.style } } } });
1363
+ ed.select(id);
1364
+ };
1329
1365
  const onPageDrop = (e) => {
1330
1366
  const kind = e.dataTransfer.getData("application/x-cms-element");
1331
1367
  if (!kind) return;
1332
1368
  e.preventDefault();
1333
- const el = document.elementFromPoint(e.clientX, e.clientY)?.closest("[data-cms]");
1334
- addNodeAt(kind, el?.getAttribute("data-cms") ?? null);
1369
+ insertRelative(kind, computeDropTarget(e.clientX, e.clientY));
1370
+ setDropHint(null);
1335
1371
  setDraggingEl(false);
1336
1372
  };
1337
1373
  const setStyle = (patch) => selection && ed.apply({ t: "set_style", id: selection, breakpoint: "base", patch });
@@ -1407,7 +1443,8 @@ function EditablePage({
1407
1443
  ref: pageRef,
1408
1444
  onClickCapture,
1409
1445
  onContextMenu: onContextMenuSelect,
1410
- onDragOver: editing ? (e) => e.preventDefault() : void 0,
1446
+ onDragOver: editing ? onPageDragOver : void 0,
1447
+ onDragLeave: editing ? () => setDropHint(null) : void 0,
1411
1448
  onDrop: editing ? onPageDrop : void 0,
1412
1449
  children: /* @__PURE__ */ jsxRuntime.jsx(CmsPage, { doc: ed.state.doc, registry, data })
1413
1450
  }
@@ -1478,10 +1515,23 @@ function EditablePage({
1478
1515
  onAdd: addNode
1479
1516
  }
1480
1517
  ) : null,
1518
+ editing && dropHint?.rect ? /* @__PURE__ */ jsxRuntime.jsx(DropIndicator, { hint: dropHint }) : null,
1481
1519
  editing ? /* @__PURE__ */ jsxRuntime.jsx(ElementPalette, { open: paletteOpen, onDragChange: setDraggingEl }) : null,
1482
1520
  editing && timelineDock ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "fixed", left: 0, right: 0, bottom: 0, zIndex: Z2 }, children: timelineDock }) : null
1483
1521
  ] });
1484
1522
  }
1523
+ function DropIndicator({
1524
+ hint
1525
+ }) {
1526
+ const r = hint.rect;
1527
+ if (!r) return null;
1528
+ const color = "#ec4899";
1529
+ if (hint.edge === "inside") {
1530
+ return /* @__PURE__ */ jsxRuntime.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 } });
1531
+ }
1532
+ const y = hint.edge === "before" ? r.y : r.y + r.h;
1533
+ return /* @__PURE__ */ jsxRuntime.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 } });
1534
+ }
1485
1535
  function ElementPalette({ open, onDragChange }) {
1486
1536
  return /* @__PURE__ */ jsxRuntime.jsxs(
1487
1537
  "div",