@orion-studios/payload-studio 0.5.0-beta.50 → 0.5.0-beta.52

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.
@@ -24,6 +24,9 @@ __export(client_exports, {
24
24
  AdminShellClient: () => AdminShellClient,
25
25
  HeaderNavEditorWithPreview: () => HeaderNavEditorWithPreview,
26
26
  HeaderNavItemsEditor: () => HeaderNavItemsEditor,
27
+ MediaDetailPanel: () => MediaDetailPanel,
28
+ MediaListItem: () => MediaListItem,
29
+ MediaUploadForm: () => MediaUploadForm,
27
30
  PageEditorFrame: () => PageEditorFrame
28
31
  });
29
32
  module.exports = __toCommonJS(client_exports);
@@ -50,6 +53,47 @@ var navItemIsActive = (pathname, item) => {
50
53
 
51
54
  // src/admin-app/components/AdminShellClient.tsx
52
55
  var import_jsx_runtime = require("react/jsx-runtime");
56
+ var iconSize = 20;
57
+ var iconStyle = { display: "block", flexShrink: 0 };
58
+ function NavIcon({ name }) {
59
+ const props = { width: iconSize, height: iconSize, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", style: iconStyle };
60
+ switch (name) {
61
+ case "dashboard":
62
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...props, children: [
63
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "3", y: "3", width: "7", height: "9", rx: "1" }),
64
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "14", y: "3", width: "7", height: "5", rx: "1" }),
65
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "14", y: "12", width: "7", height: "9", rx: "1" }),
66
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "3", y: "16", width: "7", height: "5", rx: "1" })
67
+ ] });
68
+ case "pages":
69
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...props, children: [
70
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" }),
71
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "14 2 14 8 20 8" }),
72
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "13", x2: "16", y2: "13" }),
73
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "17", x2: "12", y2: "17" })
74
+ ] });
75
+ case "globals":
76
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...props, children: [
77
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "3" }),
78
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z" })
79
+ ] });
80
+ case "media":
81
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...props, children: [
82
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
83
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
84
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "21 15 16 10 5 21" })
85
+ ] });
86
+ case "tools":
87
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76Z" }) });
88
+ case "account":
89
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...props, children: [
90
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
91
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "7", r: "4" })
92
+ ] });
93
+ default:
94
+ return null;
95
+ }
96
+ }
53
97
  function AdminShellClient({
54
98
  children,
55
99
  brandName,
@@ -117,7 +161,10 @@ function AdminShellClient({
117
161
  className: `orion-admin-nav-link ${active ? "is-active" : ""}`,
118
162
  href: item.href,
119
163
  title: item.label,
120
- children: collapsed ? item.label.slice(0, 1) : item.label
164
+ children: item.icon ? collapsed ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavIcon, { name: item.icon }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { alignItems: "center", display: "flex", gap: "0.6rem" }, children: [
165
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavIcon, { name: item.icon }),
166
+ item.label
167
+ ] }) : collapsed ? item.label.slice(0, 1) : item.label
121
168
  },
122
169
  item.href
123
170
  );
@@ -493,22 +540,311 @@ function HeaderNavEditorWithPreview({
493
540
  ] });
494
541
  }
495
542
 
496
- // src/admin-app/components/PageEditorFrame.tsx
543
+ // src/admin-app/components/MediaDetailPanel.tsx
497
544
  var import_react4 = require("react");
498
545
  var import_jsx_runtime4 = require("react/jsx-runtime");
546
+ function formatFileSize(bytes) {
547
+ if (bytes < 1024) return `${bytes} B`;
548
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
549
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
550
+ }
551
+ function MediaDetailPanel({
552
+ id,
553
+ filename,
554
+ alt,
555
+ url,
556
+ filesize,
557
+ width,
558
+ height,
559
+ mimeType,
560
+ createdAt,
561
+ updateAction,
562
+ deleteAction
563
+ }) {
564
+ const [copied, setCopied] = (0, import_react4.useState)(false);
565
+ const [confirmDelete, setConfirmDelete] = (0, import_react4.useState)(false);
566
+ const copyUrl = async () => {
567
+ if (!url) return;
568
+ try {
569
+ await navigator.clipboard.writeText(url);
570
+ setCopied(true);
571
+ setTimeout(() => setCopied(false), 2e3);
572
+ } catch {
573
+ const input = document.createElement("input");
574
+ input.value = url;
575
+ document.body.appendChild(input);
576
+ input.select();
577
+ document.execCommand("copy");
578
+ document.body.removeChild(input);
579
+ setCopied(true);
580
+ setTimeout(() => setCopied(false), 2e3);
581
+ }
582
+ };
583
+ const metaRows = [];
584
+ if (filename) metaRows.push({ label: "Filename", value: filename });
585
+ if (typeof filesize === "number") metaRows.push({ label: "File size", value: formatFileSize(filesize) });
586
+ if (typeof width === "number" && typeof height === "number") metaRows.push({ label: "Dimensions", value: `${width} \xD7 ${height} px` });
587
+ if (mimeType) metaRows.push({ label: "Type", value: mimeType });
588
+ if (createdAt) {
589
+ try {
590
+ metaRows.push({ label: "Uploaded", value: new Date(createdAt).toLocaleDateString() });
591
+ } catch {
592
+ metaRows.push({ label: "Uploaded", value: createdAt });
593
+ }
594
+ }
595
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "orion-admin-grid", style: { alignItems: "start" }, children: [
596
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
597
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "orion-admin-card", children: url ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("img", { alt: alt || filename || "Media", src: url, style: { borderRadius: 12, width: "100%" } }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "No preview available." }) }),
598
+ url ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
599
+ "button",
600
+ {
601
+ className: "orion-admin-action-button",
602
+ onClick: copyUrl,
603
+ style: { marginTop: "0.6rem", width: "100%" },
604
+ type: "button",
605
+ children: copied ? "Copied!" : "Copy URL"
606
+ }
607
+ ) : null
608
+ ] }),
609
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "grid", gap: "0.8rem" }, children: [
610
+ metaRows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "orion-admin-card orion-admin-meta-table", children: metaRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "orion-admin-meta-row", children: [
611
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "orion-admin-meta-label", children: row.label }),
612
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "orion-admin-meta-value", children: row.value })
613
+ ] }, row.label)) }) : null,
614
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { action: updateAction, className: "orion-admin-form", children: [
615
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { name: "id", type: "hidden", value: id }),
616
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
617
+ "Alt text",
618
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { defaultValue: alt || "", name: "alt", required: true, type: "text" })
619
+ ] }),
620
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "submit", children: "Save" })
621
+ ] }),
622
+ confirmDelete ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "orion-admin-form", style: { borderColor: "#b42318" }, children: [
623
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: { fontWeight: 700, margin: 0 }, children: "Are you sure you want to delete this asset?" }),
624
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: { color: "var(--orion-admin-muted)", fontSize: "0.9rem", margin: 0 }, children: "This action cannot be undone." }),
625
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: "0.5rem" }, children: [
626
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { action: deleteAction, style: { flex: 1 }, children: [
627
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { name: "id", type: "hidden", value: id }),
628
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { style: { background: "#b42318", border: 0, borderRadius: 10, color: "#fff", cursor: "pointer", fontWeight: 800, padding: "0.55rem 0.8rem", width: "100%" }, type: "submit", children: "Yes, Delete" })
629
+ ] }),
630
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
631
+ "button",
632
+ {
633
+ onClick: () => setConfirmDelete(false),
634
+ style: { background: "transparent", border: "1px solid var(--orion-admin-border)", borderRadius: 10, cursor: "pointer", flex: 1, fontWeight: 700, padding: "0.55rem 0.8rem" },
635
+ type: "button",
636
+ children: "Cancel"
637
+ }
638
+ )
639
+ ] })
640
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
641
+ "button",
642
+ {
643
+ className: "orion-admin-action-button",
644
+ onClick: () => setConfirmDelete(true),
645
+ style: { background: "#b42318" },
646
+ type: "button",
647
+ children: "Delete Asset"
648
+ }
649
+ )
650
+ ] })
651
+ ] });
652
+ }
653
+
654
+ // src/admin-app/components/MediaListItem.tsx
655
+ var import_jsx_runtime5 = require("react/jsx-runtime");
656
+ function formatFileSize2(bytes) {
657
+ if (bytes < 1024) return `${bytes} B`;
658
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
659
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
660
+ }
661
+ function MediaListItem({
662
+ id,
663
+ filename,
664
+ alt,
665
+ url,
666
+ filesize,
667
+ width,
668
+ height,
669
+ mimeType,
670
+ href
671
+ }) {
672
+ const label = filename || `Media ${id}`;
673
+ const altText = alt || "";
674
+ const metaParts = [];
675
+ if (typeof filesize === "number") metaParts.push(formatFileSize2(filesize));
676
+ if (typeof width === "number" && typeof height === "number") metaParts.push(`${width}\xD7${height}`);
677
+ if (typeof mimeType === "string") metaParts.push(mimeType);
678
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("a", { className: "orion-admin-list-item", href, children: [
679
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { alignItems: "center", display: "flex", gap: "0.8rem" }, children: [
680
+ url ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("img", { alt: altText || label, className: "orion-admin-media-preview", src: url }) : null,
681
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
682
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: label }),
683
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "orion-admin-list-meta", children: altText || "No alt text" }),
684
+ metaParts.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "orion-admin-list-meta", style: { marginTop: "0.15rem" }, children: metaParts.join(" \xB7 ") }) : null
685
+ ] })
686
+ ] }),
687
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "orion-admin-list-meta", children: "Edit" })
688
+ ] });
689
+ }
690
+
691
+ // src/admin-app/components/MediaUploadForm.tsx
692
+ var import_react5 = require("react");
693
+ var import_navigation = require("next/navigation");
694
+ var import_jsx_runtime6 = require("react/jsx-runtime");
695
+ var parseUploadError = async (response) => {
696
+ const fallback = "Upload failed. Please check the image and required fields, then try again.";
697
+ try {
698
+ const body = await response.json();
699
+ const nestedMessage = body.errors?.[0]?.data?.errors?.[0]?.message;
700
+ if (typeof nestedMessage === "string" && nestedMessage.trim().length > 0) {
701
+ return nestedMessage;
702
+ }
703
+ const topMessage = body.errors?.[0]?.message;
704
+ if (typeof topMessage === "string" && topMessage.trim().length > 0) {
705
+ return topMessage;
706
+ }
707
+ if (typeof body.message === "string" && body.message.trim().length > 0) {
708
+ return body.message;
709
+ }
710
+ } catch {
711
+ }
712
+ return fallback;
713
+ };
714
+ function MediaUploadForm() {
715
+ const router = (0, import_navigation.useRouter)();
716
+ const fileInputRef = (0, import_react5.useRef)(null);
717
+ const [alt, setAlt] = (0, import_react5.useState)("");
718
+ const [file, setFile] = (0, import_react5.useState)(null);
719
+ const [preview, setPreview] = (0, import_react5.useState)(null);
720
+ const [dragging, setDragging] = (0, import_react5.useState)(false);
721
+ const [submitting, setSubmitting] = (0, import_react5.useState)(false);
722
+ const [error, setError] = (0, import_react5.useState)(null);
723
+ const handleFile = (0, import_react5.useCallback)((selectedFile) => {
724
+ setFile(selectedFile);
725
+ if (preview) {
726
+ URL.revokeObjectURL(preview);
727
+ setPreview(null);
728
+ }
729
+ if (selectedFile && selectedFile.type.startsWith("image/")) {
730
+ setPreview(URL.createObjectURL(selectedFile));
731
+ }
732
+ }, [preview]);
733
+ const onDragOver = (0, import_react5.useCallback)((e) => {
734
+ e.preventDefault();
735
+ setDragging(true);
736
+ }, []);
737
+ const onDragLeave = (0, import_react5.useCallback)((e) => {
738
+ e.preventDefault();
739
+ setDragging(false);
740
+ }, []);
741
+ const onDrop = (0, import_react5.useCallback)((e) => {
742
+ e.preventDefault();
743
+ setDragging(false);
744
+ const droppedFile = e.dataTransfer.files?.[0] || null;
745
+ if (droppedFile) {
746
+ handleFile(droppedFile);
747
+ }
748
+ }, [handleFile]);
749
+ const upload = async (event) => {
750
+ event.preventDefault();
751
+ if (!file) {
752
+ setError("Select an image to upload.");
753
+ return;
754
+ }
755
+ setSubmitting(true);
756
+ setError(null);
757
+ try {
758
+ const formData = new FormData();
759
+ const fallbackAlt = file.name.replace(/\.[^/.]+$/, "").trim();
760
+ const resolvedAlt = alt.trim() || fallbackAlt || "Uploaded image";
761
+ formData.set("_payload", JSON.stringify({ alt: resolvedAlt }));
762
+ formData.set("alt", resolvedAlt);
763
+ formData.set("file", file);
764
+ const response = await fetch("/api/media", {
765
+ method: "POST",
766
+ credentials: "include",
767
+ body: formData
768
+ });
769
+ if (!response.ok) {
770
+ throw new Error(await parseUploadError(response));
771
+ }
772
+ setAlt("");
773
+ setFile(null);
774
+ if (preview) {
775
+ URL.revokeObjectURL(preview);
776
+ setPreview(null);
777
+ }
778
+ router.refresh();
779
+ } catch (err) {
780
+ setError(err instanceof Error ? err.message : "Upload failed");
781
+ } finally {
782
+ setSubmitting(false);
783
+ }
784
+ };
785
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("form", { className: "orion-admin-upload-form", onSubmit: upload, children: [
786
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
787
+ "Alt text",
788
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
789
+ "input",
790
+ {
791
+ onChange: (event) => setAlt(event.target.value),
792
+ placeholder: "Describe the image",
793
+ type: "text",
794
+ value: alt
795
+ }
796
+ )
797
+ ] }),
798
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
799
+ "div",
800
+ {
801
+ className: `orion-admin-dropzone${dragging ? " is-dragging" : ""}${file ? " has-file" : ""}`,
802
+ onClick: () => fileInputRef.current?.click(),
803
+ onDragLeave,
804
+ onDragOver,
805
+ onDrop,
806
+ children: [
807
+ preview ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "orion-admin-dropzone-preview", children: [
808
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { alt: "Upload preview", src: preview }),
809
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: file?.name })
810
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "orion-admin-dropzone-label", children: [
811
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "Drop an image here" }),
812
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "or click to browse" })
813
+ ] }),
814
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
815
+ "input",
816
+ {
817
+ accept: "image/*",
818
+ onChange: (event) => handleFile(event.target.files?.[0] || null),
819
+ ref: fileInputRef,
820
+ style: { display: "none" },
821
+ type: "file"
822
+ }
823
+ )
824
+ ]
825
+ }
826
+ ),
827
+ error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "orion-admin-upload-error", children: error }) : null,
828
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { disabled: submitting, type: "submit", children: submitting ? "Uploading..." : "Upload" })
829
+ ] });
830
+ }
831
+
832
+ // src/admin-app/components/PageEditorFrame.tsx
833
+ var import_react6 = require("react");
834
+ var import_jsx_runtime7 = require("react/jsx-runtime");
499
835
  function PageEditorFrame({ src }) {
500
- const iframeRef = (0, import_react4.useRef)(null);
501
- const dirtyCheckTimerRef = (0, import_react4.useRef)(null);
502
- const [saving, setSaving] = (0, import_react4.useState)(null);
503
- const [message, setMessage] = (0, import_react4.useState)("");
504
- const [error, setError] = (0, import_react4.useState)("");
505
- const [hasUnsavedChanges, setHasUnsavedChanges] = (0, import_react4.useState)(false);
506
- const [awaitingDirtyCheck, setAwaitingDirtyCheck] = (0, import_react4.useState)(false);
507
- const [pendingNavigationURL, setPendingNavigationURL] = (0, import_react4.useState)(null);
508
- const [showUnsavedDialog, setShowUnsavedDialog] = (0, import_react4.useState)(false);
509
- const [canUndo, setCanUndo] = (0, import_react4.useState)(false);
510
- const [canRedo, setCanRedo] = (0, import_react4.useState)(false);
511
- const [sessionExpired, setSessionExpired] = (0, import_react4.useState)(false);
836
+ const iframeRef = (0, import_react6.useRef)(null);
837
+ const dirtyCheckTimerRef = (0, import_react6.useRef)(null);
838
+ const [saving, setSaving] = (0, import_react6.useState)(null);
839
+ const [message, setMessage] = (0, import_react6.useState)("");
840
+ const [error, setError] = (0, import_react6.useState)("");
841
+ const [hasUnsavedChanges, setHasUnsavedChanges] = (0, import_react6.useState)(false);
842
+ const [awaitingDirtyCheck, setAwaitingDirtyCheck] = (0, import_react6.useState)(false);
843
+ const [pendingNavigationURL, setPendingNavigationURL] = (0, import_react6.useState)(null);
844
+ const [showUnsavedDialog, setShowUnsavedDialog] = (0, import_react6.useState)(false);
845
+ const [canUndo, setCanUndo] = (0, import_react6.useState)(false);
846
+ const [canRedo, setCanRedo] = (0, import_react6.useState)(false);
847
+ const [sessionExpired, setSessionExpired] = (0, import_react6.useState)(false);
512
848
  const clearDirtyCheckTimer = () => {
513
849
  if (dirtyCheckTimerRef.current) {
514
850
  window.clearTimeout(dirtyCheckTimerRef.current);
@@ -554,7 +890,7 @@ function PageEditorFrame({ src }) {
554
890
  "*"
555
891
  );
556
892
  };
557
- (0, import_react4.useEffect)(() => {
893
+ (0, import_react6.useEffect)(() => {
558
894
  const onMessage = (event) => {
559
895
  const data = event.data;
560
896
  if (!data || data.source !== "payload-visual-builder-child") {
@@ -599,7 +935,7 @@ function PageEditorFrame({ src }) {
599
935
  window.addEventListener("message", onMessage);
600
936
  return () => window.removeEventListener("message", onMessage);
601
937
  }, [awaitingDirtyCheck, pendingNavigationURL]);
602
- (0, import_react4.useEffect)(() => {
938
+ (0, import_react6.useEffect)(() => {
603
939
  const onDocumentClick = (event) => {
604
940
  if (!hasUnsavedChanges) {
605
941
  return;
@@ -662,7 +998,7 @@ function PageEditorFrame({ src }) {
662
998
  document.addEventListener("click", onDocumentClick, true);
663
999
  return () => document.removeEventListener("click", onDocumentClick, true);
664
1000
  }, [hasUnsavedChanges]);
665
- (0, import_react4.useEffect)(() => {
1001
+ (0, import_react6.useEffect)(() => {
666
1002
  if (!hasUnsavedChanges) {
667
1003
  return;
668
1004
  }
@@ -673,14 +1009,14 @@ function PageEditorFrame({ src }) {
673
1009
  window.addEventListener("beforeunload", onBeforeUnload);
674
1010
  return () => window.removeEventListener("beforeunload", onBeforeUnload);
675
1011
  }, [hasUnsavedChanges]);
676
- (0, import_react4.useEffect)(
1012
+ (0, import_react6.useEffect)(
677
1013
  () => () => {
678
1014
  clearDirtyCheckTimer();
679
1015
  },
680
1016
  []
681
1017
  );
682
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "grid", gap: "0.8rem" }, children: [
683
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1018
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "grid", gap: "0.8rem" }, children: [
1019
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
684
1020
  "div",
685
1021
  {
686
1022
  style: {
@@ -695,9 +1031,9 @@ function PageEditorFrame({ src }) {
695
1031
  padding: "0.7rem 0.8rem"
696
1032
  },
697
1033
  children: [
698
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: "var(--orion-admin-muted)", fontSize: "0.9rem" }, children: "Save changes to update the page layout and content." }),
699
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { alignItems: "center", display: "flex", flexWrap: "wrap", gap: "0.5rem" }, children: [
700
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1034
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { color: "var(--orion-admin-muted)", fontSize: "0.9rem" }, children: "Save changes to update the page layout and content." }),
1035
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { alignItems: "center", display: "flex", flexWrap: "wrap", gap: "0.5rem" }, children: [
1036
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
701
1037
  "button",
702
1038
  {
703
1039
  className: "orion-admin-action-button",
@@ -708,7 +1044,7 @@ function PageEditorFrame({ src }) {
708
1044
  children: "Undo"
709
1045
  }
710
1046
  ),
711
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1047
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
712
1048
  "button",
713
1049
  {
714
1050
  className: "orion-admin-action-button",
@@ -719,7 +1055,7 @@ function PageEditorFrame({ src }) {
719
1055
  children: "Redo"
720
1056
  }
721
1057
  ),
722
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1058
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
723
1059
  "button",
724
1060
  {
725
1061
  className: "orion-admin-action-button",
@@ -729,7 +1065,7 @@ function PageEditorFrame({ src }) {
729
1065
  children: saving === "draft" ? "Saving..." : "Save Draft"
730
1066
  }
731
1067
  ),
732
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1068
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
733
1069
  "button",
734
1070
  {
735
1071
  className: "orion-admin-action-button",
@@ -744,9 +1080,9 @@ function PageEditorFrame({ src }) {
744
1080
  ]
745
1081
  }
746
1082
  ),
747
- message ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: "#0f7d52", fontSize: "0.9rem", fontWeight: 700 }, children: message }) : null,
748
- error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "orion-admin-error", children: error }) : null,
749
- sessionExpired ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1083
+ message ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { color: "#0f7d52", fontSize: "0.9rem", fontWeight: 700 }, children: message }) : null,
1084
+ error ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "orion-admin-error", children: error }) : null,
1085
+ sessionExpired ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
750
1086
  "div",
751
1087
  {
752
1088
  style: {
@@ -761,7 +1097,7 @@ function PageEditorFrame({ src }) {
761
1097
  children: "Session expired. Log in again in a new tab, then save your changes."
762
1098
  }
763
1099
  ) : null,
764
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1100
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
765
1101
  "iframe",
766
1102
  {
767
1103
  ref: iframeRef,
@@ -781,7 +1117,7 @@ function PageEditorFrame({ src }) {
781
1117
  }
782
1118
  }
783
1119
  ),
784
- pendingNavigationURL && showUnsavedDialog ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1120
+ pendingNavigationURL && showUnsavedDialog ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
785
1121
  "div",
786
1122
  {
787
1123
  "data-orion-unsaved-dialog": "true",
@@ -795,7 +1131,7 @@ function PageEditorFrame({ src }) {
795
1131
  position: "fixed",
796
1132
  zIndex: 2e3
797
1133
  },
798
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1134
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
799
1135
  "div",
800
1136
  {
801
1137
  style: {
@@ -810,12 +1146,12 @@ function PageEditorFrame({ src }) {
810
1146
  width: "100%"
811
1147
  },
812
1148
  children: [
813
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
814
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: "var(--orion-admin-text)", fontSize: "1rem", fontWeight: 700 }, children: "Unsaved changes" }),
815
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: "var(--orion-admin-muted)", fontSize: "0.9rem", marginTop: "0.4rem" }, children: "You have unsaved edits in the page builder. Save before leaving this page?" })
1149
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
1150
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { color: "var(--orion-admin-text)", fontSize: "1rem", fontWeight: 700 }, children: "Unsaved changes" }),
1151
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { color: "var(--orion-admin-muted)", fontSize: "0.9rem", marginTop: "0.4rem" }, children: "You have unsaved edits in the page builder. Save before leaving this page?" })
816
1152
  ] }),
817
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: "0.6rem", justifyContent: "flex-end" }, children: [
818
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1153
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: "0.6rem", justifyContent: "flex-end" }, children: [
1154
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
819
1155
  "button",
820
1156
  {
821
1157
  className: "orion-admin-action-button",
@@ -827,7 +1163,7 @@ function PageEditorFrame({ src }) {
827
1163
  children: "Stay"
828
1164
  }
829
1165
  ),
830
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1166
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
831
1167
  "button",
832
1168
  {
833
1169
  className: "orion-admin-action-button",
@@ -855,5 +1191,8 @@ function PageEditorFrame({ src }) {
855
1191
  AdminShellClient,
856
1192
  HeaderNavEditorWithPreview,
857
1193
  HeaderNavItemsEditor,
1194
+ MediaDetailPanel,
1195
+ MediaListItem,
1196
+ MediaUploadForm,
858
1197
  PageEditorFrame
859
1198
  });