@tecof/theme-editor 0.0.34 → 0.0.37

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/index.mjs CHANGED
@@ -1,7 +1,11 @@
1
1
  import * as React__default from 'react';
2
2
  import React__default__default, { createContext, forwardRef, createElement, memo, useRef, useCallback, useContext, useState, useEffect, useMemo, Component, useLayoutEffect } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
- import { blocksPlugin, outlinePlugin, fieldsPlugin, Puck, Render, FieldLabel, usePuck, ActionBar } from '@puckeditor/core';
4
+ import { create } from 'zustand';
5
+ import { immer } from 'zustand/middleware/immer';
6
+ import { nanoid } from 'nanoid';
7
+ import * as ReactDOM from 'react-dom';
8
+ import ReactDOM__default, { createPortal } from 'react-dom';
5
9
  import { useEditor, EditorContent } from '@tiptap/react';
6
10
  import Document from '@tiptap/extension-document';
7
11
  import Paragraph from '@tiptap/extension-paragraph';
@@ -20,8 +24,6 @@ import Link3 from '@tiptap/extension-link';
20
24
  import Code2 from '@tiptap/extension-code';
21
25
  import CodeBlock from '@tiptap/extension-code-block';
22
26
  import Image3 from '@tiptap/extension-image';
23
- import * as ReactDOM from 'react-dom';
24
- import ReactDOM__default from 'react-dom';
25
27
 
26
28
  // src/components/TecofProvider.tsx
27
29
 
@@ -295,6 +297,494 @@ function useTecof() {
295
297
  return ctx;
296
298
  }
297
299
 
300
+ // src/engine/document.ts
301
+ var EMPTY_DOCUMENT = {
302
+ root: { props: {} },
303
+ content: [],
304
+ zones: {}
305
+ };
306
+ var parseDocument = (rawData) => {
307
+ if (!rawData) return { ...EMPTY_DOCUMENT };
308
+ return {
309
+ root: rawData.root || { props: {} },
310
+ content: rawData.content || [],
311
+ zones: rawData.zones || {}
312
+ };
313
+ };
314
+ var serializeDocument = (doc) => {
315
+ return {
316
+ root: doc.root,
317
+ content: doc.content,
318
+ zones: doc.zones
319
+ };
320
+ };
321
+
322
+ // src/engine/zones.ts
323
+ var parseZoneKey = (zoneKey) => {
324
+ const parts = zoneKey.split(":");
325
+ return {
326
+ parentId: parts[0],
327
+ slotName: parts[1] || "default"
328
+ };
329
+ };
330
+ var findNodeById = (doc, id) => {
331
+ for (let i2 = 0; i2 < doc.content.length; i2++) {
332
+ if (doc.content[i2].props.id === id) {
333
+ return { node: doc.content[i2], path: { index: i2 } };
334
+ }
335
+ }
336
+ for (const [zoneKey, items] of Object.entries(doc.zones)) {
337
+ for (let i2 = 0; i2 < items.length; i2++) {
338
+ if (items[i2].props.id === id) {
339
+ return { node: items[i2], path: { zoneKey, index: i2 } };
340
+ }
341
+ }
342
+ }
343
+ return null;
344
+ };
345
+ var getDescendantZoneKeys = (zones, nodeId, acc = []) => {
346
+ const prefix = `${nodeId}:`;
347
+ for (const zoneKey of Object.keys(zones)) {
348
+ if (zoneKey.startsWith(prefix)) {
349
+ acc.push(zoneKey);
350
+ for (const child of zones[zoneKey]) {
351
+ getDescendantZoneKeys(zones, child.props.id, acc);
352
+ }
353
+ }
354
+ }
355
+ return acc;
356
+ };
357
+ var getParentId = (doc, id) => {
358
+ const res2 = findNodeById(doc, id);
359
+ if (!res2 || !res2.path.zoneKey) return null;
360
+ return parseZoneKey(res2.path.zoneKey).parentId;
361
+ };
362
+ var getBreadcrumbs = (doc, id) => {
363
+ const crumbs = [];
364
+ let currentId = id;
365
+ while (currentId) {
366
+ const res2 = findNodeById(doc, currentId);
367
+ if (!res2) break;
368
+ crumbs.unshift({ id: currentId, type: res2.node.type });
369
+ currentId = res2.path.zoneKey ? parseZoneKey(res2.path.zoneKey).parentId : null;
370
+ }
371
+ return crumbs;
372
+ };
373
+ var generateId = () => nanoid(8);
374
+ var remapNodeIds = (node, sourceZones, idMap = /* @__PURE__ */ new Map()) => {
375
+ const oldId = node.props.id;
376
+ const newId = generateId();
377
+ idMap.set(oldId, newId);
378
+ const remappedNode = {
379
+ ...node,
380
+ props: {
381
+ ...node.props,
382
+ id: newId
383
+ }
384
+ };
385
+ const newZones = {};
386
+ const prefix = `${oldId}:`;
387
+ for (const [zoneKey, zoneItems] of Object.entries(sourceZones)) {
388
+ if (zoneKey.startsWith(prefix)) {
389
+ const slotName = zoneKey.split(":")[1];
390
+ const newZoneKey = `${newId}:${slotName}`;
391
+ const newZoneItems = [];
392
+ for (const item2 of zoneItems) {
393
+ const { remappedNode: childNode, newZones: childZones } = remapNodeIds(item2, sourceZones, idMap);
394
+ newZoneItems.push(childNode);
395
+ Object.assign(newZones, childZones);
396
+ }
397
+ newZones[newZoneKey] = newZoneItems;
398
+ }
399
+ }
400
+ return { remappedNode, newZones };
401
+ };
402
+
403
+ // src/engine/operations.ts
404
+ var insertNode = (draft, node, targetZoneKey, index2) => {
405
+ if (!node.props.id) {
406
+ node.props.id = generateId();
407
+ }
408
+ let list3 = targetZoneKey ? draft.zones[targetZoneKey] : draft.content;
409
+ if (!list3) {
410
+ list3 = [];
411
+ if (targetZoneKey) {
412
+ draft.zones[targetZoneKey] = list3;
413
+ }
414
+ }
415
+ const insertIndex = typeof index2 === "number" ? index2 : list3.length;
416
+ list3.splice(insertIndex, 0, node);
417
+ };
418
+ var removeNode = (draft, id) => {
419
+ const result = findNodeById(draft, id);
420
+ if (!result) return;
421
+ const { path } = result;
422
+ const list3 = path.zoneKey ? draft.zones[path.zoneKey] : draft.content;
423
+ if (list3) {
424
+ list3.splice(path.index, 1);
425
+ }
426
+ const descendantZoneKeys = getDescendantZoneKeys(draft.zones, id);
427
+ for (const zoneKey of descendantZoneKeys) {
428
+ delete draft.zones[zoneKey];
429
+ }
430
+ };
431
+ var moveNode = (draft, id, targetZoneKey, targetIndex) => {
432
+ const result = findNodeById(draft, id);
433
+ if (!result) return;
434
+ const { node, path: sourcePath } = result;
435
+ const sourceList = sourcePath.zoneKey ? draft.zones[sourcePath.zoneKey] : draft.content;
436
+ let targetList = targetZoneKey ? draft.zones[targetZoneKey] : draft.content;
437
+ if (!targetList && targetZoneKey) {
438
+ targetList = [];
439
+ draft.zones[targetZoneKey] = targetList;
440
+ }
441
+ if (!sourceList || !targetList) return;
442
+ sourceList.splice(sourcePath.index, 1);
443
+ let finalIndex = targetIndex ?? targetList.length;
444
+ if (sourcePath.zoneKey === targetZoneKey && sourcePath.index < finalIndex) {
445
+ finalIndex -= 1;
446
+ }
447
+ targetList.splice(finalIndex, 0, node);
448
+ };
449
+ var duplicateNode = (draft, id) => {
450
+ const result = findNodeById(draft, id);
451
+ if (!result) return;
452
+ const { node, path } = result;
453
+ const { remappedNode, newZones } = remapNodeIds(node, draft.zones);
454
+ const targetList = path.zoneKey ? draft.zones[path.zoneKey] : draft.content;
455
+ if (targetList) {
456
+ targetList.splice(path.index + 1, 0, remappedNode);
457
+ }
458
+ Object.assign(draft.zones, newZones);
459
+ };
460
+ var updateProps = (draft, id, patch) => {
461
+ const result = findNodeById(draft, id);
462
+ if (!result) return;
463
+ Object.assign(result.node.props, patch);
464
+ };
465
+ var setRootProps = (draft, patch) => {
466
+ Object.assign(draft.root.props, patch);
467
+ };
468
+
469
+ // src/engine/store.ts
470
+ var pushToHistory = (state3) => {
471
+ state3.history.past.push(JSON.parse(JSON.stringify(state3.document)));
472
+ state3.history.future = [];
473
+ };
474
+ var useEditorStore = create()(
475
+ immer((set2) => ({
476
+ // Initial State
477
+ document: { ...EMPTY_DOCUMENT },
478
+ history: {
479
+ past: [],
480
+ future: []
481
+ },
482
+ selection: {
483
+ selectedId: null,
484
+ hoveredId: null
485
+ },
486
+ viewport: "desktop",
487
+ // Actions
488
+ setDocument: (doc) => set2((state3) => {
489
+ state3.document = doc;
490
+ state3.history = { past: [], future: [] };
491
+ state3.selection = { selectedId: null, hoveredId: null };
492
+ }),
493
+ selectNode: (id) => set2((state3) => {
494
+ state3.selection.selectedId = id;
495
+ }),
496
+ hoverNode: (id) => set2((state3) => {
497
+ state3.selection.hoveredId = id;
498
+ }),
499
+ setViewport: (viewport) => set2((state3) => {
500
+ state3.viewport = viewport;
501
+ }),
502
+ insertNode: (node, targetZoneKey, index2) => set2((state3) => {
503
+ pushToHistory(state3);
504
+ insertNode(state3.document, node, targetZoneKey, index2);
505
+ }),
506
+ removeNode: (id) => set2((state3) => {
507
+ pushToHistory(state3);
508
+ removeNode(state3.document, id);
509
+ if (state3.selection.selectedId === id) {
510
+ state3.selection.selectedId = null;
511
+ }
512
+ }),
513
+ moveNode: (id, targetZoneKey, index2) => set2((state3) => {
514
+ pushToHistory(state3);
515
+ moveNode(state3.document, id, targetZoneKey, index2);
516
+ }),
517
+ duplicateNode: (id) => set2((state3) => {
518
+ pushToHistory(state3);
519
+ duplicateNode(state3.document, id);
520
+ }),
521
+ updateProps: (id, patch) => set2((state3) => {
522
+ pushToHistory(state3);
523
+ updateProps(state3.document, id, patch);
524
+ }),
525
+ setRootProps: (patch) => set2((state3) => {
526
+ pushToHistory(state3);
527
+ setRootProps(state3.document, patch);
528
+ }),
529
+ undo: () => set2((state3) => {
530
+ if (state3.history.past.length === 0) return;
531
+ const previous = state3.history.past.pop();
532
+ state3.history.future.push(JSON.parse(JSON.stringify(state3.document)));
533
+ state3.document = previous;
534
+ }),
535
+ redo: () => set2((state3) => {
536
+ if (state3.history.future.length === 0) return;
537
+ const next = state3.history.future.pop();
538
+ state3.history.past.push(JSON.parse(JSON.stringify(state3.document)));
539
+ state3.document = next;
540
+ })
541
+ }))
542
+ );
543
+ var StudioContext = createContext(null);
544
+ var useStudio = () => {
545
+ const ctx = useContext(StudioContext);
546
+ if (!ctx) {
547
+ throw new Error("useStudio must be used within a StudioProvider");
548
+ }
549
+ return ctx;
550
+ };
551
+ var ParentNodeContext = createContext(null);
552
+ var DropZone = ({ zone, className, style }) => {
553
+ const parentId = useContext(ParentNodeContext);
554
+ const zoneKey = parentId ? `${parentId}:${zone}` : zone;
555
+ const items = useEditorStore((state3) => state3.document.zones[zoneKey] || []);
556
+ return /* @__PURE__ */ jsx(
557
+ "div",
558
+ {
559
+ className: `tecof-dropzone ${className || ""}`,
560
+ style: { minHeight: items.length === 0 ? "40px" : void 0, ...style },
561
+ "data-tecof-zone": zoneKey,
562
+ children: items.map((item2, index2) => /* @__PURE__ */ jsx(NodeRenderer, { node: item2, index: index2, zoneKey }, item2.props.id))
563
+ }
564
+ );
565
+ };
566
+ var renderDropZone = ({ zone, className, style }) => {
567
+ return /* @__PURE__ */ jsx(DropZone, { zone, className, style });
568
+ };
569
+ var NodeRenderer = ({ node, index: index2, zoneKey }) => {
570
+ const { config: config3, metadata, readOnly } = useStudio();
571
+ const componentConfig = config3.components[node.type];
572
+ const selectNode = useEditorStore((state3) => state3.selectNode);
573
+ const hoverNode = useEditorStore((state3) => state3.hoverNode);
574
+ const hoveredId = useEditorStore((state3) => state3.selection.hoveredId);
575
+ const handleMouseEnter = useCallback(
576
+ (e3) => {
577
+ if (readOnly) return;
578
+ e3.stopPropagation();
579
+ hoverNode(node.props.id);
580
+ },
581
+ [hoverNode, node.props.id, readOnly]
582
+ );
583
+ const handleMouseLeave = useCallback(
584
+ (e3) => {
585
+ if (readOnly) return;
586
+ e3.stopPropagation();
587
+ if (hoveredId === node.props.id) {
588
+ hoverNode(null);
589
+ }
590
+ },
591
+ [hoverNode, node.props.id, hoveredId, readOnly]
592
+ );
593
+ const handleClick = useCallback(
594
+ (e3) => {
595
+ if (readOnly) return;
596
+ e3.stopPropagation();
597
+ selectNode(node.props.id);
598
+ const isEmbedded = typeof window !== "undefined" && window.parent !== window;
599
+ if (isEmbedded) {
600
+ window.parent.postMessage(
601
+ {
602
+ type: "puck:itemSelected",
603
+ item: {
604
+ type: node.type,
605
+ id: node.props.id
606
+ }
607
+ },
608
+ "*"
609
+ );
610
+ }
611
+ },
612
+ [selectNode, node.props.id, node.type, readOnly]
613
+ );
614
+ if (!componentConfig) {
615
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "12px", background: "#fee2e2", color: "#991b1b", fontSize: "12px", borderRadius: "4px" }, children: [
616
+ "Bile\u015Fen bulunamad\u0131: ",
617
+ node.type
618
+ ] });
619
+ }
620
+ const componentProps = {
621
+ ...node.props,
622
+ puck: {
623
+ renderDropZone,
624
+ isEditing: !readOnly,
625
+ metadata: {
626
+ ...metadata || {},
627
+ ...componentConfig.metadata || {}
628
+ }
629
+ },
630
+ editMode: !readOnly
631
+ };
632
+ return /* @__PURE__ */ jsx(ParentNodeContext.Provider, { value: node.props.id, children: /* @__PURE__ */ jsx(
633
+ "div",
634
+ {
635
+ className: "tecof-node-wrapper",
636
+ "data-tecof-id": node.props.id,
637
+ "data-tecof-type": node.type,
638
+ "data-tecof-index": index2,
639
+ "data-tecof-zone": zoneKey || "root",
640
+ onMouseEnter: handleMouseEnter,
641
+ onMouseLeave: handleMouseLeave,
642
+ onClick: handleClick,
643
+ style: {
644
+ cursor: readOnly ? void 0 : "pointer"
645
+ },
646
+ children: componentConfig.render(componentProps)
647
+ }
648
+ ) });
649
+ };
650
+ var Frame = ({ children, title = "Canvas Frame", ...props }) => {
651
+ const [contentRef, setContentRef] = useState(null);
652
+ const mountNode = contentRef?.contentWindow?.document?.body;
653
+ useEffect(() => {
654
+ if (!contentRef) return;
655
+ const doc = contentRef.contentDocument;
656
+ if (!doc) return;
657
+ const copyStyles = () => {
658
+ doc.head.innerHTML = "";
659
+ Array.from(document.styleSheets).forEach((styleSheet) => {
660
+ try {
661
+ if (styleSheet.href) {
662
+ const link = doc.createElement("link");
663
+ link.rel = "stylesheet";
664
+ link.href = styleSheet.href;
665
+ doc.head.appendChild(link);
666
+ } else {
667
+ const cssRules = Array.from(styleSheet.cssRules).map((rule) => rule.cssText).join("\n");
668
+ const style2 = doc.createElement("style");
669
+ style2.textContent = cssRules;
670
+ doc.head.appendChild(style2);
671
+ }
672
+ } catch (e3) {
673
+ }
674
+ });
675
+ const style = doc.createElement("style");
676
+ style.textContent = `
677
+ html, body {
678
+ margin: 0;
679
+ padding: 0;
680
+ background-color: transparent;
681
+ min-height: 100vh;
682
+ }
683
+ body {
684
+ padding: 32px 16px;
685
+ box-sizing: border-box;
686
+ }
687
+ .tecof-node-wrapper {
688
+ position: relative;
689
+ transition: outline 0.15s ease-in-out;
690
+ }
691
+ /* Custom scrollbars for iframe */
692
+ ::-webkit-scrollbar {
693
+ width: 8px;
694
+ height: 8px;
695
+ }
696
+ ::-webkit-scrollbar-track {
697
+ background: transparent;
698
+ }
699
+ ::-webkit-scrollbar-thumb {
700
+ background: rgba(0, 0, 0, 0.15);
701
+ border-radius: 4px;
702
+ }
703
+ ::-webkit-scrollbar-thumb:hover {
704
+ background: rgba(0, 0, 0, 0.25);
705
+ }
706
+ `;
707
+ doc.head.appendChild(style);
708
+ };
709
+ copyStyles();
710
+ if (doc.body) {
711
+ doc.body.className = "tecof-canvas-body";
712
+ const handleBodyClick = (e3) => {
713
+ const target = e3.target;
714
+ if (!target.closest(".tecof-node-wrapper")) {
715
+ useEditorStore.getState().selectNode(null);
716
+ const isEmbedded = typeof window !== "undefined" && window.parent !== window;
717
+ if (isEmbedded) {
718
+ window.parent.postMessage({ type: "puck:itemDeselected" }, "*");
719
+ }
720
+ }
721
+ };
722
+ doc.body.addEventListener("click", handleBodyClick);
723
+ return () => {
724
+ doc.body.removeEventListener("click", handleBodyClick);
725
+ };
726
+ }
727
+ }, [contentRef]);
728
+ return /* @__PURE__ */ jsx(
729
+ "iframe",
730
+ {
731
+ title,
732
+ ref: setContentRef,
733
+ style: {
734
+ width: "100%",
735
+ height: "100%",
736
+ border: "none",
737
+ background: "#ffffff",
738
+ ...props.style
739
+ },
740
+ ...props,
741
+ children: mountNode && createPortal(children, mountNode)
742
+ }
743
+ );
744
+ };
745
+ var Canvas = () => {
746
+ const content = useEditorStore((state3) => state3.document.content);
747
+ const viewport = useEditorStore((state3) => state3.viewport);
748
+ const getWidth2 = () => {
749
+ switch (viewport) {
750
+ case "tablet":
751
+ return "768px";
752
+ case "mobile":
753
+ return "375px";
754
+ case "desktop":
755
+ default:
756
+ return "100%";
757
+ }
758
+ };
759
+ return /* @__PURE__ */ jsx("div", { className: "tecof-canvas-container", style: {
760
+ flex: 1,
761
+ display: "flex",
762
+ alignItems: "center",
763
+ justifyContent: "center",
764
+ background: "#f4f4f5",
765
+ padding: "24px",
766
+ overflow: "auto",
767
+ height: "100%",
768
+ boxSizing: "border-box"
769
+ }, children: /* @__PURE__ */ jsx(
770
+ "div",
771
+ {
772
+ className: "tecof-canvas-viewport-wrapper",
773
+ style: {
774
+ width: getWidth2(),
775
+ height: "100%",
776
+ maxWidth: "100%",
777
+ transition: "width 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
778
+ boxShadow: "0 10px 25px -5px rgba(0, 0, 0, 0.05), 0 8px 10px -6px rgba(0, 0, 0, 0.05)",
779
+ borderRadius: viewport === "desktop" ? "0" : "12px",
780
+ overflow: "hidden",
781
+ backgroundColor: "#ffffff"
782
+ },
783
+ children: /* @__PURE__ */ jsx(Frame, { children: /* @__PURE__ */ jsx("div", { className: "tecof-canvas-root", style: { minHeight: "100%" }, children: content.map((item2, index2) => /* @__PURE__ */ jsx(NodeRenderer, { node: item2, index: index2 }, item2.props.id)) }) })
784
+ }
785
+ ) });
786
+ };
787
+
298
788
  // node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
