@tecof/theme-editor 0.0.37 → 0.0.40

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
@@ -298,17 +298,48 @@ function useTecof() {
298
298
  }
299
299
 
300
300
  // src/engine/document.ts
301
- var EMPTY_DOCUMENT = {
301
+ var createEmptyDocument = () => ({
302
302
  root: { props: {} },
303
303
  content: [],
304
304
  zones: {}
305
+ });
306
+ var cloneValue = (value) => {
307
+ if (Array.isArray(value)) {
308
+ return value.map((item2) => cloneValue(item2));
309
+ }
310
+ if (value && typeof value === "object") {
311
+ return Object.fromEntries(
312
+ Object.entries(value).map(([key, child]) => [key, cloneValue(child)])
313
+ );
314
+ }
315
+ return value;
305
316
  };
317
+ var cloneDocument = (doc) => ({
318
+ root: {
319
+ props: cloneValue(doc.root?.props || {})
320
+ },
321
+ content: (doc.content || []).map((node) => ({
322
+ type: node.type,
323
+ props: cloneValue(node.props || {})
324
+ })),
325
+ zones: Object.fromEntries(
326
+ Object.entries(doc.zones || {}).map(([zoneKey, nodes]) => [
327
+ zoneKey,
328
+ nodes.map((node) => ({
329
+ type: node.type,
330
+ props: cloneValue(node.props || {})
331
+ }))
332
+ ])
333
+ )
334
+ });
306
335
  var parseDocument = (rawData) => {
307
- if (!rawData) return { ...EMPTY_DOCUMENT };
336
+ if (!rawData) return createEmptyDocument();
308
337
  return {
309
338
  root: rawData.root || { props: {} },
310
- content: rawData.content || [],
311
- zones: rawData.zones || {}
339
+ content: [...rawData.content || []],
340
+ zones: Object.fromEntries(
341
+ Object.entries(rawData.zones || {}).map(([zoneKey, nodes]) => [zoneKey, [...nodes]])
342
+ )
312
343
  };
313
344
  };
314
345
  var serializeDocument = (doc) => {
@@ -434,6 +465,13 @@ var moveNode = (draft, id, targetZoneKey, targetIndex) => {
434
465
  const { node, path: sourcePath } = result;
435
466
  const sourceList = sourcePath.zoneKey ? draft.zones[sourcePath.zoneKey] : draft.content;
436
467
  let targetList = targetZoneKey ? draft.zones[targetZoneKey] : draft.content;
468
+ if (targetZoneKey) {
469
+ const targetParentId = parseZoneKey(targetZoneKey).parentId;
470
+ const descendantZoneKeys = getDescendantZoneKeys(draft.zones, id);
471
+ if (targetParentId === id || descendantZoneKeys.includes(targetZoneKey)) {
472
+ return;
473
+ }
474
+ }
437
475
  if (!targetList && targetZoneKey) {
438
476
  targetList = [];
439
477
  draft.zones[targetZoneKey] = targetList;
@@ -467,14 +505,27 @@ var setRootProps = (draft, patch) => {
467
505
  };
468
506
 
469
507
  // src/engine/store.ts
508
+ var HISTORY_LIMIT = 50;
509
+ var COALESCE_MS = 500;
470
510
  var pushToHistory = (state3) => {
471
- state3.history.past.push(JSON.parse(JSON.stringify(state3.document)));
511
+ state3.history.past.push(cloneDocument(state3.document));
512
+ if (state3.history.past.length > HISTORY_LIMIT) {
513
+ state3.history.past.shift();
514
+ }
472
515
  state3.history.future = [];
516
+ state3._lastCommit = null;
517
+ };
518
+ var validateSelection = (state3) => {
519
+ const id = state3.selection.selectedId;
520
+ if (id && !findNodeById(state3.document, id)) {
521
+ state3.selection.selectedId = null;
522
+ }
523
+ state3.selection.hoveredId = null;
473
524
  };
474
525
  var useEditorStore = create()(
475
526
  immer((set2) => ({
476
527
  // Initial State
477
- document: { ...EMPTY_DOCUMENT },
528
+ document: createEmptyDocument(),
478
529
  history: {
479
530
  past: [],
480
531
  future: []
@@ -484,11 +535,14 @@ var useEditorStore = create()(
484
535
  hoveredId: null
485
536
  },
486
537
  viewport: "desktop",
538
+ drag: null,
539
+ _lastCommit: null,
487
540
  // Actions
488
541
  setDocument: (doc) => set2((state3) => {
489
- state3.document = doc;
542
+ state3.document = cloneDocument(parseDocument(doc));
490
543
  state3.history = { past: [], future: [] };
491
544
  state3.selection = { selectedId: null, hoveredId: null };
545
+ state3._lastCommit = null;
492
546
  }),
493
547
  selectNode: (id) => set2((state3) => {
494
548
  state3.selection.selectedId = id;
@@ -499,6 +553,12 @@ var useEditorStore = create()(
499
553
  setViewport: (viewport) => set2((state3) => {
500
554
  state3.viewport = viewport;
501
555
  }),
556
+ beginDrag: (payload) => set2((state3) => {
557
+ state3.drag = payload;
558
+ }),
559
+ endDrag: () => set2((state3) => {
560
+ state3.drag = null;
561
+ }),
502
562
  insertNode: (node, targetZoneKey, index2) => set2((state3) => {
503
563
  pushToHistory(state3);
504
564
  insertNode(state3.document, node, targetZoneKey, index2);
@@ -519,24 +579,48 @@ var useEditorStore = create()(
519
579
  duplicateNode(state3.document, id);
520
580
  }),
521
581
  updateProps: (id, patch) => set2((state3) => {
522
- pushToHistory(state3);
582
+ const now2 = Date.now();
583
+ const last = state3._lastCommit;
584
+ const isContinuation = last && last.id === id && now2 - last.time < COALESCE_MS;
585
+ if (!isContinuation) {
586
+ state3.history.past.push(cloneDocument(state3.document));
587
+ if (state3.history.past.length > HISTORY_LIMIT) {
588
+ state3.history.past.shift();
589
+ }
590
+ state3.history.future = [];
591
+ }
523
592
  updateProps(state3.document, id, patch);
593
+ state3._lastCommit = { id, time: now2 };
524
594
  }),
525
595
  setRootProps: (patch) => set2((state3) => {
526
- pushToHistory(state3);
596
+ const now2 = Date.now();
597
+ const last = state3._lastCommit;
598
+ const isContinuation = last && last.id === "__root__" && now2 - last.time < COALESCE_MS;
599
+ if (!isContinuation) {
600
+ state3.history.past.push(cloneDocument(state3.document));
601
+ if (state3.history.past.length > HISTORY_LIMIT) {
602
+ state3.history.past.shift();
603
+ }
604
+ state3.history.future = [];
605
+ }
527
606
  setRootProps(state3.document, patch);
607
+ state3._lastCommit = { id: "__root__", time: now2 };
528
608
  }),
529
609
  undo: () => set2((state3) => {
530
610
  if (state3.history.past.length === 0) return;
531
611
  const previous = state3.history.past.pop();
532
- state3.history.future.push(JSON.parse(JSON.stringify(state3.document)));
612
+ state3.history.future.push(cloneDocument(state3.document));
533
613
  state3.document = previous;
614
+ state3._lastCommit = null;
615
+ validateSelection(state3);
534
616
  }),
535
617
  redo: () => set2((state3) => {
536
618
  if (state3.history.future.length === 0) return;
537
619
  const next = state3.history.future.pop();
538
- state3.history.past.push(JSON.parse(JSON.stringify(state3.document)));
620
+ state3.history.past.push(cloneDocument(state3.document));
539
621
  state3.document = next;
622
+ state3._lastCommit = null;
623
+ validateSelection(state3);
540
624
  })
541
625
  }))
542
626
  );
@@ -548,106 +632,13 @@ var useStudio = () => {
548
632
  }
549
633
  return ctx;
550
634
  };
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 }) => {
635
+ var Frame = ({
636
+ children,
637
+ title = "Canvas Frame",
638
+ className,
639
+ style: _style,
640
+ ...props
641
+ }) => {
651
642
  const [contentRef, setContentRef] = useState(null);
652
643
  const mountNode = contentRef?.contentWindow?.document?.body;
653
644
  useEffect(() => {
@@ -697,16 +688,20 @@ var Frame = ({ children, title = "Canvas Frame", ...props }) => {
697
688
  background: transparent;
698
689
  }
699
690
  ::-webkit-scrollbar-thumb {
700
- background: rgba(0, 0, 0, 0.15);
701
- border-radius: 4px;
691
+ background: var(--tecof-scrollbar-thumb);
692
+ border-radius: var(--tecof-radius-xs);
702
693
  }
703
694
  ::-webkit-scrollbar-thumb:hover {
704
- background: rgba(0, 0, 0, 0.25);
695
+ background: var(--tecof-scrollbar-thumb-hover);
705
696
  }
706
697
  `;
707
698
  doc.head.appendChild(style);
708
699
  };
709
700
  copyStyles();
701
+ const observer = new MutationObserver(() => {
702
+ copyStyles();
703
+ });
704
+ observer.observe(document.head, { childList: true, subtree: true });
710
705
  if (doc.body) {
711
706
  doc.body.className = "tecof-canvas-body";
712
707
  const handleBodyClick = (e3) => {
@@ -719,9 +714,24 @@ var Frame = ({ children, title = "Canvas Frame", ...props }) => {
719
714
  }
720
715
  }
721
716
  };
717
+ const handleIframeKeyDown = (e3) => {
718
+ const event = new KeyboardEvent("keydown", {
719
+ key: e3.key,
720
+ code: e3.code,
721
+ ctrlKey: e3.ctrlKey,
722
+ metaKey: e3.metaKey,
723
+ shiftKey: e3.shiftKey,
724
+ altKey: e3.altKey,
725
+ bubbles: true
726
+ });
727
+ window.dispatchEvent(event);
728
+ };
722
729
  doc.body.addEventListener("click", handleBodyClick);
730
+ doc.addEventListener("keydown", handleIframeKeyDown);
723
731
  return () => {
732
+ observer.disconnect();
724
733
  doc.body.removeEventListener("click", handleBodyClick);
734
+ doc.removeEventListener("keydown", handleIframeKeyDown);
725
735
  };
726
736
  }
727
737
  }, [contentRef]);
@@ -730,59 +740,496 @@ var Frame = ({ children, title = "Canvas Frame", ...props }) => {
730
740
  {
731
741
  title,
732
742
  ref: setContentRef,
733
- style: {
734
- width: "100%",
735
- height: "100%",
736
- border: "none",
737
- background: "#ffffff",
738
- ...props.style
739
- },
743
+ className: ["tecof-canvas-frame", className].filter(Boolean).join(" "),
740
744
  ...props,
741
745
  children: mountNode && createPortal(children, mountNode)
742
746
  }
743
747
  );
744
748
  };
749
+
750
+ // src/studio/canvas/dndUtils.ts
751
+ var TECOF_NODE_ID = "application/tecof-node-id";
752
+ var TECOF_BLOCK_TYPE = "application/tecof-block-type";
753
+ function createNode(config3, type) {
754
+ const compConfig = config3?.components?.[type] || {};
755
+ const defaultProps = compConfig.defaultProps || {};
756
+ return {
757
+ type,
758
+ props: {
759
+ id: generateId(),
760
+ ...JSON.parse(JSON.stringify(defaultProps))
761
+ }
762
+ };
763
+ }
764
+ function readDragData(e3) {
765
+ return {
766
+ nodeId: e3.dataTransfer.getData(TECOF_NODE_ID),
767
+ type: e3.dataTransfer.getData(TECOF_BLOCK_TYPE)
768
+ };
769
+ }
770
+ function writeDragData(e3, payload) {
771
+ if (payload.nodeId) {
772
+ e3.dataTransfer.setData(TECOF_NODE_ID, payload.nodeId);
773
+ }
774
+ if (payload.type) {
775
+ e3.dataTransfer.setData(TECOF_BLOCK_TYPE, payload.type);
776
+ }
777
+ }
778
+ function getDragScrollContainer(e3) {
779
+ const ownerDoc = e3.currentTarget.ownerDocument;
780
+ return ownerDoc.scrollingElement || ownerDoc.documentElement || ownerDoc.body;
781
+ }
782
+ var EDGE = 64;
783
+ var MAX_SPEED = 18;
784
+ function createAutoScroller(getContainer) {
785
+ let raf = 0;
786
+ let velocity = 0;
787
+ const getEdgeBounds = (el) => {
788
+ const doc = el.ownerDocument;
789
+ const win = doc.defaultView;
790
+ const isDocumentScroller = el === doc.documentElement || el === doc.body || el === doc.scrollingElement;
791
+ if (isDocumentScroller && win) {
792
+ return { top: 0, bottom: win.innerHeight };
793
+ }
794
+ return el.getBoundingClientRect();
795
+ };
796
+ const loop = () => {
797
+ const el = getContainer();
798
+ if (el && velocity !== 0) {
799
+ el.scrollTop += velocity;
800
+ }
801
+ raf = requestAnimationFrame(loop);
802
+ };
803
+ const update = (clientY) => {
804
+ const el = getContainer();
805
+ if (!el) return;
806
+ const rect = getEdgeBounds(el);
807
+ if (clientY < rect.top + EDGE) {
808
+ const ratio = (rect.top + EDGE - clientY) / EDGE;
809
+ velocity = -Math.ceil(Math.min(1, ratio) * MAX_SPEED);
810
+ } else if (clientY > rect.bottom - EDGE) {
811
+ const ratio = (clientY - (rect.bottom - EDGE)) / EDGE;
812
+ velocity = Math.ceil(Math.min(1, ratio) * MAX_SPEED);
813
+ } else {
814
+ velocity = 0;
815
+ }
816
+ if (!raf) loop();
817
+ };
818
+ const stop = () => {
819
+ velocity = 0;
820
+ if (raf) {
821
+ cancelAnimationFrame(raf);
822
+ raf = 0;
823
+ }
824
+ };
825
+ return { update, stop };
826
+ }
827
+ function createEventAutoScroller() {
828
+ let container = null;
829
+ const scroller = createAutoScroller(() => container);
830
+ return {
831
+ update(e3) {
832
+ container = getDragScrollContainer(e3);
833
+ scroller.update(e3.clientY);
834
+ },
835
+ stop() {
836
+ scroller.stop();
837
+ container = null;
838
+ }
839
+ };
840
+ }
841
+ var ParentNodeContext = createContext(null);
842
+ var DropZone = ({ zone, className, style }) => {
843
+ const parentId = useContext(ParentNodeContext);
844
+ const zoneKey = parentId ? `${parentId}:${zone}` : zone;
845
+ const { config: config3 } = useStudio();
846
+ const insertNode2 = useEditorStore((state3) => state3.insertNode);
847
+ const endDrag = useEditorStore((state3) => state3.endDrag);
848
+ const drag = useEditorStore((state3) => state3.drag);
849
+ const autoScrollerRef = useRef(createEventAutoScroller());
850
+ const [isDragOver, setIsDragOver] = useState(false);
851
+ const items = useEditorStore((state3) => state3.document.zones[zoneKey] || []);
852
+ const handleDragOver = (e3) => {
853
+ e3.preventDefault();
854
+ e3.stopPropagation();
855
+ autoScrollerRef.current.update(e3);
856
+ setIsDragOver(true);
857
+ };
858
+ const handleDragLeave = (e3) => {
859
+ if (e3.currentTarget.contains(e3.relatedTarget)) return;
860
+ autoScrollerRef.current.stop();
861
+ setIsDragOver(false);
862
+ };
863
+ const handleDrop = (e3) => {
864
+ e3.preventDefault();
865
+ e3.stopPropagation();
866
+ autoScrollerRef.current.stop();
867
+ setIsDragOver(false);
868
+ const { nodeId, type } = readDragData(e3);
869
+ if (nodeId) {
870
+ useEditorStore.getState().moveNode(nodeId, zoneKey, items.length);
871
+ } else if (type) {
872
+ insertNode2(createNode(config3, type), zoneKey, items.length);
873
+ }
874
+ endDrag();
875
+ };
876
+ const dropzoneClassName = [
877
+ "tecof-dropzone",
878
+ items.length === 0 ? "is-empty" : "",
879
+ isDragOver ? "is-dragover" : "",
880
+ drag ? "is-drag-active" : "",
881
+ className
882
+ ].filter(Boolean).join(" ");
883
+ return /* @__PURE__ */ jsx(
884
+ "div",
885
+ {
886
+ className: dropzoneClassName,
887
+ onDragOver: handleDragOver,
888
+ onDragLeave: handleDragLeave,
889
+ onDrop: handleDrop,
890
+ style,
891
+ "data-tecof-zone": zoneKey,
892
+ children: items.length === 0 ? /* @__PURE__ */ jsx("span", { className: "tecof-dropzone-hint", children: isDragOver ? "Buraya B\u0131rak\u0131n" : "Bile\u015Fen S\xFCr\xFCkleyin veya T\u0131klay\u0131n" }) : items.map((item2, index2) => /* @__PURE__ */ jsx(NodeRenderer, { node: item2, index: index2, zoneKey }, item2.props.id))
893
+ }
894
+ );
895
+ };
896
+ var renderDropZone = ({ zone, className, style }) => {
897
+ return /* @__PURE__ */ jsx(DropZone, { zone, className, style });
898
+ };
899
+
900
+ // src/studio/canvas/dragGhost.ts
901
+ function setDragGhost(e3, label) {
902
+ const ownerDoc = e3.currentTarget?.ownerDocument || (typeof document !== "undefined" ? document : null);
903
+ if (!ownerDoc) return;
904
+ const ghost = ownerDoc.createElement("div");
905
+ ghost.className = "tecof-drag-ghost";
906
+ ghost.textContent = label;
907
+ ownerDoc.body.appendChild(ghost);
908
+ try {
909
+ e3.dataTransfer.setDragImage(ghost, 14, 14);
910
+ } catch {
911
+ }
912
+ const win = ownerDoc.defaultView || window;
913
+ win.requestAnimationFrame(() => {
914
+ win.requestAnimationFrame(() => ghost.remove());
915
+ });
916
+ }
917
+ var NodeRenderer = ({ node, index: index2, zoneKey }) => {
918
+ const { config: config3, metadata, readOnly } = useStudio();
919
+ const componentConfig = config3.components[node.type];
920
+ const selectNode = useEditorStore((state3) => state3.selectNode);
921
+ const hoverNode = useEditorStore((state3) => state3.hoverNode);
922
+ const hoveredId = useEditorStore((state3) => state3.selection.hoveredId);
923
+ const beginDrag = useEditorStore((state3) => state3.beginDrag);
924
+ const endDrag = useEditorStore((state3) => state3.endDrag);
925
+ const drag = useEditorStore((state3) => state3.drag);
926
+ const autoScrollerRef = useRef(createEventAutoScroller());
927
+ const handleMouseEnter = useCallback(
928
+ (e3) => {
929
+ if (readOnly) return;
930
+ e3.stopPropagation();
931
+ hoverNode(node.props.id);
932
+ },
933
+ [hoverNode, node.props.id, readOnly]
934
+ );
935
+ const handleMouseLeave = useCallback(
936
+ (e3) => {
937
+ if (readOnly) return;
938
+ e3.stopPropagation();
939
+ if (hoveredId === node.props.id) {
940
+ hoverNode(null);
941
+ }
942
+ },
943
+ [hoverNode, node.props.id, hoveredId, readOnly]
944
+ );
945
+ const handleClick = useCallback(
946
+ (e3) => {
947
+ if (readOnly) return;
948
+ e3.stopPropagation();
949
+ selectNode(node.props.id);
950
+ const isEmbedded = typeof window !== "undefined" && window.parent !== window;
951
+ if (isEmbedded) {
952
+ window.parent.postMessage(
953
+ {
954
+ type: "puck:itemSelected",
955
+ item: {
956
+ type: node.type,
957
+ id: node.props.id
958
+ }
959
+ },
960
+ "*"
961
+ );
962
+ }
963
+ },
964
+ [selectNode, node.props.id, node.type, readOnly]
965
+ );
966
+ const handleDoubleClick = useCallback(
967
+ (e3) => {
968
+ if (readOnly) return;
969
+ const target = e3.target;
970
+ const validTags = ["h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "a", "div"];
971
+ const tag = target.tagName.toLowerCase();
972
+ if (!validTags.includes(tag)) return;
973
+ const text2 = target.textContent?.trim() || "";
974
+ if (!text2) return;
975
+ let matchingPropName = null;
976
+ let isMultilingual = false;
977
+ const ownerDoc = target.ownerDocument;
978
+ const ownerWin = ownerDoc.defaultView;
979
+ let matchedLangCode = ownerDoc.documentElement.lang || "tr";
980
+ for (const [key, value] of Object.entries(node.props)) {
981
+ if (typeof value === "string" && value.trim() === text2) {
982
+ matchingPropName = key;
983
+ break;
984
+ }
985
+ if (Array.isArray(value)) {
986
+ const matchedItem = value.find(
987
+ (item2) => item2 && typeof item2 === "object" && typeof item2.value === "string" && item2.value.trim() === text2
988
+ );
989
+ if (matchedItem) {
990
+ matchingPropName = key;
991
+ isMultilingual = true;
992
+ matchedLangCode = matchedItem.code;
993
+ break;
994
+ }
995
+ }
996
+ }
997
+ if (!matchingPropName) return;
998
+ e3.stopPropagation();
999
+ const originalText = target.textContent || "";
1000
+ target.contentEditable = "true";
1001
+ target.setAttribute("data-tecof-inline-editing", "true");
1002
+ target.focus();
1003
+ const range = ownerDoc.createRange();
1004
+ range.selectNodeContents(target);
1005
+ const sel = ownerWin?.getSelection();
1006
+ sel?.removeAllRanges();
1007
+ sel?.addRange(range);
1008
+ const propName = matchingPropName;
1009
+ const finalIsMultilingual = isMultilingual;
1010
+ const finalLangCode = matchedLangCode;
1011
+ const commitInlineEdit = () => {
1012
+ target.contentEditable = "false";
1013
+ target.removeAttribute("data-tecof-inline-editing");
1014
+ target.removeEventListener("blur", handleBlur);
1015
+ target.removeEventListener("keydown", handleKeyDown);
1016
+ const newText = target.textContent?.trim() || "";
1017
+ if (finalIsMultilingual) {
1018
+ const currentArray = Array.isArray(node.props[propName]) ? node.props[propName] : [];
1019
+ const updatedArray = currentArray.map((item2) => {
1020
+ if (item2 && item2.code === finalLangCode) {
1021
+ return { ...item2, value: newText };
1022
+ }
1023
+ return item2;
1024
+ });
1025
+ if (!updatedArray.some((item2) => item2 && item2.code === finalLangCode)) {
1026
+ updatedArray.push({ code: finalLangCode, value: newText });
1027
+ }
1028
+ useEditorStore.getState().updateProps(node.props.id, {
1029
+ [propName]: updatedArray
1030
+ });
1031
+ } else {
1032
+ useEditorStore.getState().updateProps(node.props.id, {
1033
+ [propName]: newText
1034
+ });
1035
+ }
1036
+ };
1037
+ const cancelInlineEdit = () => {
1038
+ target.textContent = originalText;
1039
+ target.contentEditable = "false";
1040
+ target.removeAttribute("data-tecof-inline-editing");
1041
+ target.removeEventListener("blur", handleBlur);
1042
+ target.removeEventListener("keydown", handleKeyDown);
1043
+ };
1044
+ const handleBlur = () => {
1045
+ commitInlineEdit();
1046
+ };
1047
+ const handleKeyDown = (event) => {
1048
+ if (event.key === "Escape") {
1049
+ event.preventDefault();
1050
+ cancelInlineEdit();
1051
+ return;
1052
+ }
1053
+ if (event.key === "Enter" && !event.shiftKey) {
1054
+ event.preventDefault();
1055
+ target.blur();
1056
+ }
1057
+ };
1058
+ target.addEventListener("blur", handleBlur);
1059
+ target.addEventListener("keydown", handleKeyDown);
1060
+ },
1061
+ [node.props, node.props.id, readOnly]
1062
+ );
1063
+ const [dragOverPosition, setDragOverPosition] = useState(null);
1064
+ const handleDragOver = useCallback((e3) => {
1065
+ if (readOnly) return;
1066
+ e3.preventDefault();
1067
+ e3.stopPropagation();
1068
+ autoScrollerRef.current.update(e3);
1069
+ const rect = e3.currentTarget.getBoundingClientRect();
1070
+ const relativeY = e3.clientY - rect.top;
1071
+ if (relativeY < rect.height / 2) {
1072
+ setDragOverPosition("top");
1073
+ } else {
1074
+ setDragOverPosition("bottom");
1075
+ }
1076
+ }, [readOnly]);
1077
+ const handleDragLeave = useCallback((e3) => {
1078
+ if (e3.currentTarget.contains(e3.relatedTarget)) return;
1079
+ autoScrollerRef.current.stop();
1080
+ setDragOverPosition(null);
1081
+ }, []);
1082
+ const handleDrop = useCallback((e3) => {
1083
+ if (readOnly) return;
1084
+ e3.preventDefault();
1085
+ e3.stopPropagation();
1086
+ autoScrollerRef.current.stop();
1087
+ setDragOverPosition(null);
1088
+ const { nodeId, type } = readDragData(e3);
1089
+ const targetIndex = dragOverPosition === "top" ? index2 : index2 + 1;
1090
+ if (nodeId && nodeId !== node.props.id) {
1091
+ useEditorStore.getState().moveNode(nodeId, zoneKey || void 0, targetIndex);
1092
+ } else if (type) {
1093
+ useEditorStore.getState().insertNode(createNode(config3, type), zoneKey || void 0, targetIndex);
1094
+ }
1095
+ endDrag();
1096
+ }, [dragOverPosition, index2, node.props.id, zoneKey, config3, readOnly, endDrag]);
1097
+ if (!componentConfig) {
1098
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-node-missing", children: [
1099
+ "Bile\u015Fen bulunamad\u0131: ",
1100
+ node.type
1101
+ ] });
1102
+ }
1103
+ const label = componentConfig.label || node.type;
1104
+ const wrapperClassName = [
1105
+ "tecof-node-wrapper",
1106
+ readOnly ? "is-readonly" : "",
1107
+ drag?.id === node.props.id ? "is-dragging" : ""
1108
+ ].filter(Boolean).join(" ");
1109
+ const componentProps = {
1110
+ ...node.props,
1111
+ puck: {
1112
+ renderDropZone,
1113
+ isEditing: !readOnly,
1114
+ metadata: {
1115
+ ...metadata || {},
1116
+ ...componentConfig.metadata || {}
1117
+ }
1118
+ },
1119
+ editMode: !readOnly
1120
+ };
1121
+ return /* @__PURE__ */ jsx(ParentNodeContext.Provider, { value: node.props.id, children: /* @__PURE__ */ jsxs("div", { className: "tecof-node", children: [
1122
+ dragOverPosition === "top" && /* @__PURE__ */ jsx("div", { className: "tecof-drop-line" }),
1123
+ /* @__PURE__ */ jsx(
1124
+ "div",
1125
+ {
1126
+ className: wrapperClassName,
1127
+ "data-tecof-id": node.props.id,
1128
+ "data-tecof-type": node.type,
1129
+ "data-tecof-index": index2,
1130
+ "data-tecof-zone": zoneKey || "root",
1131
+ draggable: !readOnly,
1132
+ onDragStart: (e3) => {
1133
+ writeDragData(e3, { nodeId: node.props.id });
1134
+ e3.dataTransfer.effectAllowed = "move";
1135
+ setDragGhost(e3, label);
1136
+ beginDrag({ id: node.props.id });
1137
+ },
1138
+ onDragEnd: () => {
1139
+ autoScrollerRef.current.stop();
1140
+ endDrag();
1141
+ },
1142
+ onMouseEnter: handleMouseEnter,
1143
+ onMouseLeave: handleMouseLeave,
1144
+ onClick: handleClick,
1145
+ onDoubleClick: handleDoubleClick,
1146
+ onDragOver: handleDragOver,
1147
+ onDragLeave: handleDragLeave,
1148
+ onDrop: handleDrop,
1149
+ children: componentConfig.render(componentProps)
1150
+ }
1151
+ ),
1152
+ dragOverPosition === "bottom" && /* @__PURE__ */ jsx("div", { className: "tecof-drop-line" })
1153
+ ] }) });
1154
+ };
745
1155
  var Canvas = () => {
746
1156
  const content = useEditorStore((state3) => state3.document.content);
747
1157
  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(
1158
+ const insertNode2 = useEditorStore((state3) => state3.insertNode);
1159
+ const endDrag = useEditorStore((state3) => state3.endDrag);
1160
+ const { config: config3, readOnly } = useStudio();
1161
+ const rootProps = useEditorStore((state3) => state3.document.root?.props || {});
1162
+ const [isRootDragOver, setIsRootDragOver] = useState(false);
1163
+ const autoScrollerRef = useRef(createEventAutoScroller());
1164
+ useEffect(() => {
1165
+ if (!readOnly) return;
1166
+ autoScrollerRef.current.stop();
1167
+ setIsRootDragOver(false);
1168
+ }, [readOnly]);
1169
+ const handleRootDragOver = useCallback(
1170
+ (e3) => {
1171
+ if (readOnly) return;
1172
+ e3.preventDefault();
1173
+ autoScrollerRef.current.update(e3);
1174
+ setIsRootDragOver(true);
1175
+ },
1176
+ [readOnly]
1177
+ );
1178
+ const handleRootDragLeave = useCallback((e3) => {
1179
+ if (e3.currentTarget.contains(e3.relatedTarget)) return;
1180
+ autoScrollerRef.current.stop();
1181
+ setIsRootDragOver(false);
1182
+ }, []);
1183
+ const handleRootDrop = useCallback(
1184
+ (e3) => {
1185
+ if (readOnly) return;
1186
+ e3.preventDefault();
1187
+ autoScrollerRef.current.stop();
1188
+ setIsRootDragOver(false);
1189
+ const { nodeId, type } = readDragData(e3);
1190
+ if (nodeId) {
1191
+ useEditorStore.getState().moveNode(nodeId, void 0, content.length);
1192
+ } else if (type) {
1193
+ insertNode2(createNode(config3, type), void 0, content.length);
1194
+ }
1195
+ endDrag();
1196
+ },
1197
+ [config3, content.length, endDrag, insertNode2, readOnly]
1198
+ );
1199
+ const rootClassName = [
1200
+ "tecof-canvas-root",
1201
+ content.length === 0 ? "is-empty" : "",
1202
+ isRootDragOver ? "is-dragover" : ""
1203
+ ].filter(Boolean).join(" ");
1204
+ const viewportClassName = [
1205
+ "tecof-canvas-viewport",
1206
+ viewport !== "desktop" ? `is-${viewport}` : ""
1207
+ ].filter(Boolean).join(" ");
1208
+ const renderedContent = /* @__PURE__ */ jsx(
770
1209
  "div",
771
1210
  {
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)) }) })
1211
+ className: rootClassName,
1212
+ onDragOver: handleRootDragOver,
1213
+ onDragLeave: handleRootDragLeave,
1214
+ onDrop: handleRootDrop,
1215
+ "data-tecof-zone": "root",
1216
+ children: content.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "tecof-canvas-empty", children: [
1217
+ /* @__PURE__ */ jsx("span", { className: "tecof-canvas-empty-kicker", children: "Root" }),
1218
+ /* @__PURE__ */ jsx("p", { className: "tecof-canvas-empty-title", children: isRootDragOver ? "B\u0131rakmaya haz\u0131r" : "Canvas bo\u015F" }),
1219
+ /* @__PURE__ */ jsx("p", { className: "tecof-canvas-empty-sub", children: isRootDragOver ? "Bile\u015Fen ana ak\u0131\u015Fa eklenecek" : "\u0130lk blo\u011Fu buraya b\u0131rak\u0131n" })
1220
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1221
+ content.map((item2, index2) => /* @__PURE__ */ jsx(NodeRenderer, { node: item2, index: index2 }, item2.props.id)),
1222
+ !readOnly && /* @__PURE__ */ jsx("div", { className: "tecof-canvas-root-tail", "aria-hidden": "true" })
1223
+ ] })
784
1224
  }
785
- ) });
1225
+ );
1226
+ const rootConfig = config3.root;
1227
+ const contentWithLayout = rootConfig?.render ? rootConfig.render({
1228
+ ...rootProps,
1229
+ children: renderedContent,
1230
+ editMode: true
1231
+ }) : renderedContent;
1232
+ return /* @__PURE__ */ jsx("div", { className: "tecof-canvas-container", children: /* @__PURE__ */ jsx("div", { className: viewportClassName, children: /* @__PURE__ */ jsx(Frame, { className: "tecof-canvas-frame", children: contentWithLayout }) }) });
786
1233
  };
787
1234
 
788
1235
  // node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
@@ -989,8 +1436,18 @@ var __iconNode14 = [
989
1436
  ];
990
1437
  var Globe = createLucideIcon("globe", __iconNode14);
991
1438
 
992
- // node_modules/lucide-react/dist/esm/icons/grip-vertical.js
1439
+ // node_modules/lucide-react/dist/esm/icons/grid-3x3.js
993
1440
  var __iconNode15 = [
1441
+ ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
1442
+ ["path", { d: "M3 9h18", key: "1pudct" }],
1443
+ ["path", { d: "M3 15h18", key: "5xshup" }],
1444
+ ["path", { d: "M9 3v18", key: "fh3hqa" }],
1445
+ ["path", { d: "M15 3v18", key: "14nvp0" }]
1446
+ ];
1447
+ var Grid3x3 = createLucideIcon("grid-3x3", __iconNode15);
1448
+
1449
+ // node_modules/lucide-react/dist/esm/icons/grip-vertical.js
1450
+ var __iconNode16 = [
994
1451
  ["circle", { cx: "9", cy: "12", r: "1", key: "1vctgf" }],
995
1452
  ["circle", { cx: "9", cy: "5", r: "1", key: "hp0tcf" }],
996
1453
  ["circle", { cx: "9", cy: "19", r: "1", key: "fkjjf6" }],
@@ -998,28 +1455,28 @@ var __iconNode15 = [
998
1455
  ["circle", { cx: "15", cy: "5", r: "1", key: "19l28e" }],
999
1456
  ["circle", { cx: "15", cy: "19", r: "1", key: "f4zoj3" }]
1000
1457
  ];
1001
- var GripVertical = createLucideIcon("grip-vertical", __iconNode15);
1458
+ var GripVertical = createLucideIcon("grip-vertical", __iconNode16);
1002
1459
 
1003
1460
  // node_modules/lucide-react/dist/esm/icons/image-plus.js
1004
- var __iconNode16 = [
1461
+ var __iconNode17 = [
1005
1462
  ["path", { d: "M16 5h6", key: "1vod17" }],
1006
1463
  ["path", { d: "M19 2v6", key: "4bpg5p" }],
1007
1464
  ["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" }],
1008
1465
  ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }],
1009
1466
  ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }]
1010
1467
  ];
1011
- var ImagePlus = createLucideIcon("image-plus", __iconNode16);
1468
+ var ImagePlus = createLucideIcon("image-plus", __iconNode17);
1012
1469
 
1013
1470
  // node_modules/lucide-react/dist/esm/icons/image.js
1014
- var __iconNode17 = [
1471
+ var __iconNode18 = [
1015
1472
  ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
1016
1473
  ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
1017
1474
  ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
1018
1475
  ];
1019
- var Image2 = createLucideIcon("image", __iconNode17);
1476
+ var Image2 = createLucideIcon("image", __iconNode18);
1020
1477
 
1021
1478
  // node_modules/lucide-react/dist/esm/icons/languages.js
1022
- var __iconNode18 = [
1479
+ var __iconNode19 = [
1023
1480
  ["path", { d: "m5 8 6 6", key: "1wu5hv" }],
1024
1481
  ["path", { d: "m4 14 6-6 2-3", key: "1k1g8d" }],
1025
1482
  ["path", { d: "M2 5h12", key: "or177f" }],
@@ -1027,29 +1484,71 @@ var __iconNode18 = [
1027
1484
  ["path", { d: "m22 22-5-10-5 10", key: "don7ne" }],
1028
1485
  ["path", { d: "M14 18h6", key: "1m8k6r" }]
1029
1486
  ];
1030
- var Languages = createLucideIcon("languages", __iconNode18);
1487
+ var Languages = createLucideIcon("languages", __iconNode19);
1488
+
1489
+ // node_modules/lucide-react/dist/esm/icons/layers.js
1490
+ var __iconNode20 = [
1491
+ [
1492
+ "path",
1493
+ {
1494
+ d: "M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",
1495
+ key: "zw3jo"
1496
+ }
1497
+ ],
1498
+ [
1499
+ "path",
1500
+ {
1501
+ d: "M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",
1502
+ key: "1wduqc"
1503
+ }
1504
+ ],
1505
+ [
1506
+ "path",
1507
+ {
1508
+ d: "M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",
1509
+ key: "kqbvx6"
1510
+ }
1511
+ ]
1512
+ ];
1513
+ var Layers = createLucideIcon("layers", __iconNode20);
1031
1514
 
1032
1515
  // node_modules/lucide-react/dist/esm/icons/link-2.js
1033
- var __iconNode19 = [
1516
+ var __iconNode21 = [
1034
1517
  ["path", { d: "M9 17H7A5 5 0 0 1 7 7h2", key: "8i5ue5" }],
1035
1518
  ["path", { d: "M15 7h2a5 5 0 1 1 0 10h-2", key: "1b9ql8" }],
1036
1519
  ["line", { x1: "8", x2: "16", y1: "12", y2: "12", key: "1jonct" }]
1037
1520
  ];
1038
- var Link2 = createLucideIcon("link-2", __iconNode19);
1521
+ var Link2 = createLucideIcon("link-2", __iconNode21);
1039
1522
 
1040
1523
  // node_modules/lucide-react/dist/esm/icons/link.js
1041
- var __iconNode20 = [
1524
+ var __iconNode22 = [
1042
1525
  ["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" }],
1043
1526
  ["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" }]
1044
1527
  ];
1045
- var Link = createLucideIcon("link", __iconNode20);
1528
+ var Link = createLucideIcon("link", __iconNode22);
1046
1529
 
1047
1530
  // node_modules/lucide-react/dist/esm/icons/loader-circle.js
1048
- var __iconNode21 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
1049
- var LoaderCircle = createLucideIcon("loader-circle", __iconNode21);
1531
+ var __iconNode23 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
1532
+ var LoaderCircle = createLucideIcon("loader-circle", __iconNode23);
1533
+
1534
+ // node_modules/lucide-react/dist/esm/icons/monitor.js
1535
+ var __iconNode24 = [
1536
+ ["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
1537
+ ["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
1538
+ ["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
1539
+ ];
1540
+ var Monitor = createLucideIcon("monitor", __iconNode24);
1541
+
1542
+ // node_modules/lucide-react/dist/esm/icons/panels-top-left.js
1543
+ var __iconNode25 = [
1544
+ ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
1545
+ ["path", { d: "M3 9h18", key: "1pudct" }],
1546
+ ["path", { d: "M9 21V9", key: "1oto5p" }]
1547
+ ];
1548
+ var PanelsTopLeft = createLucideIcon("panels-top-left", __iconNode25);
1050
1549
 
1051
1550
  // node_modules/lucide-react/dist/esm/icons/pencil.js
1052
- var __iconNode22 = [
1551
+ var __iconNode26 = [
1053
1552
  [
1054
1553
  "path",
1055
1554
  {
@@ -1059,71 +1558,119 @@ var __iconNode22 = [
1059
1558
  ],
1060
1559
  ["path", { d: "m15 5 4 4", key: "1mk7zo" }]
1061
1560
  ];
1062
- var Pencil = createLucideIcon("pencil", __iconNode22);
1561
+ var Pencil = createLucideIcon("pencil", __iconNode26);
1063
1562
 
1064
1563
  // node_modules/lucide-react/dist/esm/icons/plus.js
1065
- var __iconNode23 = [
1564
+ var __iconNode27 = [
1066
1565
  ["path", { d: "M5 12h14", key: "1ays0h" }],
1067
1566
  ["path", { d: "M12 5v14", key: "s699le" }]
1068
1567
  ];
1069
- var Plus = createLucideIcon("plus", __iconNode23);
1568
+ var Plus = createLucideIcon("plus", __iconNode27);
1569
+
1570
+ // node_modules/lucide-react/dist/esm/icons/redo-2.js
1571
+ var __iconNode28 = [
1572
+ ["path", { d: "m15 14 5-5-5-5", key: "12vg1m" }],
1573
+ ["path", { d: "M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13", key: "6uklza" }]
1574
+ ];
1575
+ var Redo2 = createLucideIcon("redo-2", __iconNode28);
1070
1576
 
1071
1577
  // node_modules/lucide-react/dist/esm/icons/refresh-ccw.js
1072
- var __iconNode24 = [
1578
+ var __iconNode29 = [
1073
1579
  ["path", { d: "M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", key: "14sxne" }],
1074
1580
  ["path", { d: "M3 3v5h5", key: "1xhq8a" }],
1075
1581
  ["path", { d: "M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16", key: "1hlbsb" }],
1076
1582
  ["path", { d: "M16 16h5v5", key: "ccwih5" }]
1077
1583
  ];
1078
- var RefreshCcw = createLucideIcon("refresh-ccw", __iconNode24);
1584
+ var RefreshCcw = createLucideIcon("refresh-ccw", __iconNode29);
1079
1585
 
1080
1586
  // node_modules/lucide-react/dist/esm/icons/refresh-cw.js
1081
- var __iconNode25 = [
1587
+ var __iconNode30 = [
1082
1588
  ["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
1083
1589
  ["path", { d: "M21 3v5h-5", key: "1q7to0" }],
1084
1590
  ["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
1085
1591
  ["path", { d: "M8 16H3v5", key: "1cv678" }]
1086
1592
  ];
1087
- var RefreshCw = createLucideIcon("refresh-cw", __iconNode25);
1593
+ var RefreshCw = createLucideIcon("refresh-cw", __iconNode30);
1088
1594
 
1089
1595
  // node_modules/lucide-react/dist/esm/icons/rotate-ccw.js
1090
- var __iconNode26 = [
1596
+ var __iconNode31 = [
1091
1597
  ["path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", key: "1357e3" }],
1092
1598
  ["path", { d: "M3 3v5h5", key: "1xhq8a" }]
1093
1599
  ];
1094
- var RotateCcw = createLucideIcon("rotate-ccw", __iconNode26);
1600
+ var RotateCcw = createLucideIcon("rotate-ccw", __iconNode31);
1601
+
1602
+ // node_modules/lucide-react/dist/esm/icons/save.js
1603
+ var __iconNode32 = [
1604
+ [
1605
+ "path",
1606
+ {
1607
+ d: "M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",
1608
+ key: "1c8476"
1609
+ }
1610
+ ],
1611
+ ["path", { d: "M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7", key: "1ydtos" }],
1612
+ ["path", { d: "M7 3v4a1 1 0 0 0 1 1h7", key: "t51u73" }]
1613
+ ];
1614
+ var Save = createLucideIcon("save", __iconNode32);
1095
1615
 
1096
1616
  // node_modules/lucide-react/dist/esm/icons/search.js
1097
- var __iconNode27 = [
1617
+ var __iconNode33 = [
1098
1618
  ["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
1099
1619
  ["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
1100
1620
  ];
1101
- var Search = createLucideIcon("search", __iconNode27);
1621
+ var Search = createLucideIcon("search", __iconNode33);
1622
+
1623
+ // node_modules/lucide-react/dist/esm/icons/smartphone.js
1624
+ var __iconNode34 = [
1625
+ ["rect", { width: "14", height: "20", x: "5", y: "2", rx: "2", ry: "2", key: "1yt0o3" }],
1626
+ ["path", { d: "M12 18h.01", key: "mhygvu" }]
1627
+ ];
1628
+ var Smartphone = createLucideIcon("smartphone", __iconNode34);
1629
+
1630
+ // node_modules/lucide-react/dist/esm/icons/tablet.js
1631
+ var __iconNode35 = [
1632
+ ["rect", { width: "16", height: "20", x: "4", y: "2", rx: "2", ry: "2", key: "76otgf" }],
1633
+ ["line", { x1: "12", x2: "12.01", y1: "18", y2: "18", key: "1dp563" }]
1634
+ ];
1635
+ var Tablet = createLucideIcon("tablet", __iconNode35);
1102
1636
 
1103
1637
  // node_modules/lucide-react/dist/esm/icons/trash-2.js
1104
- var __iconNode28 = [
1638
+ var __iconNode36 = [
1105
1639
  ["path", { d: "M10 11v6", key: "nco0om" }],
1106
1640
  ["path", { d: "M14 11v6", key: "outv1u" }],
1107
1641
  ["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6", key: "miytrc" }],
1108
1642
  ["path", { d: "M3 6h18", key: "d0wm0j" }],
1109
1643
  ["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2", key: "e791ji" }]
1110
1644
  ];
1111
- var Trash2 = createLucideIcon("trash-2", __iconNode28);
1645
+ var Trash2 = createLucideIcon("trash-2", __iconNode36);
1646
+
1647
+ // node_modules/lucide-react/dist/esm/icons/undo-2.js
1648
+ var __iconNode37 = [
1649
+ ["path", { d: "M9 14 4 9l5-5", key: "102s5s" }],
1650
+ ["path", { d: "M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11", key: "f3b9sd" }]
1651
+ ];
1652
+ var Undo2 = createLucideIcon("undo-2", __iconNode37);
1112
1653
 
1113
1654
  // node_modules/lucide-react/dist/esm/icons/upload.js
1114
- var __iconNode29 = [
1655
+ var __iconNode38 = [
1115
1656
  ["path", { d: "M12 3v12", key: "1x0j5s" }],
1116
1657
  ["path", { d: "m17 8-5-5-5 5", key: "7q97r8" }],
1117
1658
  ["path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4", key: "ih7n3h" }]
1118
1659
  ];
1119
- var Upload = createLucideIcon("upload", __iconNode29);
1660
+ var Upload = createLucideIcon("upload", __iconNode38);
1120
1661
 
1121
1662
  // node_modules/lucide-react/dist/esm/icons/x.js
1122
- var __iconNode30 = [
1663
+ var __iconNode39 = [
1123
1664
  ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
1124
1665
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
1125
1666
  ];
1126
- var X = createLucideIcon("x", __iconNode30);
1667
+ var X = createLucideIcon("x", __iconNode39);
1668
+ var getOutlineStyle = (coords) => ({
1669
+ "--tecof-outline-top": `${coords.top}px`,
1670
+ "--tecof-outline-left": `${coords.left}px`,
1671
+ "--tecof-outline-width": `${coords.width}px`,
1672
+ "--tecof-outline-height": `${coords.height}px`
1673
+ });
1127
1674
  var useOverlayCoords = (id, iframeEl, containerEl, documentState) => {
1128
1675
  const [coords, setCoords] = useState(null);
1129
1676
  useEffect(() => {
@@ -1185,7 +1732,7 @@ var SelectionOverlay = () => {
1185
1732
  const [iframeEl, setIframeEl] = useState(null);
1186
1733
  const containerRef = useRef(null);
1187
1734
  useEffect(() => {
1188
- const iframe = document.querySelector(".tecof-canvas-viewport-wrapper iframe");
1735
+ const iframe = document.querySelector(".tecof-canvas-viewport iframe");
1189
1736
  setIframeEl(iframe);
1190
1737
  }, [documentState]);
1191
1738
  const selectedCoords = useOverlayCoords(selectedId, iframeEl, containerRef.current, documentState);
@@ -1214,220 +1761,95 @@ var SelectionOverlay = () => {
1214
1761
  "div",
1215
1762
  {
1216
1763
  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
- },
1764
+ className: "tecof-overlay",
1227
1765
  children: [
1228
1766
  hoveredCoords && /* @__PURE__ */ jsx(
1229
1767
  "div",
1230
1768
  {
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
- }
1769
+ className: "tecof-outline is-hover",
1770
+ style: getOutlineStyle(hoveredCoords)
1244
1771
  }
1245
1772
  ),
1246
1773
  selectedCoords && /* @__PURE__ */ jsxs(
1247
1774
  "div",
1248
1775
  {
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
- },
1776
+ className: "tecof-outline is-selected",
1777
+ style: getOutlineStyle(selectedCoords),
1262
1778
  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
- )
1779
+ /* @__PURE__ */ jsxs("div", { className: "tecof-toolbar", children: [
1780
+ parentId && /* @__PURE__ */ jsx(
1781
+ "button",
1782
+ {
1783
+ type: "button",
1784
+ onClick: () => selectNode(parentId),
1785
+ title: "\xDCst \xD6\u011Feyi Se\xE7",
1786
+ className: "tecof-toolbar-btn",
1787
+ "aria-label": "\xDCst \xF6\u011Feyi se\xE7",
1788
+ children: /* @__PURE__ */ jsx(ChevronUp, { size: 14 })
1789
+ }
1790
+ ),
1791
+ /* @__PURE__ */ jsx(
1792
+ "button",
1793
+ {
1794
+ type: "button",
1795
+ onClick: () => handleMove("up"),
1796
+ disabled: !canMoveUp,
1797
+ title: "Yukar\u0131 Ta\u015F\u0131",
1798
+ className: "tecof-toolbar-btn",
1799
+ "aria-label": "Yukar\u0131 ta\u015F\u0131",
1800
+ children: /* @__PURE__ */ jsx(ArrowUp, { size: 14 })
1801
+ }
1802
+ ),
1803
+ /* @__PURE__ */ jsx(
1804
+ "button",
1805
+ {
1806
+ type: "button",
1807
+ onClick: () => handleMove("down"),
1808
+ disabled: !canMoveDown,
1809
+ title: "A\u015Fa\u011F\u0131 Ta\u015F\u0131",
1810
+ className: "tecof-toolbar-btn",
1811
+ "aria-label": "A\u015Fa\u011F\u0131 ta\u015F\u0131",
1812
+ children: /* @__PURE__ */ jsx(ArrowDown, { size: 14 })
1813
+ }
1814
+ ),
1815
+ /* @__PURE__ */ jsx("div", { className: "tecof-toolbar-sep" }),
1816
+ /* @__PURE__ */ jsx(
1817
+ "button",
1818
+ {
1819
+ type: "button",
1820
+ onClick: () => duplicateNode2(selectedId),
1821
+ title: "Kopyala",
1822
+ className: "tecof-toolbar-btn",
1823
+ "aria-label": "Kopyala",
1824
+ children: /* @__PURE__ */ jsx(Copy, { size: 14 })
1825
+ }
1826
+ ),
1827
+ /* @__PURE__ */ jsx(
1828
+ "button",
1829
+ {
1830
+ type: "button",
1831
+ onClick: () => removeNode2(selectedId),
1832
+ title: "Sil",
1833
+ className: "tecof-toolbar-btn",
1834
+ "aria-label": "Sil",
1835
+ children: /* @__PURE__ */ jsx(Trash2, { size: 14 })
1836
+ }
1837
+ )
1838
+ ] }),
1839
+ nodeDetails && /* @__PURE__ */ jsx("div", { className: "tecof-outline-label", children: nodeDetails.node.type }),
1840
+ breadcrumbs.length > 1 && /* @__PURE__ */ jsx("div", { className: "tecof-breadcrumbs", children: breadcrumbs.map((crumb, idx) => /* @__PURE__ */ jsxs(React__default__default.Fragment, { children: [
1841
+ idx > 0 && /* @__PURE__ */ jsx("span", { className: "tecof-breadcrumb-sep", children: ">" }),
1842
+ /* @__PURE__ */ jsx(
1843
+ "span",
1844
+ {
1845
+ onClick: () => selectNode(crumb.id),
1846
+ className: `tecof-breadcrumb${crumb.id === selectedId ? " is-active" : ""}`,
1847
+ onMouseEnter: () => useEditorStore.getState().hoverNode(crumb.id),
1848
+ onMouseLeave: () => useEditorStore.getState().hoverNode(null),
1849
+ children: crumb.type
1850
+ }
1851
+ )
1852
+ ] }, crumb.id)) })
1431
1853
  ]
1432
1854
  }
1433
1855
  )
@@ -1443,55 +1865,14 @@ var FieldLabel = ({
1443
1865
  el = "label"
1444
1866
  }) => {
1445
1867
  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
- ]
1489
- }
1490
- ),
1491
- /* @__PURE__ */ jsx("div", { className: "tecof-field-label-content", style: { width: "100%" }, children })
1492
- ]
1493
- }
1494
- );
1868
+ return /* @__PURE__ */ jsxs(Component2, { className: "tecof-field-label-container", children: [
1869
+ /* @__PURE__ */ jsxs("div", { className: "tecof-field-label-header", children: [
1870
+ icon && /* @__PURE__ */ jsx("span", { className: "tecof-field-label-icon", children: icon }),
1871
+ /* @__PURE__ */ jsx("span", { children: label }),
1872
+ readOnly && /* @__PURE__ */ jsx("span", { className: "tecof-field-label-readonly", children: "Salt Okunur" })
1873
+ ] }),
1874
+ /* @__PURE__ */ jsx("div", { className: "tecof-field-label-content", children })
1875
+ ] });
1495
1876
  };
1496
1877
  var FieldRenderer = ({
1497
1878
  name: name3,
@@ -1500,10 +1881,11 @@ var FieldRenderer = ({
1500
1881
  onChange,
1501
1882
  readOnly = false
1502
1883
  }) => {
1884
+ const [expandedIndices, setExpandedIndices] = useState({});
1503
1885
  const label = definition.label || name3;
1504
1886
  const type = definition.type;
1505
1887
  if (definition.render) {
1506
- return /* @__PURE__ */ jsx("div", { className: "tecof-custom-field-wrapper", style: { width: "100%" }, children: definition.render({
1888
+ return /* @__PURE__ */ jsx("div", { className: "tecof-field-custom", children: definition.render({
1507
1889
  field: definition,
1508
1890
  name: name3,
1509
1891
  id: `field-${name3}`,
@@ -1522,18 +1904,6 @@ var FieldRenderer = ({
1522
1904
  value: value || "",
1523
1905
  disabled: readOnly,
1524
1906
  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
1907
  className: "tecof-input-text"
1538
1908
  }
1539
1909
  ) });
@@ -1546,24 +1916,11 @@ var FieldRenderer = ({
1546
1916
  value: value || "",
1547
1917
  disabled: readOnly,
1548
1918
  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
1919
  className: "tecof-input-textarea"
1563
1920
  }
1564
1921
  ) });
1565
1922
  case "select":
1566
- return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsxs("div", { style: { position: "relative", width: "100%" }, children: [
1923
+ return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsxs("div", { className: "tecof-field-select-wrap", children: [
1567
1924
  /* @__PURE__ */ jsx(
1568
1925
  "select",
1569
1926
  {
@@ -1571,100 +1928,198 @@ var FieldRenderer = ({
1571
1928
  value: value || "",
1572
1929
  disabled: readOnly,
1573
1930
  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
1931
  className: "tecof-input-select",
1588
1932
  children: (definition.options || []).map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label || opt.value }, opt.value))
1589
1933
  }
1590
1934
  ),
1591
- /* @__PURE__ */ jsx(
1592
- "div",
1935
+ /* @__PURE__ */ jsx("div", { className: "tecof-field-select-caret", children: /* @__PURE__ */ jsx(ChevronDown, { size: 12 }) })
1936
+ ] }) });
1937
+ case "number":
1938
+ return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsx(
1939
+ "input",
1940
+ {
1941
+ id: `field-${name3}`,
1942
+ type: "number",
1943
+ value: value !== void 0 ? value : "",
1944
+ disabled: readOnly,
1945
+ onChange: (e3) => {
1946
+ const val = e3.target.value;
1947
+ onChange(val === "" ? void 0 : Number(val));
1948
+ },
1949
+ className: "tecof-input-number"
1950
+ }
1951
+ ) });
1952
+ case "radio":
1953
+ return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsx("div", { className: "tecof-field-radio-group", children: (definition.options || []).map((opt) => /* @__PURE__ */ jsxs(
1954
+ "label",
1955
+ {
1956
+ className: `tecof-field-radio${readOnly ? " is-readonly" : ""}`,
1957
+ children: [
1958
+ /* @__PURE__ */ jsx(
1959
+ "input",
1960
+ {
1961
+ type: "radio",
1962
+ name: name3,
1963
+ value: opt.value,
1964
+ checked: value === opt.value,
1965
+ disabled: readOnly,
1966
+ onChange: () => onChange(opt.value)
1967
+ }
1968
+ ),
1969
+ /* @__PURE__ */ jsx("span", { children: opt.label || opt.value })
1970
+ ]
1971
+ },
1972
+ opt.value
1973
+ )) }) });
1974
+ case "array": {
1975
+ const items = Array.isArray(value) ? value : [];
1976
+ const arrayFields = definition.arrayFields || {};
1977
+ const getItemLabel = (item2, idx) => {
1978
+ if (!item2) return `\xD6\u011Fe ${idx + 1}`;
1979
+ for (const val of Object.values(item2)) {
1980
+ if (typeof val === "string" && val.trim().length > 0) {
1981
+ return val;
1982
+ }
1983
+ if (Array.isArray(val)) {
1984
+ const trVal = val.find((v2) => typeof v2 === "object" && v2 !== null && "value" in v2);
1985
+ if (trVal && typeof trVal.value === "string" && trVal.value.trim().length > 0) {
1986
+ return trVal.value;
1987
+ }
1988
+ }
1989
+ }
1990
+ return `\xD6\u011Fe ${idx + 1}`;
1991
+ };
1992
+ const toggleExpand = (idx) => {
1993
+ setExpandedIndices((prev) => ({ ...prev, [idx]: !prev[idx] }));
1994
+ };
1995
+ const handleAdd = () => {
1996
+ const newItem = {};
1997
+ Object.entries(arrayFields).forEach(([subName, subDef]) => {
1998
+ newItem[subName] = subDef.defaultValue !== void 0 ? subDef.defaultValue : null;
1999
+ });
2000
+ onChange([...items, newItem]);
2001
+ setExpandedIndices((prev) => ({ ...prev, [items.length]: true }));
2002
+ };
2003
+ const handleRemove = (idx) => {
2004
+ const copy = [...items];
2005
+ copy.splice(idx, 1);
2006
+ onChange(copy);
2007
+ const newExpanded = { ...expandedIndices };
2008
+ delete newExpanded[idx];
2009
+ setExpandedIndices(newExpanded);
2010
+ };
2011
+ const handleMove = (idx, direction) => {
2012
+ if (direction === "up" && idx === 0) return;
2013
+ if (direction === "down" && idx === items.length - 1) return;
2014
+ const copy = [...items];
2015
+ const targetIdx = direction === "up" ? idx - 1 : idx + 1;
2016
+ const temp = copy[idx];
2017
+ copy[idx] = copy[targetIdx];
2018
+ copy[targetIdx] = temp;
2019
+ onChange(copy);
2020
+ const newExpanded = { ...expandedIndices };
2021
+ const tempExpanded = newExpanded[idx];
2022
+ newExpanded[idx] = newExpanded[targetIdx];
2023
+ newExpanded[targetIdx] = tempExpanded;
2024
+ setExpandedIndices(newExpanded);
2025
+ };
2026
+ return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsxs("div", { className: "tecof-array", children: [
2027
+ items.map((item2, idx) => {
2028
+ const isExpanded = !!expandedIndices[idx];
2029
+ const itemLabel = getItemLabel(item2, idx);
2030
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-array-item", children: [
2031
+ /* @__PURE__ */ jsxs(
2032
+ "div",
2033
+ {
2034
+ onClick: () => toggleExpand(idx),
2035
+ onKeyDown: (e3) => {
2036
+ if (e3.key === "Enter" || e3.key === " ") {
2037
+ e3.preventDefault();
2038
+ toggleExpand(idx);
2039
+ }
2040
+ },
2041
+ className: "tecof-array-item-header",
2042
+ role: "button",
2043
+ tabIndex: 0,
2044
+ "aria-expanded": isExpanded,
2045
+ children: [
2046
+ /* @__PURE__ */ jsxs("div", { className: "tecof-array-item-title-wrap", children: [
2047
+ isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(ChevronRight, { size: 14 }),
2048
+ /* @__PURE__ */ jsx("span", { className: "tecof-array-item-title", children: itemLabel })
2049
+ ] }),
2050
+ /* @__PURE__ */ jsxs("div", { className: "tecof-array-item-actions", onClick: (e3) => e3.stopPropagation(), children: [
2051
+ /* @__PURE__ */ jsx(
2052
+ "button",
2053
+ {
2054
+ type: "button",
2055
+ onClick: () => handleMove(idx, "up"),
2056
+ disabled: idx === 0,
2057
+ className: "tecof-array-btn",
2058
+ title: "Yukar\u0131 ta\u015F\u0131",
2059
+ children: /* @__PURE__ */ jsx(ArrowUp, { size: 12 })
2060
+ }
2061
+ ),
2062
+ /* @__PURE__ */ jsx(
2063
+ "button",
2064
+ {
2065
+ type: "button",
2066
+ onClick: () => handleMove(idx, "down"),
2067
+ disabled: idx === items.length - 1,
2068
+ className: "tecof-array-btn",
2069
+ title: "A\u015Fa\u011F\u0131 ta\u015F\u0131",
2070
+ children: /* @__PURE__ */ jsx(ArrowDown, { size: 12 })
2071
+ }
2072
+ ),
2073
+ !readOnly && /* @__PURE__ */ jsx(
2074
+ "button",
2075
+ {
2076
+ type: "button",
2077
+ onClick: () => handleRemove(idx),
2078
+ className: "tecof-array-btn danger",
2079
+ title: "Sil",
2080
+ children: /* @__PURE__ */ jsx(Trash2, { size: 12 })
2081
+ }
2082
+ )
2083
+ ] })
2084
+ ]
2085
+ }
2086
+ ),
2087
+ isExpanded && /* @__PURE__ */ jsx("div", { className: "tecof-array-item-body", children: Object.entries(arrayFields).map(([subFieldName, subFieldDef]) => /* @__PURE__ */ jsx(
2088
+ FieldRenderer,
2089
+ {
2090
+ name: subFieldName,
2091
+ definition: subFieldDef,
2092
+ value: item2[subFieldName],
2093
+ onChange: (newSubVal) => {
2094
+ const updatedItems = [...items];
2095
+ updatedItems[idx] = {
2096
+ ...updatedItems[idx],
2097
+ [subFieldName]: newSubVal
2098
+ };
2099
+ onChange(updatedItems);
2100
+ },
2101
+ readOnly
2102
+ },
2103
+ subFieldName
2104
+ )) })
2105
+ ] }, idx);
2106
+ }),
2107
+ !readOnly && /* @__PURE__ */ jsxs(
2108
+ "button",
1593
2109
  {
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" }) })
2110
+ type: "button",
2111
+ onClick: handleAdd,
2112
+ className: "tecof-add-array-item-btn",
2113
+ children: [
2114
+ /* @__PURE__ */ jsx(Plus, { size: 14 }),
2115
+ "\xD6\u011Fe Ekle"
2116
+ ]
1605
2117
  }
1606
2118
  )
1607
2119
  ] }) });
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"
1632
- }
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
- )) }) });
2120
+ }
1666
2121
  default:
1667
- return /* @__PURE__ */ jsxs("div", { style: { padding: "8px", fontSize: "11px", color: "#71717a", background: "#fafafa", borderRadius: "4px" }, children: [
2122
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-field-unsupported", children: [
1668
2123
  'Desteklenmeyen alan t\xFCr\xFC: "',
1669
2124
  type,
1670
2125
  '" (',
@@ -1683,184 +2138,383 @@ var Inspector = () => {
1683
2138
  if (selectedId) {
1684
2139
  const nodeDetails = findNodeById(documentState, selectedId);
1685
2140
  if (!nodeDetails) {
1686
- return /* @__PURE__ */ jsx("div", { style: { padding: "24px", color: "#71717a", fontSize: "13px", textAlign: "center" }, children: "Bile\u015Fen y\xFCkleniyor veya bulunamad\u0131." });
2141
+ return /* @__PURE__ */ jsx("div", { className: "tecof-inspector", children: /* @__PURE__ */ jsx("div", { className: "tecof-inspector-empty", children: "Bile\u015Fen y\xFCkleniyor veya bulunamad\u0131." }) });
1687
2142
  }
1688
2143
  const { node } = nodeDetails;
1689
2144
  const componentConfig = config3.components[node.type];
1690
2145
  const fields = componentConfig?.fields || {};
1691
2146
  const label = componentConfig?.label || node.type;
1692
- return /* @__PURE__ */ jsxs(
2147
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-inspector", children: [
2148
+ /* @__PURE__ */ jsxs("div", { className: "tecof-inspector-header", children: [
2149
+ /* @__PURE__ */ jsxs("div", { children: [
2150
+ /* @__PURE__ */ jsx("h3", { className: "tecof-inspector-title", children: label }),
2151
+ /* @__PURE__ */ jsx("span", { className: "tecof-inspector-id", children: selectedId })
2152
+ ] }),
2153
+ /* @__PURE__ */ jsx("button", { onClick: () => selectNode(null), className: "tecof-inspector-deselect", children: "Se\xE7imi Kald\u0131r" })
2154
+ ] }),
2155
+ /* @__PURE__ */ jsx("div", { className: "tecof-inspector-fields", children: Object.keys(fields).length === 0 ? /* @__PURE__ */ jsx("div", { className: "tecof-inspector-empty-fields", children: "Bu bile\u015Fenin d\xFCzenlenebilir alan\u0131 bulunmuyor." }) : Object.entries(fields).map(([fieldName, fieldDef]) => /* @__PURE__ */ jsx(
2156
+ FieldRenderer,
2157
+ {
2158
+ name: fieldName,
2159
+ definition: fieldDef,
2160
+ value: node.props[fieldName],
2161
+ onChange: (newVal) => updateProps2(selectedId, { [fieldName]: newVal }),
2162
+ readOnly
2163
+ },
2164
+ fieldName
2165
+ )) })
2166
+ ] });
2167
+ }
2168
+ const rootFields = config3.root?.fields || {};
2169
+ const hasRootFields = Object.keys(rootFields).length > 0;
2170
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-inspector", children: [
2171
+ /* @__PURE__ */ jsx("div", { className: "tecof-inspector-header", children: /* @__PURE__ */ jsxs("div", { children: [
2172
+ /* @__PURE__ */ jsx("h3", { className: "tecof-inspector-title", children: "Sayfa Ayarlar\u0131" }),
2173
+ /* @__PURE__ */ jsx("span", { className: "tecof-inspector-id", children: "Genel sayfa konfig\xFCrasyonu" })
2174
+ ] }) }),
2175
+ /* @__PURE__ */ jsx("div", { className: "tecof-inspector-fields", children: hasRootFields ? Object.entries(rootFields).map(([fieldName, fieldDef]) => /* @__PURE__ */ jsx(
2176
+ FieldRenderer,
2177
+ {
2178
+ name: fieldName,
2179
+ definition: fieldDef,
2180
+ value: documentState.root.props[fieldName],
2181
+ onChange: (newVal) => setRootProps2({ [fieldName]: newVal }),
2182
+ readOnly
2183
+ },
2184
+ fieldName
2185
+ )) : /* @__PURE__ */ jsxs("div", { className: "tecof-inspector-empty", children: [
2186
+ /* @__PURE__ */ jsxs(
2187
+ "svg",
2188
+ {
2189
+ width: "24",
2190
+ height: "24",
2191
+ viewBox: "0 0 24 24",
2192
+ fill: "none",
2193
+ stroke: "currentColor",
2194
+ strokeWidth: "2",
2195
+ strokeLinecap: "round",
2196
+ strokeLinejoin: "round",
2197
+ className: "tecof-inspector-empty-icon",
2198
+ children: [
2199
+ /* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }),
2200
+ /* @__PURE__ */ jsx("path", { d: "M9 3v18" })
2201
+ ]
2202
+ }
2203
+ ),
2204
+ "Bile\u015Fen se\xE7ilmedi. D\xFCzenlemek istedi\u011Finiz bir bile\u015Fene t\u0131klay\u0131n."
2205
+ ] }) })
2206
+ ] });
2207
+ };
2208
+ var TopBar = ({ onSave, saving, saveStatus }) => {
2209
+ const viewport = useEditorStore((state3) => state3.viewport);
2210
+ const setViewport = useEditorStore((state3) => state3.setViewport);
2211
+ const pastCount = useEditorStore((state3) => state3.history.past.length);
2212
+ const futureCount = useEditorStore((state3) => state3.history.future.length);
2213
+ const undo = useEditorStore((state3) => state3.undo);
2214
+ const redo = useEditorStore((state3) => state3.redo);
2215
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-topbar", children: [
2216
+ /* @__PURE__ */ jsxs("div", { className: "tecof-topbar-title", children: [
2217
+ /* @__PURE__ */ jsx("span", { children: "Sayfa D\xFCzenleyici" }),
2218
+ saveStatus === "success" && /* @__PURE__ */ jsxs("span", { className: "tecof-topbar-saved", children: [
2219
+ /* @__PURE__ */ jsx(Check, { size: 12 }),
2220
+ " Kaydedildi"
2221
+ ] })
2222
+ ] }),
2223
+ /* @__PURE__ */ jsxs("div", { className: "tecof-topbar-viewports", children: [
2224
+ /* @__PURE__ */ jsx(
2225
+ "button",
2226
+ {
2227
+ type: "button",
2228
+ onClick: () => setViewport("desktop"),
2229
+ className: `tecof-vp-btn${viewport === "desktop" ? " is-active" : ""}`,
2230
+ title: "Masa\xFCst\xFC",
2231
+ "aria-label": "Masa\xFCst\xFC g\xF6r\xFCn\xFCm\xFC",
2232
+ "aria-pressed": viewport === "desktop",
2233
+ children: /* @__PURE__ */ jsx(Monitor, { size: 16 })
2234
+ }
2235
+ ),
2236
+ /* @__PURE__ */ jsx(
2237
+ "button",
2238
+ {
2239
+ type: "button",
2240
+ onClick: () => setViewport("tablet"),
2241
+ className: `tecof-vp-btn${viewport === "tablet" ? " is-active" : ""}`,
2242
+ title: "Tablet",
2243
+ "aria-label": "Tablet g\xF6r\xFCn\xFCm\xFC",
2244
+ "aria-pressed": viewport === "tablet",
2245
+ children: /* @__PURE__ */ jsx(Tablet, { size: 16 })
2246
+ }
2247
+ ),
2248
+ /* @__PURE__ */ jsx(
2249
+ "button",
2250
+ {
2251
+ type: "button",
2252
+ onClick: () => setViewport("mobile"),
2253
+ className: `tecof-vp-btn${viewport === "mobile" ? " is-active" : ""}`,
2254
+ title: "Mobil",
2255
+ "aria-label": "Mobil g\xF6r\xFCn\xFCm\xFC",
2256
+ "aria-pressed": viewport === "mobile",
2257
+ children: /* @__PURE__ */ jsx(Smartphone, { size: 16 })
2258
+ }
2259
+ )
2260
+ ] }),
2261
+ /* @__PURE__ */ jsxs("div", { className: "tecof-topbar-actions", children: [
2262
+ /* @__PURE__ */ jsxs("div", { className: "tecof-topbar-undoredo", children: [
2263
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: undo, disabled: pastCount === 0, className: "tecof-icon-btn", title: "Geri Al", "aria-label": "Geri al", children: /* @__PURE__ */ jsx(Undo2, { size: 16 }) }),
2264
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: redo, disabled: futureCount === 0, className: "tecof-icon-btn", title: "Yinele", "aria-label": "Yinele", children: /* @__PURE__ */ jsx(Redo2, { size: 16 }) })
2265
+ ] }),
2266
+ /* @__PURE__ */ jsx("div", { className: "tecof-topbar-divider" }),
2267
+ /* @__PURE__ */ jsxs("button", { type: "button", onClick: onSave, disabled: saving, className: "tecof-btn-primary", "aria-busy": saving, children: [
2268
+ /* @__PURE__ */ jsx(Save, { size: 14 }),
2269
+ saving ? "Kaydediliyor..." : "Taslak Kaydet"
2270
+ ] })
2271
+ ] })
2272
+ ] });
2273
+ };
2274
+ var getLayerRowStyle = (depth) => ({ "--tecof-layer-indent": `${depth * 12 + 8}px` });
2275
+ var getLayerZoneStyle = (depth) => ({ "--tecof-layer-zone-indent": `${(depth + 1) * 12 + 14}px` });
2276
+ var TreeNode = ({ node, depth }) => {
2277
+ const { config: config3 } = useStudio();
2278
+ const documentState = useEditorStore((state3) => state3.document);
2279
+ const selectedId = useEditorStore((state3) => state3.selection.selectedId);
2280
+ const selectNode = useEditorStore((state3) => state3.selectNode);
2281
+ const hoverNode = useEditorStore((state3) => state3.hoverNode);
2282
+ const removeNode2 = useEditorStore((state3) => state3.removeNode);
2283
+ const beginDrag = useEditorStore((state3) => state3.beginDrag);
2284
+ const endDrag = useEditorStore((state3) => state3.endDrag);
2285
+ const [expanded, setExpanded] = useState(true);
2286
+ const [dragOverPos, setDragOverPos] = useState(null);
2287
+ const isSelected = selectedId === node.props.id;
2288
+ const componentConfig = config3.components[node.type];
2289
+ const label = componentConfig?.label || node.type;
2290
+ const childZoneKeys = Object.keys(documentState.zones).filter(
2291
+ (key) => key.startsWith(`${node.props.id}:`)
2292
+ );
2293
+ const hasChildren = childZoneKeys.some(
2294
+ (key) => (documentState.zones[key] || []).length > 0
2295
+ );
2296
+ const handleDragOver = (e3) => {
2297
+ e3.preventDefault();
2298
+ e3.stopPropagation();
2299
+ const rect = e3.currentTarget.getBoundingClientRect();
2300
+ const relativeY = e3.clientY - rect.top;
2301
+ setDragOverPos(relativeY < rect.height / 2 ? "top" : "bottom");
2302
+ };
2303
+ const handleDragLeave = () => {
2304
+ setDragOverPos(null);
2305
+ };
2306
+ const handleDrop = (e3) => {
2307
+ e3.preventDefault();
2308
+ e3.stopPropagation();
2309
+ setDragOverPos(null);
2310
+ const { nodeId: draggedId } = readDragData(e3);
2311
+ if (!draggedId || draggedId === node.props.id) return;
2312
+ const doc = useEditorStore.getState().document;
2313
+ const res2 = findNodeById(doc, node.props.id);
2314
+ if (!res2) return;
2315
+ const { path } = res2;
2316
+ const targetZoneKey = path.zoneKey;
2317
+ const targetIndex = dragOverPos === "top" ? path.index : path.index + 1;
2318
+ useEditorStore.getState().moveNode(draggedId, targetZoneKey, targetIndex);
2319
+ };
2320
+ const handleRowKeyDown = (e3) => {
2321
+ if (e3.key === "Enter" || e3.key === " ") {
2322
+ e3.preventDefault();
2323
+ selectNode(node.props.id);
2324
+ return;
2325
+ }
2326
+ if ((e3.key === "Delete" || e3.key === "Backspace") && isSelected) {
2327
+ e3.preventDefault();
2328
+ removeNode2(node.props.id);
2329
+ }
2330
+ };
2331
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-layer-node", children: [
2332
+ dragOverPos === "top" && /* @__PURE__ */ jsx("div", { className: "tecof-drop-line sm" }),
2333
+ /* @__PURE__ */ jsxs(
1693
2334
  "div",
1694
2335
  {
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"
2336
+ draggable: true,
2337
+ onDragStart: (e3) => {
2338
+ writeDragData(e3, { nodeId: node.props.id });
2339
+ e3.dataTransfer.effectAllowed = "move";
2340
+ setDragGhost(e3, label);
2341
+ beginDrag({ id: node.props.id });
1704
2342
  },
2343
+ onDragEnd: endDrag,
2344
+ onDragOver: handleDragOver,
2345
+ onDragLeave: handleDragLeave,
2346
+ onDrop: handleDrop,
2347
+ onMouseEnter: () => hoverNode(node.props.id),
2348
+ onMouseLeave: () => hoverNode(null),
2349
+ onClick: () => selectNode(node.props.id),
2350
+ onKeyDown: handleRowKeyDown,
2351
+ className: `tecof-layer-row${isSelected ? " is-selected" : ""}`,
2352
+ role: "treeitem",
2353
+ tabIndex: 0,
2354
+ "aria-selected": isSelected,
2355
+ "aria-expanded": hasChildren ? expanded : void 0,
2356
+ style: getLayerRowStyle(depth),
1705
2357
  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
- ),
2358
+ /* @__PURE__ */ jsxs("div", { className: "tecof-layer-row-main", children: [
2359
+ hasChildren ? /* @__PURE__ */ jsx(
2360
+ "button",
2361
+ {
2362
+ type: "button",
2363
+ onClick: (e3) => {
2364
+ e3.stopPropagation();
2365
+ setExpanded(!expanded);
2366
+ },
2367
+ className: "tecof-layer-caret",
2368
+ "aria-label": expanded ? `${label} katman\u0131n\u0131 daralt` : `${label} katman\u0131n\u0131 geni\u015Flet`,
2369
+ "aria-expanded": expanded,
2370
+ children: expanded ? /* @__PURE__ */ jsx(ChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(ChevronRight, { size: 14 })
2371
+ }
2372
+ ) : /* @__PURE__ */ jsx("div", { className: "tecof-layer-caret-spacer" }),
2373
+ /* @__PURE__ */ jsx(PanelsTopLeft, { size: 14, className: "tecof-layer-icon" }),
2374
+ /* @__PURE__ */ jsx("span", { className: "tecof-layer-label", children: label })
2375
+ ] }),
1742
2376
  /* @__PURE__ */ jsx(
1743
- "div",
2377
+ "button",
1744
2378
  {
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"
2379
+ type: "button",
2380
+ onClick: (e3) => {
2381
+ e3.stopPropagation();
2382
+ removeNode2(node.props.id);
1753
2383
  },
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
- ))
2384
+ className: "tecof-layer-delete",
2385
+ title: "Sil",
2386
+ "aria-label": `${label} katman\u0131n\u0131 sil`,
2387
+ children: /* @__PURE__ */ jsx(Trash2, { size: 12 })
1765
2388
  }
1766
2389
  )
1767
2390
  ]
1768
2391
  }
1769
- );
2392
+ ),
2393
+ dragOverPos === "bottom" && /* @__PURE__ */ jsx("div", { className: "tecof-drop-line sm" }),
2394
+ expanded && childZoneKeys.map((zoneKey) => {
2395
+ const zoneItems = documentState.zones[zoneKey] || [];
2396
+ const zoneName = zoneKey.split(":").pop() || "";
2397
+ if (zoneItems.length === 0) return null;
2398
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-layer-node", children: [
2399
+ /* @__PURE__ */ jsx("div", { className: "tecof-layer-zone-label", style: getLayerZoneStyle(depth), children: zoneName }),
2400
+ zoneItems.map((childNode) => /* @__PURE__ */ jsx(TreeNode, { node: childNode, depth: depth + 1 }, childNode.props.id))
2401
+ ] }, zoneKey);
2402
+ })
2403
+ ] });
2404
+ };
2405
+ var LayersTree = () => {
2406
+ const documentState = useEditorStore((state3) => state3.document);
2407
+ return /* @__PURE__ */ jsx("div", { className: "tecof-layers", role: "tree", "aria-label": "Sayfa katmanlar\u0131", children: documentState.content.length === 0 ? /* @__PURE__ */ jsx("div", { className: "tecof-layers-empty", children: "S\xFCr\xFCklenmi\u015F katman yok" }) : documentState.content.map((node) => /* @__PURE__ */ jsx(TreeNode, { node, depth: 0 }, node.props.id)) });
2408
+ };
2409
+ var LeftPanel = () => {
2410
+ const { config: config3 } = useStudio();
2411
+ const insertNode2 = useEditorStore((state3) => state3.insertNode);
2412
+ const beginDrag = useEditorStore((state3) => state3.beginDrag);
2413
+ const endDrag = useEditorStore((state3) => state3.endDrag);
2414
+ const [activeTab, setActiveTab] = useState("blocks");
2415
+ const [searchQuery, setSearchQuery] = useState("");
2416
+ const categories = config3.categories || {};
2417
+ const components = config3.components || {};
2418
+ const groupedComponents = {};
2419
+ if (Object.keys(categories).length > 0) {
2420
+ Object.entries(categories).forEach(([key, value]) => {
2421
+ groupedComponents[value.title || key] = value.components;
2422
+ });
2423
+ } else {
2424
+ Object.entries(components).forEach(([name3, compConfig]) => {
2425
+ const cat = compConfig.category || "Genel";
2426
+ if (!groupedComponents[cat]) {
2427
+ groupedComponents[cat] = [];
2428
+ }
2429
+ groupedComponents[cat].push(name3);
2430
+ });
1770
2431
  }
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
- ),
2432
+ const handleAddBlock = (type) => {
2433
+ insertNode2(createNode(config3, type));
2434
+ };
2435
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-left-panel", children: [
2436
+ /* @__PURE__ */ jsxs("div", { className: "tecof-panel-tabs", role: "tablist", "aria-label": "Sol panel g\xF6r\xFCn\xFCm\xFC", children: [
2437
+ /* @__PURE__ */ jsxs(
2438
+ "button",
2439
+ {
2440
+ type: "button",
2441
+ onClick: () => setActiveTab("blocks"),
2442
+ className: `tecof-tab${activeTab === "blocks" ? " is-active" : ""}`,
2443
+ role: "tab",
2444
+ "aria-selected": activeTab === "blocks",
2445
+ children: [
2446
+ /* @__PURE__ */ jsx(Grid3x3, { size: 14 }),
2447
+ "Blok Ekle"
2448
+ ]
2449
+ }
2450
+ ),
2451
+ /* @__PURE__ */ jsxs(
2452
+ "button",
2453
+ {
2454
+ type: "button",
2455
+ onClick: () => setActiveTab("layers"),
2456
+ className: `tecof-tab${activeTab === "layers" ? " is-active" : ""}`,
2457
+ role: "tab",
2458
+ "aria-selected": activeTab === "layers",
2459
+ children: [
2460
+ /* @__PURE__ */ jsx(Layers, { size: 14 }),
2461
+ "Katmanlar"
2462
+ ]
2463
+ }
2464
+ )
2465
+ ] }),
2466
+ /* @__PURE__ */ jsx("div", { className: "tecof-panel-body", children: activeTab === "blocks" ? /* @__PURE__ */ jsxs("div", { className: "tecof-blocks", children: [
2467
+ /* @__PURE__ */ jsxs("div", { className: "tecof-search", children: [
2468
+ /* @__PURE__ */ jsx(Search, { size: 14, className: "tecof-icon-muted" }),
1800
2469
  /* @__PURE__ */ jsx(
1801
- "div",
2470
+ "input",
1802
2471
  {
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",
2472
+ type: "text",
2473
+ placeholder: "Bile\u015Fen ara...",
2474
+ value: searchQuery,
2475
+ onChange: (e3) => setSearchQuery(e3.target.value),
2476
+ className: "tecof-search-input"
2477
+ }
2478
+ )
2479
+ ] }),
2480
+ Object.entries(groupedComponents).map(([catTitle, blockTypes]) => {
2481
+ const filteredTypes = blockTypes.filter((type) => {
2482
+ const label = components[type]?.label || type;
2483
+ return label.toLowerCase().includes(searchQuery.toLowerCase());
2484
+ });
2485
+ if (filteredTypes.length === 0) return null;
2486
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-block-cat", children: [
2487
+ /* @__PURE__ */ jsx("div", { className: "tecof-block-cat-title", children: catTitle }),
2488
+ /* @__PURE__ */ jsx("div", { className: "tecof-block-grid", children: filteredTypes.map((type) => {
2489
+ const compConfig = components[type] || {};
2490
+ const label = compConfig.label || type;
2491
+ return /* @__PURE__ */ jsxs(
2492
+ "button",
1824
2493
  {
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"
2494
+ type: "button",
2495
+ onClick: () => handleAddBlock(type),
2496
+ draggable: true,
2497
+ onDragStart: (e3) => {
2498
+ writeDragData(e3, { type });
2499
+ e3.dataTransfer.effectAllowed = "copy";
2500
+ setDragGhost(e3, label);
2501
+ beginDrag({ type });
1835
2502
  },
2503
+ onDragEnd: endDrag,
2504
+ className: "tecof-block-btn",
2505
+ title: `${label} ekle`,
1836
2506
  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."
2507
+ /* @__PURE__ */ jsx("span", { children: label }),
2508
+ /* @__PURE__ */ jsx(Plus, { size: 14, className: "tecof-block-btn-icon" })
1856
2509
  ]
1857
- }
1858
- )
1859
- }
1860
- )
1861
- ]
1862
- }
1863
- );
2510
+ },
2511
+ type
2512
+ );
2513
+ }) })
2514
+ ] }, catTitle);
2515
+ })
2516
+ ] }) : /* @__PURE__ */ jsx(LayersTree, {}) })
2517
+ ] });
1864
2518
  };
1865
2519
  var TecofStudio = ({
1866
2520
  pageId,
@@ -1928,7 +2582,7 @@ var TecofStudio = ({
1928
2582
  setTimeout(() => setSaveStatus("idle"), 3e3);
1929
2583
  onSave?.(serialized);
1930
2584
  if (isEmbedded) {
1931
- window.parent.postMessage({ type: "puck:saved" }, "*");
2585
+ window.parent.postMessage({ type: "puck:saved", data: serialized }, "*");
1932
2586
  }
1933
2587
  } else {
1934
2588
  setSaveStatus("error");
@@ -1950,6 +2604,7 @@ var TecofStudio = ({
1950
2604
  const onMessage = (e3) => {
1951
2605
  switch (e3.data?.type) {
1952
2606
  case "puck:save":
2607
+ case "puck:publish":
1953
2608
  handleSaveDraft();
1954
2609
  break;
1955
2610
  case "puck:undo":
@@ -1975,74 +2630,117 @@ var TecofStudio = ({
1975
2630
  window.addEventListener("message", onMessage);
1976
2631
  return () => window.removeEventListener("message", onMessage);
1977
2632
  }, [isEmbedded, handleSaveDraft, undo, redo, setViewport]);
2633
+ useEffect(() => {
2634
+ const handleKeyDown = (e3) => {
2635
+ const isInput2 = () => {
2636
+ const activeEl = document.activeElement;
2637
+ if (activeEl) {
2638
+ const tag = activeEl.tagName.toLowerCase();
2639
+ if (tag === "input" || tag === "textarea" || activeEl.hasAttribute("contenteditable")) {
2640
+ return true;
2641
+ }
2642
+ }
2643
+ const iframe = document.querySelector(".tecof-canvas-viewport iframe");
2644
+ const iframeDoc = iframe?.contentDocument;
2645
+ const iframeActiveEl = iframeDoc?.activeElement;
2646
+ if (iframeActiveEl) {
2647
+ const tag = iframeActiveEl.tagName.toLowerCase();
2648
+ if (tag === "input" || tag === "textarea" || iframeActiveEl.hasAttribute("contenteditable")) {
2649
+ return true;
2650
+ }
2651
+ }
2652
+ return false;
2653
+ };
2654
+ const selectedId = useEditorStore.getState().selection.selectedId;
2655
+ const isCmdOrCtrl = e3.metaKey || e3.ctrlKey;
2656
+ if (e3.key === "Escape") {
2657
+ useEditorStore.getState().selectNode(null);
2658
+ if (isEmbedded) {
2659
+ window.parent.postMessage({ type: "puck:itemDeselected" }, "*");
2660
+ }
2661
+ return;
2662
+ }
2663
+ if (isCmdOrCtrl && e3.key.toLowerCase() === "z") {
2664
+ e3.preventDefault();
2665
+ if (e3.shiftKey) {
2666
+ redo();
2667
+ } else {
2668
+ undo();
2669
+ }
2670
+ return;
2671
+ }
2672
+ if (isCmdOrCtrl && e3.key.toLowerCase() === "y") {
2673
+ e3.preventDefault();
2674
+ redo();
2675
+ return;
2676
+ }
2677
+ if (isInput2()) return;
2678
+ if ((e3.key === "Delete" || e3.key === "Backspace") && selectedId) {
2679
+ e3.preventDefault();
2680
+ useEditorStore.getState().removeNode(selectedId);
2681
+ return;
2682
+ }
2683
+ if (isCmdOrCtrl && e3.key.toLowerCase() === "d" && selectedId) {
2684
+ e3.preventDefault();
2685
+ useEditorStore.getState().duplicateNode(selectedId);
2686
+ return;
2687
+ }
2688
+ };
2689
+ window.addEventListener("keydown", handleKeyDown);
2690
+ return () => {
2691
+ window.removeEventListener("keydown", handleKeyDown);
2692
+ };
2693
+ }, [undo, redo, isEmbedded]);
1978
2694
  const studioContextValue = useMemo(() => ({
1979
2695
  config: config3,
1980
2696
  readOnly: false,
1981
2697
  apiClient
1982
2698
  }), [config3, apiClient]);
1983
2699
  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..." })
2001
- ] }) });
2002
- }
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: [
2700
+ return /* @__PURE__ */ jsx(StudioSkeleton, { className });
2701
+ }
2702
+ return /* @__PURE__ */ jsx(StudioContext.Provider, { value: studioContextValue, children: /* @__PURE__ */ jsxs("div", { className: `tecof-studio-root ${className || ""}`.trim(), children: [
2703
+ /* @__PURE__ */ jsx(TopBar, { onSave: handleSaveDraft, saving, saveStatus }),
2704
+ /* @__PURE__ */ jsxs("div", { className: "tecof-studio-workspace-container", children: [
2705
+ /* @__PURE__ */ jsx(LeftPanel, {}),
2706
+ /* @__PURE__ */ jsxs("div", { className: "tecof-studio-workspace", children: [
2026
2707
  /* @__PURE__ */ jsx(Canvas, {}),
2027
2708
  /* @__PURE__ */ jsx(SelectionOverlay, {})
2028
2709
  ] }),
2029
2710
  /* @__PURE__ */ jsx(Inspector, {})
2030
2711
  ] }),
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..." })
2712
+ saving && /* @__PURE__ */ jsx("div", { className: `tecof-studio-save-indicator${saveStatus === "error" ? " is-error" : ""}`, children: saveStatus === "error" ? "Kaydedilemedi" : "Kaydediliyor..." })
2044
2713
  ] }) });
2045
2714
  };
2715
+ var StudioSkeleton = ({ className }) => /* @__PURE__ */ jsxs("div", { className: `tecof-studio-skeleton ${className || ""}`.trim(), "aria-busy": "true", "aria-label": "St\xFCdyo y\xFCkleniyor", children: [
2716
+ /* @__PURE__ */ jsxs("div", { className: "tecof-studio-skeleton-topbar", children: [
2717
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-studio-skeleton-title" }),
2718
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-studio-skeleton-vp" }),
2719
+ /* @__PURE__ */ jsxs("div", { className: "tecof-studio-skeleton-toolgroup", children: [
2720
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-studio-skeleton-dot" }),
2721
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-studio-skeleton-dot" }),
2722
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-studio-skeleton-cta" })
2723
+ ] })
2724
+ ] }),
2725
+ /* @__PURE__ */ jsxs("div", { className: "tecof-studio-skeleton-body", children: [
2726
+ /* @__PURE__ */ jsxs("div", { className: "tecof-studio-skeleton-side", children: [
2727
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-studio-skeleton-search" }),
2728
+ Array.from({ length: 6 }).map((_2, i2) => /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-studio-skeleton-blockrow" }, i2))
2729
+ ] }),
2730
+ /* @__PURE__ */ jsxs("div", { className: "tecof-studio-skeleton-canvas", children: [
2731
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-block" }),
2732
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-block" }),
2733
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-block" })
2734
+ ] }),
2735
+ /* @__PURE__ */ jsxs("div", { className: "tecof-studio-skeleton-side right", children: [
2736
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-text w-60" }),
2737
+ Array.from({ length: 5 }).map((_2, i2) => /* @__PURE__ */ jsxs(React__default__default.Fragment, { children: [
2738
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-text sm w-40" }),
2739
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-studio-skeleton-field" })
2740
+ ] }, i2))
2741
+ ] })
2742
+ ] })
2743
+ ] });
2046
2744
 
2047
2745
  // src/components/TecofEditor.tsx
2048
2746
  var TecofEditor = TecofStudio;
@@ -2082,7 +2780,15 @@ var TecofRender = ({ data: data3, config: config3, className, cmsData }) => {
2082
2780
  config: config3,
2083
2781
  cmsData: cmsData || null
2084
2782
  };
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)) }) });
2783
+ const renderedContent = data3.content.map((item2, index2) => /* @__PURE__ */ jsx(RenderNode, { node: item2, index: index2 }, item2.props.id || index2));
2784
+ const rootProps = data3.root?.props || {};
2785
+ const rootConfig = config3.root;
2786
+ const contentWithLayout = rootConfig?.render ? rootConfig.render({
2787
+ ...rootProps,
2788
+ children: renderedContent,
2789
+ editMode: false
2790
+ }) : renderedContent;
2791
+ return /* @__PURE__ */ jsx(RenderContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx("div", { className, children: contentWithLayout }) });
2086
2792
  };
2087
2793
  var IMAGE_EXTENSIONS = ["png", "jpg", "jpeg", "webp", "gif", "svg", "avif", "bmp", "tiff", "heic"];
2088
2794
  var VIDEO_EXTENSIONS = ["mp4", "webm", "ogg", "avi", "mov", "quicktime"];
@@ -2192,7 +2898,7 @@ var TecofPicture = memo(({
2192
2898
  {
2193
2899
  "data-fancybox": fancyboxName,
2194
2900
  href: fileURL,
2195
- style: { display: "block", textDecoration: "none" },
2901
+ className: "tecof-picture-link",
2196
2902
  children: /* @__PURE__ */ jsx("div", { style, className: containerClassName, children: isVideoType ? renderVideo() : renderImg() })
2197
2903
  }
2198
2904
  );
@@ -2550,10 +3256,15 @@ var LanguageTabBar = ({
2550
3256
  code
2551
3257
  )) });
2552
3258
  };
2553
- var FieldLoading = () => /* @__PURE__ */ jsxs("div", { className: "tecof-lang-loading", children: [
2554
- /* @__PURE__ */ jsx("span", { className: "tecof-lang-loading-dot" }),
2555
- /* @__PURE__ */ jsx("span", { className: "tecof-lang-loading-dot" }),
2556
- /* @__PURE__ */ jsx("span", { className: "tecof-lang-loading-dot" })
3259
+ var FieldLoading = () => /* @__PURE__ */ jsxs("div", { className: "tecof-field-loading", "aria-busy": "true", children: [
3260
+ /* @__PURE__ */ jsxs("div", { className: "tecof-field-loading-row", children: [
3261
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-circle tecof-field-loading-thumb" }),
3262
+ /* @__PURE__ */ jsxs("div", { className: "tecof-field-loading-lines", children: [
3263
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-text w-60" }),
3264
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-text sm w-80" })
3265
+ ] })
3266
+ ] }),
3267
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-block tecof-studio-skeleton-field" })
2557
3268
  ] });
2558
3269
  var StableInput = ({
2559
3270
  value: externalValue,
@@ -6340,7 +7051,7 @@ var MediaDrawer = ({
6340
7051
  ] })
6341
7052
  ] }),
6342
7053
  /* @__PURE__ */ jsxs("div", { className: "tecof-upload-search-box", children: [
6343
- /* @__PURE__ */ jsx(Search, { size: 15, color: "#a1a1aa" }),
7054
+ /* @__PURE__ */ jsx(Search, { size: 15, className: "tecof-icon-muted" }),
6344
7055
  /* @__PURE__ */ jsx(
6345
7056
  "input",
6346
7057
  {
@@ -6361,11 +7072,11 @@ var MediaDrawer = ({
6361
7072
  }
6362
7073
  )
6363
7074
  ] }),
6364
- loading ? /* @__PURE__ */ jsxs("div", { className: "tecof-upload-gallery-empty", children: [
6365
- /* @__PURE__ */ jsx("div", { className: "tecof-upload-gallery-empty-icon", children: /* @__PURE__ */ jsx(RefreshCcw, { size: 24, color: "#a1a1aa", className: "tecof-upload-spin" }) }),
6366
- /* @__PURE__ */ jsx("p", { className: "tecof-upload-loading-text", children: "Y\xFCkleniyor..." })
6367
- ] }) : filteredGallery.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "tecof-upload-gallery-empty", children: [
6368
- /* @__PURE__ */ jsx("div", { className: "tecof-upload-gallery-empty-icon", children: /* @__PURE__ */ jsx(Image2, { size: 24, color: "#a1a1aa" }) }),
7075
+ loading ? /* @__PURE__ */ jsx("div", { className: "tecof-media-skeleton-grid", "aria-busy": "true", children: Array.from({ length: 8 }).map((_2, index2) => /* @__PURE__ */ jsxs("div", { className: "tecof-media-skeleton-card", children: [
7076
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-block tecof-media-skeleton-thumb" }),
7077
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-text w-80" })
7078
+ ] }, index2)) }) : filteredGallery.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "tecof-upload-gallery-empty", children: [
7079
+ /* @__PURE__ */ jsx("div", { className: "tecof-upload-gallery-empty-icon", children: /* @__PURE__ */ jsx(Image2, { size: 24, className: "tecof-icon-muted" }) }),
6369
7080
  /* @__PURE__ */ jsx("p", { className: "tecof-upload-empty-heading", children: gallerySearch ? "Sonu\xE7 bulunamad\u0131" : "Hen\xFCz dosya yok" }),
6370
7081
  /* @__PURE__ */ jsx("p", { className: "tecof-upload-empty-subheading", children: gallerySearch ? "Farkl\u0131 bir arama terimi deneyin" : "Dosyalar\u0131n\u0131z burada g\xF6r\xFCnecek" })
6371
7082
  ] }) : /* @__PURE__ */ jsx("div", { className: "tecof-upload-gallery-grid", children: filteredGallery.map((file2) => {
@@ -6383,10 +7094,9 @@ var MediaDrawer = ({
6383
7094
  data: file2,
6384
7095
  alt: file2.name,
6385
7096
  size: "thumbnail",
6386
- className: "tecof-upload-gallery-thumb",
6387
- imgStyle: { width: "100%", height: "100%", objectFit: "cover", borderRadius: "8px" }
7097
+ className: "tecof-upload-gallery-thumb"
6388
7098
  }
6389
- ) : /* @__PURE__ */ jsx("div", { className: "tecof-upload-gallery-thumb tecof-upload-gallery-file-icon-wrap", children: /* @__PURE__ */ jsx(File2, { size: 24, color: "#a1a1aa" }) }),
7099
+ ) : /* @__PURE__ */ jsx("div", { className: "tecof-upload-gallery-thumb tecof-upload-gallery-file-icon-wrap", children: /* @__PURE__ */ jsx(File2, { size: 24, className: "tecof-icon-muted" }) }),
6390
7100
  /* @__PURE__ */ jsx("p", { className: "tecof-upload-gallery-file-name", children: file2.meta?.originalName || file2.name })
6391
7101
  ]
6392
7102
  },
@@ -24262,14 +24972,13 @@ var FileItemRenderer = ({
24262
24972
  `${cdnUrl}/${file2.name}`;
24263
24973
  const ext = getFileExtension(file2.name);
24264
24974
  return /* @__PURE__ */ jsxs("div", { className: "tecof-upload-file-item", children: [
24265
- file2.type === "image/reference" ? /* @__PURE__ */ jsx("div", { className: "tecof-upload-file-icon", style: { backgroundColor: "#f4f4f5", color: "#18181b" }, children: /* @__PURE__ */ jsx(Code, { size: 16 }) }) : isImageType2(file2.type) ? /* @__PURE__ */ jsx(
24975
+ file2.type === "image/reference" ? /* @__PURE__ */ jsx("div", { className: "tecof-upload-file-icon is-reference", children: /* @__PURE__ */ jsx(Code, { size: 16 }) }) : isImageType2(file2.type) ? /* @__PURE__ */ jsx(
24266
24976
  TecofPicture,
24267
24977
  {
24268
24978
  data: file2,
24269
24979
  alt: file2.meta?.originalName || file2.name,
24270
24980
  size: "thumbnail",
24271
- className: "tecof-upload-file-thumb",
24272
- imgStyle: { width: "100%", height: "100%", objectFit: "cover", borderRadius: "6px" }
24981
+ className: "tecof-upload-file-thumb"
24273
24982
  }
24274
24983
  ) : /* @__PURE__ */ jsx("div", { className: "tecof-upload-file-icon", children: /* @__PURE__ */ jsx(File2, { size: 16 }) }),
24275
24984
  /* @__PURE__ */ jsxs("div", { className: "tecof-upload-file-info", children: [
@@ -24583,12 +25292,12 @@ var UploadField = ({
24583
25292
  " Y\xFCkle"
24584
25293
  ] })
24585
25294
  ] }),
24586
- showRefInput && /* @__PURE__ */ jsxs("div", { className: "tecof-upload-ref-section", style: { background: "#ffffff", padding: "10px", borderRadius: "8px", border: "1px solid #e4e4e7", display: "flex", flexDirection: "column", gap: "8px", marginTop: "4px" }, children: [
24587
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
24588
- /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", fontWeight: 500, color: "#71717a" }, children: "Dinamik CMS De\u011Fi\u015Fkeni" }),
24589
- /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setShowRefInput(false), style: { background: "none", border: "none", cursor: "pointer", color: "#a1a1aa", padding: 0 }, children: /* @__PURE__ */ jsx(X, { size: 12 }) })
25295
+ showRefInput && /* @__PURE__ */ jsxs("div", { className: "tecof-upload-ref-section", children: [
25296
+ /* @__PURE__ */ jsxs("div", { className: "tecof-upload-ref-header", children: [
25297
+ /* @__PURE__ */ jsx("span", { className: "tecof-upload-ref-title", children: "Dinamik CMS De\u011Fi\u015Fkeni" }),
25298
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setShowRefInput(false), className: "tecof-upload-ref-close", title: "Kapat", children: /* @__PURE__ */ jsx(X, { size: 12 }) })
24590
25299
  ] }),
24591
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "6px" }, children: [
25300
+ /* @__PURE__ */ jsxs("div", { className: "tecof-upload-ref-row", children: [
24592
25301
  /* @__PURE__ */ jsx(
24593
25302
  "input",
24594
25303
  {
@@ -24596,7 +25305,7 @@ var UploadField = ({
24596
25305
  value: refCode,
24597
25306
  onChange: (e3) => setRefCode(e3.target.value),
24598
25307
  placeholder: "{{ data. }}",
24599
- style: { flex: 1, padding: "6px 8px", fontSize: "12px", borderRadius: "6px", border: "1px solid #cbd5e1", outline: "none" },
25308
+ className: "tecof-upload-ref-input",
24600
25309
  autoFocus: true,
24601
25310
  onKeyDown: (e3) => {
24602
25311
  if (e3.key === "Enter") {
@@ -24611,7 +25320,7 @@ var UploadField = ({
24611
25320
  {
24612
25321
  type: "button",
24613
25322
  onClick: handleAddRef,
24614
- style: { padding: "0 10px", background: "#18181b", color: "#fff", fontSize: "11px", fontWeight: 500, borderRadius: "6px", border: "none", cursor: "pointer" },
25323
+ className: "tecof-upload-ref-add",
24615
25324
  children: "Ekle"
24616
25325
  }
24617
25326
  )
@@ -25500,7 +26209,7 @@ var LinkField = ({
25500
26209
  /* @__PURE__ */ jsx("p", { className: "tecof-link-value-url", children: activeValue.url })
25501
26210
  ] }),
25502
26211
  /* @__PURE__ */ jsx("span", { className: `tecof-link-value-badge ${activeValue.type === "page" ? "tecof-link-badge-page" : "tecof-link-badge-custom"}`, children: activeValue.type === "page" ? "Sayfa" : "Link" }),
25503
- activeValue.target === "_blank" && /* @__PURE__ */ jsx(ExternalLink, { size: 14, color: "#a1a1aa" }),
26212
+ activeValue.target === "_blank" && /* @__PURE__ */ jsx(ExternalLink, { size: 14, className: "tecof-icon-muted" }),
25504
26213
  !readOnly && /* @__PURE__ */ jsxs(Fragment, { children: [
25505
26214
  /* @__PURE__ */ jsx("button", { type: "button", className: "tecof-link-action-btn-small", onClick: handleEditManual, title: "D\xFCzenle", children: /* @__PURE__ */ jsx(Pencil, { size: 14 }) }),
25506
26215
  /* @__PURE__ */ jsx("button", { type: "button", className: "tecof-link-action-btn-small", onClick: handleClear, title: "Kald\u0131r", children: /* @__PURE__ */ jsx(X, { size: 14 }) })
@@ -25573,7 +26282,7 @@ var LinkField = ({
25573
26282
  /* @__PURE__ */ jsx("button", { className: "tecof-link-drawer-close-btn", onClick: () => setDrawerOpen(false), children: /* @__PURE__ */ jsx(X, { size: 16 }) })
25574
26283
  ] }),
25575
26284
  /* @__PURE__ */ jsxs("div", { className: "tecof-link-search-box", children: [
25576
- /* @__PURE__ */ jsx(Search, { size: 16, color: "#a1a1aa" }),
26285
+ /* @__PURE__ */ jsx(Search, { size: 16, className: "tecof-icon-muted" }),
25577
26286
  /* @__PURE__ */ jsx(
25578
26287
  "input",
25579
26288
  {
@@ -25585,7 +26294,13 @@ var LinkField = ({
25585
26294
  }
25586
26295
  )
25587
26296
  ] }),
25588
- loading ? /* @__PURE__ */ jsx("div", { className: "tecof-text-center tecof-p-40 tecof-text-muted", children: "Y\xFCkleniyor..." }) : filteredPages.length === 0 ? /* @__PURE__ */ jsx("div", { className: "tecof-text-center tecof-p-40 tecof-text-muted", children: search ? "Sonu\xE7 bulunamad\u0131" : "Hen\xFCz sayfa yok" }) : /* @__PURE__ */ jsx("div", { className: "tecof-link-page-list", children: filteredPages.map((page) => {
26297
+ loading ? /* @__PURE__ */ jsx("div", { className: "tecof-field-loading", "aria-busy": "true", children: [0, 1, 2].map((item2) => /* @__PURE__ */ jsxs("div", { className: "tecof-field-loading-row", children: [
26298
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-circle tecof-field-loading-thumb" }),
26299
+ /* @__PURE__ */ jsxs("div", { className: "tecof-field-loading-lines", children: [
26300
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-text w-60" }),
26301
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-text sm w-80" })
26302
+ ] })
26303
+ ] }, item2)) }) : filteredPages.length === 0 ? /* @__PURE__ */ jsx("div", { className: "tecof-text-center tecof-p-40 tecof-text-muted", children: search ? "Sonu\xE7 bulunamad\u0131" : "Hen\xFCz sayfa yok" }) : /* @__PURE__ */ jsx("div", { className: "tecof-link-page-list", children: filteredPages.map((page) => {
25589
26304
  const selected = activeValue?.url === `/${page.slug}`;
25590
26305
  return /* @__PURE__ */ jsxs(
25591
26306
  "div",
@@ -25601,7 +26316,7 @@ var LinkField = ({
25601
26316
  ] }),
25602
26317
  page.title && /* @__PURE__ */ jsx("p", { className: "tecof-link-page-title", children: page.title })
25603
26318
  ] }),
25604
- /* @__PURE__ */ jsx(ChevronRight, { size: 16, color: "#d4d4d8" })
26319
+ /* @__PURE__ */ jsx(ChevronRight, { size: 16, className: "tecof-icon-faint" })
25605
26320
  ]
25606
26321
  },
25607
26322
  page._id
@@ -25752,7 +26467,7 @@ var ColorField = ({
25752
26467
  "div",
25753
26468
  {
25754
26469
  className: `tecof-color-swatch ${focused ? "focused" : ""}`,
25755
- style: { background: isValid && currentColor ? currentColor : "#ffffff" },
26470
+ style: { background: isValid && currentColor ? currentColor : "var(--tecof-surface)" },
25756
26471
  children: !readOnly && /* @__PURE__ */ jsx(
25757
26472
  "input",
25758
26473
  {
@@ -26235,9 +26950,9 @@ var CmsCollectionField = ({
26235
26950
  );
26236
26951
  }, [collections, searchQuery]);
26237
26952
  if (loading) {
26238
- return /* @__PURE__ */ jsxs("div", { className: "tecof-cms-col-loading", children: [
26239
- /* @__PURE__ */ jsx(LoaderCircle, { size: 16, className: "tecof-spin" }),
26240
- /* @__PURE__ */ jsx("span", { children: "Koleksiyonlar y\xFCkleniyor\u2026" })
26953
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-cms-col-loading tecof-field-loading-compact", "aria-busy": "true", children: [
26954
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-circle" }),
26955
+ /* @__PURE__ */ jsx("span", { className: "tecof-skeleton tecof-skeleton-text w-60" })
26241
26956
  ] });
26242
26957
  }
26243
26958
  if (error2) {
@@ -26443,9 +27158,9 @@ var createCmsCollectionField = (options = {}) => {
26443
27158
  function hexToHsl(hex) {
26444
27159
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
26445
27160
  if (!result) return { h: 0, s: 0, l: 0 };
26446
- let r2 = parseInt(result[1], 16) / 255;
26447
- let g = parseInt(result[2], 16) / 255;
26448
- let b = parseInt(result[3], 16) / 255;
27161
+ const r2 = parseInt(result[1], 16) / 255;
27162
+ const g = parseInt(result[2], 16) / 255;
27163
+ const b = parseInt(result[3], 16) / 255;
26449
27164
  const max = Math.max(r2, g, b);
26450
27165
  const min = Math.min(r2, g, b);
26451
27166
  let h2 = 0;
@@ -26610,20 +27325,29 @@ lucide-react/dist/esm/icons/file-text.js:
26610
27325
  lucide-react/dist/esm/icons/file.js:
26611
27326
  lucide-react/dist/esm/icons/folder-open.js:
26612
27327
  lucide-react/dist/esm/icons/globe.js:
27328
+ lucide-react/dist/esm/icons/grid-3x3.js:
26613
27329
  lucide-react/dist/esm/icons/grip-vertical.js:
26614
27330
  lucide-react/dist/esm/icons/image-plus.js:
26615
27331
  lucide-react/dist/esm/icons/image.js:
26616
27332
  lucide-react/dist/esm/icons/languages.js:
27333
+ lucide-react/dist/esm/icons/layers.js:
26617
27334
  lucide-react/dist/esm/icons/link-2.js:
26618
27335
  lucide-react/dist/esm/icons/link.js:
26619
27336
  lucide-react/dist/esm/icons/loader-circle.js:
27337
+ lucide-react/dist/esm/icons/monitor.js:
27338
+ lucide-react/dist/esm/icons/panels-top-left.js:
26620
27339
  lucide-react/dist/esm/icons/pencil.js:
26621
27340
  lucide-react/dist/esm/icons/plus.js:
27341
+ lucide-react/dist/esm/icons/redo-2.js:
26622
27342
  lucide-react/dist/esm/icons/refresh-ccw.js:
26623
27343
  lucide-react/dist/esm/icons/refresh-cw.js:
26624
27344
  lucide-react/dist/esm/icons/rotate-ccw.js:
27345
+ lucide-react/dist/esm/icons/save.js:
26625
27346
  lucide-react/dist/esm/icons/search.js:
27347
+ lucide-react/dist/esm/icons/smartphone.js:
27348
+ lucide-react/dist/esm/icons/tablet.js:
26626
27349
  lucide-react/dist/esm/icons/trash-2.js:
27350
+ lucide-react/dist/esm/icons/undo-2.js:
26627
27351
  lucide-react/dist/esm/icons/upload.js:
26628
27352
  lucide-react/dist/esm/icons/x.js:
26629
27353
  lucide-react/dist/esm/lucide-react.js: