@orion-studios/payload-studio 0.5.0-beta.51 → 0.5.0-beta.53
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/admin-app/client.d.mts +3 -0
- package/dist/admin-app/client.d.ts +3 -0
- package/dist/admin-app/client.js +332 -37
- package/dist/admin-app/client.mjs +326 -34
- package/dist/admin-app/index.d.mts +1 -1
- package/dist/admin-app/index.d.ts +1 -1
- package/dist/admin-app/styles.css +96 -0
- package/dist/{index-TJmWr6aF.d.mts → index-ZbOx4OCF.d.mts} +30 -2
- package/dist/{index-TJmWr6aF.d.ts → index-ZbOx4OCF.d.ts} +30 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export { AdminShellClient } from './components/AdminShellClient'
|
|
2
2
|
export { HeaderNavItemsEditor } from './components/HeaderNavItemsEditor'
|
|
3
3
|
export { HeaderNavEditorWithPreview } from './components/HeaderNavEditorWithPreview'
|
|
4
|
+
export { MediaDetailPanel } from './components/MediaDetailPanel'
|
|
5
|
+
export { MediaListItem } from './components/MediaListItem'
|
|
6
|
+
export { MediaUploadForm } from './components/MediaUploadForm'
|
|
4
7
|
export { PageEditorFrame } from './components/PageEditorFrame'
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export { AdminShellClient } from './components/AdminShellClient'
|
|
2
2
|
export { HeaderNavItemsEditor } from './components/HeaderNavItemsEditor'
|
|
3
3
|
export { HeaderNavEditorWithPreview } from './components/HeaderNavEditorWithPreview'
|
|
4
|
+
export { MediaDetailPanel } from './components/MediaDetailPanel'
|
|
5
|
+
export { MediaListItem } from './components/MediaListItem'
|
|
6
|
+
export { MediaUploadForm } from './components/MediaUploadForm'
|
|
4
7
|
export { PageEditorFrame } from './components/PageEditorFrame'
|
package/dist/admin-app/client.js
CHANGED
|
@@ -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);
|
|
@@ -537,22 +540,311 @@ function HeaderNavEditorWithPreview({
|
|
|
537
540
|
] });
|
|
538
541
|
}
|
|
539
542
|
|
|
540
|
-
// src/admin-app/components/
|
|
543
|
+
// src/admin-app/components/MediaDetailPanel.tsx
|
|
541
544
|
var import_react4 = require("react");
|
|
542
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");
|
|
543
835
|
function PageEditorFrame({ src }) {
|
|
544
|
-
const iframeRef = (0,
|
|
545
|
-
const dirtyCheckTimerRef = (0,
|
|
546
|
-
const [saving, setSaving] = (0,
|
|
547
|
-
const [message, setMessage] = (0,
|
|
548
|
-
const [error, setError] = (0,
|
|
549
|
-
const [hasUnsavedChanges, setHasUnsavedChanges] = (0,
|
|
550
|
-
const [awaitingDirtyCheck, setAwaitingDirtyCheck] = (0,
|
|
551
|
-
const [pendingNavigationURL, setPendingNavigationURL] = (0,
|
|
552
|
-
const [showUnsavedDialog, setShowUnsavedDialog] = (0,
|
|
553
|
-
const [canUndo, setCanUndo] = (0,
|
|
554
|
-
const [canRedo, setCanRedo] = (0,
|
|
555
|
-
const [sessionExpired, setSessionExpired] = (0,
|
|
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);
|
|
556
848
|
const clearDirtyCheckTimer = () => {
|
|
557
849
|
if (dirtyCheckTimerRef.current) {
|
|
558
850
|
window.clearTimeout(dirtyCheckTimerRef.current);
|
|
@@ -598,7 +890,7 @@ function PageEditorFrame({ src }) {
|
|
|
598
890
|
"*"
|
|
599
891
|
);
|
|
600
892
|
};
|
|
601
|
-
(0,
|
|
893
|
+
(0, import_react6.useEffect)(() => {
|
|
602
894
|
const onMessage = (event) => {
|
|
603
895
|
const data = event.data;
|
|
604
896
|
if (!data || data.source !== "payload-visual-builder-child") {
|
|
@@ -643,7 +935,7 @@ function PageEditorFrame({ src }) {
|
|
|
643
935
|
window.addEventListener("message", onMessage);
|
|
644
936
|
return () => window.removeEventListener("message", onMessage);
|
|
645
937
|
}, [awaitingDirtyCheck, pendingNavigationURL]);
|
|
646
|
-
(0,
|
|
938
|
+
(0, import_react6.useEffect)(() => {
|
|
647
939
|
const onDocumentClick = (event) => {
|
|
648
940
|
if (!hasUnsavedChanges) {
|
|
649
941
|
return;
|
|
@@ -706,7 +998,7 @@ function PageEditorFrame({ src }) {
|
|
|
706
998
|
document.addEventListener("click", onDocumentClick, true);
|
|
707
999
|
return () => document.removeEventListener("click", onDocumentClick, true);
|
|
708
1000
|
}, [hasUnsavedChanges]);
|
|
709
|
-
(0,
|
|
1001
|
+
(0, import_react6.useEffect)(() => {
|
|
710
1002
|
if (!hasUnsavedChanges) {
|
|
711
1003
|
return;
|
|
712
1004
|
}
|
|
@@ -717,14 +1009,14 @@ function PageEditorFrame({ src }) {
|
|
|
717
1009
|
window.addEventListener("beforeunload", onBeforeUnload);
|
|
718
1010
|
return () => window.removeEventListener("beforeunload", onBeforeUnload);
|
|
719
1011
|
}, [hasUnsavedChanges]);
|
|
720
|
-
(0,
|
|
1012
|
+
(0, import_react6.useEffect)(
|
|
721
1013
|
() => () => {
|
|
722
1014
|
clearDirtyCheckTimer();
|
|
723
1015
|
},
|
|
724
1016
|
[]
|
|
725
1017
|
);
|
|
726
|
-
return /* @__PURE__ */ (0,
|
|
727
|
-
/* @__PURE__ */ (0,
|
|
1018
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "grid", gap: "0.8rem" }, children: [
|
|
1019
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
728
1020
|
"div",
|
|
729
1021
|
{
|
|
730
1022
|
style: {
|
|
@@ -739,9 +1031,9 @@ function PageEditorFrame({ src }) {
|
|
|
739
1031
|
padding: "0.7rem 0.8rem"
|
|
740
1032
|
},
|
|
741
1033
|
children: [
|
|
742
|
-
/* @__PURE__ */ (0,
|
|
743
|
-
/* @__PURE__ */ (0,
|
|
744
|
-
/* @__PURE__ */ (0,
|
|
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)(
|
|
745
1037
|
"button",
|
|
746
1038
|
{
|
|
747
1039
|
className: "orion-admin-action-button",
|
|
@@ -752,7 +1044,7 @@ function PageEditorFrame({ src }) {
|
|
|
752
1044
|
children: "Undo"
|
|
753
1045
|
}
|
|
754
1046
|
),
|
|
755
|
-
/* @__PURE__ */ (0,
|
|
1047
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
756
1048
|
"button",
|
|
757
1049
|
{
|
|
758
1050
|
className: "orion-admin-action-button",
|
|
@@ -763,7 +1055,7 @@ function PageEditorFrame({ src }) {
|
|
|
763
1055
|
children: "Redo"
|
|
764
1056
|
}
|
|
765
1057
|
),
|
|
766
|
-
/* @__PURE__ */ (0,
|
|
1058
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
767
1059
|
"button",
|
|
768
1060
|
{
|
|
769
1061
|
className: "orion-admin-action-button",
|
|
@@ -773,7 +1065,7 @@ function PageEditorFrame({ src }) {
|
|
|
773
1065
|
children: saving === "draft" ? "Saving..." : "Save Draft"
|
|
774
1066
|
}
|
|
775
1067
|
),
|
|
776
|
-
/* @__PURE__ */ (0,
|
|
1068
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
777
1069
|
"button",
|
|
778
1070
|
{
|
|
779
1071
|
className: "orion-admin-action-button",
|
|
@@ -788,9 +1080,9 @@ function PageEditorFrame({ src }) {
|
|
|
788
1080
|
]
|
|
789
1081
|
}
|
|
790
1082
|
),
|
|
791
|
-
message ? /* @__PURE__ */ (0,
|
|
792
|
-
error ? /* @__PURE__ */ (0,
|
|
793
|
-
sessionExpired ? /* @__PURE__ */ (0,
|
|
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)(
|
|
794
1086
|
"div",
|
|
795
1087
|
{
|
|
796
1088
|
style: {
|
|
@@ -805,7 +1097,7 @@ function PageEditorFrame({ src }) {
|
|
|
805
1097
|
children: "Session expired. Log in again in a new tab, then save your changes."
|
|
806
1098
|
}
|
|
807
1099
|
) : null,
|
|
808
|
-
/* @__PURE__ */ (0,
|
|
1100
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
809
1101
|
"iframe",
|
|
810
1102
|
{
|
|
811
1103
|
ref: iframeRef,
|
|
@@ -825,7 +1117,7 @@ function PageEditorFrame({ src }) {
|
|
|
825
1117
|
}
|
|
826
1118
|
}
|
|
827
1119
|
),
|
|
828
|
-
pendingNavigationURL && showUnsavedDialog ? /* @__PURE__ */ (0,
|
|
1120
|
+
pendingNavigationURL && showUnsavedDialog ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
829
1121
|
"div",
|
|
830
1122
|
{
|
|
831
1123
|
"data-orion-unsaved-dialog": "true",
|
|
@@ -839,7 +1131,7 @@ function PageEditorFrame({ src }) {
|
|
|
839
1131
|
position: "fixed",
|
|
840
1132
|
zIndex: 2e3
|
|
841
1133
|
},
|
|
842
|
-
children: /* @__PURE__ */ (0,
|
|
1134
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
843
1135
|
"div",
|
|
844
1136
|
{
|
|
845
1137
|
style: {
|
|
@@ -854,12 +1146,12 @@ function PageEditorFrame({ src }) {
|
|
|
854
1146
|
width: "100%"
|
|
855
1147
|
},
|
|
856
1148
|
children: [
|
|
857
|
-
/* @__PURE__ */ (0,
|
|
858
|
-
/* @__PURE__ */ (0,
|
|
859
|
-
/* @__PURE__ */ (0,
|
|
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?" })
|
|
860
1152
|
] }),
|
|
861
|
-
/* @__PURE__ */ (0,
|
|
862
|
-
/* @__PURE__ */ (0,
|
|
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)(
|
|
863
1155
|
"button",
|
|
864
1156
|
{
|
|
865
1157
|
className: "orion-admin-action-button",
|
|
@@ -871,7 +1163,7 @@ function PageEditorFrame({ src }) {
|
|
|
871
1163
|
children: "Stay"
|
|
872
1164
|
}
|
|
873
1165
|
),
|
|
874
|
-
/* @__PURE__ */ (0,
|
|
1166
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
875
1167
|
"button",
|
|
876
1168
|
{
|
|
877
1169
|
className: "orion-admin-action-button",
|
|
@@ -899,5 +1191,8 @@ function PageEditorFrame({ src }) {
|
|
|
899
1191
|
AdminShellClient,
|
|
900
1192
|
HeaderNavEditorWithPreview,
|
|
901
1193
|
HeaderNavItemsEditor,
|
|
1194
|
+
MediaDetailPanel,
|
|
1195
|
+
MediaListItem,
|
|
1196
|
+
MediaUploadForm,
|
|
902
1197
|
PageEditorFrame
|
|
903
1198
|
});
|
|
@@ -509,22 +509,311 @@ function HeaderNavEditorWithPreview({
|
|
|
509
509
|
] });
|
|
510
510
|
}
|
|
511
511
|
|
|
512
|
-
// src/admin-app/components/
|
|
513
|
-
import {
|
|
512
|
+
// src/admin-app/components/MediaDetailPanel.tsx
|
|
513
|
+
import { useState as useState4 } from "react";
|
|
514
514
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
515
|
+
function formatFileSize(bytes) {
|
|
516
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
517
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
518
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
519
|
+
}
|
|
520
|
+
function MediaDetailPanel({
|
|
521
|
+
id,
|
|
522
|
+
filename,
|
|
523
|
+
alt,
|
|
524
|
+
url,
|
|
525
|
+
filesize,
|
|
526
|
+
width,
|
|
527
|
+
height,
|
|
528
|
+
mimeType,
|
|
529
|
+
createdAt,
|
|
530
|
+
updateAction,
|
|
531
|
+
deleteAction
|
|
532
|
+
}) {
|
|
533
|
+
const [copied, setCopied] = useState4(false);
|
|
534
|
+
const [confirmDelete, setConfirmDelete] = useState4(false);
|
|
535
|
+
const copyUrl = async () => {
|
|
536
|
+
if (!url) return;
|
|
537
|
+
try {
|
|
538
|
+
await navigator.clipboard.writeText(url);
|
|
539
|
+
setCopied(true);
|
|
540
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
541
|
+
} catch {
|
|
542
|
+
const input = document.createElement("input");
|
|
543
|
+
input.value = url;
|
|
544
|
+
document.body.appendChild(input);
|
|
545
|
+
input.select();
|
|
546
|
+
document.execCommand("copy");
|
|
547
|
+
document.body.removeChild(input);
|
|
548
|
+
setCopied(true);
|
|
549
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
const metaRows = [];
|
|
553
|
+
if (filename) metaRows.push({ label: "Filename", value: filename });
|
|
554
|
+
if (typeof filesize === "number") metaRows.push({ label: "File size", value: formatFileSize(filesize) });
|
|
555
|
+
if (typeof width === "number" && typeof height === "number") metaRows.push({ label: "Dimensions", value: `${width} \xD7 ${height} px` });
|
|
556
|
+
if (mimeType) metaRows.push({ label: "Type", value: mimeType });
|
|
557
|
+
if (createdAt) {
|
|
558
|
+
try {
|
|
559
|
+
metaRows.push({ label: "Uploaded", value: new Date(createdAt).toLocaleDateString() });
|
|
560
|
+
} catch {
|
|
561
|
+
metaRows.push({ label: "Uploaded", value: createdAt });
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
return /* @__PURE__ */ jsxs4("div", { className: "orion-admin-grid", style: { alignItems: "start" }, children: [
|
|
565
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
566
|
+
/* @__PURE__ */ jsx4("div", { className: "orion-admin-card", children: url ? /* @__PURE__ */ jsx4("img", { alt: alt || filename || "Media", src: url, style: { borderRadius: 12, width: "100%" } }) : /* @__PURE__ */ jsx4("span", { children: "No preview available." }) }),
|
|
567
|
+
url ? /* @__PURE__ */ jsx4(
|
|
568
|
+
"button",
|
|
569
|
+
{
|
|
570
|
+
className: "orion-admin-action-button",
|
|
571
|
+
onClick: copyUrl,
|
|
572
|
+
style: { marginTop: "0.6rem", width: "100%" },
|
|
573
|
+
type: "button",
|
|
574
|
+
children: copied ? "Copied!" : "Copy URL"
|
|
575
|
+
}
|
|
576
|
+
) : null
|
|
577
|
+
] }),
|
|
578
|
+
/* @__PURE__ */ jsxs4("div", { style: { display: "grid", gap: "0.8rem" }, children: [
|
|
579
|
+
metaRows.length > 0 ? /* @__PURE__ */ jsx4("div", { className: "orion-admin-card orion-admin-meta-table", children: metaRows.map((row) => /* @__PURE__ */ jsxs4("div", { className: "orion-admin-meta-row", children: [
|
|
580
|
+
/* @__PURE__ */ jsx4("span", { className: "orion-admin-meta-label", children: row.label }),
|
|
581
|
+
/* @__PURE__ */ jsx4("span", { className: "orion-admin-meta-value", children: row.value })
|
|
582
|
+
] }, row.label)) }) : null,
|
|
583
|
+
/* @__PURE__ */ jsxs4("form", { action: updateAction, className: "orion-admin-form", children: [
|
|
584
|
+
/* @__PURE__ */ jsx4("input", { name: "id", type: "hidden", value: id }),
|
|
585
|
+
/* @__PURE__ */ jsxs4("label", { children: [
|
|
586
|
+
"Alt text",
|
|
587
|
+
/* @__PURE__ */ jsx4("input", { defaultValue: alt || "", name: "alt", required: true, type: "text" })
|
|
588
|
+
] }),
|
|
589
|
+
/* @__PURE__ */ jsx4("button", { type: "submit", children: "Save" })
|
|
590
|
+
] }),
|
|
591
|
+
confirmDelete ? /* @__PURE__ */ jsxs4("div", { className: "orion-admin-form", style: { borderColor: "#b42318" }, children: [
|
|
592
|
+
/* @__PURE__ */ jsx4("p", { style: { fontWeight: 700, margin: 0 }, children: "Are you sure you want to delete this asset?" }),
|
|
593
|
+
/* @__PURE__ */ jsx4("p", { style: { color: "var(--orion-admin-muted)", fontSize: "0.9rem", margin: 0 }, children: "This action cannot be undone." }),
|
|
594
|
+
/* @__PURE__ */ jsxs4("div", { style: { display: "flex", gap: "0.5rem" }, children: [
|
|
595
|
+
/* @__PURE__ */ jsxs4("form", { action: deleteAction, style: { flex: 1 }, children: [
|
|
596
|
+
/* @__PURE__ */ jsx4("input", { name: "id", type: "hidden", value: id }),
|
|
597
|
+
/* @__PURE__ */ jsx4("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" })
|
|
598
|
+
] }),
|
|
599
|
+
/* @__PURE__ */ jsx4(
|
|
600
|
+
"button",
|
|
601
|
+
{
|
|
602
|
+
onClick: () => setConfirmDelete(false),
|
|
603
|
+
style: { background: "transparent", border: "1px solid var(--orion-admin-border)", borderRadius: 10, cursor: "pointer", flex: 1, fontWeight: 700, padding: "0.55rem 0.8rem" },
|
|
604
|
+
type: "button",
|
|
605
|
+
children: "Cancel"
|
|
606
|
+
}
|
|
607
|
+
)
|
|
608
|
+
] })
|
|
609
|
+
] }) : /* @__PURE__ */ jsx4(
|
|
610
|
+
"button",
|
|
611
|
+
{
|
|
612
|
+
className: "orion-admin-action-button",
|
|
613
|
+
onClick: () => setConfirmDelete(true),
|
|
614
|
+
style: { background: "#b42318" },
|
|
615
|
+
type: "button",
|
|
616
|
+
children: "Delete Asset"
|
|
617
|
+
}
|
|
618
|
+
)
|
|
619
|
+
] })
|
|
620
|
+
] });
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// src/admin-app/components/MediaListItem.tsx
|
|
624
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
625
|
+
function formatFileSize2(bytes) {
|
|
626
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
627
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
628
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
629
|
+
}
|
|
630
|
+
function MediaListItem({
|
|
631
|
+
id,
|
|
632
|
+
filename,
|
|
633
|
+
alt,
|
|
634
|
+
url,
|
|
635
|
+
filesize,
|
|
636
|
+
width,
|
|
637
|
+
height,
|
|
638
|
+
mimeType,
|
|
639
|
+
href
|
|
640
|
+
}) {
|
|
641
|
+
const label = filename || `Media ${id}`;
|
|
642
|
+
const altText = alt || "";
|
|
643
|
+
const metaParts = [];
|
|
644
|
+
if (typeof filesize === "number") metaParts.push(formatFileSize2(filesize));
|
|
645
|
+
if (typeof width === "number" && typeof height === "number") metaParts.push(`${width}\xD7${height}`);
|
|
646
|
+
if (typeof mimeType === "string") metaParts.push(mimeType);
|
|
647
|
+
return /* @__PURE__ */ jsxs5("a", { className: "orion-admin-list-item", href, children: [
|
|
648
|
+
/* @__PURE__ */ jsxs5("div", { style: { alignItems: "center", display: "flex", gap: "0.8rem" }, children: [
|
|
649
|
+
url ? /* @__PURE__ */ jsx5("img", { alt: altText || label, className: "orion-admin-media-preview", src: url }) : null,
|
|
650
|
+
/* @__PURE__ */ jsxs5("div", { children: [
|
|
651
|
+
/* @__PURE__ */ jsx5("strong", { children: label }),
|
|
652
|
+
/* @__PURE__ */ jsx5("div", { className: "orion-admin-list-meta", children: altText || "No alt text" }),
|
|
653
|
+
metaParts.length > 0 ? /* @__PURE__ */ jsx5("div", { className: "orion-admin-list-meta", style: { marginTop: "0.15rem" }, children: metaParts.join(" \xB7 ") }) : null
|
|
654
|
+
] })
|
|
655
|
+
] }),
|
|
656
|
+
/* @__PURE__ */ jsx5("span", { className: "orion-admin-list-meta", children: "Edit" })
|
|
657
|
+
] });
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// src/admin-app/components/MediaUploadForm.tsx
|
|
661
|
+
import { useState as useState5, useRef, useCallback } from "react";
|
|
662
|
+
import { useRouter } from "next/navigation";
|
|
663
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
664
|
+
var parseUploadError = async (response) => {
|
|
665
|
+
const fallback = "Upload failed. Please check the image and required fields, then try again.";
|
|
666
|
+
try {
|
|
667
|
+
const body = await response.json();
|
|
668
|
+
const nestedMessage = body.errors?.[0]?.data?.errors?.[0]?.message;
|
|
669
|
+
if (typeof nestedMessage === "string" && nestedMessage.trim().length > 0) {
|
|
670
|
+
return nestedMessage;
|
|
671
|
+
}
|
|
672
|
+
const topMessage = body.errors?.[0]?.message;
|
|
673
|
+
if (typeof topMessage === "string" && topMessage.trim().length > 0) {
|
|
674
|
+
return topMessage;
|
|
675
|
+
}
|
|
676
|
+
if (typeof body.message === "string" && body.message.trim().length > 0) {
|
|
677
|
+
return body.message;
|
|
678
|
+
}
|
|
679
|
+
} catch {
|
|
680
|
+
}
|
|
681
|
+
return fallback;
|
|
682
|
+
};
|
|
683
|
+
function MediaUploadForm() {
|
|
684
|
+
const router = useRouter();
|
|
685
|
+
const fileInputRef = useRef(null);
|
|
686
|
+
const [alt, setAlt] = useState5("");
|
|
687
|
+
const [file, setFile] = useState5(null);
|
|
688
|
+
const [preview, setPreview] = useState5(null);
|
|
689
|
+
const [dragging, setDragging] = useState5(false);
|
|
690
|
+
const [submitting, setSubmitting] = useState5(false);
|
|
691
|
+
const [error, setError] = useState5(null);
|
|
692
|
+
const handleFile = useCallback((selectedFile) => {
|
|
693
|
+
setFile(selectedFile);
|
|
694
|
+
if (preview) {
|
|
695
|
+
URL.revokeObjectURL(preview);
|
|
696
|
+
setPreview(null);
|
|
697
|
+
}
|
|
698
|
+
if (selectedFile && selectedFile.type.startsWith("image/")) {
|
|
699
|
+
setPreview(URL.createObjectURL(selectedFile));
|
|
700
|
+
}
|
|
701
|
+
}, [preview]);
|
|
702
|
+
const onDragOver = useCallback((e) => {
|
|
703
|
+
e.preventDefault();
|
|
704
|
+
setDragging(true);
|
|
705
|
+
}, []);
|
|
706
|
+
const onDragLeave = useCallback((e) => {
|
|
707
|
+
e.preventDefault();
|
|
708
|
+
setDragging(false);
|
|
709
|
+
}, []);
|
|
710
|
+
const onDrop = useCallback((e) => {
|
|
711
|
+
e.preventDefault();
|
|
712
|
+
setDragging(false);
|
|
713
|
+
const droppedFile = e.dataTransfer.files?.[0] || null;
|
|
714
|
+
if (droppedFile) {
|
|
715
|
+
handleFile(droppedFile);
|
|
716
|
+
}
|
|
717
|
+
}, [handleFile]);
|
|
718
|
+
const upload = async (event) => {
|
|
719
|
+
event.preventDefault();
|
|
720
|
+
if (!file) {
|
|
721
|
+
setError("Select an image to upload.");
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
setSubmitting(true);
|
|
725
|
+
setError(null);
|
|
726
|
+
try {
|
|
727
|
+
const formData = new FormData();
|
|
728
|
+
const fallbackAlt = file.name.replace(/\.[^/.]+$/, "").trim();
|
|
729
|
+
const resolvedAlt = alt.trim() || fallbackAlt || "Uploaded image";
|
|
730
|
+
formData.set("_payload", JSON.stringify({ alt: resolvedAlt }));
|
|
731
|
+
formData.set("alt", resolvedAlt);
|
|
732
|
+
formData.set("file", file);
|
|
733
|
+
const response = await fetch("/api/media", {
|
|
734
|
+
method: "POST",
|
|
735
|
+
credentials: "include",
|
|
736
|
+
body: formData
|
|
737
|
+
});
|
|
738
|
+
if (!response.ok) {
|
|
739
|
+
throw new Error(await parseUploadError(response));
|
|
740
|
+
}
|
|
741
|
+
setAlt("");
|
|
742
|
+
setFile(null);
|
|
743
|
+
if (preview) {
|
|
744
|
+
URL.revokeObjectURL(preview);
|
|
745
|
+
setPreview(null);
|
|
746
|
+
}
|
|
747
|
+
router.refresh();
|
|
748
|
+
} catch (err) {
|
|
749
|
+
setError(err instanceof Error ? err.message : "Upload failed");
|
|
750
|
+
} finally {
|
|
751
|
+
setSubmitting(false);
|
|
752
|
+
}
|
|
753
|
+
};
|
|
754
|
+
return /* @__PURE__ */ jsxs6("form", { className: "orion-admin-upload-form", onSubmit: upload, children: [
|
|
755
|
+
/* @__PURE__ */ jsxs6("label", { children: [
|
|
756
|
+
"Alt text",
|
|
757
|
+
/* @__PURE__ */ jsx6(
|
|
758
|
+
"input",
|
|
759
|
+
{
|
|
760
|
+
onChange: (event) => setAlt(event.target.value),
|
|
761
|
+
placeholder: "Describe the image",
|
|
762
|
+
type: "text",
|
|
763
|
+
value: alt
|
|
764
|
+
}
|
|
765
|
+
)
|
|
766
|
+
] }),
|
|
767
|
+
/* @__PURE__ */ jsxs6(
|
|
768
|
+
"div",
|
|
769
|
+
{
|
|
770
|
+
className: `orion-admin-dropzone${dragging ? " is-dragging" : ""}${file ? " has-file" : ""}`,
|
|
771
|
+
onClick: () => fileInputRef.current?.click(),
|
|
772
|
+
onDragLeave,
|
|
773
|
+
onDragOver,
|
|
774
|
+
onDrop,
|
|
775
|
+
children: [
|
|
776
|
+
preview ? /* @__PURE__ */ jsxs6("div", { className: "orion-admin-dropzone-preview", children: [
|
|
777
|
+
/* @__PURE__ */ jsx6("img", { alt: "Upload preview", src: preview }),
|
|
778
|
+
/* @__PURE__ */ jsx6("span", { children: file?.name })
|
|
779
|
+
] }) : /* @__PURE__ */ jsxs6("div", { className: "orion-admin-dropzone-label", children: [
|
|
780
|
+
/* @__PURE__ */ jsx6("strong", { children: "Drop an image here" }),
|
|
781
|
+
/* @__PURE__ */ jsx6("span", { children: "or click to browse" })
|
|
782
|
+
] }),
|
|
783
|
+
/* @__PURE__ */ jsx6(
|
|
784
|
+
"input",
|
|
785
|
+
{
|
|
786
|
+
accept: "image/*",
|
|
787
|
+
onChange: (event) => handleFile(event.target.files?.[0] || null),
|
|
788
|
+
ref: fileInputRef,
|
|
789
|
+
style: { display: "none" },
|
|
790
|
+
type: "file"
|
|
791
|
+
}
|
|
792
|
+
)
|
|
793
|
+
]
|
|
794
|
+
}
|
|
795
|
+
),
|
|
796
|
+
error ? /* @__PURE__ */ jsx6("div", { className: "orion-admin-upload-error", children: error }) : null,
|
|
797
|
+
/* @__PURE__ */ jsx6("button", { disabled: submitting, type: "submit", children: submitting ? "Uploading..." : "Upload" })
|
|
798
|
+
] });
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// src/admin-app/components/PageEditorFrame.tsx
|
|
802
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState6 } from "react";
|
|
803
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
515
804
|
function PageEditorFrame({ src }) {
|
|
516
|
-
const iframeRef =
|
|
517
|
-
const dirtyCheckTimerRef =
|
|
518
|
-
const [saving, setSaving] =
|
|
519
|
-
const [message, setMessage] =
|
|
520
|
-
const [error, setError] =
|
|
521
|
-
const [hasUnsavedChanges, setHasUnsavedChanges] =
|
|
522
|
-
const [awaitingDirtyCheck, setAwaitingDirtyCheck] =
|
|
523
|
-
const [pendingNavigationURL, setPendingNavigationURL] =
|
|
524
|
-
const [showUnsavedDialog, setShowUnsavedDialog] =
|
|
525
|
-
const [canUndo, setCanUndo] =
|
|
526
|
-
const [canRedo, setCanRedo] =
|
|
527
|
-
const [sessionExpired, setSessionExpired] =
|
|
805
|
+
const iframeRef = useRef2(null);
|
|
806
|
+
const dirtyCheckTimerRef = useRef2(null);
|
|
807
|
+
const [saving, setSaving] = useState6(null);
|
|
808
|
+
const [message, setMessage] = useState6("");
|
|
809
|
+
const [error, setError] = useState6("");
|
|
810
|
+
const [hasUnsavedChanges, setHasUnsavedChanges] = useState6(false);
|
|
811
|
+
const [awaitingDirtyCheck, setAwaitingDirtyCheck] = useState6(false);
|
|
812
|
+
const [pendingNavigationURL, setPendingNavigationURL] = useState6(null);
|
|
813
|
+
const [showUnsavedDialog, setShowUnsavedDialog] = useState6(false);
|
|
814
|
+
const [canUndo, setCanUndo] = useState6(false);
|
|
815
|
+
const [canRedo, setCanRedo] = useState6(false);
|
|
816
|
+
const [sessionExpired, setSessionExpired] = useState6(false);
|
|
528
817
|
const clearDirtyCheckTimer = () => {
|
|
529
818
|
if (dirtyCheckTimerRef.current) {
|
|
530
819
|
window.clearTimeout(dirtyCheckTimerRef.current);
|
|
@@ -695,8 +984,8 @@ function PageEditorFrame({ src }) {
|
|
|
695
984
|
},
|
|
696
985
|
[]
|
|
697
986
|
);
|
|
698
|
-
return /* @__PURE__ */
|
|
699
|
-
/* @__PURE__ */
|
|
987
|
+
return /* @__PURE__ */ jsxs7("div", { style: { display: "grid", gap: "0.8rem" }, children: [
|
|
988
|
+
/* @__PURE__ */ jsxs7(
|
|
700
989
|
"div",
|
|
701
990
|
{
|
|
702
991
|
style: {
|
|
@@ -711,9 +1000,9 @@ function PageEditorFrame({ src }) {
|
|
|
711
1000
|
padding: "0.7rem 0.8rem"
|
|
712
1001
|
},
|
|
713
1002
|
children: [
|
|
714
|
-
/* @__PURE__ */
|
|
715
|
-
/* @__PURE__ */
|
|
716
|
-
/* @__PURE__ */
|
|
1003
|
+
/* @__PURE__ */ jsx7("div", { style: { color: "var(--orion-admin-muted)", fontSize: "0.9rem" }, children: "Save changes to update the page layout and content." }),
|
|
1004
|
+
/* @__PURE__ */ jsxs7("div", { style: { alignItems: "center", display: "flex", flexWrap: "wrap", gap: "0.5rem" }, children: [
|
|
1005
|
+
/* @__PURE__ */ jsx7(
|
|
717
1006
|
"button",
|
|
718
1007
|
{
|
|
719
1008
|
className: "orion-admin-action-button",
|
|
@@ -724,7 +1013,7 @@ function PageEditorFrame({ src }) {
|
|
|
724
1013
|
children: "Undo"
|
|
725
1014
|
}
|
|
726
1015
|
),
|
|
727
|
-
/* @__PURE__ */
|
|
1016
|
+
/* @__PURE__ */ jsx7(
|
|
728
1017
|
"button",
|
|
729
1018
|
{
|
|
730
1019
|
className: "orion-admin-action-button",
|
|
@@ -735,7 +1024,7 @@ function PageEditorFrame({ src }) {
|
|
|
735
1024
|
children: "Redo"
|
|
736
1025
|
}
|
|
737
1026
|
),
|
|
738
|
-
/* @__PURE__ */
|
|
1027
|
+
/* @__PURE__ */ jsx7(
|
|
739
1028
|
"button",
|
|
740
1029
|
{
|
|
741
1030
|
className: "orion-admin-action-button",
|
|
@@ -745,7 +1034,7 @@ function PageEditorFrame({ src }) {
|
|
|
745
1034
|
children: saving === "draft" ? "Saving..." : "Save Draft"
|
|
746
1035
|
}
|
|
747
1036
|
),
|
|
748
|
-
/* @__PURE__ */
|
|
1037
|
+
/* @__PURE__ */ jsx7(
|
|
749
1038
|
"button",
|
|
750
1039
|
{
|
|
751
1040
|
className: "orion-admin-action-button",
|
|
@@ -760,9 +1049,9 @@ function PageEditorFrame({ src }) {
|
|
|
760
1049
|
]
|
|
761
1050
|
}
|
|
762
1051
|
),
|
|
763
|
-
message ? /* @__PURE__ */
|
|
764
|
-
error ? /* @__PURE__ */
|
|
765
|
-
sessionExpired ? /* @__PURE__ */
|
|
1052
|
+
message ? /* @__PURE__ */ jsx7("div", { style: { color: "#0f7d52", fontSize: "0.9rem", fontWeight: 700 }, children: message }) : null,
|
|
1053
|
+
error ? /* @__PURE__ */ jsx7("div", { className: "orion-admin-error", children: error }) : null,
|
|
1054
|
+
sessionExpired ? /* @__PURE__ */ jsx7(
|
|
766
1055
|
"div",
|
|
767
1056
|
{
|
|
768
1057
|
style: {
|
|
@@ -777,7 +1066,7 @@ function PageEditorFrame({ src }) {
|
|
|
777
1066
|
children: "Session expired. Log in again in a new tab, then save your changes."
|
|
778
1067
|
}
|
|
779
1068
|
) : null,
|
|
780
|
-
/* @__PURE__ */
|
|
1069
|
+
/* @__PURE__ */ jsx7(
|
|
781
1070
|
"iframe",
|
|
782
1071
|
{
|
|
783
1072
|
ref: iframeRef,
|
|
@@ -797,7 +1086,7 @@ function PageEditorFrame({ src }) {
|
|
|
797
1086
|
}
|
|
798
1087
|
}
|
|
799
1088
|
),
|
|
800
|
-
pendingNavigationURL && showUnsavedDialog ? /* @__PURE__ */
|
|
1089
|
+
pendingNavigationURL && showUnsavedDialog ? /* @__PURE__ */ jsx7(
|
|
801
1090
|
"div",
|
|
802
1091
|
{
|
|
803
1092
|
"data-orion-unsaved-dialog": "true",
|
|
@@ -811,7 +1100,7 @@ function PageEditorFrame({ src }) {
|
|
|
811
1100
|
position: "fixed",
|
|
812
1101
|
zIndex: 2e3
|
|
813
1102
|
},
|
|
814
|
-
children: /* @__PURE__ */
|
|
1103
|
+
children: /* @__PURE__ */ jsxs7(
|
|
815
1104
|
"div",
|
|
816
1105
|
{
|
|
817
1106
|
style: {
|
|
@@ -826,12 +1115,12 @@ function PageEditorFrame({ src }) {
|
|
|
826
1115
|
width: "100%"
|
|
827
1116
|
},
|
|
828
1117
|
children: [
|
|
829
|
-
/* @__PURE__ */
|
|
830
|
-
/* @__PURE__ */
|
|
831
|
-
/* @__PURE__ */
|
|
1118
|
+
/* @__PURE__ */ jsxs7("div", { children: [
|
|
1119
|
+
/* @__PURE__ */ jsx7("div", { style: { color: "var(--orion-admin-text)", fontSize: "1rem", fontWeight: 700 }, children: "Unsaved changes" }),
|
|
1120
|
+
/* @__PURE__ */ jsx7("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?" })
|
|
832
1121
|
] }),
|
|
833
|
-
/* @__PURE__ */
|
|
834
|
-
/* @__PURE__ */
|
|
1122
|
+
/* @__PURE__ */ jsxs7("div", { style: { display: "flex", gap: "0.6rem", justifyContent: "flex-end" }, children: [
|
|
1123
|
+
/* @__PURE__ */ jsx7(
|
|
835
1124
|
"button",
|
|
836
1125
|
{
|
|
837
1126
|
className: "orion-admin-action-button",
|
|
@@ -843,7 +1132,7 @@ function PageEditorFrame({ src }) {
|
|
|
843
1132
|
children: "Stay"
|
|
844
1133
|
}
|
|
845
1134
|
),
|
|
846
|
-
/* @__PURE__ */
|
|
1135
|
+
/* @__PURE__ */ jsx7(
|
|
847
1136
|
"button",
|
|
848
1137
|
{
|
|
849
1138
|
className: "orion-admin-action-button",
|
|
@@ -870,5 +1159,8 @@ export {
|
|
|
870
1159
|
AdminShellClient,
|
|
871
1160
|
HeaderNavEditorWithPreview,
|
|
872
1161
|
HeaderNavItemsEditor,
|
|
1162
|
+
MediaDetailPanel,
|
|
1163
|
+
MediaListItem,
|
|
1164
|
+
MediaUploadForm,
|
|
873
1165
|
PageEditorFrame
|
|
874
1166
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { A as AdminBreadcrumbItem, a as AdminBreadcrumbs, b as AdminNavIcon, c as AdminNavInput, d as AdminNavItem, e as AdminNavLinkItem, f as AdminPage, g as AdminPageLinkOption, h as AdminPageRecord, j as AdminRole, N as NestedNavItem,
|
|
1
|
+
export { A as AdminBreadcrumbItem, a as AdminBreadcrumbs, b as AdminNavIcon, c as AdminNavInput, d as AdminNavItem, e as AdminNavLinkItem, f as AdminPage, g as AdminPageLinkOption, h as AdminPageRecord, j as AdminRole, M as MediaDetailPanelProps, k as MediaListItemProps, N as NestedNavItem, l as NestedNavItemInput, m as NestedNavTree, n as buildAdminPageLinkOptions, o as buildNestedNavTree, p as getAdminNavRows, q as navItemIsActive, r as normalizeAdminNavInputs, s as normalizeNestedNavItems, t as parseAdminHeaderNavFromForm, u as roleCanAccessNav } from '../index-ZbOx4OCF.mjs';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import 'react';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { A as AdminBreadcrumbItem, a as AdminBreadcrumbs, b as AdminNavIcon, c as AdminNavInput, d as AdminNavItem, e as AdminNavLinkItem, f as AdminPage, g as AdminPageLinkOption, h as AdminPageRecord, j as AdminRole, N as NestedNavItem,
|
|
1
|
+
export { A as AdminBreadcrumbItem, a as AdminBreadcrumbs, b as AdminNavIcon, c as AdminNavInput, d as AdminNavItem, e as AdminNavLinkItem, f as AdminPage, g as AdminPageLinkOption, h as AdminPageRecord, j as AdminRole, M as MediaDetailPanelProps, k as MediaListItemProps, N as NestedNavItem, l as NestedNavItemInput, m as NestedNavTree, n as buildAdminPageLinkOptions, o as buildNestedNavTree, p as getAdminNavRows, q as navItemIsActive, r as normalizeAdminNavInputs, s as normalizeNestedNavItems, t as parseAdminHeaderNavFromForm, u as roleCanAccessNav } from '../index-ZbOx4OCF.js';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import 'react';
|
|
@@ -253,3 +253,99 @@
|
|
|
253
253
|
grid-template-columns: 1fr;
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
|
+
|
|
257
|
+
.orion-admin-media-preview {
|
|
258
|
+
border-radius: 10px;
|
|
259
|
+
display: block;
|
|
260
|
+
height: 68px;
|
|
261
|
+
object-fit: cover;
|
|
262
|
+
width: 68px;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.orion-admin-meta-table {
|
|
266
|
+
display: grid;
|
|
267
|
+
gap: 0;
|
|
268
|
+
padding: 0;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.orion-admin-meta-row {
|
|
272
|
+
align-items: center;
|
|
273
|
+
display: flex;
|
|
274
|
+
gap: 1rem;
|
|
275
|
+
justify-content: space-between;
|
|
276
|
+
padding: 0.6rem 1rem;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.orion-admin-meta-row:not(:last-child) {
|
|
280
|
+
border-bottom: 1px solid var(--orion-admin-card-border);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.orion-admin-meta-label {
|
|
284
|
+
color: var(--orion-admin-muted);
|
|
285
|
+
font-size: 0.88rem;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.orion-admin-meta-value {
|
|
289
|
+
font-size: 0.92rem;
|
|
290
|
+
font-weight: 700;
|
|
291
|
+
text-align: right;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.orion-admin-dropzone {
|
|
295
|
+
align-items: center;
|
|
296
|
+
border: 2px dashed var(--orion-admin-border);
|
|
297
|
+
border-radius: 12px;
|
|
298
|
+
cursor: pointer;
|
|
299
|
+
display: flex;
|
|
300
|
+
justify-content: center;
|
|
301
|
+
min-height: 120px;
|
|
302
|
+
padding: 1rem;
|
|
303
|
+
transition: border-color 0.15s ease, background 0.15s ease;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.orion-admin-dropzone:hover {
|
|
307
|
+
border-color: var(--orion-admin-muted);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.orion-admin-dropzone.is-dragging {
|
|
311
|
+
background: rgba(24, 95, 69, 0.06);
|
|
312
|
+
border-color: rgba(24, 95, 69, 0.5);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.orion-admin-dropzone.has-file {
|
|
316
|
+
border-style: solid;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.orion-admin-dropzone-label {
|
|
320
|
+
display: grid;
|
|
321
|
+
gap: 0.2rem;
|
|
322
|
+
text-align: center;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.orion-admin-dropzone-label strong {
|
|
326
|
+
font-size: 0.95rem;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.orion-admin-dropzone-label span {
|
|
330
|
+
color: var(--orion-admin-muted);
|
|
331
|
+
font-size: 0.85rem;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.orion-admin-dropzone-preview {
|
|
335
|
+
align-items: center;
|
|
336
|
+
display: flex;
|
|
337
|
+
gap: 0.8rem;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.orion-admin-dropzone-preview img {
|
|
341
|
+
border-radius: 8px;
|
|
342
|
+
height: 60px;
|
|
343
|
+
object-fit: cover;
|
|
344
|
+
width: 60px;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.orion-admin-dropzone-preview span {
|
|
348
|
+
color: var(--orion-admin-text);
|
|
349
|
+
font-size: 0.9rem;
|
|
350
|
+
font-weight: 600;
|
|
351
|
+
}
|
|
@@ -31,6 +31,32 @@ type AdminPageProps = {
|
|
|
31
31
|
};
|
|
32
32
|
declare function AdminPage({ title, description, breadcrumbs, actions, children }: AdminPageProps): react_jsx_runtime.JSX.Element;
|
|
33
33
|
|
|
34
|
+
type MediaDetailPanelProps = {
|
|
35
|
+
id: string;
|
|
36
|
+
filename?: string;
|
|
37
|
+
alt?: string;
|
|
38
|
+
url?: string;
|
|
39
|
+
filesize?: number;
|
|
40
|
+
width?: number;
|
|
41
|
+
height?: number;
|
|
42
|
+
mimeType?: string;
|
|
43
|
+
createdAt?: string;
|
|
44
|
+
updateAction: (formData: FormData) => void;
|
|
45
|
+
deleteAction: (formData: FormData) => void;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
type MediaListItemProps = {
|
|
49
|
+
id: string;
|
|
50
|
+
filename?: string;
|
|
51
|
+
alt?: string;
|
|
52
|
+
url?: string;
|
|
53
|
+
filesize?: number;
|
|
54
|
+
width?: number;
|
|
55
|
+
height?: number;
|
|
56
|
+
mimeType?: string;
|
|
57
|
+
href: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
34
60
|
type NestedNavItemInput = {
|
|
35
61
|
href?: string;
|
|
36
62
|
label?: string;
|
|
@@ -82,6 +108,8 @@ declare const index_AdminPage: typeof AdminPage;
|
|
|
82
108
|
type index_AdminPageLinkOption = AdminPageLinkOption;
|
|
83
109
|
type index_AdminPageRecord = AdminPageRecord;
|
|
84
110
|
type index_AdminRole = AdminRole;
|
|
111
|
+
type index_MediaDetailPanelProps = MediaDetailPanelProps;
|
|
112
|
+
type index_MediaListItemProps = MediaListItemProps;
|
|
85
113
|
type index_NestedNavItem = NestedNavItem;
|
|
86
114
|
type index_NestedNavItemInput = NestedNavItemInput;
|
|
87
115
|
type index_NestedNavTree = NestedNavTree;
|
|
@@ -94,7 +122,7 @@ declare const index_normalizeNestedNavItems: typeof normalizeNestedNavItems;
|
|
|
94
122
|
declare const index_parseAdminHeaderNavFromForm: typeof parseAdminHeaderNavFromForm;
|
|
95
123
|
declare const index_roleCanAccessNav: typeof roleCanAccessNav;
|
|
96
124
|
declare namespace index {
|
|
97
|
-
export { type index_AdminBreadcrumbItem as AdminBreadcrumbItem, index_AdminBreadcrumbs as AdminBreadcrumbs, type index_AdminNavIcon as AdminNavIcon, type index_AdminNavInput as AdminNavInput, type index_AdminNavItem as AdminNavItem, type index_AdminNavLinkItem as AdminNavLinkItem, index_AdminPage as AdminPage, type index_AdminPageLinkOption as AdminPageLinkOption, type index_AdminPageRecord as AdminPageRecord, type index_AdminRole as AdminRole, type index_NestedNavItem as NestedNavItem, type index_NestedNavItemInput as NestedNavItemInput, type index_NestedNavTree as NestedNavTree, index_buildAdminPageLinkOptions as buildAdminPageLinkOptions, index_buildNestedNavTree as buildNestedNavTree, index_getAdminNavRows as getAdminNavRows, index_navItemIsActive as navItemIsActive, index_normalizeAdminNavInputs as normalizeAdminNavInputs, index_normalizeNestedNavItems as normalizeNestedNavItems, index_parseAdminHeaderNavFromForm as parseAdminHeaderNavFromForm, index_roleCanAccessNav as roleCanAccessNav };
|
|
125
|
+
export { type index_AdminBreadcrumbItem as AdminBreadcrumbItem, index_AdminBreadcrumbs as AdminBreadcrumbs, type index_AdminNavIcon as AdminNavIcon, type index_AdminNavInput as AdminNavInput, type index_AdminNavItem as AdminNavItem, type index_AdminNavLinkItem as AdminNavLinkItem, index_AdminPage as AdminPage, type index_AdminPageLinkOption as AdminPageLinkOption, type index_AdminPageRecord as AdminPageRecord, type index_AdminRole as AdminRole, type index_MediaDetailPanelProps as MediaDetailPanelProps, type index_MediaListItemProps as MediaListItemProps, type index_NestedNavItem as NestedNavItem, type index_NestedNavItemInput as NestedNavItemInput, type index_NestedNavTree as NestedNavTree, index_buildAdminPageLinkOptions as buildAdminPageLinkOptions, index_buildNestedNavTree as buildNestedNavTree, index_getAdminNavRows as getAdminNavRows, index_navItemIsActive as navItemIsActive, index_normalizeAdminNavInputs as normalizeAdminNavInputs, index_normalizeNestedNavItems as normalizeNestedNavItems, index_parseAdminHeaderNavFromForm as parseAdminHeaderNavFromForm, index_roleCanAccessNav as roleCanAccessNav };
|
|
98
126
|
}
|
|
99
127
|
|
|
100
|
-
export { type AdminBreadcrumbItem as A, type NestedNavItem as N, AdminBreadcrumbs as a, type AdminNavIcon as b, type AdminNavInput as c, type AdminNavItem as d, type AdminNavLinkItem as e, AdminPage as f, type AdminPageLinkOption as g, type AdminPageRecord as h, index as i, type AdminRole as j, type
|
|
128
|
+
export { type AdminBreadcrumbItem as A, type MediaDetailPanelProps as M, type NestedNavItem as N, AdminBreadcrumbs as a, type AdminNavIcon as b, type AdminNavInput as c, type AdminNavItem as d, type AdminNavLinkItem as e, AdminPage as f, type AdminPageLinkOption as g, type AdminPageRecord as h, index as i, type AdminRole as j, type MediaListItemProps as k, type NestedNavItemInput as l, type NestedNavTree as m, buildAdminPageLinkOptions as n, buildNestedNavTree as o, getAdminNavRows as p, navItemIsActive as q, normalizeAdminNavInputs as r, normalizeNestedNavItems as s, parseAdminHeaderNavFromForm as t, roleCanAccessNav as u };
|
|
@@ -31,6 +31,32 @@ type AdminPageProps = {
|
|
|
31
31
|
};
|
|
32
32
|
declare function AdminPage({ title, description, breadcrumbs, actions, children }: AdminPageProps): react_jsx_runtime.JSX.Element;
|
|
33
33
|
|
|
34
|
+
type MediaDetailPanelProps = {
|
|
35
|
+
id: string;
|
|
36
|
+
filename?: string;
|
|
37
|
+
alt?: string;
|
|
38
|
+
url?: string;
|
|
39
|
+
filesize?: number;
|
|
40
|
+
width?: number;
|
|
41
|
+
height?: number;
|
|
42
|
+
mimeType?: string;
|
|
43
|
+
createdAt?: string;
|
|
44
|
+
updateAction: (formData: FormData) => void;
|
|
45
|
+
deleteAction: (formData: FormData) => void;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
type MediaListItemProps = {
|
|
49
|
+
id: string;
|
|
50
|
+
filename?: string;
|
|
51
|
+
alt?: string;
|
|
52
|
+
url?: string;
|
|
53
|
+
filesize?: number;
|
|
54
|
+
width?: number;
|
|
55
|
+
height?: number;
|
|
56
|
+
mimeType?: string;
|
|
57
|
+
href: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
34
60
|
type NestedNavItemInput = {
|
|
35
61
|
href?: string;
|
|
36
62
|
label?: string;
|
|
@@ -82,6 +108,8 @@ declare const index_AdminPage: typeof AdminPage;
|
|
|
82
108
|
type index_AdminPageLinkOption = AdminPageLinkOption;
|
|
83
109
|
type index_AdminPageRecord = AdminPageRecord;
|
|
84
110
|
type index_AdminRole = AdminRole;
|
|
111
|
+
type index_MediaDetailPanelProps = MediaDetailPanelProps;
|
|
112
|
+
type index_MediaListItemProps = MediaListItemProps;
|
|
85
113
|
type index_NestedNavItem = NestedNavItem;
|
|
86
114
|
type index_NestedNavItemInput = NestedNavItemInput;
|
|
87
115
|
type index_NestedNavTree = NestedNavTree;
|
|
@@ -94,7 +122,7 @@ declare const index_normalizeNestedNavItems: typeof normalizeNestedNavItems;
|
|
|
94
122
|
declare const index_parseAdminHeaderNavFromForm: typeof parseAdminHeaderNavFromForm;
|
|
95
123
|
declare const index_roleCanAccessNav: typeof roleCanAccessNav;
|
|
96
124
|
declare namespace index {
|
|
97
|
-
export { type index_AdminBreadcrumbItem as AdminBreadcrumbItem, index_AdminBreadcrumbs as AdminBreadcrumbs, type index_AdminNavIcon as AdminNavIcon, type index_AdminNavInput as AdminNavInput, type index_AdminNavItem as AdminNavItem, type index_AdminNavLinkItem as AdminNavLinkItem, index_AdminPage as AdminPage, type index_AdminPageLinkOption as AdminPageLinkOption, type index_AdminPageRecord as AdminPageRecord, type index_AdminRole as AdminRole, type index_NestedNavItem as NestedNavItem, type index_NestedNavItemInput as NestedNavItemInput, type index_NestedNavTree as NestedNavTree, index_buildAdminPageLinkOptions as buildAdminPageLinkOptions, index_buildNestedNavTree as buildNestedNavTree, index_getAdminNavRows as getAdminNavRows, index_navItemIsActive as navItemIsActive, index_normalizeAdminNavInputs as normalizeAdminNavInputs, index_normalizeNestedNavItems as normalizeNestedNavItems, index_parseAdminHeaderNavFromForm as parseAdminHeaderNavFromForm, index_roleCanAccessNav as roleCanAccessNav };
|
|
125
|
+
export { type index_AdminBreadcrumbItem as AdminBreadcrumbItem, index_AdminBreadcrumbs as AdminBreadcrumbs, type index_AdminNavIcon as AdminNavIcon, type index_AdminNavInput as AdminNavInput, type index_AdminNavItem as AdminNavItem, type index_AdminNavLinkItem as AdminNavLinkItem, index_AdminPage as AdminPage, type index_AdminPageLinkOption as AdminPageLinkOption, type index_AdminPageRecord as AdminPageRecord, type index_AdminRole as AdminRole, type index_MediaDetailPanelProps as MediaDetailPanelProps, type index_MediaListItemProps as MediaListItemProps, type index_NestedNavItem as NestedNavItem, type index_NestedNavItemInput as NestedNavItemInput, type index_NestedNavTree as NestedNavTree, index_buildAdminPageLinkOptions as buildAdminPageLinkOptions, index_buildNestedNavTree as buildNestedNavTree, index_getAdminNavRows as getAdminNavRows, index_navItemIsActive as navItemIsActive, index_normalizeAdminNavInputs as normalizeAdminNavInputs, index_normalizeNestedNavItems as normalizeNestedNavItems, index_parseAdminHeaderNavFromForm as parseAdminHeaderNavFromForm, index_roleCanAccessNav as roleCanAccessNav };
|
|
98
126
|
}
|
|
99
127
|
|
|
100
|
-
export { type AdminBreadcrumbItem as A, type NestedNavItem as N, AdminBreadcrumbs as a, type AdminNavIcon as b, type AdminNavInput as c, type AdminNavItem as d, type AdminNavLinkItem as e, AdminPage as f, type AdminPageLinkOption as g, type AdminPageRecord as h, index as i, type AdminRole as j, type
|
|
128
|
+
export { type AdminBreadcrumbItem as A, type MediaDetailPanelProps as M, type NestedNavItem as N, AdminBreadcrumbs as a, type AdminNavIcon as b, type AdminNavInput as c, type AdminNavItem as d, type AdminNavLinkItem as e, AdminPage as f, type AdminPageLinkOption as g, type AdminPageRecord as h, index as i, type AdminRole as j, type MediaListItemProps as k, type NestedNavItemInput as l, type NestedNavTree as m, buildAdminPageLinkOptions as n, buildNestedNavTree as o, getAdminNavRows as p, navItemIsActive as q, normalizeAdminNavInputs as r, normalizeNestedNavItems as s, parseAdminHeaderNavFromForm as t, roleCanAccessNav as u };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { i as admin } from './index-Dj21uD_B.mjs';
|
|
2
|
-
export { i as adminApp } from './index-
|
|
2
|
+
export { i as adminApp } from './index-ZbOx4OCF.mjs';
|
|
3
3
|
export { i as blocks } from './index-CluwY0ZQ.mjs';
|
|
4
4
|
export { i as nextjs } from './index-CpG3UHcS.mjs';
|
|
5
5
|
export { i as studio } from './index-CmR6NInu.mjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { i as admin } from './index-Dj21uD_B.js';
|
|
2
|
-
export { i as adminApp } from './index-
|
|
2
|
+
export { i as adminApp } from './index-ZbOx4OCF.js';
|
|
3
3
|
export { i as blocks } from './index-CluwY0ZQ.js';
|
|
4
4
|
export { i as nextjs } from './index-CpG3UHcS.js';
|
|
5
5
|
export { i as studio } from './index-CmR6NInu.js';
|