299
789
  var mergeClasses = (...classes) => classes.filter((className, index2, array) => {
300
790
  return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index2;
@@ -416,38 +906,42 @@ var ChevronDown = createLucideIcon("chevron-down", __iconNode4);
416
906
  var __iconNode5 = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
417
907
  var ChevronRight = createLucideIcon("chevron-right", __iconNode5);
418
908
 
909
+ // node_modules/lucide-react/dist/esm/icons/chevron-up.js
910
+ var __iconNode6 = [["path", { d: "m18 15-6-6-6 6", key: "153udz" }]];
911
+ var ChevronUp = createLucideIcon("chevron-up", __iconNode6);
912
+
419
913
  // node_modules/lucide-react/dist/esm/icons/code.js
420
- var __iconNode6 = [
914
+ var __iconNode7 = [
421
915
  ["path", { d: "m16 18 6-6-6-6", key: "eg8j8" }],
422
916
  ["path", { d: "m8 6-6 6 6 6", key: "ppft3o" }]
423
917
  ];
424
- var Code = createLucideIcon("code", __iconNode6);
918
+ var Code = createLucideIcon("code", __iconNode7);
425
919
 
426
920
  // node_modules/lucide-react/dist/esm/icons/copy.js
427
- var __iconNode7 = [
921
+ var __iconNode8 = [
428
922
  ["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2", key: "17jyea" }],
429
923
  ["path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2", key: "zix9uf" }]
430
924
  ];
431
- var Copy = createLucideIcon("copy", __iconNode7);
925
+ var Copy = createLucideIcon("copy", __iconNode8);
432
926
 
433
927
  // node_modules/lucide-react/dist/esm/icons/database.js
434
- var __iconNode8 = [
928
+ var __iconNode9 = [
435
929
  ["ellipse", { cx: "12", cy: "5", rx: "9", ry: "3", key: "msslwz" }],
436
930
  ["path", { d: "M3 5V19A9 3 0 0 0 21 19V5", key: "1wlel7" }],
437
931
  ["path", { d: "M3 12A9 3 0 0 0 21 12", key: "mv7ke4" }]
438
932
  ];
439
- var Database = createLucideIcon("database", __iconNode8);
933
+ var Database = createLucideIcon("database", __iconNode9);
440
934
 
441
935
  // node_modules/lucide-react/dist/esm/icons/external-link.js
442
- var __iconNode9 = [
936
+ var __iconNode10 = [
443
937
  ["path", { d: "M15 3h6v6", key: "1q9fwt" }],
444
938
  ["path", { d: "M10 14 21 3", key: "gplh6r" }],
445
939
  ["path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6", key: "a6xqqp" }]
446
940
  ];
447
- var ExternalLink = createLucideIcon("external-link", __iconNode9);
941
+ var ExternalLink = createLucideIcon("external-link", __iconNode10);
448
942
 
449
943
  // node_modules/lucide-react/dist/esm/icons/file-text.js
450
- var __iconNode10 = [
944
+ var __iconNode11 = [
451
945
  [
452
946
  "path",
453
947
  {
@@ -460,10 +954,10 @@ var __iconNode10 = [
460
954
  ["path", { d: "M16 13H8", key: "t4e002" }],
461
955
  ["path", { d: "M16 17H8", key: "z1uh3a" }]
462
956
  ];
463
- var FileText = createLucideIcon("file-text", __iconNode10);
957
+ var FileText = createLucideIcon("file-text", __iconNode11);
464
958
 
465
959
  // node_modules/lucide-react/dist/esm/icons/file.js
466
- var __iconNode11 = [
960
+ var __iconNode12 = [
467
961
  [
468
962
  "path",
469
963
  {
@@ -473,10 +967,10 @@ var __iconNode11 = [
473
967
  ],
474
968
  ["path", { d: "M14 2v5a1 1 0 0 0 1 1h5", key: "wfsgrz" }]
475
969
  ];
476
- var File2 = createLucideIcon("file", __iconNode11);
970
+ var File2 = createLucideIcon("file", __iconNode12);
477
971
 
478
972
  // node_modules/lucide-react/dist/esm/icons/folder-open.js
479
- var __iconNode12 = [
973
+ var __iconNode13 = [
480
974
  [
481
975
  "path",
482
976
  {
@@ -485,18 +979,18 @@ var __iconNode12 = [
485
979
  }
486
980
  ]
487
981
  ];
488
- var FolderOpen = createLucideIcon("folder-open", __iconNode12);
982
+ var FolderOpen = createLucideIcon("folder-open", __iconNode13);
489
983
 
490
984
  // node_modules/lucide-react/dist/esm/icons/globe.js
491
- var __iconNode13 = [
985
+ var __iconNode14 = [
492
986
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
493
987
  ["path", { d: "M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20", key: "13o1zl" }],
494
988
  ["path", { d: "M2 12h20", key: "9i4pu4" }]
495
989
  ];
496
- var Globe = createLucideIcon("globe", __iconNode13);
990
+ var Globe = createLucideIcon("globe", __iconNode14);
497
991
 
498
992
  // node_modules/lucide-react/dist/esm/icons/grip-vertical.js
499
- var __iconNode14 = [
993
+ var __iconNode15 = [
500
994
  ["circle", { cx: "9", cy: "12", r: "1", key: "1vctgf" }],
501
995
  ["circle", { cx: "9", cy: "5", r: "1", key: "hp0tcf" }],
502
996
  ["circle", { cx: "9", cy: "19", r: "1", key: "fkjjf6" }],
@@ -504,28 +998,28 @@ var __iconNode14 = [
504
998
  ["circle", { cx: "15", cy: "5", r: "1", key: "19l28e" }],
505
999
  ["circle", { cx: "15", cy: "19", r: "1", key: "f4zoj3" }]
506
1000
  ];
507
- var GripVertical = createLucideIcon("grip-vertical", __iconNode14);
1001
+ var GripVertical = createLucideIcon("grip-vertical", __iconNode15);
508
1002
 
509
1003
  // node_modules/lucide-react/dist/esm/icons/image-plus.js
510
- var __iconNode15 = [
1004
+ var __iconNode16 = [
511
1005
  ["path", { d: "M16 5h6", key: "1vod17" }],
512
1006
  ["path", { d: "M19 2v6", key: "4bpg5p" }],
513
1007
  ["path", { d: "M21 11.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7.5", key: "1ue2ih" }],
514
1008
  ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }],
515
1009
  ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }]
516
1010
  ];
517
- var ImagePlus = createLucideIcon("image-plus", __iconNode15);
1011
+ var ImagePlus = createLucideIcon("image-plus", __iconNode16);
518
1012
 
519
1013
  // node_modules/lucide-react/dist/esm/icons/image.js
520
- var __iconNode16 = [
1014
+ var __iconNode17 = [
521
1015
  ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
522
1016
  ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
523
1017
  ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
524
1018
  ];
525
- var Image2 = createLucideIcon("image", __iconNode16);
1019
+ var Image2 = createLucideIcon("image", __iconNode17);
526
1020
 
527
1021
  // node_modules/lucide-react/dist/esm/icons/languages.js
528
- var __iconNode17 = [
1022
+ var __iconNode18 = [
529
1023
  ["path", { d: "m5 8 6 6", key: "1wu5hv" }],
530
1024
  ["path", { d: "m4 14 6-6 2-3", key: "1k1g8d" }],
531
1025
  ["path", { d: "M2 5h12", key: "or177f" }],
@@ -533,29 +1027,29 @@ var __iconNode17 = [
533
1027
  ["path", { d: "m22 22-5-10-5 10", key: "don7ne" }],
534
1028
  ["path", { d: "M14 18h6", key: "1m8k6r" }]
535
1029
  ];
536
- var Languages = createLucideIcon("languages", __iconNode17);
1030
+ var Languages = createLucideIcon("languages", __iconNode18);
537
1031
 
538
1032
  // node_modules/lucide-react/dist/esm/icons/link-2.js
539
- var __iconNode18 = [
1033
+ var __iconNode19 = [
540
1034
  ["path", { d: "M9 17H7A5 5 0 0 1 7 7h2", key: "8i5ue5" }],
541
1035
  ["path", { d: "M15 7h2a5 5 0 1 1 0 10h-2", key: "1b9ql8" }],
542
1036
  ["line", { x1: "8", x2: "16", y1: "12", y2: "12", key: "1jonct" }]
543
1037
  ];
544
- var Link2 = createLucideIcon("link-2", __iconNode18);
1038
+ var Link2 = createLucideIcon("link-2", __iconNode19);
545
1039
 
546
1040
  // node_modules/lucide-react/dist/esm/icons/link.js
547
- var __iconNode19 = [
1041
+ var __iconNode20 = [
548
1042
  ["path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71", key: "1cjeqo" }],
549
1043
  ["path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71", key: "19qd67" }]
550
1044
  ];
551
- var Link = createLucideIcon("link", __iconNode19);
1045
+ var Link = createLucideIcon("link", __iconNode20);
552
1046
 
553
1047
  // node_modules/lucide-react/dist/esm/icons/loader-circle.js
554
- var __iconNode20 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
555
- var LoaderCircle = createLucideIcon("loader-circle", __iconNode20);
1048
+ var __iconNode21 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
1049
+ var LoaderCircle = createLucideIcon("loader-circle", __iconNode21);
556
1050
 
557
1051
  // node_modules/lucide-react/dist/esm/icons/pencil.js
558
- var __iconNode21 = [
1052
+ var __iconNode22 = [
559
1053
  [
560
1054
  "path",
561
1055
  {
@@ -565,429 +1059,1030 @@ var __iconNode21 = [
565
1059
  ],
566
1060
  ["path", { d: "m15 5 4 4", key: "1mk7zo" }]
567
1061
  ];
568
- var Pencil = createLucideIcon("pencil", __iconNode21);
1062
+ var Pencil = createLucideIcon("pencil", __iconNode22);
569
1063
 
570
1064
  // node_modules/lucide-react/dist/esm/icons/plus.js
571
- var __iconNode22 = [
1065
+ var __iconNode23 = [
572
1066
  ["path", { d: "M5 12h14", key: "1ays0h" }],
573
1067
  ["path", { d: "M12 5v14", key: "s699le" }]
574
1068
  ];
575
- var Plus = createLucideIcon("plus", __iconNode22);
1069
+ var Plus = createLucideIcon("plus", __iconNode23);
576
1070
 
577
1071
  // node_modules/lucide-react/dist/esm/icons/refresh-ccw.js
578
- var __iconNode23 = [
1072
+ var __iconNode24 = [
579
1073
  ["path", { d: "M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", key: "14sxne" }],
580
1074
  ["path", { d: "M3 3v5h5", key: "1xhq8a" }],
581
1075
  ["path", { d: "M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16", key: "1hlbsb" }],
582
1076
  ["path", { d: "M16 16h5v5", key: "ccwih5" }]
583
1077
  ];
584
- var RefreshCcw = createLucideIcon("refresh-ccw", __iconNode23);
1078
+ var RefreshCcw = createLucideIcon("refresh-ccw", __iconNode24);
585
1079
 
586
1080
  // node_modules/lucide-react/dist/esm/icons/refresh-cw.js
587
- var __iconNode24 = [
1081
+ var __iconNode25 = [
588
1082
  ["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
589
1083
  ["path", { d: "M21 3v5h-5", key: "1q7to0" }],
590
1084
  ["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
591
1085
  ["path", { d: "M8 16H3v5", key: "1cv678" }]
592
1086
  ];
593
- var RefreshCw = createLucideIcon("refresh-cw", __iconNode24);
1087
+ var RefreshCw = createLucideIcon("refresh-cw", __iconNode25);
594
1088
 
595
1089
  // node_modules/lucide-react/dist/esm/icons/rotate-ccw.js
596
- var __iconNode25 = [
1090
+ var __iconNode26 = [
597
1091
  ["path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", key: "1357e3" }],
598
1092
  ["path", { d: "M3 3v5h5", key: "1xhq8a" }]
599
1093
  ];
600
- var RotateCcw = createLucideIcon("rotate-ccw", __iconNode25);
1094
+ var RotateCcw = createLucideIcon("rotate-ccw", __iconNode26);
601
1095
 
602
1096
  // node_modules/lucide-react/dist/esm/icons/search.js
603
- var __iconNode26 = [
1097
+ var __iconNode27 = [
604
1098
  ["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
605
1099
  ["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
606
1100
  ];
607
- var Search = createLucideIcon("search", __iconNode26);
1101
+ var Search = createLucideIcon("search", __iconNode27);
608
1102
 
609
1103
  // node_modules/lucide-react/dist/esm/icons/trash-2.js
610
- var __iconNode27 = [
1104
+ var __iconNode28 = [
611
1105
  ["path", { d: "M10 11v6", key: "nco0om" }],
612
1106
  ["path", { d: "M14 11v6", key: "outv1u" }],
613
1107
  ["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6", key: "miytrc" }],
614
1108
  ["path", { d: "M3 6h18", key: "d0wm0j" }],
615
1109
  ["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2", key: "e791ji" }]
616
1110
  ];
617
- var Trash2 = createLucideIcon("trash-2", __iconNode27);
1111
+ var Trash2 = createLucideIcon("trash-2", __iconNode28);
618
1112
 
619
1113
  // node_modules/lucide-react/dist/esm/icons/upload.js
620
- var __iconNode28 = [
1114
+ var __iconNode29 = [
621
1115
  ["path", { d: "M12 3v12", key: "1x0j5s" }],
622
1116
  ["path", { d: "m17 8-5-5-5 5", key: "7q97r8" }],
623
1117
  ["path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4", key: "ih7n3h" }]
624
1118
  ];
625
- var Upload = createLucideIcon("upload", __iconNode28);
1119
+ var Upload = createLucideIcon("upload", __iconNode29);
626
1120
 
627
1121
  // node_modules/lucide-react/dist/esm/icons/x.js
628
- var __iconNode29 = [
1122
+ var __iconNode30 = [
629
1123
  ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
630
1124
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
631
1125
  ];
632
- var X = createLucideIcon("x", __iconNode29);
633
- var EMPTY_PAGE = { content: [], root: { props: {} }, zones: {} };
634
- var ComponentDrawerItem = ({
635
- name: name3,
636
- apiClient,
637
- children
638
- }) => {
639
- const [imgSrc, setImgSrc] = useState(null);
640
- const [loading, setLoading] = useState(false);
641
- const [error2, setError] = useState(false);
642
- const fetchedRef = useRef(false);
643
- const handleMouseEnter = useCallback(async () => {
644
- if (fetchedRef.current) return;
645
- fetchedRef.current = true;
646
- setLoading(true);
647
- try {
648
- const domain = typeof window !== "undefined" ? window.location.hostname : "";
649
- const blobUrl = await apiClient.getComponentPreview(domain, name3);
650
- if (blobUrl) {
651
- setImgSrc(blobUrl);
652
- } else {
653
- setError(true);
654
- }
655
- } catch {
656
- setError(true);
657
- } finally {
658
- setLoading(false);
1126
+ var X = createLucideIcon("x", __iconNode30);
1127
+ var useOverlayCoords = (id, iframeEl, containerEl, documentState) => {
1128
+ const [coords, setCoords] = useState(null);
1129
+ useEffect(() => {
1130
+ if (!id || !iframeEl || !containerEl) {
1131
+ setCoords(null);
1132
+ return;
659
1133
  }
660
- }, [name3, apiClient]);
661
- return /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-item-group group", onMouseEnter: handleMouseEnter, children: [
662
- children,
663
- /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-popover", children: [
664
- /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-popover-header", children: [
665
- name3,
666
- " \xD6nizleme"
667
- ] }),
668
- /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-popover-body", children: [
669
- (loading || !imgSrc && !error2) && /* @__PURE__ */ jsx("div", { className: "tecof-drawer-skeleton" }),
670
- imgSrc && /* @__PURE__ */ jsx(
671
- "img",
1134
+ let resizeObserver = null;
1135
+ let targetResizeObserver = null;
1136
+ const updateCoords = () => {
1137
+ const doc = iframeEl.contentDocument;
1138
+ if (!doc) return;
1139
+ const element = doc.querySelector(`[data-tecof-id="${id}"]`);
1140
+ if (!element) {
1141
+ setCoords(null);
1142
+ return;
1143
+ }
1144
+ const rect = element.getBoundingClientRect();
1145
+ const iframeRect = iframeEl.getBoundingClientRect();
1146
+ const containerRect = containerEl.getBoundingClientRect();
1147
+ setCoords({
1148
+ top: rect.top + iframeRect.top - containerRect.top,
1149
+ left: rect.left + iframeRect.left - containerRect.left,
1150
+ width: rect.width,
1151
+ height: rect.height
1152
+ });
1153
+ if (!targetResizeObserver) {
1154
+ targetResizeObserver = new ResizeObserver(() => {
1155
+ updateCoords();
1156
+ });
1157
+ targetResizeObserver.observe(element);
1158
+ }
1159
+ };
1160
+ updateCoords();
1161
+ const iframeWin = iframeEl.contentWindow;
1162
+ resizeObserver = new ResizeObserver(() => {
1163
+ updateCoords();
1164
+ });
1165
+ resizeObserver.observe(iframeEl);
1166
+ iframeWin?.addEventListener("scroll", updateCoords);
1167
+ window.addEventListener("resize", updateCoords);
1168
+ return () => {
1169
+ if (resizeObserver) resizeObserver.disconnect();
1170
+ if (targetResizeObserver) targetResizeObserver.disconnect();
1171
+ iframeWin?.removeEventListener("scroll", updateCoords);
1172
+ window.removeEventListener("resize", updateCoords);
1173
+ };
1174
+ }, [id, iframeEl, containerEl, documentState]);
1175
+ return coords;
1176
+ };
1177
+ var SelectionOverlay = () => {
1178
+ const documentState = useEditorStore((state3) => state3.document);
1179
+ const selectedId = useEditorStore((state3) => state3.selection.selectedId);
1180
+ const hoveredId = useEditorStore((state3) => state3.selection.hoveredId);
1181
+ const selectNode = useEditorStore((state3) => state3.selectNode);
1182
+ const removeNode2 = useEditorStore((state3) => state3.removeNode);
1183
+ const duplicateNode2 = useEditorStore((state3) => state3.duplicateNode);
1184
+ const moveNode2 = useEditorStore((state3) => state3.moveNode);
1185
+ const [iframeEl, setIframeEl] = useState(null);
1186
+ const containerRef = useRef(null);
1187
+ useEffect(() => {
1188
+ const iframe = document.querySelector(".tecof-canvas-viewport-wrapper iframe");
1189
+ setIframeEl(iframe);
1190
+ }, [documentState]);
1191
+ const selectedCoords = useOverlayCoords(selectedId, iframeEl, containerRef.current, documentState);
1192
+ const hoveredCoords = useOverlayCoords(
1193
+ hoveredId !== selectedId ? hoveredId : null,
1194
+ iframeEl,
1195
+ containerRef.current,
1196
+ documentState
1197
+ );
1198
+ const nodeDetails = selectedId ? findNodeById(documentState, selectedId) : null;
1199
+ const parentId = selectedId ? getParentId(documentState, selectedId) : null;
1200
+ const canMoveUp = nodeDetails ? nodeDetails.path.index > 0 : false;
1201
+ const canMoveDown = nodeDetails ? (() => {
1202
+ const { zoneKey, index: index2 } = nodeDetails.path;
1203
+ const items = zoneKey ? documentState.zones[zoneKey] || [] : documentState.content;
1204
+ return index2 < items.length - 1;
1205
+ })() : false;
1206
+ const handleMove = (direction) => {
1207
+ if (!selectedId || !nodeDetails) return;
1208
+ const { zoneKey, index: index2 } = nodeDetails.path;
1209
+ const newIndex = direction === "up" ? index2 - 1 : index2 + 1;
1210
+ moveNode2(selectedId, zoneKey, newIndex);
1211
+ };
1212
+ const breadcrumbs = selectedId ? getBreadcrumbs(documentState, selectedId) : [];
1213
+ return /* @__PURE__ */ jsxs(
1214
+ "div",
1215
+ {
1216
+ ref: containerRef,
1217
+ className: "tecof-selection-overlay-container",
1218
+ style: {
1219
+ position: "absolute",
1220
+ top: 0,
1221
+ left: 0,
1222
+ right: 0,
1223
+ bottom: 0,
1224
+ pointerEvents: "none",
1225
+ zIndex: 1e3
1226
+ },
1227
+ children: [
1228
+ hoveredCoords && /* @__PURE__ */ jsx(
1229
+ "div",
672
1230
  {
673
- src: imgSrc,
674
- alt: `${name3} preview`,
675
- className: "tecof-drawer-img"
1231
+ className: "tecof-hover-outline",
1232
+ style: {
1233
+ position: "absolute",
1234
+ top: hoveredCoords.top,
1235
+ left: hoveredCoords.left,
1236
+ width: hoveredCoords.width,
1237
+ height: hoveredCoords.height,
1238
+ border: "1.5px dashed #3b82f6",
1239
+ borderRadius: "4px",
1240
+ boxSizing: "border-box",
1241
+ pointerEvents: "none",
1242
+ transition: "all 0.1s ease-out"
1243
+ }
676
1244
  }
677
1245
  ),
678
- error2 && /* @__PURE__ */ jsx("div", { className: "tecof-drawer-preview-error", children: "\xD6nizleme y\xFCklenemedi" })
679
- ] })
680
- ] })
681
- ] });
682
- };
683
- var AutoFieldsOnSelect = () => {
684
- const { selectedItem, dispatch } = usePuck();
685
- const prevSelectedRef = useRef(null);
686
- useEffect(() => {
687
- const currentId = selectedItem?.props?.id || null;
688
- if (currentId && currentId !== prevSelectedRef.current) {
689
- dispatch({
690
- type: "setUi",
691
- ui: { plugin: { current: "fields" } }
692
- });
1246
+ selectedCoords && /* @__PURE__ */ jsxs(
1247
+ "div",
1248
+ {
1249
+ className: "tecof-selected-outline",
1250
+ style: {
1251
+ position: "absolute",
1252
+ top: selectedCoords.top,
1253
+ left: selectedCoords.left,
1254
+ width: selectedCoords.width,
1255
+ height: selectedCoords.height,
1256
+ border: "2px solid #3b82f6",
1257
+ borderRadius: "4px",
1258
+ boxSizing: "border-box",
1259
+ pointerEvents: "none",
1260
+ transition: "all 0.1s ease-out"
1261
+ },
1262
+ children: [
1263
+ /* @__PURE__ */ jsxs(
1264
+ "div",
1265
+ {
1266
+ className: "tecof-floating-toolbar",
1267
+ style: {
1268
+ position: "absolute",
1269
+ top: "-36px",
1270
+ right: "-2px",
1271
+ display: "flex",
1272
+ alignItems: "center",
1273
+ gap: "4px",
1274
+ background: "#3b82f6",
1275
+ borderRadius: "6px",
1276
+ padding: "4px",
1277
+ pointerEvents: "auto",
1278
+ boxShadow: "0 4px 6px -1px rgba(59, 130, 246, 0.2)"
1279
+ },
1280
+ children: [
1281
+ parentId && /* @__PURE__ */ jsx(
1282
+ "button",
1283
+ {
1284
+ onClick: () => selectNode(parentId),
1285
+ title: "\xDCst \xD6\u011Feyi Se\xE7",
1286
+ style: {
1287
+ background: "transparent",
1288
+ border: "none",
1289
+ color: "#ffffff",
1290
+ cursor: "pointer",
1291
+ padding: "4px",
1292
+ borderRadius: "4px",
1293
+ display: "flex"
1294
+ },
1295
+ children: /* @__PURE__ */ jsx(ChevronUp, { size: 14 })
1296
+ }
1297
+ ),
1298
+ /* @__PURE__ */ jsx(
1299
+ "button",
1300
+ {
1301
+ onClick: () => handleMove("up"),
1302
+ disabled: !canMoveUp,
1303
+ title: "Yukar\u0131 Ta\u015F\u0131",
1304
+ style: {
1305
+ background: "transparent",
1306
+ border: "none",
1307
+ color: "#ffffff",
1308
+ opacity: canMoveUp ? 1 : 0.5,
1309
+ cursor: canMoveUp ? "pointer" : "not-allowed",
1310
+ padding: "4px",
1311
+ borderRadius: "4px",
1312
+ display: "flex"
1313
+ },
1314
+ children: /* @__PURE__ */ jsx(ArrowUp, { size: 14 })
1315
+ }
1316
+ ),
1317
+ /* @__PURE__ */ jsx(
1318
+ "button",
1319
+ {
1320
+ onClick: () => handleMove("down"),
1321
+ disabled: !canMoveDown,
1322
+ title: "A\u015Fa\u011F\u0131 Ta\u015F\u0131",
1323
+ style: {
1324
+ background: "transparent",
1325
+ border: "none",
1326
+ color: "#ffffff",
1327
+ opacity: canMoveDown ? 1 : 0.5,
1328
+ cursor: canMoveDown ? "pointer" : "not-allowed",
1329
+ padding: "4px",
1330
+ borderRadius: "4px",
1331
+ display: "flex"
1332
+ },
1333
+ children: /* @__PURE__ */ jsx(ArrowDown, { size: 14 })
1334
+ }
1335
+ ),
1336
+ /* @__PURE__ */ jsx("div", { style: { width: "1px", height: "14px", background: "rgba(255,255,255,0.3)", margin: "0 2px" } }),
1337
+ /* @__PURE__ */ jsx(
1338
+ "button",
1339
+ {
1340
+ onClick: () => duplicateNode2(selectedId),
1341
+ title: "Kopyala",
1342
+ style: {
1343
+ background: "transparent",
1344
+ border: "none",
1345
+ color: "#ffffff",
1346
+ cursor: "pointer",
1347
+ padding: "4px",
1348
+ borderRadius: "4px",
1349
+ display: "flex"
1350
+ },
1351
+ children: /* @__PURE__ */ jsx(Copy, { size: 14 })
1352
+ }
1353
+ ),
1354
+ /* @__PURE__ */ jsx(
1355
+ "button",
1356
+ {
1357
+ onClick: () => removeNode2(selectedId),
1358
+ title: "Sil",
1359
+ style: {
1360
+ background: "transparent",
1361
+ border: "none",
1362
+ color: "#ffffff",
1363
+ cursor: "pointer",
1364
+ padding: "4px",
1365
+ borderRadius: "4px",
1366
+ display: "flex"
1367
+ },
1368
+ children: /* @__PURE__ */ jsx(Trash2, { size: 14 })
1369
+ }
1370
+ )
1371
+ ]
1372
+ }
1373
+ ),
1374
+ nodeDetails && /* @__PURE__ */ jsx(
1375
+ "div",
1376
+ {
1377
+ className: "tecof-outline-label",
1378
+ style: {
1379
+ position: "absolute",
1380
+ top: "-26px",
1381
+ left: "-2px",
1382
+ background: "#3b82f6",
1383
+ color: "#ffffff",
1384
+ fontSize: "11px",
1385
+ fontWeight: 600,
1386
+ padding: "2px 8px",
1387
+ borderRadius: "4px 4px 0 0",
1388
+ userSelect: "none"
1389
+ },
1390
+ children: nodeDetails.node.type
1391
+ }
1392
+ ),
1393
+ breadcrumbs.length > 1 && /* @__PURE__ */ jsx(
1394
+ "div",
1395
+ {
1396
+ className: "tecof-selected-breadcrumbs",
1397
+ style: {
1398
+ position: "absolute",
1399
+ bottom: "-28px",
1400
+ left: "-2px",
1401
+ display: "flex",
1402
+ alignItems: "center",
1403
+ gap: "4px",
1404
+ background: "#18181b",
1405
+ color: "#a1a1aa",
1406
+ fontSize: "10px",
1407
+ padding: "4px 8px",
1408
+ borderRadius: "0 0 6px 6px",
1409
+ pointerEvents: "auto",
1410
+ boxShadow: "0 2px 4px rgba(0,0,0,0.05)"
1411
+ },
1412
+ children: breadcrumbs.map((crumb, idx) => /* @__PURE__ */ jsxs(React__default__default.Fragment, { children: [
1413
+ idx > 0 && /* @__PURE__ */ jsx("span", { style: { color: "#52525b" }, children: ">" }),
1414
+ /* @__PURE__ */ jsx(
1415
+ "span",
1416
+ {
1417
+ onClick: () => selectNode(crumb.id),
1418
+ style: {
1419
+ cursor: "pointer",
1420
+ color: crumb.id === selectedId ? "#ffffff" : void 0,
1421
+ fontWeight: crumb.id === selectedId ? 600 : void 0
1422
+ },
1423
+ onMouseEnter: () => useEditorStore.getState().hoverNode(crumb.id),
1424
+ onMouseLeave: () => useEditorStore.getState().hoverNode(null),
1425
+ children: crumb.type
1426
+ }
1427
+ )
1428
+ ] }, crumb.id))
1429
+ }
1430
+ )
1431
+ ]
1432
+ }
1433
+ )
1434
+ ]
693
1435
  }
694
- prevSelectedRef.current = currentId;
695
- }, [selectedItem, dispatch]);
696
- return null;
1436
+ );
697
1437
  };
698
- var CustomActionBar = ({ children, label }) => {
699
- const { appState, dispatch, getSelectorForId, selectedItem } = usePuck();
700
- const canMoveUp = useMemo(() => {
701
- if (!selectedItem || !selectedItem.props?.id) return false;
702
- const selector = getSelectorForId(selectedItem.props.id);
703
- if (!selector) return false;
704
- return selector.index > 0;
705
- }, [selectedItem, getSelectorForId]);
706
- const canMoveDown = useMemo(() => {
707
- if (!selectedItem || !selectedItem.props?.id) return false;
708
- const selector = getSelectorForId(selectedItem.props.id);
709
- if (!selector) return false;
710
- const { index: index2, zone } = selector;
711
- const items = zone ? appState.data.zones?.[zone] || [] : appState.data.content || [];
712
- return index2 < items.length - 1;
713
- }, [selectedItem, getSelectorForId, appState.data]);
714
- const handleMove = useCallback((direction) => {
715
- if (!selectedItem || !selectedItem.props?.id) return;
716
- const selector = getSelectorForId(selectedItem.props.id);
717
- if (!selector) return;
718
- const { index: index2, zone } = selector;
719
- let items = zone ? [...appState.data.zones?.[zone] || []] : [...appState.data.content || []];
720
- const targetIndex = direction === "up" ? index2 - 1 : index2 + 1;
721
- if (targetIndex < 0 || targetIndex >= items.length) return;
722
- const temp = items[index2];
723
- items[index2] = items[targetIndex];
724
- items[targetIndex] = temp;
725
- if (zone) {
726
- dispatch({
727
- type: "setData",
728
- data: {
729
- ...appState.data,
730
- zones: {
731
- ...appState.data.zones,
732
- [zone]: items
733
- }
734
- }
735
- });
736
- dispatch({
737
- type: "setUi",
738
- ui: {
739
- itemSelector: {
740
- index: targetIndex,
741
- zone
1438
+ var FieldLabel = ({
1439
+ label,
1440
+ icon,
1441
+ readOnly,
1442
+ children,
1443
+ el = "label"
1444
+ }) => {
1445
+ const Component2 = el;
1446
+ return /* @__PURE__ */ jsxs(
1447
+ Component2,
1448
+ {
1449
+ className: "tecof-field-label-container",
1450
+ style: {
1451
+ display: "flex",
1452
+ flexDirection: "column",
1453
+ gap: "6px",
1454
+ marginBottom: "16px",
1455
+ width: "100%",
1456
+ boxSizing: "border-box",
1457
+ userSelect: "none"
1458
+ },
1459
+ children: [
1460
+ /* @__PURE__ */ jsxs(
1461
+ "div",
1462
+ {
1463
+ className: "tecof-field-label-header",
1464
+ style: {
1465
+ display: "flex",
1466
+ alignItems: "center",
1467
+ gap: "6px",
1468
+ fontSize: "12px",
1469
+ fontWeight: 600,
1470
+ color: "#27272a"
1471
+ // zinc-800
1472
+ },
1473
+ children: [
1474
+ icon && /* @__PURE__ */ jsx("span", { style: { display: "inline-flex" }, children: icon }),
1475
+ /* @__PURE__ */ jsx("span", { children: label }),
1476
+ readOnly && /* @__PURE__ */ jsx(
1477
+ "span",
1478
+ {
1479
+ style: {
1480
+ fontSize: "10px",
1481
+ color: "#a1a1aa",
1482
+ fontWeight: 400,
1483
+ marginLeft: "auto"
1484
+ },
1485
+ children: "Salt Okunur"
1486
+ }
1487
+ )
1488
+ ]
742
1489
  }
1490
+ ),
1491
+ /* @__PURE__ */ jsx("div", { className: "tecof-field-label-content", style: { width: "100%" }, children })
1492
+ ]
1493
+ }
1494
+ );
1495
+ };
1496
+ var FieldRenderer = ({
1497
+ name: name3,
1498
+ definition,
1499
+ value,
1500
+ onChange,
1501
+ readOnly = false
1502
+ }) => {
1503
+ const label = definition.label || name3;
1504
+ const type = definition.type;
1505
+ if (definition.render) {
1506
+ return /* @__PURE__ */ jsx("div", { className: "tecof-custom-field-wrapper", style: { width: "100%" }, children: definition.render({
1507
+ field: definition,
1508
+ name: name3,
1509
+ id: `field-${name3}`,
1510
+ value,
1511
+ onChange,
1512
+ readOnly
1513
+ }) });
1514
+ }
1515
+ switch (type) {
1516
+ case "text":
1517
+ return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsx(
1518
+ "input",
1519
+ {
1520
+ id: `field-${name3}`,
1521
+ type: "text",
1522
+ value: value || "",
1523
+ disabled: readOnly,
1524
+ onChange: (e3) => onChange(e3.target.value),
1525
+ style: {
1526
+ width: "100%",
1527
+ padding: "10px 12px",
1528
+ borderRadius: "8px",
1529
+ border: "1px solid #e4e4e7",
1530
+ fontSize: "13px",
1531
+ color: "#18181b",
1532
+ backgroundColor: readOnly ? "#f4f4f5" : "#ffffff",
1533
+ outline: "none",
1534
+ boxSizing: "border-box",
1535
+ transition: "border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out"
1536
+ },
1537
+ className: "tecof-input-text"
743
1538
  }
744
- });
745
- } else {
746
- dispatch({
747
- type: "setData",
748
- data: {
749
- ...appState.data,
750
- content: items
1539
+ ) });
1540
+ case "textarea":
1541
+ return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsx(
1542
+ "textarea",
1543
+ {
1544
+ id: `field-${name3}`,
1545
+ rows: 4,
1546
+ value: value || "",
1547
+ disabled: readOnly,
1548
+ onChange: (e3) => onChange(e3.target.value),
1549
+ style: {
1550
+ width: "100%",
1551
+ padding: "10px 12px",
1552
+ borderRadius: "8px",
1553
+ border: "1px solid #e4e4e7",
1554
+ fontSize: "13px",
1555
+ color: "#18181b",
1556
+ backgroundColor: readOnly ? "#f4f4f5" : "#ffffff",
1557
+ outline: "none",
1558
+ resize: "vertical",
1559
+ boxSizing: "border-box",
1560
+ transition: "border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out"
1561
+ },
1562
+ className: "tecof-input-textarea"
751
1563
  }
752
- });
753
- dispatch({
754
- type: "setUi",
755
- ui: {
756
- itemSelector: {
757
- index: targetIndex
1564
+ ) });
1565
+ case "select":
1566
+ return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsxs("div", { style: { position: "relative", width: "100%" }, children: [
1567
+ /* @__PURE__ */ jsx(
1568
+ "select",
1569
+ {
1570
+ id: `field-${name3}`,
1571
+ value: value || "",
1572
+ disabled: readOnly,
1573
+ onChange: (e3) => onChange(e3.target.value),
1574
+ style: {
1575
+ width: "100%",
1576
+ padding: "10px 32px 10px 12px",
1577
+ borderRadius: "8px",
1578
+ border: "1px solid #e4e4e7",
1579
+ fontSize: "13px",
1580
+ color: "#18181b",
1581
+ backgroundColor: readOnly ? "#f4f4f5" : "#ffffff",
1582
+ outline: "none",
1583
+ appearance: "none",
1584
+ boxSizing: "border-box",
1585
+ cursor: readOnly ? "not-allowed" : "pointer"
1586
+ },
1587
+ className: "tecof-input-select",
1588
+ children: (definition.options || []).map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label || opt.value }, opt.value))
1589
+ }
1590
+ ),
1591
+ /* @__PURE__ */ jsx(
1592
+ "div",
1593
+ {
1594
+ style: {
1595
+ position: "absolute",
1596
+ top: "50%",
1597
+ right: "12px",
1598
+ transform: "translateY(-50%)",
1599
+ pointerEvents: "none",
1600
+ display: "flex",
1601
+ alignItems: "center",
1602
+ color: "#71717a"
1603
+ },
1604
+ children: /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M2.5 4.5L6 8L9.5 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
758
1605
  }
1606
+ )
1607
+ ] }) });
1608
+ case "number":
1609
+ return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsx(
1610
+ "input",
1611
+ {
1612
+ id: `field-${name3}`,
1613
+ type: "number",
1614
+ value: value !== void 0 ? value : "",
1615
+ disabled: readOnly,
1616
+ onChange: (e3) => {
1617
+ const val = e3.target.value;
1618
+ onChange(val === "" ? void 0 : Number(val));
1619
+ },
1620
+ style: {
1621
+ width: "100%",
1622
+ padding: "10px 12px",
1623
+ borderRadius: "8px",
1624
+ border: "1px solid #e4e4e7",
1625
+ fontSize: "13px",
1626
+ color: "#18181b",
1627
+ backgroundColor: readOnly ? "#f4f4f5" : "#ffffff",
1628
+ outline: "none",
1629
+ boxSizing: "border-box"
1630
+ },
1631
+ className: "tecof-input-number"
759
1632
  }
760
- });
1633
+ ) });
1634
+ case "radio":
1635
+ return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: (definition.options || []).map((opt) => /* @__PURE__ */ jsxs(
1636
+ "label",
1637
+ {
1638
+ style: {
1639
+ display: "flex",
1640
+ alignItems: "center",
1641
+ gap: "8px",
1642
+ fontSize: "13px",
1643
+ color: "#27272a",
1644
+ cursor: readOnly ? "not-allowed" : "pointer"
1645
+ },
1646
+ children: [
1647
+ /* @__PURE__ */ jsx(
1648
+ "input",
1649
+ {
1650
+ type: "radio",
1651
+ name: name3,
1652
+ value: opt.value,
1653
+ checked: value === opt.value,
1654
+ disabled: readOnly,
1655
+ onChange: () => onChange(opt.value),
1656
+ style: {
1657
+ cursor: readOnly ? "not-allowed" : "pointer"
1658
+ }
1659
+ }
1660
+ ),
1661
+ /* @__PURE__ */ jsx("span", { children: opt.label || opt.value })
1662
+ ]
1663
+ },
1664
+ opt.value
1665
+ )) }) });
1666
+ default:
1667
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "8px", fontSize: "11px", color: "#71717a", background: "#fafafa", borderRadius: "4px" }, children: [
1668
+ 'Desteklenmeyen alan t\xFCr\xFC: "',
1669
+ type,
1670
+ '" (',
1671
+ name3,
1672
+ ")"
1673
+ ] });
1674
+ }
1675
+ };
1676
+ var Inspector = () => {
1677
+ const documentState = useEditorStore((state3) => state3.document);
1678
+ const selectedId = useEditorStore((state3) => state3.selection.selectedId);
1679
+ const updateProps2 = useEditorStore((state3) => state3.updateProps);
1680
+ const setRootProps2 = useEditorStore((state3) => state3.setRootProps);
1681
+ const selectNode = useEditorStore((state3) => state3.selectNode);
1682
+ const { config: config3, readOnly } = useStudio();
1683
+ if (selectedId) {
1684
+ const nodeDetails = findNodeById(documentState, selectedId);
1685
+ if (!nodeDetails) {
1686
+ return /* @__PURE__ */ jsx("div", { style: { padding: "24px", color: "#71717a", fontSize: "13px", textAlign: "center" }, children: "Bile\u015Fen y\xFCkleniyor veya bulunamad\u0131." });
1687
+ }
1688
+ const { node } = nodeDetails;
1689
+ const componentConfig = config3.components[node.type];
1690
+ const fields = componentConfig?.fields || {};
1691
+ const label = componentConfig?.label || node.type;
1692
+ return /* @__PURE__ */ jsxs(
1693
+ "div",
1694
+ {
1695
+ className: "tecof-inspector",
1696
+ style: {
1697
+ width: "320px",
1698
+ height: "100%",
1699
+ borderLeft: "1px solid #e4e4e7",
1700
+ background: "#ffffff",
1701
+ display: "flex",
1702
+ flexDirection: "column",
1703
+ boxSizing: "border-box"
1704
+ },
1705
+ children: [
1706
+ /* @__PURE__ */ jsxs(
1707
+ "div",
1708
+ {
1709
+ style: {
1710
+ padding: "16px 20px",
1711
+ borderBottom: "1px solid #f4f4f5",
1712
+ display: "flex",
1713
+ alignItems: "center",
1714
+ justifyContent: "space-between"
1715
+ },
1716
+ children: [
1717
+ /* @__PURE__ */ jsxs("div", { children: [
1718
+ /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "14px", fontWeight: 700, color: "#18181b" }, children: label }),
1719
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: "#a1a1aa", fontFamily: "monospace" }, children: selectedId })
1720
+ ] }),
1721
+ /* @__PURE__ */ jsx(
1722
+ "button",
1723
+ {
1724
+ onClick: () => selectNode(null),
1725
+ style: {
1726
+ background: "transparent",
1727
+ border: "none",
1728
+ color: "#71717a",
1729
+ cursor: "pointer",
1730
+ fontSize: "11px",
1731
+ fontWeight: 500,
1732
+ padding: "4px 8px",
1733
+ borderRadius: "4px",
1734
+ hover: { background: "#f4f4f5" }
1735
+ },
1736
+ children: "Se\xE7imi Kald\u0131r"
1737
+ }
1738
+ )
1739
+ ]
1740
+ }
1741
+ ),
1742
+ /* @__PURE__ */ jsx(
1743
+ "div",
1744
+ {
1745
+ className: "tecof-inspector-fields",
1746
+ style: {
1747
+ flex: 1,
1748
+ overflowY: "auto",
1749
+ padding: "20px",
1750
+ display: "flex",
1751
+ flexDirection: "column",
1752
+ gap: "4px"
1753
+ },
1754
+ children: Object.keys(fields).length === 0 ? /* @__PURE__ */ jsx("div", { style: { color: "#a1a1aa", fontSize: "12px", textAlign: "center", marginTop: "16px" }, children: "Bu bile\u015Fenin d\xFCzenlenebilir alan\u0131 bulunmuyor." }) : Object.entries(fields).map(([fieldName, fieldDef]) => /* @__PURE__ */ jsx(
1755
+ FieldRenderer,
1756
+ {
1757
+ name: fieldName,
1758
+ definition: fieldDef,
1759
+ value: node.props[fieldName],
1760
+ onChange: (newVal) => updateProps2(selectedId, { [fieldName]: newVal }),
1761
+ readOnly
1762
+ },
1763
+ fieldName
1764
+ ))
1765
+ }
1766
+ )
1767
+ ]
1768
+ }
1769
+ );
1770
+ }
1771
+ const rootFields = config3.root?.fields || {};
1772
+ const hasRootFields = Object.keys(rootFields).length > 0;
1773
+ return /* @__PURE__ */ jsxs(
1774
+ "div",
1775
+ {
1776
+ className: "tecof-inspector",
1777
+ style: {
1778
+ width: "320px",
1779
+ height: "100%",
1780
+ borderLeft: "1px solid #e4e4e7",
1781
+ background: "#ffffff",
1782
+ display: "flex",
1783
+ flexDirection: "column",
1784
+ boxSizing: "border-box"
1785
+ },
1786
+ children: [
1787
+ /* @__PURE__ */ jsxs(
1788
+ "div",
1789
+ {
1790
+ style: {
1791
+ padding: "16px 20px",
1792
+ borderBottom: "1px solid #f4f4f5"
1793
+ },
1794
+ children: [
1795
+ /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "14px", fontWeight: 700, color: "#18181b" }, children: "Sayfa Ayarlar\u0131" }),
1796
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: "#a1a1aa" }, children: "Genel sayfa konfig\xFCrasyonu" })
1797
+ ]
1798
+ }
1799
+ ),
1800
+ /* @__PURE__ */ jsx(
1801
+ "div",
1802
+ {
1803
+ className: "tecof-inspector-fields",
1804
+ style: {
1805
+ flex: 1,
1806
+ overflowY: "auto",
1807
+ padding: "20px",
1808
+ display: "flex",
1809
+ flexDirection: "column",
1810
+ gap: "4px"
1811
+ },
1812
+ children: hasRootFields ? Object.entries(rootFields).map(([fieldName, fieldDef]) => /* @__PURE__ */ jsx(
1813
+ FieldRenderer,
1814
+ {
1815
+ name: fieldName,
1816
+ definition: fieldDef,
1817
+ value: documentState.root.props[fieldName],
1818
+ onChange: (newVal) => setRootProps2({ [fieldName]: newVal }),
1819
+ readOnly
1820
+ },
1821
+ fieldName
1822
+ )) : /* @__PURE__ */ jsxs(
1823
+ "div",
1824
+ {
1825
+ style: {
1826
+ display: "flex",
1827
+ flexDirection: "column",
1828
+ alignItems: "center",
1829
+ justifyContent: "center",
1830
+ height: "100%",
1831
+ color: "#a1a1aa",
1832
+ fontSize: "12px",
1833
+ textAlign: "center",
1834
+ padding: "20px"
1835
+ },
1836
+ children: [
1837
+ /* @__PURE__ */ jsxs(
1838
+ "svg",
1839
+ {
1840
+ width: "24",
1841
+ height: "24",
1842
+ viewBox: "0 0 24 24",
1843
+ fill: "none",
1844
+ stroke: "currentColor",
1845
+ strokeWidth: "2",
1846
+ strokeLinecap: "round",
1847
+ strokeLinejoin: "round",
1848
+ style: { marginBottom: "8px", opacity: 0.6 },
1849
+ children: [
1850
+ /* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }),
1851
+ /* @__PURE__ */ jsx("path", { d: "M9 3v18" })
1852
+ ]
1853
+ }
1854
+ ),
1855
+ "Bile\u015Fen se\xE7ilmedi. D\xFCzenlemek istedi\u011Finiz bir bile\u015Fene t\u0131klay\u0131n."
1856
+ ]
1857
+ }
1858
+ )
1859
+ }
1860
+ )
1861
+ ]
761
1862
  }
762
- }, [selectedItem, getSelectorForId, appState.data, dispatch]);
763
- return /* @__PURE__ */ jsx(ActionBar, { label, children: /* @__PURE__ */ jsxs(ActionBar.Group, { children: [
764
- /* @__PURE__ */ jsx(ActionBar.Action, { onClick: () => handleMove("up"), disabled: !canMoveUp, label: "Yukar\u0131 Ta\u015F\u0131", children: /* @__PURE__ */ jsx(ArrowUp, { size: 14 }) }),
765
- /* @__PURE__ */ jsx(ActionBar.Action, { onClick: () => handleMove("down"), disabled: !canMoveDown, label: "A\u015Fa\u011F\u0131 Ta\u015F\u0131", children: /* @__PURE__ */ jsx(ArrowDown, { size: 14 }) }),
766
- /* @__PURE__ */ jsx(ActionBar.Separator, {}),
767
- children
768
- ] }) });
1863
+ );
769
1864
  };
770
- var TecofEditor = ({
1865
+ var TecofStudio = ({
771
1866
  pageId,
772
1867
  config: config3,
773
1868
  accessToken,
774
1869
  onSave,
775
1870
  onChange,
776
- overrides,
777
- plugins: extraPlugins,
778
1871
  className
779
1872
  }) => {
780
- const { apiClient, secretKey } = useTecof();
781
- const [initialData, setInitialData] = useState(null);
1873
+ const { apiClient } = useTecof();
782
1874
  const [loading, setLoading] = useState(true);
783
1875
  const [saving, setSaving] = useState(false);
784
1876
  const [saveStatus, setSaveStatus] = useState("idle");
785
- const [searchQuery, setSearchQuery] = useState("");
786
- const draftDataRef = useRef(null);
1877
+ const setDocument = useEditorStore((state3) => state3.setDocument);
1878
+ const documentState = useEditorStore((state3) => state3.document);
1879
+ const undo = useEditorStore((state3) => state3.undo);
1880
+ const redo = useEditorStore((state3) => state3.redo);
1881
+ const setViewport = useEditorStore((state3) => state3.setViewport);
1882
+ const documentStateRef = useRef(documentState);
1883
+ documentStateRef.current = documentState;
787
1884
  const isEmbedded = typeof window !== "undefined" && window.parent !== window;
788
1885
  useEffect(() => {
789
1886
  let cancelled = false;
790
1887
  const load = async () => {
791
1888
  setLoading(true);
792
- const res2 = await apiClient.getPage(pageId);
793
- if (cancelled) return;
794
- const data3 = res2.success && res2.data?.draftData ? res2.data.draftData : EMPTY_PAGE;
795
- setInitialData(data3);
796
- draftDataRef.current = data3;
797
- setLoading(false);
1889
+ try {
1890
+ const res2 = await apiClient.getPage(pageId);
1891
+ if (cancelled) return;
1892
+ const rawData = res2.success && res2.data?.draftData ? res2.data.draftData : null;
1893
+ const parsedDoc = parseDocument(rawData);
1894
+ setDocument(parsedDoc);
1895
+ } catch (err) {
1896
+ console.error("Failed to load page:", err);
1897
+ } finally {
1898
+ setLoading(false);
1899
+ }
798
1900
  };
799
1901
  load();
800
1902
  return () => {
801
1903
  cancelled = true;
802
1904
  };
803
- }, [pageId, apiClient]);
804
- const handleSaveDraft = useCallback(
805
- async (data3) => {
806
- const currentData = data3 || draftDataRef.current;
807
- if (!currentData) return;
808
- const draftData = currentData;
809
- setSaving(true);
810
- setSaveStatus("idle");
811
- const res2 = await apiClient.savePage(pageId, draftData, void 0, accessToken);
1905
+ }, [pageId, apiClient, setDocument]);
1906
+ const isFirstRender = useRef(true);
1907
+ useEffect(() => {
1908
+ if (loading) return;
1909
+ if (isFirstRender.current) {
1910
+ isFirstRender.current = false;
1911
+ return;
1912
+ }
1913
+ const serialized = serializeDocument(documentState);
1914
+ onChange?.(serialized);
1915
+ if (isEmbedded) {
1916
+ window.parent.postMessage({ type: "puck:changed" }, "*");
1917
+ }
1918
+ }, [documentState, loading, onChange, isEmbedded]);
1919
+ const handleSaveDraft = useCallback(async () => {
1920
+ const currentDoc = documentStateRef.current;
1921
+ const serialized = serializeDocument(currentDoc);
1922
+ setSaving(true);
1923
+ setSaveStatus("idle");
1924
+ try {
1925
+ const res2 = await apiClient.savePage(pageId, serialized, void 0, accessToken);
812
1926
  if (res2.success) {
813
1927
  setSaveStatus("success");
814
1928
  setTimeout(() => setSaveStatus("idle"), 3e3);
815
- onSave?.(draftData);
816
- if (isEmbedded) window.parent.postMessage({ type: "puck:saved" }, "*");
1929
+ onSave?.(serialized);
1930
+ if (isEmbedded) {
1931
+ window.parent.postMessage({ type: "puck:saved" }, "*");
1932
+ }
817
1933
  } else {
818
1934
  setSaveStatus("error");
819
- if (isEmbedded) window.parent.postMessage({ type: "puck:saveError", message: res2.message }, "*");
1935
+ if (isEmbedded) {
1936
+ window.parent.postMessage({ type: "puck:saveError", message: res2.message }, "*");
1937
+ }
1938
+ }
1939
+ } catch (err) {
1940
+ setSaveStatus("error");
1941
+ if (isEmbedded) {
1942
+ window.parent.postMessage({ type: "puck:saveError", message: err.message }, "*");
820
1943
  }
1944
+ } finally {
821
1945
  setSaving(false);
822
- },
823
- [pageId, apiClient, isEmbedded, onSave, accessToken]
824
- );
825
- const handleChange = useCallback(
826
- (data3) => {
827
- draftDataRef.current = data3;
828
- const draftData = data3;
829
- onChange?.(draftData);
830
- if (isEmbedded) window.parent.postMessage({ type: "puck:changed" }, "*");
831
- },
832
- [onChange, isEmbedded]
833
- );
834
- const handlePuckPublish = useCallback(
835
- (data3) => {
836
- handleSaveDraft(data3);
837
- },
838
- [handleSaveDraft]
839
- );
1946
+ }
1947
+ }, [pageId, apiClient, accessToken, onSave, isEmbedded]);
840
1948
  useEffect(() => {
841
1949
  if (!isEmbedded) return;
842
1950
  const onMessage = (e3) => {
843
1951
  switch (e3.data?.type) {
844
- case "puck:save": {
1952
+ case "puck:save":
845
1953
  handleSaveDraft();
846
1954
  break;
847
- }
848
1955
  case "puck:undo":
849
- document.dispatchEvent(new KeyboardEvent("keydown", { key: "z", code: "KeyZ", ctrlKey: true, bubbles: true }));
1956
+ undo();
850
1957
  break;
851
1958
  case "puck:redo":
852
- document.dispatchEvent(new KeyboardEvent("keydown", { key: "z", code: "KeyZ", ctrlKey: true, shiftKey: true, bubbles: true }));
1959
+ redo();
853
1960
  break;
854
- case "puck:viewport": {
855
- const frame = document.querySelector('[data-testid="puck-frame"]');
856
- if (frame) {
857
- const w = e3.data.width || "100%";
858
- frame.style.maxWidth = w;
859
- frame.style.margin = w === "100%" ? "0" : "0 auto";
860
- frame.style.transition = "max-width 0.3s ease";
1961
+ case "puck:viewport":
1962
+ if (e3.data.width) {
1963
+ const width = e3.data.width;
1964
+ if (width === "375px" || width === 375) {
1965
+ setViewport("mobile");
1966
+ } else if (width === "768px" || width === 768) {
1967
+ setViewport("tablet");
1968
+ } else {
1969
+ setViewport("desktop");
1970
+ }
861
1971
  }
862
1972
  break;
863
- }
864
1973
  }
865
1974
  };
866
1975
  window.addEventListener("message", onMessage);
867
1976
  return () => window.removeEventListener("message", onMessage);
868
- }, [isEmbedded, handleSaveDraft]);
869
- useEffect(() => {
870
- if (!isEmbedded) return;
871
- const handleClick = (e3) => {
872
- const target = e3.target;
873
- const puckComponent = target.closest("[data-puck-component]");
874
- if (puckComponent) {
875
- const componentType = puckComponent.getAttribute("data-puck-component");
876
- const draggableId = puckComponent.closest("[data-rfd-draggable-id]")?.getAttribute("data-rfd-draggable-id");
877
- window.parent.postMessage({
878
- type: "puck:itemSelected",
879
- item: {
880
- type: componentType,
881
- id: draggableId || null
882
- }
883
- }, "*");
884
- }
885
- };
886
- const handleDeselect = (e3) => {
887
- const target = e3.target;
888
- if (!target.closest("[data-puck-component]")) {
889
- window.parent.postMessage({ type: "puck:itemDeselected" }, "*");
890
- }
891
- };
892
- document.addEventListener("click", handleClick, true);
893
- document.addEventListener("click", handleDeselect, false);
894
- return () => {
895
- document.removeEventListener("click", handleClick, true);
896
- document.removeEventListener("click", handleDeselect, false);
897
- };
898
- }, [isEmbedded]);
899
- if (loading || !initialData) {
900
- return /* @__PURE__ */ jsx("div", { className: `tecof-editor-loading ${className || ""}`.trim(), children: /* @__PURE__ */ jsxs("div", { className: "tecof-editor-loading-inner", children: [
901
- /* @__PURE__ */ jsx("div", { className: "tecof-editor-spinner" }),
902
- /* @__PURE__ */ jsx("p", { className: "tecof-editor-loading-text", children: "Loading editor..." })
1977
+ }, [isEmbedded, handleSaveDraft, undo, redo, setViewport]);
1978
+ const studioContextValue = useMemo(() => ({
1979
+ config: config3,
1980
+ readOnly: false,
1981
+ apiClient
1982
+ }), [config3, apiClient]);
1983
+ if (loading) {
1984
+ return /* @__PURE__ */ jsx("div", { className: `tecof-editor-loading ${className || ""}`.trim(), style: {
1985
+ display: "flex",
1986
+ alignItems: "center",
1987
+ justifyContent: "center",
1988
+ height: "100vh",
1989
+ background: "#f4f4f5"
1990
+ }, children: /* @__PURE__ */ jsxs("div", { style: { textAlign: "center" }, children: [
1991
+ /* @__PURE__ */ jsx("div", { className: "tecof-editor-spinner", style: {
1992
+ width: "40px",
1993
+ height: "40px",
1994
+ border: "3px solid #e4e4e7",
1995
+ borderTopColor: "#3b82f6",
1996
+ borderRadius: "50%",
1997
+ animation: "spin 1s linear infinite",
1998
+ margin: "0 auto 16px"
1999
+ } }),
2000
+ /* @__PURE__ */ jsx("p", { style: { color: "#71717a", fontSize: "14px", margin: 0 }, children: "St\xFCdyo y\xFCkleniyor..." })
903
2001
  ] }) });
904
2002
  }
905
- const plugins = [
906
- { ...blocksPlugin(), label: "Bloklar" },
907
- { ...outlinePlugin(), label: "Anahat" },
908
- { ...fieldsPlugin({ desktopSideBar: "right" }), label: "Alanlar" },
909
- ...extraPlugins || []
910
- ];
911
- const mergedOverrides = {
912
- header: () => /* @__PURE__ */ jsx(Fragment, {}),
913
- drawer: ({ children }) => {
914
- return /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-wrapper-layout", children: [
915
- /* @__PURE__ */ jsx("div", { className: "tecof-drawer-search-wrapper", children: /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-search-box", children: [
916
- /* @__PURE__ */ jsx(Search, { size: 14, color: "#71717a" }),
917
- /* @__PURE__ */ jsx(
918
- "input",
919
- {
920
- type: "text",
921
- placeholder: "Blok ara...",
922
- value: searchQuery,
923
- onChange: (e3) => setSearchQuery(e3.target.value),
924
- className: "tecof-drawer-search-input"
925
- }
926
- ),
927
- searchQuery && /* @__PURE__ */ jsx(
928
- "button",
929
- {
930
- type: "button",
931
- onClick: () => setSearchQuery(""),
932
- className: "tecof-drawer-clear-btn",
933
- title: "Temizle",
934
- children: /* @__PURE__ */ jsx(X, { size: 14 })
935
- }
936
- )
937
- ] }) }),
938
- /* @__PURE__ */ jsx("div", { className: "tecof-drawer-list-layout", children })
939
- ] });
940
- },
941
- drawerItem: ({ children, name: name3 }) => {
942
- const componentConfig = config3.components?.[name3];
943
- const label = componentConfig?.label || name3;
944
- if (searchQuery.trim()) {
945
- const query = searchQuery.toLowerCase();
946
- const matchesName = name3.toLowerCase().includes(query);
947
- const matchesLabel = label.toLowerCase().includes(query);
948
- if (!matchesName && !matchesLabel) {
949
- return /* @__PURE__ */ jsx(Fragment, {});
950
- }
2003
+ return /* @__PURE__ */ jsx(StudioContext.Provider, { value: studioContextValue, children: /* @__PURE__ */ jsxs("div", { className: `tecof-studio-root ${className || ""}`.trim(), style: {
2004
+ display: "flex",
2005
+ flexDirection: "column",
2006
+ height: "100vh",
2007
+ width: "100vw",
2008
+ overflow: "hidden",
2009
+ position: "relative",
2010
+ background: "#f4f4f5"
2011
+ }, children: [
2012
+ /* @__PURE__ */ jsxs("div", { className: "tecof-studio-workspace-container", style: {
2013
+ display: "flex",
2014
+ flex: 1,
2015
+ height: "100%",
2016
+ width: "100%",
2017
+ overflow: "hidden"
2018
+ }, children: [
2019
+ /* @__PURE__ */ jsxs("div", { className: "tecof-studio-workspace", style: {
2020
+ display: "flex",
2021
+ flex: 1,
2022
+ height: "100%",
2023
+ position: "relative",
2024
+ overflow: "hidden"
2025
+ }, children: [
2026
+ /* @__PURE__ */ jsx(Canvas, {}),
2027
+ /* @__PURE__ */ jsx(SelectionOverlay, {})
2028
+ ] }),
2029
+ /* @__PURE__ */ jsx(Inspector, {})
2030
+ ] }),
2031
+ saving && /* @__PURE__ */ jsx("div", { className: "tecof-editor-save-indicator", style: {
2032
+ position: "absolute",
2033
+ bottom: "24px",
2034
+ right: "24px",
2035
+ background: saveStatus === "error" ? "#ef4444" : "#18181b",
2036
+ color: "#ffffff",
2037
+ padding: "8px 16px",
2038
+ borderRadius: "24px",
2039
+ fontSize: "12px",
2040
+ fontWeight: 500,
2041
+ boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1)",
2042
+ zIndex: 9999
2043
+ }, children: saveStatus === "error" ? "Kaydedilemedi" : "Kaydediliyor..." })
2044
+ ] }) });
2045
+ };
2046
+
2047
+ // src/components/TecofEditor.tsx
2048
+ var TecofEditor = TecofStudio;
2049
+ var RenderContext = createContext(null);
2050
+ var ParentNodeContext2 = createContext(null);
2051
+ var RenderDropZone = ({ zone, className, style }) => {
2052
+ const parentId = useContext(ParentNodeContext2);
2053
+ const zoneKey = parentId ? `${parentId}:${zone}` : zone;
2054
+ const context = useContext(RenderContext);
2055
+ if (!context) return null;
2056
+ const items = context.zones[zoneKey] || [];
2057
+ return /* @__PURE__ */ jsx("div", { className, style, children: items.map((item2, index2) => /* @__PURE__ */ jsx(RenderNode, { node: item2, index: index2 }, item2.props.id || index2)) });
2058
+ };
2059
+ var RenderNode = ({ node, index: index2 }) => {
2060
+ const context = useContext(RenderContext);
2061
+ if (!context) return null;
2062
+ const componentConfig = context.config.components[node.type];
2063
+ if (!componentConfig) return null;
2064
+ const componentProps = {
2065
+ ...node.props,
2066
+ puck: {
2067
+ renderDropZone: RenderDropZone,
2068
+ isEditing: false,
2069
+ metadata: {
2070
+ cmsData: context.cmsData || null,
2071
+ ...componentConfig.metadata || {}
951
2072
  }
952
- return /* @__PURE__ */ jsx(ComponentDrawerItem, { name: name3, apiClient, children });
953
- },
954
- actionBar: ({ children, label }) => {
955
- return /* @__PURE__ */ jsx(CustomActionBar, { label, children });
956
2073
  },
957
- puck: ({ children }) => {
958
- return /* @__PURE__ */ jsxs(Fragment, { children: [
959
- /* @__PURE__ */ jsx(AutoFieldsOnSelect, {}),
960
- children
961
- ] });
962
- },
963
- ...overrides || {}
2074
+ editMode: false
964
2075
  };
965
- return /* @__PURE__ */ jsxs("div", { className: `tecof-editor-wrapper ${className || ""}`.trim(), children: [
966
- /* @__PURE__ */ jsx(
967
- Puck,
968
- {
969
- plugins,
970
- config: config3,
971
- data: initialData,
972
- onPublish: handlePuckPublish,
973
- onChange: handleChange,
974
- overrides: mergedOverrides,
975
- metadata: { editMode: true }
976
- }
977
- ),
978
- saving && /* @__PURE__ */ jsx("div", { className: "tecof-editor-save-indicator", children: saveStatus === "error" ? "Save failed" : "Saving..." })
979
- ] });
2076
+ return /* @__PURE__ */ jsx(ParentNodeContext2.Provider, { value: node.props.id || null, children: componentConfig.render(componentProps) });
980
2077
  };
981
2078
  var TecofRender = ({ data: data3, config: config3, className, cmsData }) => {
982
2079
  if (!data3) return null;
983
- return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx(
984
- Render,
985
- {
986
- config: config3,
987
- data: data3,
988
- metadata: { cmsData: cmsData || null }
989
- }
990
- ) });
2080
+ const contextValue = {
2081
+ zones: data3.zones || {},
2082
+ config: config3,
2083
+ cmsData: cmsData || null
2084
+ };
2085
+ return /* @__PURE__ */ jsx(RenderContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx("div", { className, children: data3.content.map((item2, index2) => /* @__PURE__ */ jsx(RenderNode, { node: item2, index: index2 }, item2.props.id || index2)) }) });
991
2086
  };
992
2087
  var IMAGE_EXTENSIONS = ["png", "jpg", "jpeg", "webp", "gif", "svg", "avif", "bmp", "tiff", "heic"];
993
2088
  var VIDEO_EXTENSIONS = ["mp4", "webm", "ogg", "avi", "mov", "quicktime"];
@@ -6209,7 +7304,7 @@ var createView = (
6209
7304
  },
6210
7305
  write: write2 = () => {
6211
7306
  },
6212
- create: create4 = () => {
7307
+ create: create5 = () => {
6213
7308
  },
6214
7309
  destroy: destroy3 = () => {
6215
7310
  },
@@ -6413,7 +7508,7 @@ var createView = (
6413
7508
  }
6414
7509
  });
6415
7510
  const internalAPI = createObject(internalAPIDefinition);
6416
- create4({
7511
+ create5({
6417
7512
  root: internalAPI,
6418
7513
  props
6419
7514
  });
@@ -9143,7 +10238,7 @@ var percentageArc = (x, y, radius, from, to) => {
9143
10238
  arcSweep
9144
10239
  );
9145
10240
  };
9146
- var create = ({ root: root3, props }) => {
10241
+ var create2 = ({ root: root3, props }) => {
9147
10242
  props.spin = false;
9148
10243
  props.progress = 0;
9149
10244
  props.opacity = 0;
@@ -9183,7 +10278,7 @@ var progressIndicator = createView({
9183
10278
  name: "progress-indicator",
9184
10279
  ignoreRectUpdate: true,
9185
10280
  ignoreRect: true,
9186
- create,
10281
+ create: create2,
9187
10282
  write,
9188
10283
  mixins: {
9189
10284
  apis: ["progress", "spin", "align"],
@@ -14023,7 +15118,7 @@ var createImageWrapperView = (_2) => {
14023
15118
  root3.ref.overlayShadow.opacity = 0.25;
14024
15119
  root3.ref.overlaySuccess.opacity = 1;
14025
15120
  };
14026
- const create4 = ({ root: root3 }) => {
15121
+ const create5 = ({ root: root3 }) => {
14027
15122
  root3.ref.images = [];
14028
15123
  root3.ref.imageData = null;
14029
15124
  root3.ref.imageViewBin = [];
@@ -14048,7 +15143,7 @@ var createImageWrapperView = (_2) => {
14048
15143
  };
14049
15144
  return _2.utils.createView({
14050
15145
  name: "image-preview-wrapper",
14051
- create: create4,
15146
+ create: create5,
14052
15147
  styles: ["height"],
14053
15148
  apis: ["height"],
14054
15149
  destroy: ({ root: root3 }) => {
@@ -15858,7 +16953,7 @@ var plugin7 = ({ addFilter: addFilter2, utils }) => {
15858
16953
  }).catch(reject);
15859
16954
  });
15860
16955
  const variantPromises = variants.map(
15861
- (create4) => create4(transform, file2, item2.getMetadata())
16956
+ (create5) => create5(transform, file2, item2.getMetadata())
15862
16957
  );
15863
16958
  Promise.all(variantPromises).then((files) => {
15864
16959
  resolve(
@@ -19198,7 +20293,7 @@ var createTexture = function(e3, t2, r2, n, i2) {
19198
20293
  }
19199
20294
  return o2;
19200
20295
  };
19201
- var create2 = function() {
20296
+ var create3 = function() {
19202
20297
  var e3 = new Float32Array(16);
19203
20298
  return e3[0] = 1, e3[5] = 1, e3[10] = 1, e3[15] = 1, e3;
19204
20299
  };
@@ -19226,7 +20321,7 @@ var rotateZ = function(e3, t2) {
19226
20321
  var r2 = Math.sin(t2), n = Math.cos(t2), i2 = e3[0], o2 = e3[1], a2 = e3[2], c2 = e3[3], l3 = e3[4], u = e3[5], s2 = e3[6], d = e3[7];
19227
20322
  e3[0] = i2 * n + l3 * r2, e3[1] = o2 * n + u * r2, e3[2] = a2 * n + s2 * r2, e3[3] = c2 * n + d * r2, e3[4] = l3 * n - i2 * r2, e3[5] = u * n - o2 * r2, e3[6] = s2 * n - a2 * r2, e3[7] = d * n - c2 * r2;
19228
20323
  };
19229
- var mat4 = { create: create2, perspective, translate, scale, rotateX, rotateY, rotateZ };
20324
+ var mat4 = { create: create3, perspective, translate, scale, rotateX, rotateY, rotateZ };
19230
20325
  var degToRad = function(e3) {
19231
20326
  return e3 * Math.PI / 180;
19232
20327
  };
@@ -23821,7 +24916,7 @@ var validators = {
23821
24916
  handler: validateHandler,
23822
24917
  initial: validateInitial
23823
24918
  };
23824
- function create3(initial) {
24919
+ function create4(initial) {
23825
24920
  var handler = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
23826
24921
  validators.initial(initial);
23827
24922
  validators.handler(handler);
@@ -23859,7 +24954,7 @@ function didStateUpdate(state3, handler, changes) {
23859
24954
  return changes;
23860
24955
  }
23861
24956
  var index = {
23862
- create: create3
24957
+ create: create4
23863
24958
  };
23864
24959
  var state_local_default = index;
23865
24960
 
@@ -25506,6 +26601,7 @@ lucide-react/dist/esm/icons/arrow-up.js:
25506
26601
  lucide-react/dist/esm/icons/check.js:
25507
26602
  lucide-react/dist/esm/icons/chevron-down.js:
25508
26603
  lucide-react/dist/esm/icons/chevron-right.js:
26604
+ lucide-react/dist/esm/icons/chevron-up.js:
25509
26605
  lucide-react/dist/esm/icons/code.js:
25510
26606
  lucide-react/dist/esm/icons/copy.js:
25511
26607
  lucide-react/dist/esm/icons/database.js:
@@ -25613,6 +26709,6 @@ filepond-plugin-image-edit/dist/filepond-plugin-image-edit.esm.js:
25613
26709
  *)
25614
26710
  */
25615
26711
 
25616
- export { CmsCollectionField, CodeEditorField, ColorField, EditorField, FieldErrorBoundary, LanguageField, LinkField, RepeaterField, TecofApiClient, TecofEditor, TecofPicture, TecofProvider, TecofRender, UnderConstruction, UploadField, createCmsCollectionField, createCodeEditorField, createColorField, createEditorField, createLanguageField, createLinkField, createRepeaterField, createUploadField, darken, generateCSSVariables, getDefaultTheme, hexToHsl, hslToHex, lighten, mergeTheme, useTecof };
26712
+ export { CmsCollectionField, CodeEditorField, ColorField, EditorField, FieldErrorBoundary, LanguageField, LinkField, RepeaterField, TecofApiClient, TecofEditor, TecofPicture, TecofProvider, TecofRender, TecofStudio, UnderConstruction, UploadField, createCmsCollectionField, createCodeEditorField, createColorField, createEditorField, createLanguageField, createLinkField, createRepeaterField, createUploadField, darken, generateCSSVariables, getDefaultTheme, hexToHsl, hslToHex, lighten, mergeTheme, useTecof };
25617
26713
  //# sourceMappingURL=index.mjs.map
25618
26714
  //# sourceMappingURL=index.mjs.map