@particle-academy/fancy-cms-ui 0.0.1-dev.11 → 0.0.1-dev.12

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
@@ -1255,6 +1255,43 @@ function EditablePage({
1255
1255
  },
1256
1256
  [ed, selNode]
1257
1257
  );
1258
+ const addNodeAt = react.useCallback(
1259
+ (kind, targetId) => {
1260
+ const doc2 = ed.state.doc;
1261
+ const target = targetId ? doc2.nodes[targetId] : null;
1262
+ const parent = target ? CONTAINER_TYPES2.has(target.type) ? target.id : target.parent : doc2.sections[doc2.sections.length - 1] ?? null;
1263
+ const siblings = childrenOf(doc2, parent);
1264
+ const order = keyBetween(siblings.length ? siblings[siblings.length - 1].order : null, null);
1265
+ const id = `n${doc2.seq + 1}-${Math.floor(performance.now())}`;
1266
+ const def = ADD_DEFAULTS[kind];
1267
+ ed.apply({ t: "insert_node", node: { id, type: def.type, parent, order, props: { ...def.props }, style: { base: { ...def.style } } } });
1268
+ ed.select(id);
1269
+ },
1270
+ [ed]
1271
+ );
1272
+ const [paletteOpen, setPaletteOpen] = react.useState(false);
1273
+ const [draggingEl, setDraggingEl] = react.useState(false);
1274
+ react.useEffect(() => {
1275
+ if (!editing) {
1276
+ setPaletteOpen(false);
1277
+ return;
1278
+ }
1279
+ const onMove = (e) => {
1280
+ if (draggingEl) return;
1281
+ if (e.clientX >= window.innerWidth - 26) setPaletteOpen(true);
1282
+ else if (e.clientX < window.innerWidth - 236) setPaletteOpen(false);
1283
+ };
1284
+ window.addEventListener("mousemove", onMove);
1285
+ return () => window.removeEventListener("mousemove", onMove);
1286
+ }, [editing, draggingEl]);
1287
+ const onPageDrop = (e) => {
1288
+ const kind = e.dataTransfer.getData("application/x-cms-element");
1289
+ if (!kind) return;
1290
+ e.preventDefault();
1291
+ const el = document.elementFromPoint(e.clientX, e.clientY)?.closest("[data-cms]");
1292
+ addNodeAt(kind, el?.getAttribute("data-cms") ?? null);
1293
+ setDraggingEl(false);
1294
+ };
1258
1295
  const setStyle = (patch) => selection && ed.apply({ t: "set_style", id: selection, breakpoint: "base", patch });
1259
1296
  const setProps = (patch) => selection && ed.apply({ t: "set_props", id: selection, patch });
1260
1297
  const setLayout = (layout) => selection && ed.apply({ t: "set_layout", id: selection, layout });
@@ -1322,7 +1359,17 @@ function EditablePage({
1322
1359
  if (el) ed.select(el.getAttribute("data-cms"));
1323
1360
  else ed.select(null);
1324
1361
  };
1325
- const page = /* @__PURE__ */ jsxRuntime.jsx("div", { ref: pageRef, onClickCapture, onContextMenu: onContextMenuSelect, children: /* @__PURE__ */ jsxRuntime.jsx(CmsPage, { doc: ed.state.doc, registry }) });
1362
+ const page = /* @__PURE__ */ jsxRuntime.jsx(
1363
+ "div",
1364
+ {
1365
+ ref: pageRef,
1366
+ onClickCapture,
1367
+ onContextMenu: onContextMenuSelect,
1368
+ onDragOver: editing ? (e) => e.preventDefault() : void 0,
1369
+ onDrop: editing ? onPageDrop : void 0,
1370
+ children: /* @__PURE__ */ jsxRuntime.jsx(CmsPage, { doc: ed.state.doc, registry })
1371
+ }
1372
+ );
1326
1373
  const pageShell = pinned ? /* @__PURE__ */ jsxRuntime.jsx("div", { ref: spacerRef, style: { height: `${Math.max(1, frames) * 100}vh` }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "sticky", top: 0, height: "100vh", overflow: "hidden" }, children: page }) }) : frames > 1 ? (
1327
1374
  // Normal flow, but "expanded" — extra scroll length below the content so a
1328
1375
  // page can be made longer than its content (the + Frame control).
@@ -1389,9 +1436,72 @@ function EditablePage({
1389
1436
  onAdd: addNode
1390
1437
  }
1391
1438
  ) : null,
1439
+ editing ? /* @__PURE__ */ jsxRuntime.jsx(ElementPalette, { open: paletteOpen, onDragChange: setDraggingEl }) : null,
1392
1440
  editing && timelineDock ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "fixed", left: 0, right: 0, bottom: 0, zIndex: Z2 }, children: timelineDock }) : null
1393
1441
  ] });
1394
1442
  }
1443
+ function ElementPalette({ open, onDragChange }) {
1444
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1445
+ "div",
1446
+ {
1447
+ style: {
1448
+ position: "fixed",
1449
+ top: 64,
1450
+ bottom: 96,
1451
+ right: 0,
1452
+ width: 216,
1453
+ transform: open ? "translateX(0)" : "translateX(100%)",
1454
+ transition: "transform 0.18s ease",
1455
+ background: "#0b1220",
1456
+ color: "#e2e8f0",
1457
+ borderLeft: "1px solid #1e293b",
1458
+ borderTopLeftRadius: 12,
1459
+ borderBottomLeftRadius: 12,
1460
+ boxShadow: "-18px 0 48px -20px rgba(0,0,0,0.6)",
1461
+ zIndex: Z2 + 2,
1462
+ fontFamily: "system-ui, sans-serif",
1463
+ padding: 12,
1464
+ overflowY: "auto"
1465
+ },
1466
+ children: [
1467
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, letterSpacing: "0.06em", textTransform: "uppercase", opacity: 0.5, marginBottom: 10 }, children: "Elements" }),
1468
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }, children: ADD_MENU.map((m) => /* @__PURE__ */ jsxRuntime.jsxs(
1469
+ "div",
1470
+ {
1471
+ draggable: true,
1472
+ onDragStart: (e) => {
1473
+ e.dataTransfer.setData("application/x-cms-element", m.kind);
1474
+ e.dataTransfer.effectAllowed = "copy";
1475
+ onDragChange(true);
1476
+ },
1477
+ onDragEnd: () => onDragChange(false),
1478
+ title: `Drag "${m.label}" onto the page`,
1479
+ style: {
1480
+ display: "flex",
1481
+ flexDirection: "column",
1482
+ alignItems: "center",
1483
+ justifyContent: "center",
1484
+ gap: 4,
1485
+ height: 56,
1486
+ borderRadius: 8,
1487
+ background: "#0f172a",
1488
+ border: "1px solid #1e293b",
1489
+ cursor: "grab",
1490
+ fontSize: 12,
1491
+ userSelect: "none"
1492
+ },
1493
+ children: [
1494
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 16, opacity: 0.7 }, children: "\uFF0B" }),
1495
+ m.label
1496
+ ]
1497
+ },
1498
+ m.kind
1499
+ )) }),
1500
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 10.5, opacity: 0.45, marginTop: 12, lineHeight: 1.4 }, children: "Drag an Element onto the page. It drops into the container you release over." })
1501
+ ]
1502
+ }
1503
+ );
1504
+ }
1395
1505
  var CONTAINER_TYPES2 = /* @__PURE__ */ new Set(["section", "frame", "stack", "grid", "shape"]);
1396
1506
  var ADD_DEFAULTS = {
1397
1507
  text: { type: "text", props: { content: "New text" }, style: { color: "inherit" } },
@@ -1620,7 +1730,7 @@ function EditBar({
1620
1730
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: { ...btn, background: editing ? "#8b5cf6" : "transparent" }, onClick: onToggle, children: editing ? "\u25CF Editing" : "Edit" }),
1621
1731
  editing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1622
1732
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
1623
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: { ...btn, background: open ? "#1e293b" : "transparent" }, onClick: () => setOpen((v) => !v), title: "Add an element", children: "\uFF0B Add \u25BE" }),
1733
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: { ...btn, background: open ? "#1e293b" : "transparent" }, onClick: () => setOpen((v) => !v), title: "Add an Element (or drag from the right-edge palette)", children: "\uFF0B Element \u25BE" }),
1624
1734
  open ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", top: "calc(100% + 6px)", right: 0, background: "#0f172a", border: "1px solid #1e293b", borderRadius: 10, padding: 4, display: "flex", flexDirection: "column", minWidth: 132, boxShadow: "0 12px 32px -10px rgba(0,0,0,0.6)" }, children: ADD_MENU.map((m) => /* @__PURE__ */ jsxRuntime.jsx(
1625
1735
  "button",
1626
1736
  {
@@ -1658,7 +1768,7 @@ function EditMenuItems({
1658
1768
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1659
1769
  editable ? /* @__PURE__ */ jsxRuntime.jsx(reactFancy.ContextMenu.Item, { onClick: onEditText, children: "Edit text" }) : null,
1660
1770
  /* @__PURE__ */ jsxRuntime.jsxs(reactFancy.ContextMenu.Sub, { children: [
1661
- /* @__PURE__ */ jsxRuntime.jsx(reactFancy.ContextMenu.SubTrigger, { children: isContainer ? "Add inside" : "Add" }),
1771
+ /* @__PURE__ */ jsxRuntime.jsx(reactFancy.ContextMenu.SubTrigger, { children: isContainer ? "Add Element inside" : "Add Element" }),
1662
1772
  /* @__PURE__ */ jsxRuntime.jsx(reactFancy.ContextMenu.SubContent, { className: "!z-[2147483647]", children: ADD_MENU.map((m) => /* @__PURE__ */ jsxRuntime.jsx(reactFancy.ContextMenu.Item, { onClick: () => onAdd(m.kind), children: m.label }, m.kind)) })
1663
1773
  ] }),
1664
1774
  node ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [