@tecof/theme-editor 0.0.39 → 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(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(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(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,30 +632,298 @@ var useStudio = () => {
548
632
  }
549
633
  return ctx;
550
634
  };
635
+ var Frame = ({
636
+ children,
637
+ title = "Canvas Frame",
638
+ className,
639
+ style: _style,
640
+ ...props
641
+ }) => {
642
+ const [contentRef, setContentRef] = useState(null);
643
+ const mountNode = contentRef?.contentWindow?.document?.body;
644
+ useEffect(() => {
645
+ if (!contentRef) return;
646
+ const doc = contentRef.contentDocument;
647
+ if (!doc) return;
648
+ const copyStyles = () => {
649
+ doc.head.innerHTML = "";
650
+ Array.from(document.styleSheets).forEach((styleSheet) => {
651
+ try {
652
+ if (styleSheet.href) {
653
+ const link = doc.createElement("link");
654
+ link.rel = "stylesheet";
655
+ link.href = styleSheet.href;
656
+ doc.head.appendChild(link);
657
+ } else {
658
+ const cssRules = Array.from(styleSheet.cssRules).map((rule) => rule.cssText).join("\n");
659
+ const style2 = doc.createElement("style");
660
+ style2.textContent = cssRules;
661
+ doc.head.appendChild(style2);
662
+ }
663
+ } catch (e3) {
664
+ }
665
+ });
666
+ const style = doc.createElement("style");
667
+ style.textContent = `
668
+ html, body {
669
+ margin: 0;
670
+ padding: 0;
671
+ background-color: transparent;
672
+ min-height: 100vh;
673
+ }
674
+ body {
675
+ padding: 32px 16px;
676
+ box-sizing: border-box;
677
+ }
678
+ .tecof-node-wrapper {
679
+ position: relative;
680
+ transition: outline 0.15s ease-in-out;
681
+ }
682
+ /* Custom scrollbars for iframe */
683
+ ::-webkit-scrollbar {
684
+ width: 8px;
685
+ height: 8px;
686
+ }
687
+ ::-webkit-scrollbar-track {
688
+ background: transparent;
689
+ }
690
+ ::-webkit-scrollbar-thumb {
691
+ background: var(--tecof-scrollbar-thumb);
692
+ border-radius: var(--tecof-radius-xs);
693
+ }
694
+ ::-webkit-scrollbar-thumb:hover {
695
+ background: var(--tecof-scrollbar-thumb-hover);
696
+ }
697
+ `;
698
+ doc.head.appendChild(style);
699
+ };
700
+ copyStyles();
701
+ const observer = new MutationObserver(() => {
702
+ copyStyles();
703
+ });
704
+ observer.observe(document.head, { childList: true, subtree: true });
705
+ if (doc.body) {
706
+ doc.body.className = "tecof-canvas-body";
707
+ const handleBodyClick = (e3) => {
708
+ const target = e3.target;
709
+ if (!target.closest(".tecof-node-wrapper")) {
710
+ useEditorStore.getState().selectNode(null);
711
+ const isEmbedded = typeof window !== "undefined" && window.parent !== window;
712
+ if (isEmbedded) {
713
+ window.parent.postMessage({ type: "puck:itemDeselected" }, "*");
714
+ }
715
+ }
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
+ };
729
+ doc.body.addEventListener("click", handleBodyClick);
730
+ doc.addEventListener("keydown", handleIframeKeyDown);
731
+ return () => {
732
+ observer.disconnect();
733
+ doc.body.removeEventListener("click", handleBodyClick);
734
+ doc.removeEventListener("keydown", handleIframeKeyDown);
735
+ };
736
+ }
737
+ }, [contentRef]);
738
+ return /* @__PURE__ */ jsx(
739
+ "iframe",
740
+ {
741
+ title,
742
+ ref: setContentRef,
743
+ className: ["tecof-canvas-frame", className].filter(Boolean).join(" "),
744
+ ...props,
745
+ children: mountNode && createPortal(children, mountNode)
746
+ }
747
+ );
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
+ }
551
841
  var ParentNodeContext = createContext(null);
552
842
  var DropZone = ({ zone, className, style }) => {
553
843
  const parentId = useContext(ParentNodeContext);
554
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);
555
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(" ");
556
883
  return /* @__PURE__ */ jsx(
557
884
  "div",
558
885
  {
559
- className: `tecof-dropzone ${className || ""}`,
560
- style: { minHeight: items.length === 0 ? "40px" : void 0, ...style },
886
+ className: dropzoneClassName,
887
+ onDragOver: handleDragOver,
888
+ onDragLeave: handleDragLeave,
889
+ onDrop: handleDrop,
890
+ style,
561
891
  "data-tecof-zone": zoneKey,
562
- children: items.map((item2, index2) => /* @__PURE__ */ jsx(NodeRenderer, { node: item2, index: index2, zoneKey }, item2.props.id))
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))
563
893
  }
564
894
  );
565
895
  };
566
896
  var renderDropZone = ({ zone, className, style }) => {
567
897
  return /* @__PURE__ */ jsx(DropZone, { zone, className, style });
568
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
+ }
569
917
  var NodeRenderer = ({ node, index: index2, zoneKey }) => {
570
918
  const { config: config3, metadata, readOnly } = useStudio();
571
919
  const componentConfig = config3.components[node.type];
572
920
  const selectNode = useEditorStore((state3) => state3.selectNode);
573
921
  const hoverNode = useEditorStore((state3) => state3.hoverNode);
574
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());
575
927
  const handleMouseEnter = useCallback(
576
928
  (e3) => {
577
929
  if (readOnly) return;
@@ -621,40 +973,139 @@ var NodeRenderer = ({ node, index: index2, zoneKey }) => {
621
973
  const text2 = target.textContent?.trim() || "";
622
974
  if (!text2) return;
623
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";
624
980
  for (const [key, value] of Object.entries(node.props)) {
625
981
  if (typeof value === "string" && value.trim() === text2) {
626
982
  matchingPropName = key;
627
983
  break;
628
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
+ }
629
996
  }
630
997
  if (!matchingPropName) return;
631
998
  e3.stopPropagation();
999
+ const originalText = target.textContent || "";
632
1000
  target.contentEditable = "true";
1001
+ target.setAttribute("data-tecof-inline-editing", "true");
633
1002
  target.focus();
634
- const range = document.createRange();
1003
+ const range = ownerDoc.createRange();
635
1004
  range.selectNodeContents(target);
636
- const sel = window.getSelection();
1005
+ const sel = ownerWin?.getSelection();
637
1006
  sel?.removeAllRanges();
638
1007
  sel?.addRange(range);
639
1008
  const propName = matchingPropName;
640
- const handleBlur = () => {
1009
+ const finalIsMultilingual = isMultilingual;
1010
+ const finalLangCode = matchedLangCode;
1011
+ const commitInlineEdit = () => {
641
1012
  target.contentEditable = "false";
1013
+ target.removeAttribute("data-tecof-inline-editing");
642
1014
  target.removeEventListener("blur", handleBlur);
1015
+ target.removeEventListener("keydown", handleKeyDown);
643
1016
  const newText = target.textContent?.trim() || "";
644
- useEditorStore.getState().updateProps(node.props.id, {
645
- [propName]: newText
646
- });
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
+ }
647
1057
  };
648
1058
  target.addEventListener("blur", handleBlur);
1059
+ target.addEventListener("keydown", handleKeyDown);
649
1060
  },
650
1061
  [node.props, node.props.id, readOnly]
651
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]);
652
1097
  if (!componentConfig) {
653
- return /* @__PURE__ */ jsxs("div", { style: { padding: "12px", background: "#fee2e2", color: "#991b1b", fontSize: "12px", borderRadius: "4px" }, children: [
1098
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-node-missing", children: [
654
1099
  "Bile\u015Fen bulunamad\u0131: ",
655
1100
  node.type
656
1101
  ] });
657
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(" ");
658
1109
  const componentProps = {
659
1110
  ...node.props,
660
1111
  puck: {
@@ -667,180 +1118,118 @@ var NodeRenderer = ({ node, index: index2, zoneKey }) => {
667
1118
  },
668
1119
  editMode: !readOnly
669
1120
  };
670
- return /* @__PURE__ */ jsx(ParentNodeContext.Provider, { value: node.props.id, children: /* @__PURE__ */ jsx(
671
- "div",
672
- {
673
- className: "tecof-node-wrapper",
674
- "data-tecof-id": node.props.id,
675
- "data-tecof-type": node.type,
676
- "data-tecof-index": index2,
677
- "data-tecof-zone": zoneKey || "root",
678
- onMouseEnter: handleMouseEnter,
679
- onMouseLeave: handleMouseLeave,
680
- onClick: handleClick,
681
- onDoubleClick: handleDoubleClick,
682
- style: {
683
- cursor: readOnly ? void 0 : "pointer"
684
- },
685
- children: componentConfig.render(componentProps)
686
- }
687
- ) });
688
- };
689
- var Frame = ({ children, title = "Canvas Frame", ...props }) => {
690
- const [contentRef, setContentRef] = useState(null);
691
- const mountNode = contentRef?.contentWindow?.document?.body;
692
- useEffect(() => {
693
- if (!contentRef) return;
694
- const doc = contentRef.contentDocument;
695
- if (!doc) return;
696
- const copyStyles = () => {
697
- doc.head.innerHTML = "";
698
- Array.from(document.styleSheets).forEach((styleSheet) => {
699
- try {
700
- if (styleSheet.href) {
701
- const link = doc.createElement("link");
702
- link.rel = "stylesheet";
703
- link.href = styleSheet.href;
704
- doc.head.appendChild(link);
705
- } else {
706
- const cssRules = Array.from(styleSheet.cssRules).map((rule) => rule.cssText).join("\n");
707
- const style2 = doc.createElement("style");
708
- style2.textContent = cssRules;
709
- doc.head.appendChild(style2);
710
- }
711
- } catch (e3) {
712
- }
713
- });
714
- const style = doc.createElement("style");
715
- style.textContent = `
716
- html, body {
717
- margin: 0;
718
- padding: 0;
719
- background-color: transparent;
720
- min-height: 100vh;
721
- }
722
- body {
723
- padding: 32px 16px;
724
- box-sizing: border-box;
725
- }
726
- .tecof-node-wrapper {
727
- position: relative;
728
- transition: outline 0.15s ease-in-out;
729
- }
730
- /* Custom scrollbars for iframe */
731
- ::-webkit-scrollbar {
732
- width: 8px;
733
- height: 8px;
734
- }
735
- ::-webkit-scrollbar-track {
736
- background: transparent;
737
- }
738
- ::-webkit-scrollbar-thumb {
739
- background: rgba(0, 0, 0, 0.15);
740
- border-radius: 4px;
741
- }
742
- ::-webkit-scrollbar-thumb:hover {
743
- background: rgba(0, 0, 0, 0.25);
744
- }
745
- `;
746
- doc.head.appendChild(style);
747
- };
748
- copyStyles();
749
- const observer = new MutationObserver(() => {
750
- copyStyles();
751
- });
752
- observer.observe(document.head, { childList: true, subtree: true });
753
- if (doc.body) {
754
- doc.body.className = "tecof-canvas-body";
755
- const handleBodyClick = (e3) => {
756
- const target = e3.target;
757
- if (!target.closest(".tecof-node-wrapper")) {
758
- useEditorStore.getState().selectNode(null);
759
- const isEmbedded = typeof window !== "undefined" && window.parent !== window;
760
- if (isEmbedded) {
761
- window.parent.postMessage({ type: "puck:itemDeselected" }, "*");
762
- }
763
- }
764
- };
765
- const handleIframeKeyDown = (e3) => {
766
- const event = new KeyboardEvent("keydown", {
767
- key: e3.key,
768
- code: e3.code,
769
- ctrlKey: e3.ctrlKey,
770
- metaKey: e3.metaKey,
771
- shiftKey: e3.shiftKey,
772
- altKey: e3.altKey,
773
- bubbles: true
774
- });
775
- window.dispatchEvent(event);
776
- };
777
- doc.body.addEventListener("click", handleBodyClick);
778
- doc.addEventListener("keydown", handleIframeKeyDown);
779
- return () => {
780
- observer.disconnect();
781
- doc.body.removeEventListener("click", handleBodyClick);
782
- doc.removeEventListener("keydown", handleIframeKeyDown);
783
- };
784
- }
785
- }, [contentRef]);
786
- return /* @__PURE__ */ jsx(
787
- "iframe",
788
- {
789
- title,
790
- ref: setContentRef,
791
- style: {
792
- width: "100%",
793
- height: "100%",
794
- border: "none",
795
- background: "#ffffff",
796
- ...props.style
797
- },
798
- ...props,
799
- children: mountNode && createPortal(children, mountNode)
800
- }
801
- );
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
+ ] }) });
802
1154
  };
803
1155
  var Canvas = () => {
804
1156
  const content = useEditorStore((state3) => state3.document.content);
805
1157
  const viewport = useEditorStore((state3) => state3.viewport);
806
- const getWidth2 = () => {
807
- switch (viewport) {
808
- case "tablet":
809
- return "768px";
810
- case "mobile":
811
- return "375px";
812
- case "desktop":
813
- default:
814
- return "100%";
815
- }
816
- };
817
- return /* @__PURE__ */ jsx("div", { className: "tecof-canvas-container", style: {
818
- flex: 1,
819
- display: "flex",
820
- alignItems: "center",
821
- justifyContent: "center",
822
- background: "#f4f4f5",
823
- padding: "24px",
824
- overflow: "auto",
825
- height: "100%",
826
- boxSizing: "border-box"
827
- }, 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(
828
1209
  "div",
829
1210
  {
830
- className: "tecof-canvas-viewport-wrapper",
831
- style: {
832
- width: getWidth2(),
833
- height: "100%",
834
- maxWidth: "100%",
835
- transition: "width 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
836
- boxShadow: "0 10px 25px -5px rgba(0, 0, 0, 0.05), 0 8px 10px -6px rgba(0, 0, 0, 0.05)",
837
- borderRadius: viewport === "desktop" ? "0" : "12px",
838
- overflow: "hidden",
839
- backgroundColor: "#ffffff"
840
- },
841
- 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
+ ] })
842
1224
  }
843
- ) });
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 }) }) });
844
1233
  };
845
1234
 
846
1235
  // node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
@@ -1276,6 +1665,12 @@ var __iconNode39 = [
1276
1665
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
1277
1666
  ];
1278
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
+ });
1279
1674
  var useOverlayCoords = (id, iframeEl, containerEl, documentState) => {
1280
1675
  const [coords, setCoords] = useState(null);
1281
1676
  useEffect(() => {
@@ -1337,7 +1732,7 @@ var SelectionOverlay = () => {
1337
1732
  const [iframeEl, setIframeEl] = useState(null);
1338
1733
  const containerRef = useRef(null);
1339
1734
  useEffect(() => {
1340
- const iframe = document.querySelector(".tecof-canvas-viewport-wrapper iframe");
1735
+ const iframe = document.querySelector(".tecof-canvas-viewport iframe");
1341
1736
  setIframeEl(iframe);
1342
1737
  }, [documentState]);
1343
1738
  const selectedCoords = useOverlayCoords(selectedId, iframeEl, containerRef.current, documentState);
@@ -1366,220 +1761,95 @@ var SelectionOverlay = () => {
1366
1761
  "div",
1367
1762
  {
1368
1763
  ref: containerRef,
1369
- className: "tecof-selection-overlay-container",
1370
- style: {
1371
- position: "absolute",
1372
- top: 0,
1373
- left: 0,
1374
- right: 0,
1375
- bottom: 0,
1376
- pointerEvents: "none",
1377
- zIndex: 1e3
1378
- },
1764
+ className: "tecof-overlay",
1379
1765
  children: [
1380
1766
  hoveredCoords && /* @__PURE__ */ jsx(
1381
1767
  "div",
1382
1768
  {
1383
- className: "tecof-hover-outline",
1384
- style: {
1385
- position: "absolute",
1386
- top: hoveredCoords.top,
1387
- left: hoveredCoords.left,
1388
- width: hoveredCoords.width,
1389
- height: hoveredCoords.height,
1390
- border: "1.5px dashed #3b82f6",
1391
- borderRadius: "4px",
1392
- boxSizing: "border-box",
1393
- pointerEvents: "none",
1394
- transition: "all 0.1s ease-out"
1395
- }
1769
+ className: "tecof-outline is-hover",
1770
+ style: getOutlineStyle(hoveredCoords)
1396
1771
  }
1397
1772
  ),
1398
1773
  selectedCoords && /* @__PURE__ */ jsxs(
1399
1774
  "div",
1400
1775
  {
1401
- className: "tecof-selected-outline",
1402
- style: {
1403
- position: "absolute",
1404
- top: selectedCoords.top,
1405
- left: selectedCoords.left,
1406
- width: selectedCoords.width,
1407
- height: selectedCoords.height,
1408
- border: "2px solid #3b82f6",
1409
- borderRadius: "4px",
1410
- boxSizing: "border-box",
1411
- pointerEvents: "none",
1412
- transition: "all 0.1s ease-out"
1413
- },
1776
+ className: "tecof-outline is-selected",
1777
+ style: getOutlineStyle(selectedCoords),
1414
1778
  children: [
1415
- /* @__PURE__ */ jsxs(
1416
- "div",
1417
- {
1418
- className: "tecof-floating-toolbar",
1419
- style: {
1420
- position: "absolute",
1421
- top: "-36px",
1422
- right: "-2px",
1423
- display: "flex",
1424
- alignItems: "center",
1425
- gap: "4px",
1426
- background: "#3b82f6",
1427
- borderRadius: "6px",
1428
- padding: "4px",
1429
- pointerEvents: "auto",
1430
- boxShadow: "0 4px 6px -1px rgba(59, 130, 246, 0.2)"
1431
- },
1432
- children: [
1433
- parentId && /* @__PURE__ */ jsx(
1434
- "button",
1435
- {
1436
- onClick: () => selectNode(parentId),
1437
- title: "\xDCst \xD6\u011Feyi Se\xE7",
1438
- style: {
1439
- background: "transparent",
1440
- border: "none",
1441
- color: "#ffffff",
1442
- cursor: "pointer",
1443
- padding: "4px",
1444
- borderRadius: "4px",
1445
- display: "flex"
1446
- },
1447
- children: /* @__PURE__ */ jsx(ChevronUp, { size: 14 })
1448
- }
1449
- ),
1450
- /* @__PURE__ */ jsx(
1451
- "button",
1452
- {
1453
- onClick: () => handleMove("up"),
1454
- disabled: !canMoveUp,
1455
- title: "Yukar\u0131 Ta\u015F\u0131",
1456
- style: {
1457
- background: "transparent",
1458
- border: "none",
1459
- color: "#ffffff",
1460
- opacity: canMoveUp ? 1 : 0.5,
1461
- cursor: canMoveUp ? "pointer" : "not-allowed",
1462
- padding: "4px",
1463
- borderRadius: "4px",
1464
- display: "flex"
1465
- },
1466
- children: /* @__PURE__ */ jsx(ArrowUp, { size: 14 })
1467
- }
1468
- ),
1469
- /* @__PURE__ */ jsx(
1470
- "button",
1471
- {
1472
- onClick: () => handleMove("down"),
1473
- disabled: !canMoveDown,
1474
- title: "A\u015Fa\u011F\u0131 Ta\u015F\u0131",
1475
- style: {
1476
- background: "transparent",
1477
- border: "none",
1478
- color: "#ffffff",
1479
- opacity: canMoveDown ? 1 : 0.5,
1480
- cursor: canMoveDown ? "pointer" : "not-allowed",
1481
- padding: "4px",
1482
- borderRadius: "4px",
1483
- display: "flex"
1484
- },
1485
- children: /* @__PURE__ */ jsx(ArrowDown, { size: 14 })
1486
- }
1487
- ),
1488
- /* @__PURE__ */ jsx("div", { style: { width: "1px", height: "14px", background: "rgba(255,255,255,0.3)", margin: "0 2px" } }),
1489
- /* @__PURE__ */ jsx(
1490
- "button",
1491
- {
1492
- onClick: () => duplicateNode2(selectedId),
1493
- title: "Kopyala",
1494
- style: {
1495
- background: "transparent",
1496
- border: "none",
1497
- color: "#ffffff",
1498
- cursor: "pointer",
1499
- padding: "4px",
1500
- borderRadius: "4px",
1501
- display: "flex"
1502
- },
1503
- children: /* @__PURE__ */ jsx(Copy, { size: 14 })
1504
- }
1505
- ),
1506
- /* @__PURE__ */ jsx(
1507
- "button",
1508
- {
1509
- onClick: () => removeNode2(selectedId),
1510
- title: "Sil",
1511
- style: {
1512
- background: "transparent",
1513
- border: "none",
1514
- color: "#ffffff",
1515
- cursor: "pointer",
1516
- padding: "4px",
1517
- borderRadius: "4px",
1518
- display: "flex"
1519
- },
1520
- children: /* @__PURE__ */ jsx(Trash2, { size: 14 })
1521
- }
1522
- )
1523
- ]
1524
- }
1525
- ),
1526
- nodeDetails && /* @__PURE__ */ jsx(
1527
- "div",
1528
- {
1529
- className: "tecof-outline-label",
1530
- style: {
1531
- position: "absolute",
1532
- top: "-26px",
1533
- left: "-2px",
1534
- background: "#3b82f6",
1535
- color: "#ffffff",
1536
- fontSize: "11px",
1537
- fontWeight: 600,
1538
- padding: "2px 8px",
1539
- borderRadius: "4px 4px 0 0",
1540
- userSelect: "none"
1541
- },
1542
- children: nodeDetails.node.type
1543
- }
1544
- ),
1545
- breadcrumbs.length > 1 && /* @__PURE__ */ jsx(
1546
- "div",
1547
- {
1548
- className: "tecof-selected-breadcrumbs",
1549
- style: {
1550
- position: "absolute",
1551
- bottom: "-28px",
1552
- left: "-2px",
1553
- display: "flex",
1554
- alignItems: "center",
1555
- gap: "4px",
1556
- background: "#18181b",
1557
- color: "#a1a1aa",
1558
- fontSize: "10px",
1559
- padding: "4px 8px",
1560
- borderRadius: "0 0 6px 6px",
1561
- pointerEvents: "auto",
1562
- boxShadow: "0 2px 4px rgba(0,0,0,0.05)"
1563
- },
1564
- children: breadcrumbs.map((crumb, idx) => /* @__PURE__ */ jsxs(React__default__default.Fragment, { children: [
1565
- idx > 0 && /* @__PURE__ */ jsx("span", { style: { color: "#52525b" }, children: ">" }),
1566
- /* @__PURE__ */ jsx(
1567
- "span",
1568
- {
1569
- onClick: () => selectNode(crumb.id),
1570
- style: {
1571
- cursor: "pointer",
1572
- color: crumb.id === selectedId ? "#ffffff" : void 0,
1573
- fontWeight: crumb.id === selectedId ? 600 : void 0
1574
- },
1575
- onMouseEnter: () => useEditorStore.getState().hoverNode(crumb.id),
1576
- onMouseLeave: () => useEditorStore.getState().hoverNode(null),
1577
- children: crumb.type
1578
- }
1579
- )
1580
- ] }, crumb.id))
1581
- }
1582
- )
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)) })
1583
1853
  ]
1584
1854
  }
1585
1855
  )
@@ -1595,55 +1865,14 @@ var FieldLabel = ({
1595
1865
  el = "label"
1596
1866
  }) => {
1597
1867
  const Component2 = el;
1598
- return /* @__PURE__ */ jsxs(
1599
- Component2,
1600
- {
1601
- className: "tecof-field-label-container",
1602
- style: {
1603
- display: "flex",
1604
- flexDirection: "column",
1605
- gap: "6px",
1606
- marginBottom: "16px",
1607
- width: "100%",
1608
- boxSizing: "border-box",
1609
- userSelect: "none"
1610
- },
1611
- children: [
1612
- /* @__PURE__ */ jsxs(
1613
- "div",
1614
- {
1615
- className: "tecof-field-label-header",
1616
- style: {
1617
- display: "flex",
1618
- alignItems: "center",
1619
- gap: "6px",
1620
- fontSize: "12px",
1621
- fontWeight: 600,
1622
- color: "#27272a"
1623
- // zinc-800
1624
- },
1625
- children: [
1626
- icon && /* @__PURE__ */ jsx("span", { style: { display: "inline-flex" }, children: icon }),
1627
- /* @__PURE__ */ jsx("span", { children: label }),
1628
- readOnly && /* @__PURE__ */ jsx(
1629
- "span",
1630
- {
1631
- style: {
1632
- fontSize: "10px",
1633
- color: "#a1a1aa",
1634
- fontWeight: 400,
1635
- marginLeft: "auto"
1636
- },
1637
- children: "Salt Okunur"
1638
- }
1639
- )
1640
- ]
1641
- }
1642
- ),
1643
- /* @__PURE__ */ jsx("div", { className: "tecof-field-label-content", style: { width: "100%" }, children })
1644
- ]
1645
- }
1646
- );
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
+ ] });
1647
1876
  };
1648
1877
  var FieldRenderer = ({
1649
1878
  name: name3,
@@ -1656,7 +1885,7 @@ var FieldRenderer = ({
1656
1885
  const label = definition.label || name3;
1657
1886
  const type = definition.type;
1658
1887
  if (definition.render) {
1659
- 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({
1660
1889
  field: definition,
1661
1890
  name: name3,
1662
1891
  id: `field-${name3}`,
@@ -1675,18 +1904,6 @@ var FieldRenderer = ({
1675
1904
  value: value || "",
1676
1905
  disabled: readOnly,
1677
1906
  onChange: (e3) => onChange(e3.target.value),
1678
- style: {
1679
- width: "100%",
1680
- padding: "10px 12px",
1681
- borderRadius: "8px",
1682
- border: "1px solid #e4e4e7",
1683
- fontSize: "13px",
1684
- color: "#18181b",
1685
- backgroundColor: readOnly ? "#f4f4f5" : "#ffffff",
1686
- outline: "none",
1687
- boxSizing: "border-box",
1688
- transition: "border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out"
1689
- },
1690
1907
  className: "tecof-input-text"
1691
1908
  }
1692
1909
  ) });
@@ -1699,24 +1916,11 @@ var FieldRenderer = ({
1699
1916
  value: value || "",
1700
1917
  disabled: readOnly,
1701
1918
  onChange: (e3) => onChange(e3.target.value),
1702
- style: {
1703
- width: "100%",
1704
- padding: "10px 12px",
1705
- borderRadius: "8px",
1706
- border: "1px solid #e4e4e7",
1707
- fontSize: "13px",
1708
- color: "#18181b",
1709
- backgroundColor: readOnly ? "#f4f4f5" : "#ffffff",
1710
- outline: "none",
1711
- resize: "vertical",
1712
- boxSizing: "border-box",
1713
- transition: "border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out"
1714
- },
1715
1919
  className: "tecof-input-textarea"
1716
1920
  }
1717
1921
  ) });
1718
1922
  case "select":
1719
- 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: [
1720
1924
  /* @__PURE__ */ jsx(
1721
1925
  "select",
1722
1926
  {
@@ -1724,39 +1928,11 @@ var FieldRenderer = ({
1724
1928
  value: value || "",
1725
1929
  disabled: readOnly,
1726
1930
  onChange: (e3) => onChange(e3.target.value),
1727
- style: {
1728
- width: "100%",
1729
- padding: "10px 32px 10px 12px",
1730
- borderRadius: "8px",
1731
- border: "1px solid #e4e4e7",
1732
- fontSize: "13px",
1733
- color: "#18181b",
1734
- backgroundColor: readOnly ? "#f4f4f5" : "#ffffff",
1735
- outline: "none",
1736
- appearance: "none",
1737
- boxSizing: "border-box",
1738
- cursor: readOnly ? "not-allowed" : "pointer"
1739
- },
1740
1931
  className: "tecof-input-select",
1741
1932
  children: (definition.options || []).map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label || opt.value }, opt.value))
1742
1933
  }
1743
1934
  ),
1744
- /* @__PURE__ */ jsx(
1745
- "div",
1746
- {
1747
- style: {
1748
- position: "absolute",
1749
- top: "50%",
1750
- right: "12px",
1751
- transform: "translateY(-50%)",
1752
- pointerEvents: "none",
1753
- display: "flex",
1754
- alignItems: "center",
1755
- color: "#71717a"
1756
- },
1757
- 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" }) })
1758
- }
1759
- )
1935
+ /* @__PURE__ */ jsx("div", { className: "tecof-field-select-caret", children: /* @__PURE__ */ jsx(ChevronDown, { size: 12 }) })
1760
1936
  ] }) });
1761
1937
  case "number":
1762
1938
  return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsx(
@@ -1770,32 +1946,14 @@ var FieldRenderer = ({
1770
1946
  const val = e3.target.value;
1771
1947
  onChange(val === "" ? void 0 : Number(val));
1772
1948
  },
1773
- style: {
1774
- width: "100%",
1775
- padding: "10px 12px",
1776
- borderRadius: "8px",
1777
- border: "1px solid #e4e4e7",
1778
- fontSize: "13px",
1779
- color: "#18181b",
1780
- backgroundColor: readOnly ? "#f4f4f5" : "#ffffff",
1781
- outline: "none",
1782
- boxSizing: "border-box"
1783
- },
1784
1949
  className: "tecof-input-number"
1785
1950
  }
1786
1951
  ) });
1787
1952
  case "radio":
1788
- return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: (definition.options || []).map((opt) => /* @__PURE__ */ jsxs(
1953
+ return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsx("div", { className: "tecof-field-radio-group", children: (definition.options || []).map((opt) => /* @__PURE__ */ jsxs(
1789
1954
  "label",
1790
1955
  {
1791
- style: {
1792
- display: "flex",
1793
- alignItems: "center",
1794
- gap: "8px",
1795
- fontSize: "13px",
1796
- color: "#27272a",
1797
- cursor: readOnly ? "not-allowed" : "pointer"
1798
- },
1956
+ className: `tecof-field-radio${readOnly ? " is-readonly" : ""}`,
1799
1957
  children: [
1800
1958
  /* @__PURE__ */ jsx(
1801
1959
  "input",
@@ -1805,10 +1963,7 @@ var FieldRenderer = ({
1805
1963
  value: opt.value,
1806
1964
  checked: value === opt.value,
1807
1965
  disabled: readOnly,
1808
- onChange: () => onChange(opt.value),
1809
- style: {
1810
- cursor: readOnly ? "not-allowed" : "pointer"
1811
- }
1966
+ onChange: () => onChange(opt.value)
1812
1967
  }
1813
1968
  ),
1814
1969
  /* @__PURE__ */ jsx("span", { children: opt.label || opt.value })
@@ -1868,165 +2023,103 @@ var FieldRenderer = ({
1868
2023
  newExpanded[targetIdx] = tempExpanded;
1869
2024
  setExpandedIndices(newExpanded);
1870
2025
  };
1871
- return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "8px", width: "100%" }, children: [
2026
+ return /* @__PURE__ */ jsx(FieldLabel, { label, readOnly, children: /* @__PURE__ */ jsxs("div", { className: "tecof-array", children: [
1872
2027
  items.map((item2, idx) => {
1873
2028
  const isExpanded = !!expandedIndices[idx];
1874
2029
  const itemLabel = getItemLabel(item2, idx);
1875
- return /* @__PURE__ */ jsxs(
1876
- "div",
1877
- {
1878
- style: {
1879
- border: "1px solid #e4e4e7",
1880
- borderRadius: "8px",
1881
- overflow: "hidden",
1882
- background: "#f8fafc",
1883
- display: "flex",
1884
- flexDirection: "column"
1885
- },
1886
- children: [
1887
- /* @__PURE__ */ jsxs(
1888
- "div",
1889
- {
1890
- onClick: () => toggleExpand(idx),
1891
- style: {
1892
- padding: "8px 12px",
1893
- display: "flex",
1894
- alignItems: "center",
1895
- justifyContent: "space-between",
1896
- cursor: "pointer",
1897
- background: "#ffffff",
1898
- userSelect: "none"
1899
- },
1900
- children: [
1901
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
1902
- isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { size: 14, color: "#71717a" }) : /* @__PURE__ */ jsx(ChevronRight, { size: 14, color: "#71717a" }),
1903
- /* @__PURE__ */ jsx("span", { style: { fontSize: "13px", fontWeight: 500, color: "#3f3f46" }, children: itemLabel })
1904
- ] }),
1905
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, onClick: (e3) => e3.stopPropagation(), children: [
1906
- /* @__PURE__ */ jsx(
1907
- "button",
1908
- {
1909
- onClick: () => handleMove(idx, "up"),
1910
- disabled: idx === 0,
1911
- style: {
1912
- background: "transparent",
1913
- border: "none",
1914
- cursor: idx === 0 ? "not-allowed" : "pointer",
1915
- padding: "2px",
1916
- color: idx === 0 ? "#e4e4e7" : "#71717a"
1917
- },
1918
- children: /* @__PURE__ */ jsx(ArrowUp, { size: 12 })
1919
- }
1920
- ),
1921
- /* @__PURE__ */ jsx(
1922
- "button",
1923
- {
1924
- onClick: () => handleMove(idx, "down"),
1925
- disabled: idx === items.length - 1,
1926
- style: {
1927
- background: "transparent",
1928
- border: "none",
1929
- cursor: idx === items.length - 1 ? "not-allowed" : "pointer",
1930
- padding: "2px",
1931
- color: idx === items.length - 1 ? "#e4e4e7" : "#71717a"
1932
- },
1933
- children: /* @__PURE__ */ jsx(ArrowDown, { size: 12 })
1934
- }
1935
- ),
1936
- !readOnly && /* @__PURE__ */ jsx(
1937
- "button",
1938
- {
1939
- onClick: () => handleRemove(idx),
1940
- style: {
1941
- background: "transparent",
1942
- border: "none",
1943
- cursor: "pointer",
1944
- padding: "2px",
1945
- color: "#ef4444",
1946
- marginLeft: "4px"
1947
- },
1948
- children: /* @__PURE__ */ jsx(Trash2, { size: 12 })
1949
- }
1950
- )
1951
- ] })
1952
- ]
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);
1953
2039
  }
1954
- ),
1955
- isExpanded && /* @__PURE__ */ jsx(
1956
- "div",
1957
- {
1958
- style: {
1959
- padding: "12px",
1960
- borderTop: "1px solid #e4e4e7",
1961
- display: "flex",
1962
- flexDirection: "column",
1963
- gap: "12px",
1964
- background: "#ffffff"
1965
- },
1966
- children: Object.entries(arrayFields).map(([subFieldName, subFieldDef]) => /* @__PURE__ */ jsx(
1967
- FieldRenderer,
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",
1968
2053
  {
1969
- name: subFieldName,
1970
- definition: subFieldDef,
1971
- value: item2[subFieldName],
1972
- onChange: (newSubVal) => {
1973
- const updatedItems = [...items];
1974
- updatedItems[idx] = {
1975
- ...updatedItems[idx],
1976
- [subFieldName]: newSubVal
1977
- };
1978
- onChange(updatedItems);
1979
- },
1980
- readOnly
1981
- },
1982
- subFieldName
1983
- ))
1984
- }
1985
- )
1986
- ]
1987
- },
1988
- idx
1989
- );
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);
1990
2106
  }),
1991
2107
  !readOnly && /* @__PURE__ */ jsxs(
1992
2108
  "button",
1993
2109
  {
1994
2110
  type: "button",
1995
2111
  onClick: handleAdd,
1996
- style: {
1997
- display: "flex",
1998
- alignItems: "center",
1999
- justifyContent: "center",
2000
- gap: "6px",
2001
- width: "100%",
2002
- padding: "10px",
2003
- borderRadius: "8px",
2004
- border: "1px dashed #cbd5e1",
2005
- background: "#ffffff",
2006
- color: "#64748b",
2007
- fontSize: "13px",
2008
- fontWeight: 500,
2009
- cursor: "pointer",
2010
- transition: "all 0.2s"
2011
- },
2012
2112
  className: "tecof-add-array-item-btn",
2013
2113
  children: [
2014
2114
  /* @__PURE__ */ jsx(Plus, { size: 14 }),
2015
2115
  "\xD6\u011Fe Ekle"
2016
2116
  ]
2017
2117
  }
2018
- ),
2019
- /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: `
2020
- .tecof-add-array-item-btn:hover {
2021
- border-color: #3b82f6 !important;
2022
- color: #2563eb !important;
2023
- background-color: #eff6ff !important;
2024
- }
2025
- ` } })
2118
+ )
2026
2119
  ] }) });
2027
2120
  }
2028
2121
  default:
2029
- 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: [
2030
2123
  'Desteklenmeyen alan t\xFCr\xFC: "',
2031
2124
  type,
2032
2125
  '" (',
@@ -2045,184 +2138,72 @@ var Inspector = () => {
2045
2138
  if (selectedId) {
2046
2139
  const nodeDetails = findNodeById(documentState, selectedId);
2047
2140
  if (!nodeDetails) {
2048
- 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." }) });
2049
2142
  }
2050
2143
  const { node } = nodeDetails;
2051
2144
  const componentConfig = config3.components[node.type];
2052
2145
  const fields = componentConfig?.fields || {};
2053
2146
  const label = componentConfig?.label || node.type;
2054
- return /* @__PURE__ */ jsxs(
2055
- "div",
2056
- {
2057
- className: "tecof-inspector",
2058
- style: {
2059
- width: "320px",
2060
- height: "100%",
2061
- borderLeft: "1px solid #e4e4e7",
2062
- background: "#ffffff",
2063
- display: "flex",
2064
- flexDirection: "column",
2065
- boxSizing: "border-box"
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
2066
2163
  },
2067
- children: [
2068
- /* @__PURE__ */ jsxs(
2069
- "div",
2070
- {
2071
- style: {
2072
- padding: "16px 20px",
2073
- borderBottom: "1px solid #f4f4f5",
2074
- display: "flex",
2075
- alignItems: "center",
2076
- justifyContent: "space-between"
2077
- },
2078
- children: [
2079
- /* @__PURE__ */ jsxs("div", { children: [
2080
- /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "14px", fontWeight: 700, color: "#18181b" }, children: label }),
2081
- /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: "#a1a1aa", fontFamily: "monospace" }, children: selectedId })
2082
- ] }),
2083
- /* @__PURE__ */ jsx(
2084
- "button",
2085
- {
2086
- onClick: () => selectNode(null),
2087
- style: {
2088
- background: "transparent",
2089
- border: "none",
2090
- color: "#71717a",
2091
- cursor: "pointer",
2092
- fontSize: "11px",
2093
- fontWeight: 500,
2094
- padding: "4px 8px",
2095
- borderRadius: "4px",
2096
- hover: { background: "#f4f4f5" }
2097
- },
2098
- children: "Se\xE7imi Kald\u0131r"
2099
- }
2100
- )
2101
- ]
2102
- }
2103
- ),
2104
- /* @__PURE__ */ jsx(
2105
- "div",
2106
- {
2107
- className: "tecof-inspector-fields",
2108
- style: {
2109
- flex: 1,
2110
- overflowY: "auto",
2111
- padding: "20px",
2112
- display: "flex",
2113
- flexDirection: "column",
2114
- gap: "4px"
2115
- },
2116
- 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(
2117
- FieldRenderer,
2118
- {
2119
- name: fieldName,
2120
- definition: fieldDef,
2121
- value: node.props[fieldName],
2122
- onChange: (newVal) => updateProps2(selectedId, { [fieldName]: newVal }),
2123
- readOnly
2124
- },
2125
- fieldName
2126
- ))
2127
- }
2128
- )
2129
- ]
2130
- }
2131
- );
2164
+ fieldName
2165
+ )) })
2166
+ ] });
2132
2167
  }
2133
2168
  const rootFields = config3.root?.fields || {};
2134
2169
  const hasRootFields = Object.keys(rootFields).length > 0;
2135
- return /* @__PURE__ */ jsxs(
2136
- "div",
2137
- {
2138
- className: "tecof-inspector",
2139
- style: {
2140
- width: "320px",
2141
- height: "100%",
2142
- borderLeft: "1px solid #e4e4e7",
2143
- background: "#ffffff",
2144
- display: "flex",
2145
- flexDirection: "column",
2146
- boxSizing: "border-box"
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
2147
2183
  },
2148
- children: [
2149
- /* @__PURE__ */ jsxs(
2150
- "div",
2151
- {
2152
- style: {
2153
- padding: "16px 20px",
2154
- borderBottom: "1px solid #f4f4f5"
2155
- },
2156
- children: [
2157
- /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "14px", fontWeight: 700, color: "#18181b" }, children: "Sayfa Ayarlar\u0131" }),
2158
- /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: "#a1a1aa" }, children: "Genel sayfa konfig\xFCrasyonu" })
2159
- ]
2160
- }
2161
- ),
2162
- /* @__PURE__ */ jsx(
2163
- "div",
2164
- {
2165
- className: "tecof-inspector-fields",
2166
- style: {
2167
- flex: 1,
2168
- overflowY: "auto",
2169
- padding: "20px",
2170
- display: "flex",
2171
- flexDirection: "column",
2172
- gap: "4px"
2173
- },
2174
- children: hasRootFields ? Object.entries(rootFields).map(([fieldName, fieldDef]) => /* @__PURE__ */ jsx(
2175
- FieldRenderer,
2176
- {
2177
- name: fieldName,
2178
- definition: fieldDef,
2179
- value: documentState.root.props[fieldName],
2180
- onChange: (newVal) => setRootProps2({ [fieldName]: newVal }),
2181
- readOnly
2182
- },
2183
- fieldName
2184
- )) : /* @__PURE__ */ jsxs(
2185
- "div",
2186
- {
2187
- style: {
2188
- display: "flex",
2189
- flexDirection: "column",
2190
- alignItems: "center",
2191
- justifyContent: "center",
2192
- height: "100%",
2193
- color: "#a1a1aa",
2194
- fontSize: "12px",
2195
- textAlign: "center",
2196
- padding: "20px"
2197
- },
2198
- children: [
2199
- /* @__PURE__ */ jsxs(
2200
- "svg",
2201
- {
2202
- width: "24",
2203
- height: "24",
2204
- viewBox: "0 0 24 24",
2205
- fill: "none",
2206
- stroke: "currentColor",
2207
- strokeWidth: "2",
2208
- strokeLinecap: "round",
2209
- strokeLinejoin: "round",
2210
- style: { marginBottom: "8px", opacity: 0.6 },
2211
- children: [
2212
- /* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }),
2213
- /* @__PURE__ */ jsx("path", { d: "M9 3v18" })
2214
- ]
2215
- }
2216
- ),
2217
- "Bile\u015Fen se\xE7ilmedi. D\xFCzenlemek istedi\u011Finiz bir bile\u015Fene t\u0131klay\u0131n."
2218
- ]
2219
- }
2220
- )
2221
- }
2222
- )
2223
- ]
2224
- }
2225
- );
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
+ ] });
2226
2207
  };
2227
2208
  var TopBar = ({ onSave, saving, saveStatus }) => {
2228
2209
  const viewport = useEditorStore((state3) => state3.viewport);
@@ -2231,192 +2212,67 @@ var TopBar = ({ onSave, saving, saveStatus }) => {
2231
2212
  const futureCount = useEditorStore((state3) => state3.history.future.length);
2232
2213
  const undo = useEditorStore((state3) => state3.undo);
2233
2214
  const redo = useEditorStore((state3) => state3.redo);
2234
- return /* @__PURE__ */ jsxs("div", { className: "tecof-studio-topbar", style: {
2235
- height: "56px",
2236
- borderBottom: "1px solid #e4e4e7",
2237
- background: "#ffffff",
2238
- display: "flex",
2239
- alignItems: "center",
2240
- justifyContent: "space-between",
2241
- padding: "0 20px",
2242
- boxSizing: "border-box",
2243
- zIndex: 100
2244
- }, children: [
2245
- /* @__PURE__ */ jsxs("div", { className: "tecof-studio-topbar-title", style: {
2246
- fontSize: "14px",
2247
- fontWeight: 600,
2248
- color: "#18181b",
2249
- display: "flex",
2250
- alignItems: "center",
2251
- gap: "8px"
2252
- }, children: [
2215
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-topbar", children: [
2216
+ /* @__PURE__ */ jsxs("div", { className: "tecof-topbar-title", children: [
2253
2217
  /* @__PURE__ */ jsx("span", { children: "Sayfa D\xFCzenleyici" }),
2254
- saveStatus === "success" && /* @__PURE__ */ jsxs("span", { style: {
2255
- fontSize: "11px",
2256
- color: "#10b981",
2257
- display: "inline-flex",
2258
- alignItems: "center",
2259
- gap: "4px",
2260
- fontWeight: 500
2261
- }, children: [
2218
+ saveStatus === "success" && /* @__PURE__ */ jsxs("span", { className: "tecof-topbar-saved", children: [
2262
2219
  /* @__PURE__ */ jsx(Check, { size: 12 }),
2263
2220
  " Kaydedildi"
2264
2221
  ] })
2265
2222
  ] }),
2266
- /* @__PURE__ */ jsxs("div", { className: "tecof-studio-topbar-viewports", style: {
2267
- display: "flex",
2268
- alignItems: "center",
2269
- background: "#f4f4f5",
2270
- padding: "3px",
2271
- borderRadius: "8px",
2272
- gap: "2px"
2273
- }, children: [
2223
+ /* @__PURE__ */ jsxs("div", { className: "tecof-topbar-viewports", children: [
2274
2224
  /* @__PURE__ */ jsx(
2275
2225
  "button",
2276
2226
  {
2227
+ type: "button",
2277
2228
  onClick: () => setViewport("desktop"),
2278
- style: {
2279
- background: viewport === "desktop" ? "#ffffff" : "transparent",
2280
- border: "none",
2281
- outline: "none",
2282
- cursor: "pointer",
2283
- padding: "6px 12px",
2284
- borderRadius: "6px",
2285
- color: viewport === "desktop" ? "#18181b" : "#71717a",
2286
- display: "flex",
2287
- alignItems: "center",
2288
- justifyContent: "center",
2289
- boxShadow: viewport === "desktop" ? "0 1px 3px 0 rgba(0, 0, 0, 0.1)" : "none",
2290
- transition: "all 0.2s"
2291
- },
2229
+ className: `tecof-vp-btn${viewport === "desktop" ? " is-active" : ""}`,
2292
2230
  title: "Masa\xFCst\xFC",
2231
+ "aria-label": "Masa\xFCst\xFC g\xF6r\xFCn\xFCm\xFC",
2232
+ "aria-pressed": viewport === "desktop",
2293
2233
  children: /* @__PURE__ */ jsx(Monitor, { size: 16 })
2294
2234
  }
2295
2235
  ),
2296
2236
  /* @__PURE__ */ jsx(
2297
2237
  "button",
2298
2238
  {
2239
+ type: "button",
2299
2240
  onClick: () => setViewport("tablet"),
2300
- style: {
2301
- background: viewport === "tablet" ? "#ffffff" : "transparent",
2302
- border: "none",
2303
- outline: "none",
2304
- cursor: "pointer",
2305
- padding: "6px 12px",
2306
- borderRadius: "6px",
2307
- color: viewport === "tablet" ? "#18181b" : "#71717a",
2308
- display: "flex",
2309
- alignItems: "center",
2310
- justifyContent: "center",
2311
- boxShadow: viewport === "tablet" ? "0 1px 3px 0 rgba(0, 0, 0, 0.1)" : "none",
2312
- transition: "all 0.2s"
2313
- },
2241
+ className: `tecof-vp-btn${viewport === "tablet" ? " is-active" : ""}`,
2314
2242
  title: "Tablet",
2243
+ "aria-label": "Tablet g\xF6r\xFCn\xFCm\xFC",
2244
+ "aria-pressed": viewport === "tablet",
2315
2245
  children: /* @__PURE__ */ jsx(Tablet, { size: 16 })
2316
2246
  }
2317
2247
  ),
2318
2248
  /* @__PURE__ */ jsx(
2319
2249
  "button",
2320
2250
  {
2251
+ type: "button",
2321
2252
  onClick: () => setViewport("mobile"),
2322
- style: {
2323
- background: viewport === "mobile" ? "#ffffff" : "transparent",
2324
- border: "none",
2325
- outline: "none",
2326
- cursor: "pointer",
2327
- padding: "6px 12px",
2328
- borderRadius: "6px",
2329
- color: viewport === "mobile" ? "#18181b" : "#71717a",
2330
- display: "flex",
2331
- alignItems: "center",
2332
- justifyContent: "center",
2333
- boxShadow: viewport === "mobile" ? "0 1px 3px 0 rgba(0, 0, 0, 0.1)" : "none",
2334
- transition: "all 0.2s"
2335
- },
2253
+ className: `tecof-vp-btn${viewport === "mobile" ? " is-active" : ""}`,
2336
2254
  title: "Mobil",
2255
+ "aria-label": "Mobil g\xF6r\xFCn\xFCm\xFC",
2256
+ "aria-pressed": viewport === "mobile",
2337
2257
  children: /* @__PURE__ */ jsx(Smartphone, { size: 16 })
2338
2258
  }
2339
2259
  )
2340
2260
  ] }),
2341
- /* @__PURE__ */ jsxs("div", { className: "tecof-studio-topbar-actions", style: {
2342
- display: "flex",
2343
- alignItems: "center",
2344
- gap: "12px"
2345
- }, children: [
2346
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "4px" }, children: [
2347
- /* @__PURE__ */ jsx(
2348
- "button",
2349
- {
2350
- onClick: undo,
2351
- disabled: pastCount === 0,
2352
- style: {
2353
- background: "transparent",
2354
- border: "none",
2355
- cursor: pastCount === 0 ? "not-allowed" : "pointer",
2356
- padding: "8px",
2357
- borderRadius: "6px",
2358
- color: pastCount === 0 ? "#d4d4d8" : "#71717a",
2359
- display: "flex",
2360
- alignItems: "center",
2361
- justifyContent: "center",
2362
- transition: "background 0.2s"
2363
- },
2364
- title: "Geri Al",
2365
- children: /* @__PURE__ */ jsx(Undo2, { size: 16 })
2366
- }
2367
- ),
2368
- /* @__PURE__ */ jsx(
2369
- "button",
2370
- {
2371
- onClick: redo,
2372
- disabled: futureCount === 0,
2373
- style: {
2374
- background: "transparent",
2375
- border: "none",
2376
- cursor: futureCount === 0 ? "not-allowed" : "pointer",
2377
- padding: "8px",
2378
- borderRadius: "6px",
2379
- color: futureCount === 0 ? "#d4d4d8" : "#71717a",
2380
- display: "flex",
2381
- alignItems: "center",
2382
- justifyContent: "center",
2383
- transition: "background 0.2s"
2384
- },
2385
- title: "Yinele",
2386
- children: /* @__PURE__ */ jsx(Redo2, { size: 16 })
2387
- }
2388
- )
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 }) })
2389
2265
  ] }),
2390
- /* @__PURE__ */ jsx("div", { style: { width: "1px", height: "20px", background: "#e4e4e7" } }),
2391
- /* @__PURE__ */ jsxs(
2392
- "button",
2393
- {
2394
- onClick: onSave,
2395
- disabled: saving,
2396
- style: {
2397
- background: "#2563eb",
2398
- color: "#ffffff",
2399
- border: "none",
2400
- cursor: saving ? "wait" : "pointer",
2401
- padding: "8px 16px",
2402
- borderRadius: "8px",
2403
- fontSize: "13px",
2404
- fontWeight: 500,
2405
- display: "flex",
2406
- alignItems: "center",
2407
- gap: "8px",
2408
- transition: "background 0.2s",
2409
- opacity: saving ? 0.7 : 1
2410
- },
2411
- children: [
2412
- /* @__PURE__ */ jsx(Save, { size: 14 }),
2413
- saving ? "Kaydediliyor..." : "Taslak Kaydet"
2414
- ]
2415
- }
2416
- )
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
+ ] })
2417
2271
  ] })
2418
2272
  ] });
2419
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` });
2420
2276
  var TreeNode = ({ node, depth }) => {
2421
2277
  const { config: config3 } = useStudio();
2422
2278
  const documentState = useEditorStore((state3) => state3.document);
@@ -2424,7 +2280,10 @@ var TreeNode = ({ node, depth }) => {
2424
2280
  const selectNode = useEditorStore((state3) => state3.selectNode);
2425
2281
  const hoverNode = useEditorStore((state3) => state3.hoverNode);
2426
2282
  const removeNode2 = useEditorStore((state3) => state3.removeNode);
2283
+ const beginDrag = useEditorStore((state3) => state3.beginDrag);
2284
+ const endDrag = useEditorStore((state3) => state3.endDrag);
2427
2285
  const [expanded, setExpanded] = useState(true);
2286
+ const [dragOverPos, setDragOverPos] = useState(null);
2428
2287
  const isSelected = selectedId === node.props.id;
2429
2288
  const componentConfig = config3.components[node.type];
2430
2289
  const label = componentConfig?.label || node.type;
@@ -2434,103 +2293,110 @@ var TreeNode = ({ node, depth }) => {
2434
2293
  const hasChildren = childZoneKeys.some(
2435
2294
  (key) => (documentState.zones[key] || []).length > 0
2436
2295
  );
2437
- return /* @__PURE__ */ jsxs("div", { className: "tecof-layers-tree-node", style: { display: "flex", flexDirection: "column" }, children: [
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" }),
2438
2333
  /* @__PURE__ */ jsxs(
2439
2334
  "div",
2440
2335
  {
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 });
2342
+ },
2343
+ onDragEnd: endDrag,
2344
+ onDragOver: handleDragOver,
2345
+ onDragLeave: handleDragLeave,
2346
+ onDrop: handleDrop,
2441
2347
  onMouseEnter: () => hoverNode(node.props.id),
2442
2348
  onMouseLeave: () => hoverNode(null),
2443
2349
  onClick: () => selectNode(node.props.id),
2444
- style: {
2445
- display: "flex",
2446
- alignItems: "center",
2447
- justifyContent: "space-between",
2448
- padding: "6px 8px",
2449
- paddingLeft: `${depth * 12 + 8}px`,
2450
- background: isSelected ? "#eff6ff" : "transparent",
2451
- color: isSelected ? "#1d4ed8" : "#3f3f46",
2452
- cursor: "pointer",
2453
- borderRadius: "6px",
2454
- fontSize: "13px",
2455
- fontWeight: isSelected ? 500 : 400,
2456
- transition: "all 0.15s"
2457
- },
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),
2458
2357
  children: [
2459
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
2358
+ /* @__PURE__ */ jsxs("div", { className: "tecof-layer-row-main", children: [
2460
2359
  hasChildren ? /* @__PURE__ */ jsx(
2461
2360
  "button",
2462
2361
  {
2362
+ type: "button",
2463
2363
  onClick: (e3) => {
2464
2364
  e3.stopPropagation();
2465
2365
  setExpanded(!expanded);
2466
2366
  },
2467
- style: {
2468
- background: "transparent",
2469
- border: "none",
2470
- cursor: "pointer",
2471
- padding: 0,
2472
- display: "flex",
2473
- alignItems: "center",
2474
- color: "#a1a1aa"
2475
- },
2367
+ className: "tecof-layer-caret",
2368
+ "aria-label": expanded ? `${label} katman\u0131n\u0131 daralt` : `${label} katman\u0131n\u0131 geni\u015Flet`,
2369
+ "aria-expanded": expanded,
2476
2370
  children: expanded ? /* @__PURE__ */ jsx(ChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(ChevronRight, { size: 14 })
2477
2371
  }
2478
- ) : /* @__PURE__ */ jsx("div", { style: { width: "14px" } }),
2479
- /* @__PURE__ */ jsx(PanelsTopLeft, { size: 14, style: { color: isSelected ? "#3b82f6" : "#71717a" } }),
2480
- /* @__PURE__ */ jsx("span", { style: {
2481
- whiteSpace: "nowrap",
2482
- overflow: "hidden",
2483
- textOverflow: "ellipsis",
2484
- maxWidth: "120px"
2485
- }, children: label })
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 })
2486
2375
  ] }),
2487
2376
  /* @__PURE__ */ jsx(
2488
2377
  "button",
2489
2378
  {
2379
+ type: "button",
2490
2380
  onClick: (e3) => {
2491
2381
  e3.stopPropagation();
2492
2382
  removeNode2(node.props.id);
2493
2383
  },
2494
- className: "tecof-layers-delete-btn",
2495
- style: {
2496
- background: "transparent",
2497
- border: "none",
2498
- cursor: "pointer",
2499
- padding: "2px",
2500
- color: "#a1a1aa",
2501
- display: "flex",
2502
- alignItems: "center",
2503
- opacity: 0,
2504
- transition: "opacity 0.2s"
2505
- },
2384
+ className: "tecof-layer-delete",
2385
+ title: "Sil",
2386
+ "aria-label": `${label} katman\u0131n\u0131 sil`,
2506
2387
  children: /* @__PURE__ */ jsx(Trash2, { size: 12 })
2507
2388
  }
2508
2389
  )
2509
2390
  ]
2510
2391
  }
2511
2392
  ),
2512
- /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: `
2513
- .tecof-layers-tree-node:hover .tecof-layers-delete-btn {
2514
- opacity: 1 !important;
2515
- }
2516
- .tecof-layers-delete-btn:hover {
2517
- color: #ef4444 !important;
2518
- }
2519
- ` } }),
2393
+ dragOverPos === "bottom" && /* @__PURE__ */ jsx("div", { className: "tecof-drop-line sm" }),
2520
2394
  expanded && childZoneKeys.map((zoneKey) => {
2521
2395
  const zoneItems = documentState.zones[zoneKey] || [];
2522
2396
  const zoneName = zoneKey.split(":").pop() || "";
2523
2397
  if (zoneItems.length === 0) return null;
2524
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column" }, children: [
2525
- /* @__PURE__ */ jsx("div", { style: {
2526
- fontSize: "10px",
2527
- textTransform: "uppercase",
2528
- letterSpacing: "0.05em",
2529
- color: "#a1a1aa",
2530
- padding: "4px 8px",
2531
- paddingLeft: `${(depth + 1) * 12 + 14}px`,
2532
- fontWeight: 600
2533
- }, children: zoneName }),
2398
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-layer-node", children: [
2399
+ /* @__PURE__ */ jsx("div", { className: "tecof-layer-zone-label", style: getLayerZoneStyle(depth), children: zoneName }),
2534
2400
  zoneItems.map((childNode) => /* @__PURE__ */ jsx(TreeNode, { node: childNode, depth: depth + 1 }, childNode.props.id))
2535
2401
  ] }, zoneKey);
2536
2402
  })
@@ -2538,24 +2404,13 @@ var TreeNode = ({ node, depth }) => {
2538
2404
  };
2539
2405
  var LayersTree = () => {
2540
2406
  const documentState = useEditorStore((state3) => state3.document);
2541
- return /* @__PURE__ */ jsx("div", { className: "tecof-studio-layers-tree", style: {
2542
- display: "flex",
2543
- flexDirection: "column",
2544
- gap: "2px",
2545
- overflowY: "auto",
2546
- height: "100%"
2547
- }, children: documentState.content.length === 0 ? /* @__PURE__ */ jsx("div", { style: {
2548
- textAlign: "center",
2549
- color: "#a1a1aa",
2550
- fontSize: "13px",
2551
- padding: "24px 12px"
2552
- }, children: "S\xFCr\xFCklenmi\u015F katman yok" }) : documentState.content.map((node) => /* @__PURE__ */ jsx(TreeNode, { node, depth: 0 }, node.props.id)) });
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)) });
2553
2408
  };
2554
2409
  var LeftPanel = () => {
2555
2410
  const { config: config3 } = useStudio();
2556
2411
  const insertNode2 = useEditorStore((state3) => state3.insertNode);
2557
- useEditorStore((state3) => state3.selection.selectedId);
2558
- useEditorStore((state3) => state3.document);
2412
+ const beginDrag = useEditorStore((state3) => state3.beginDrag);
2413
+ const endDrag = useEditorStore((state3) => state3.endDrag);
2559
2414
  const [activeTab, setActiveTab] = useState("blocks");
2560
2415
  const [searchQuery, setSearchQuery] = useState("");
2561
2416
  const categories = config3.categories || {};
@@ -2575,53 +2430,18 @@ var LeftPanel = () => {
2575
2430
  });
2576
2431
  }
2577
2432
  const handleAddBlock = (type) => {
2578
- const compConfig = components[type] || {};
2579
- const defaultProps = compConfig.defaultProps || {};
2580
- const newNode = {
2581
- type,
2582
- props: {
2583
- id: generateId(),
2584
- ...JSON.parse(JSON.stringify(defaultProps))
2585
- }
2586
- };
2587
- insertNode2(newNode);
2588
- };
2589
- return /* @__PURE__ */ jsxs("div", { className: "tecof-studio-left-panel", style: {
2590
- width: "280px",
2591
- borderRight: "1px solid #e4e4e7",
2592
- background: "#ffffff",
2593
- display: "flex",
2594
- flexDirection: "column",
2595
- height: "100%",
2596
- boxSizing: "border-box"
2597
- }, children: [
2598
- /* @__PURE__ */ jsxs("div", { style: {
2599
- display: "flex",
2600
- borderBottom: "1px solid #e4e4e7",
2601
- padding: "8px 12px",
2602
- gap: "4px"
2603
- }, children: [
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: [
2604
2437
  /* @__PURE__ */ jsxs(
2605
2438
  "button",
2606
2439
  {
2440
+ type: "button",
2607
2441
  onClick: () => setActiveTab("blocks"),
2608
- style: {
2609
- flex: 1,
2610
- display: "flex",
2611
- alignItems: "center",
2612
- justifyContent: "center",
2613
- gap: "6px",
2614
- border: "none",
2615
- outline: "none",
2616
- padding: "8px",
2617
- borderRadius: "6px",
2618
- fontSize: "12px",
2619
- fontWeight: 600,
2620
- cursor: "pointer",
2621
- background: activeTab === "blocks" ? "#f4f4f5" : "transparent",
2622
- color: activeTab === "blocks" ? "#18181b" : "#71717a",
2623
- transition: "all 0.2s"
2624
- },
2442
+ className: `tecof-tab${activeTab === "blocks" ? " is-active" : ""}`,
2443
+ role: "tab",
2444
+ "aria-selected": activeTab === "blocks",
2625
2445
  children: [
2626
2446
  /* @__PURE__ */ jsx(Grid3x3, { size: 14 }),
2627
2447
  "Blok Ekle"
@@ -2631,24 +2451,11 @@ var LeftPanel = () => {
2631
2451
  /* @__PURE__ */ jsxs(
2632
2452
  "button",
2633
2453
  {
2454
+ type: "button",
2634
2455
  onClick: () => setActiveTab("layers"),
2635
- style: {
2636
- flex: 1,
2637
- display: "flex",
2638
- alignItems: "center",
2639
- justifyContent: "center",
2640
- gap: "6px",
2641
- border: "none",
2642
- outline: "none",
2643
- padding: "8px",
2644
- borderRadius: "6px",
2645
- fontSize: "12px",
2646
- fontWeight: 600,
2647
- cursor: "pointer",
2648
- background: activeTab === "layers" ? "#f4f4f5" : "transparent",
2649
- color: activeTab === "layers" ? "#18181b" : "#71717a",
2650
- transition: "all 0.2s"
2651
- },
2456
+ className: `tecof-tab${activeTab === "layers" ? " is-active" : ""}`,
2457
+ role: "tab",
2458
+ "aria-selected": activeTab === "layers",
2652
2459
  children: [
2653
2460
  /* @__PURE__ */ jsx(Layers, { size: 14 }),
2654
2461
  "Katmanlar"
@@ -2656,16 +2463,9 @@ var LeftPanel = () => {
2656
2463
  }
2657
2464
  )
2658
2465
  ] }),
2659
- /* @__PURE__ */ jsx("div", { style: { flex: 1, overflowY: "auto", padding: "12px" }, children: activeTab === "blocks" ? /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "16px" }, children: [
2660
- /* @__PURE__ */ jsxs("div", { style: {
2661
- display: "flex",
2662
- alignItems: "center",
2663
- background: "#f4f4f5",
2664
- padding: "6px 10px",
2665
- borderRadius: "8px",
2666
- gap: "8px"
2667
- }, children: [
2668
- /* @__PURE__ */ jsx(Search, { size: 14, color: "#a1a1aa" }),
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" }),
2669
2469
  /* @__PURE__ */ jsx(
2670
2470
  "input",
2671
2471
  {
@@ -2673,14 +2473,7 @@ var LeftPanel = () => {
2673
2473
  placeholder: "Bile\u015Fen ara...",
2674
2474
  value: searchQuery,
2675
2475
  onChange: (e3) => setSearchQuery(e3.target.value),
2676
- style: {
2677
- border: "none",
2678
- outline: "none",
2679
- background: "transparent",
2680
- fontSize: "12px",
2681
- color: "#18181b",
2682
- width: "100%"
2683
- }
2476
+ className: "tecof-search-input"
2684
2477
  }
2685
2478
  )
2686
2479
  ] }),
@@ -2690,59 +2483,36 @@ var LeftPanel = () => {
2690
2483
  return label.toLowerCase().includes(searchQuery.toLowerCase());
2691
2484
  });
2692
2485
  if (filteredTypes.length === 0) return null;
2693
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
2694
- /* @__PURE__ */ jsx("div", { style: {
2695
- fontSize: "11px",
2696
- fontWeight: 700,
2697
- color: "#71717a",
2698
- textTransform: "uppercase",
2699
- letterSpacing: "0.05em"
2700
- }, children: catTitle }),
2701
- /* @__PURE__ */ jsx("div", { style: {
2702
- display: "grid",
2703
- gridTemplateColumns: "1fr",
2704
- gap: "6px"
2705
- }, children: filteredTypes.map((type) => {
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) => {
2706
2489
  const compConfig = components[type] || {};
2707
2490
  const label = compConfig.label || type;
2708
2491
  return /* @__PURE__ */ jsxs(
2709
2492
  "button",
2710
2493
  {
2494
+ type: "button",
2711
2495
  onClick: () => handleAddBlock(type),
2712
- style: {
2713
- background: "#ffffff",
2714
- border: "1px solid #e4e4e7",
2715
- padding: "10px 12px",
2716
- borderRadius: "8px",
2717
- fontSize: "13px",
2718
- fontWeight: 500,
2719
- color: "#3f3f46",
2720
- cursor: "pointer",
2721
- display: "flex",
2722
- alignItems: "center",
2723
- justifyContent: "space-between",
2724
- textAlign: "left",
2725
- transition: "all 0.2s",
2726
- boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.02)"
2496
+ draggable: true,
2497
+ onDragStart: (e3) => {
2498
+ writeDragData(e3, { type });
2499
+ e3.dataTransfer.effectAllowed = "copy";
2500
+ setDragGhost(e3, label);
2501
+ beginDrag({ type });
2727
2502
  },
2728
- className: "tecof-studio-block-btn",
2503
+ onDragEnd: endDrag,
2504
+ className: "tecof-block-btn",
2505
+ title: `${label} ekle`,
2729
2506
  children: [
2730
2507
  /* @__PURE__ */ jsx("span", { children: label }),
2731
- /* @__PURE__ */ jsx(Plus, { size: 14, style: { color: "#a1a1aa" } })
2508
+ /* @__PURE__ */ jsx(Plus, { size: 14, className: "tecof-block-btn-icon" })
2732
2509
  ]
2733
2510
  },
2734
2511
  type
2735
2512
  );
2736
2513
  }) })
2737
2514
  ] }, catTitle);
2738
- }),
2739
- /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: `
2740
- .tecof-studio-block-btn:hover {
2741
- border-color: #3b82f6 !important;
2742
- color: #2563eb !important;
2743
- background-color: #eff6ff !important;
2744
- }
2745
- ` } })
2515
+ })
2746
2516
  ] }) : /* @__PURE__ */ jsx(LayersTree, {}) })
2747
2517
  ] });
2748
2518
  };
@@ -2812,7 +2582,7 @@ var TecofStudio = ({
2812
2582
  setTimeout(() => setSaveStatus("idle"), 3e3);
2813
2583
  onSave?.(serialized);
2814
2584
  if (isEmbedded) {
2815
- window.parent.postMessage({ type: "puck:saved" }, "*");
2585
+ window.parent.postMessage({ type: "puck:saved", data: serialized }, "*");
2816
2586
  }
2817
2587
  } else {
2818
2588
  setSaveStatus("error");
@@ -2834,6 +2604,7 @@ var TecofStudio = ({
2834
2604
  const onMessage = (e3) => {
2835
2605
  switch (e3.data?.type) {
2836
2606
  case "puck:save":
2607
+ case "puck:publish":
2837
2608
  handleSaveDraft();
2838
2609
  break;
2839
2610
  case "puck:undo":
@@ -2869,7 +2640,7 @@ var TecofStudio = ({
2869
2640
  return true;
2870
2641
  }
2871
2642
  }
2872
- const iframe = document.querySelector(".tecof-canvas-viewport-wrapper iframe");
2643
+ const iframe = document.querySelector(".tecof-canvas-viewport iframe");
2873
2644
  const iframeDoc = iframe?.contentDocument;
2874
2645
  const iframeActiveEl = iframeDoc?.activeElement;
2875
2646
  if (iframeActiveEl) {
@@ -2926,70 +2697,50 @@ var TecofStudio = ({
2926
2697
  apiClient
2927
2698
  }), [config3, apiClient]);
2928
2699
  if (loading) {
2929
- return /* @__PURE__ */ jsx("div", { className: `tecof-editor-loading ${className || ""}`.trim(), style: {
2930
- display: "flex",
2931
- alignItems: "center",
2932
- justifyContent: "center",
2933
- height: "100vh",
2934
- background: "#f4f4f5"
2935
- }, children: /* @__PURE__ */ jsxs("div", { style: { textAlign: "center" }, children: [
2936
- /* @__PURE__ */ jsx("div", { className: "tecof-editor-spinner", style: {
2937
- width: "40px",
2938
- height: "40px",
2939
- border: "3px solid #e4e4e7",
2940
- borderTopColor: "#3b82f6",
2941
- borderRadius: "50%",
2942
- animation: "spin 1s linear infinite",
2943
- margin: "0 auto 16px"
2944
- } }),
2945
- /* @__PURE__ */ jsx("p", { style: { color: "#71717a", fontSize: "14px", margin: 0 }, children: "St\xFCdyo y\xFCkleniyor..." })
2946
- ] }) });
2947
- }
2948
- return /* @__PURE__ */ jsx(StudioContext.Provider, { value: studioContextValue, children: /* @__PURE__ */ jsxs("div", { className: `tecof-studio-root ${className || ""}`.trim(), style: {
2949
- display: "flex",
2950
- flexDirection: "column",
2951
- height: "100vh",
2952
- width: "100vw",
2953
- overflow: "hidden",
2954
- position: "relative",
2955
- background: "#f4f4f5"
2956
- }, 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: [
2957
2703
  /* @__PURE__ */ jsx(TopBar, { onSave: handleSaveDraft, saving, saveStatus }),
2958
- /* @__PURE__ */ jsxs("div", { className: "tecof-studio-workspace-container", style: {
2959
- display: "flex",
2960
- flex: 1,
2961
- height: "calc(100% - 56px)",
2962
- width: "100%",
2963
- overflow: "hidden"
2964
- }, children: [
2704
+ /* @__PURE__ */ jsxs("div", { className: "tecof-studio-workspace-container", children: [
2965
2705
  /* @__PURE__ */ jsx(LeftPanel, {}),
2966
- /* @__PURE__ */ jsxs("div", { className: "tecof-studio-workspace", style: {
2967
- display: "flex",
2968
- flex: 1,
2969
- height: "100%",
2970
- position: "relative",
2971
- overflow: "hidden"
2972
- }, children: [
2706
+ /* @__PURE__ */ jsxs("div", { className: "tecof-studio-workspace", children: [
2973
2707
  /* @__PURE__ */ jsx(Canvas, {}),
2974
2708
  /* @__PURE__ */ jsx(SelectionOverlay, {})
2975
2709
  ] }),
2976
2710
  /* @__PURE__ */ jsx(Inspector, {})
2977
2711
  ] }),
2978
- saving && /* @__PURE__ */ jsx("div", { className: "tecof-editor-save-indicator", style: {
2979
- position: "absolute",
2980
- bottom: "24px",
2981
- right: "24px",
2982
- background: saveStatus === "error" ? "#ef4444" : "#18181b",
2983
- color: "#ffffff",
2984
- padding: "8px 16px",
2985
- borderRadius: "24px",
2986
- fontSize: "12px",
2987
- fontWeight: 500,
2988
- boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1)",
2989
- zIndex: 9999
2990
- }, children: saveStatus === "error" ? "Kaydedilemedi" : "Kaydediliyor..." })
2712
+ saving && /* @__PURE__ */ jsx("div", { className: `tecof-studio-save-indicator${saveStatus === "error" ? " is-error" : ""}`, children: saveStatus === "error" ? "Kaydedilemedi" : "Kaydediliyor..." })
2991
2713
  ] }) });
2992
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
+ ] });
2993
2744
 
2994
2745
  // src/components/TecofEditor.tsx
2995
2746
  var TecofEditor = TecofStudio;
@@ -3029,7 +2780,15 @@ var TecofRender = ({ data: data3, config: config3, className, cmsData }) => {
3029
2780
  config: config3,
3030
2781
  cmsData: cmsData || null
3031
2782
  };
3032
- 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 }) });
3033
2792
  };
3034
2793
  var IMAGE_EXTENSIONS = ["png", "jpg", "jpeg", "webp", "gif", "svg", "avif", "bmp", "tiff", "heic"];
3035
2794
  var VIDEO_EXTENSIONS = ["mp4", "webm", "ogg", "avi", "mov", "quicktime"];
@@ -3139,7 +2898,7 @@ var TecofPicture = memo(({
3139
2898
  {
3140
2899
  "data-fancybox": fancyboxName,
3141
2900
  href: fileURL,
3142
- style: { display: "block", textDecoration: "none" },
2901
+ className: "tecof-picture-link",
3143
2902
  children: /* @__PURE__ */ jsx("div", { style, className: containerClassName, children: isVideoType ? renderVideo() : renderImg() })
3144
2903
  }
3145
2904
  );
@@ -3497,10 +3256,15 @@ var LanguageTabBar = ({
3497
3256
  code
3498
3257
  )) });
3499
3258
  };
3500
- var FieldLoading = () => /* @__PURE__ */ jsxs("div", { className: "tecof-lang-loading", children: [
3501
- /* @__PURE__ */ jsx("span", { className: "tecof-lang-loading-dot" }),
3502
- /* @__PURE__ */ jsx("span", { className: "tecof-lang-loading-dot" }),
3503
- /* @__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" })
3504
3268
  ] });
3505
3269
  var StableInput = ({
3506
3270
  value: externalValue,
@@ -7287,7 +7051,7 @@ var MediaDrawer = ({
7287
7051
  ] })
7288
7052
  ] }),
7289
7053
  /* @__PURE__ */ jsxs("div", { className: "tecof-upload-search-box", children: [
7290
- /* @__PURE__ */ jsx(Search, { size: 15, color: "#a1a1aa" }),
7054
+ /* @__PURE__ */ jsx(Search, { size: 15, className: "tecof-icon-muted" }),
7291
7055
  /* @__PURE__ */ jsx(
7292
7056
  "input",
7293
7057
  {
@@ -7308,11 +7072,11 @@ var MediaDrawer = ({
7308
7072
  }
7309
7073
  )
7310
7074
  ] }),
7311
- loading ? /* @__PURE__ */ jsxs("div", { className: "tecof-upload-gallery-empty", children: [
7312
- /* @__PURE__ */ jsx("div", { className: "tecof-upload-gallery-empty-icon", children: /* @__PURE__ */ jsx(RefreshCcw, { size: 24, color: "#a1a1aa", className: "tecof-upload-spin" }) }),
7313
- /* @__PURE__ */ jsx("p", { className: "tecof-upload-loading-text", children: "Y\xFCkleniyor..." })
7314
- ] }) : filteredGallery.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "tecof-upload-gallery-empty", children: [
7315
- /* @__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" }) }),
7316
7080
  /* @__PURE__ */ jsx("p", { className: "tecof-upload-empty-heading", children: gallerySearch ? "Sonu\xE7 bulunamad\u0131" : "Hen\xFCz dosya yok" }),
7317
7081
  /* @__PURE__ */ jsx("p", { className: "tecof-upload-empty-subheading", children: gallerySearch ? "Farkl\u0131 bir arama terimi deneyin" : "Dosyalar\u0131n\u0131z burada g\xF6r\xFCnecek" })
7318
7082
  ] }) : /* @__PURE__ */ jsx("div", { className: "tecof-upload-gallery-grid", children: filteredGallery.map((file2) => {
@@ -7330,10 +7094,9 @@ var MediaDrawer = ({
7330
7094
  data: file2,
7331
7095
  alt: file2.name,
7332
7096
  size: "thumbnail",
7333
- className: "tecof-upload-gallery-thumb",
7334
- imgStyle: { width: "100%", height: "100%", objectFit: "cover", borderRadius: "8px" }
7097
+ className: "tecof-upload-gallery-thumb"
7335
7098
  }
7336
- ) : /* @__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" }) }),
7337
7100
  /* @__PURE__ */ jsx("p", { className: "tecof-upload-gallery-file-name", children: file2.meta?.originalName || file2.name })
7338
7101
  ]
7339
7102
  },
@@ -25209,14 +24972,13 @@ var FileItemRenderer = ({
25209
24972
  `${cdnUrl}/${file2.name}`;
25210
24973
  const ext = getFileExtension(file2.name);
25211
24974
  return /* @__PURE__ */ jsxs("div", { className: "tecof-upload-file-item", children: [
25212
- 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(
25213
24976
  TecofPicture,
25214
24977
  {
25215
24978
  data: file2,
25216
24979
  alt: file2.meta?.originalName || file2.name,
25217
24980
  size: "thumbnail",
25218
- className: "tecof-upload-file-thumb",
25219
- imgStyle: { width: "100%", height: "100%", objectFit: "cover", borderRadius: "6px" }
24981
+ className: "tecof-upload-file-thumb"
25220
24982
  }
25221
24983
  ) : /* @__PURE__ */ jsx("div", { className: "tecof-upload-file-icon", children: /* @__PURE__ */ jsx(File2, { size: 16 }) }),
25222
24984
  /* @__PURE__ */ jsxs("div", { className: "tecof-upload-file-info", children: [
@@ -25530,12 +25292,12 @@ var UploadField = ({
25530
25292
  " Y\xFCkle"
25531
25293
  ] })
25532
25294
  ] }),
25533
- 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: [
25534
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
25535
- /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", fontWeight: 500, color: "#71717a" }, children: "Dinamik CMS De\u011Fi\u015Fkeni" }),
25536
- /* @__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 }) })
25537
25299
  ] }),
25538
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "6px" }, children: [
25300
+ /* @__PURE__ */ jsxs("div", { className: "tecof-upload-ref-row", children: [
25539
25301
  /* @__PURE__ */ jsx(
25540
25302
  "input",
25541
25303
  {
@@ -25543,7 +25305,7 @@ var UploadField = ({
25543
25305
  value: refCode,
25544
25306
  onChange: (e3) => setRefCode(e3.target.value),
25545
25307
  placeholder: "{{ data. }}",
25546
- style: { flex: 1, padding: "6px 8px", fontSize: "12px", borderRadius: "6px", border: "1px solid #cbd5e1", outline: "none" },
25308
+ className: "tecof-upload-ref-input",
25547
25309
  autoFocus: true,
25548
25310
  onKeyDown: (e3) => {
25549
25311
  if (e3.key === "Enter") {
@@ -25558,7 +25320,7 @@ var UploadField = ({
25558
25320
  {
25559
25321
  type: "button",
25560
25322
  onClick: handleAddRef,
25561
- style: { padding: "0 10px", background: "#18181b", color: "#fff", fontSize: "11px", fontWeight: 500, borderRadius: "6px", border: "none", cursor: "pointer" },
25323
+ className: "tecof-upload-ref-add",
25562
25324
  children: "Ekle"
25563
25325
  }
25564
25326
  )
@@ -26447,7 +26209,7 @@ var LinkField = ({
26447
26209
  /* @__PURE__ */ jsx("p", { className: "tecof-link-value-url", children: activeValue.url })
26448
26210
  ] }),
26449
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" }),
26450
- activeValue.target === "_blank" && /* @__PURE__ */ jsx(ExternalLink, { size: 14, color: "#a1a1aa" }),
26212
+ activeValue.target === "_blank" && /* @__PURE__ */ jsx(ExternalLink, { size: 14, className: "tecof-icon-muted" }),
26451
26213
  !readOnly && /* @__PURE__ */ jsxs(Fragment, { children: [
26452
26214
  /* @__PURE__ */ jsx("button", { type: "button", className: "tecof-link-action-btn-small", onClick: handleEditManual, title: "D\xFCzenle", children: /* @__PURE__ */ jsx(Pencil, { size: 14 }) }),
26453
26215
  /* @__PURE__ */ jsx("button", { type: "button", className: "tecof-link-action-btn-small", onClick: handleClear, title: "Kald\u0131r", children: /* @__PURE__ */ jsx(X, { size: 14 }) })
@@ -26520,7 +26282,7 @@ var LinkField = ({
26520
26282
  /* @__PURE__ */ jsx("button", { className: "tecof-link-drawer-close-btn", onClick: () => setDrawerOpen(false), children: /* @__PURE__ */ jsx(X, { size: 16 }) })
26521
26283
  ] }),
26522
26284
  /* @__PURE__ */ jsxs("div", { className: "tecof-link-search-box", children: [
26523
- /* @__PURE__ */ jsx(Search, { size: 16, color: "#a1a1aa" }),
26285
+ /* @__PURE__ */ jsx(Search, { size: 16, className: "tecof-icon-muted" }),
26524
26286
  /* @__PURE__ */ jsx(
26525
26287
  "input",
26526
26288
  {
@@ -26532,7 +26294,13 @@ var LinkField = ({
26532
26294
  }
26533
26295
  )
26534
26296
  ] }),
26535
- 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) => {
26536
26304
  const selected = activeValue?.url === `/${page.slug}`;
26537
26305
  return /* @__PURE__ */ jsxs(
26538
26306
  "div",
@@ -26548,7 +26316,7 @@ var LinkField = ({
26548
26316
  ] }),
26549
26317
  page.title && /* @__PURE__ */ jsx("p", { className: "tecof-link-page-title", children: page.title })
26550
26318
  ] }),
26551
- /* @__PURE__ */ jsx(ChevronRight, { size: 16, color: "#d4d4d8" })
26319
+ /* @__PURE__ */ jsx(ChevronRight, { size: 16, className: "tecof-icon-faint" })
26552
26320
  ]
26553
26321
  },
26554
26322
  page._id
@@ -26699,7 +26467,7 @@ var ColorField = ({
26699
26467
  "div",
26700
26468
  {
26701
26469
  className: `tecof-color-swatch ${focused ? "focused" : ""}`,
26702
- style: { background: isValid && currentColor ? currentColor : "#ffffff" },
26470
+ style: { background: isValid && currentColor ? currentColor : "var(--tecof-surface)" },
26703
26471
  children: !readOnly && /* @__PURE__ */ jsx(
26704
26472
  "input",
26705
26473
  {
@@ -27182,9 +26950,9 @@ var CmsCollectionField = ({
27182
26950
  );
27183
26951
  }, [collections, searchQuery]);
27184
26952
  if (loading) {
27185
- return /* @__PURE__ */ jsxs("div", { className: "tecof-cms-col-loading", children: [
27186
- /* @__PURE__ */ jsx(LoaderCircle, { size: 16, className: "tecof-spin" }),
27187
- /* @__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" })
27188
26956
  ] });
27189
26957
  }
27190
26958
  if (error2) {
@@ -27390,9 +27158,9 @@ var createCmsCollectionField = (options = {}) => {
27390
27158
  function hexToHsl(hex) {
27391
27159
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
27392
27160
  if (!result) return { h: 0, s: 0, l: 0 };
27393
- let r2 = parseInt(result[1], 16) / 255;
27394
- let g = parseInt(result[2], 16) / 255;
27395
- 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;
27396
27164
  const max = Math.max(r2, g, b);
27397
27165
  const min = Math.min(r2, g, b);
27398
27166
  let h2 = 0;