@orion-studios/payload-studio 0.6.0-beta.106 → 0.6.0-beta.108

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.
@@ -2873,8 +2873,26 @@ function NavIcon({ sectionID }) {
2873
2873
  return null;
2874
2874
  }
2875
2875
  }
2876
+ function LogoutIcon() {
2877
+ const props = {
2878
+ fill: "none",
2879
+ height: iconSize2,
2880
+ stroke: "currentColor",
2881
+ strokeLinecap: "round",
2882
+ strokeLinejoin: "round",
2883
+ strokeWidth: 2,
2884
+ viewBox: "0 0 24 24",
2885
+ width: iconSize2
2886
+ };
2887
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("svg", { ...props, "aria-hidden": "true", children: [
2888
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
2889
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("polyline", { points: "8 17 3 12 8 7" }),
2890
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("line", { x1: "3", y1: "12", x2: "15", y2: "12" })
2891
+ ] });
2892
+ }
2876
2893
  function AdminStudioNav(props) {
2877
2894
  const { user } = (0, import_ui3.useAuth)();
2895
+ const [loggingOut, setLoggingOut] = (0, import_react13.useState)(false);
2878
2896
  const brandName = getPropString(props, "brandName", "Orion Studio");
2879
2897
  const logoUrl = getPropString(props, "logoUrl", "");
2880
2898
  const compact = getPropBoolean(props, "compact", false);
@@ -2885,6 +2903,18 @@ function AdminStudioNav(props) {
2885
2903
  const dashboardPath = adminBasePath;
2886
2904
  const userRole = readUserRole(user);
2887
2905
  const links = (0, import_react13.useMemo)(() => buildStudioNavItems(props, adminBasePath), [adminBasePath, props]);
2906
+ const logout = async () => {
2907
+ setLoggingOut(true);
2908
+ try {
2909
+ await fetch("/api/users/logout", {
2910
+ credentials: "include",
2911
+ method: "POST"
2912
+ });
2913
+ window.location.href = `${adminBasePath}/login`;
2914
+ } finally {
2915
+ setLoggingOut(false);
2916
+ }
2917
+ };
2888
2918
  if (isStudioShellRoute(pathname, props, adminBasePath)) {
2889
2919
  return null;
2890
2920
  }
@@ -2975,7 +3005,38 @@ function AdminStudioNav(props) {
2975
3005
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { color: "var(--theme-elevation-700)", fontSize: "0.85rem" }, children: "Signed in as" }),
2976
3006
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { fontWeight: 800, marginBottom: "0.55rem" }, children: typeof user?.email === "string" ? user.email : "User" })
2977
3007
  ] }) : null,
2978
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ui3.Logout, {})
3008
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3009
+ "button",
3010
+ {
3011
+ "aria-label": "Log out",
3012
+ disabled: loggingOut,
3013
+ onClick: () => void logout(),
3014
+ style: {
3015
+ alignItems: "center",
3016
+ background: "transparent",
3017
+ border: "1px solid var(--theme-elevation-150)",
3018
+ borderRadius: 10,
3019
+ color: "var(--theme-elevation-900)",
3020
+ cursor: loggingOut ? "not-allowed" : "pointer",
3021
+ display: "inline-flex",
3022
+ font: "inherit",
3023
+ fontWeight: 800,
3024
+ gap: compact ? 0 : "0.45rem",
3025
+ justifyContent: "center",
3026
+ minHeight: compact ? 48 : 34,
3027
+ minWidth: compact ? 48 : 0,
3028
+ opacity: loggingOut ? 0.55 : 1,
3029
+ padding: compact ? 0 : "0.4rem 0.62rem",
3030
+ width: compact ? 48 : "auto"
3031
+ },
3032
+ title: "Log out",
3033
+ type: "button",
3034
+ children: [
3035
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(LogoutIcon, {}),
3036
+ !compact ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: loggingOut ? "Logging out..." : "Log out" }) : null
3037
+ ]
3038
+ }
3039
+ )
2979
3040
  ]
2980
3041
  }
2981
3042
  )
@@ -3048,6 +3109,14 @@ function NavIcon2({ name }) {
3048
3109
  return null;
3049
3110
  }
3050
3111
  }
3112
+ function LogoutIcon2() {
3113
+ const props = { width: iconSize3, height: iconSize3, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", style: iconStyle };
3114
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("svg", { ...props, "aria-hidden": "true", children: [
3115
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
3116
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("polyline", { points: "8 17 3 12 8 7" }),
3117
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("line", { x1: "3", y1: "12", x2: "15", y2: "12" })
3118
+ ] });
3119
+ }
3051
3120
  function AdminShellClient({
3052
3121
  children,
3053
3122
  brandName,
@@ -3126,7 +3195,10 @@ function AdminShellClient({
3126
3195
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "orion-admin-user-label", children: "Signed in as" }),
3127
3196
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "orion-admin-user-email", children: userEmail })
3128
3197
  ] }) : null,
3129
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { className: "orion-admin-logout", disabled: loggingOut, onClick: handleLogout, type: "button", children: loggingOut ? "..." : "Log out" })
3198
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { className: "orion-admin-logout", disabled: loggingOut, onClick: handleLogout, type: "button", children: [
3199
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(LogoutIcon2, {}),
3200
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: loggingOut ? "Logging out..." : "Log out" })
3201
+ ] })
3130
3202
  ] })
3131
3203
  ] }),
3132
3204
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("main", { className: "orion-admin-main", children })
@@ -9,7 +9,7 @@ import {
9
9
  SiteFooterPreview,
10
10
  adminNavIcons,
11
11
  buildAdminPageLinkOptions
12
- } from "../chunk-3ZKXHSG5.mjs";
12
+ } from "../chunk-I7IBEYC5.mjs";
13
13
  import "../chunk-ROTPP5CU.mjs";
14
14
  import {
15
15
  BlockPicker,
@@ -1273,9 +1273,9 @@ function WelcomeHeader({
1273
1273
  }
1274
1274
 
1275
1275
  // src/admin/components/studio/AdminStudioNav.tsx
1276
- import { useMemo } from "react";
1276
+ import { useMemo, useState as useState7 } from "react";
1277
1277
  import { usePathname } from "next/navigation";
1278
- import { Logout, useAuth } from "@payloadcms/ui";
1278
+ import { useAuth } from "@payloadcms/ui";
1279
1279
 
1280
1280
  // src/admin/components/studio/adminPathUtils.ts
1281
1281
  import { useEffect as useEffect6, useState as useState6 } from "react";
@@ -1648,8 +1648,26 @@ function NavIcon({ sectionID }) {
1648
1648
  return null;
1649
1649
  }
1650
1650
  }
1651
+ function LogoutIcon() {
1652
+ const props = {
1653
+ fill: "none",
1654
+ height: iconSize2,
1655
+ stroke: "currentColor",
1656
+ strokeLinecap: "round",
1657
+ strokeLinejoin: "round",
1658
+ strokeWidth: 2,
1659
+ viewBox: "0 0 24 24",
1660
+ width: iconSize2
1661
+ };
1662
+ return /* @__PURE__ */ jsxs11("svg", { ...props, "aria-hidden": "true", children: [
1663
+ /* @__PURE__ */ jsx12("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
1664
+ /* @__PURE__ */ jsx12("polyline", { points: "8 17 3 12 8 7" }),
1665
+ /* @__PURE__ */ jsx12("line", { x1: "3", y1: "12", x2: "15", y2: "12" })
1666
+ ] });
1667
+ }
1651
1668
  function AdminStudioNav(props) {
1652
1669
  const { user } = useAuth();
1670
+ const [loggingOut, setLoggingOut] = useState7(false);
1653
1671
  const brandName = getPropString(props, "brandName", "Orion Studio");
1654
1672
  const logoUrl = getPropString(props, "logoUrl", "");
1655
1673
  const compact = getPropBoolean(props, "compact", false);
@@ -1660,6 +1678,18 @@ function AdminStudioNav(props) {
1660
1678
  const dashboardPath = adminBasePath;
1661
1679
  const userRole = readUserRole(user);
1662
1680
  const links = useMemo(() => buildStudioNavItems(props, adminBasePath), [adminBasePath, props]);
1681
+ const logout = async () => {
1682
+ setLoggingOut(true);
1683
+ try {
1684
+ await fetch("/api/users/logout", {
1685
+ credentials: "include",
1686
+ method: "POST"
1687
+ });
1688
+ window.location.href = `${adminBasePath}/login`;
1689
+ } finally {
1690
+ setLoggingOut(false);
1691
+ }
1692
+ };
1663
1693
  if (isStudioShellRoute(pathname, props, adminBasePath)) {
1664
1694
  return null;
1665
1695
  }
@@ -1750,7 +1780,38 @@ function AdminStudioNav(props) {
1750
1780
  /* @__PURE__ */ jsx12("div", { style: { color: "var(--theme-elevation-700)", fontSize: "0.85rem" }, children: "Signed in as" }),
1751
1781
  /* @__PURE__ */ jsx12("div", { style: { fontWeight: 800, marginBottom: "0.55rem" }, children: typeof user?.email === "string" ? user.email : "User" })
1752
1782
  ] }) : null,
1753
- /* @__PURE__ */ jsx12(Logout, {})
1783
+ /* @__PURE__ */ jsxs11(
1784
+ "button",
1785
+ {
1786
+ "aria-label": "Log out",
1787
+ disabled: loggingOut,
1788
+ onClick: () => void logout(),
1789
+ style: {
1790
+ alignItems: "center",
1791
+ background: "transparent",
1792
+ border: "1px solid var(--theme-elevation-150)",
1793
+ borderRadius: 10,
1794
+ color: "var(--theme-elevation-900)",
1795
+ cursor: loggingOut ? "not-allowed" : "pointer",
1796
+ display: "inline-flex",
1797
+ font: "inherit",
1798
+ fontWeight: 800,
1799
+ gap: compact ? 0 : "0.45rem",
1800
+ justifyContent: "center",
1801
+ minHeight: compact ? 48 : 34,
1802
+ minWidth: compact ? 48 : 0,
1803
+ opacity: loggingOut ? 0.55 : 1,
1804
+ padding: compact ? 0 : "0.4rem 0.62rem",
1805
+ width: compact ? 48 : "auto"
1806
+ },
1807
+ title: "Log out",
1808
+ type: "button",
1809
+ children: [
1810
+ /* @__PURE__ */ jsx12(LogoutIcon, {}),
1811
+ !compact ? /* @__PURE__ */ jsx12("span", { children: loggingOut ? "Logging out..." : "Log out" }) : null
1812
+ ]
1813
+ }
1814
+ )
1754
1815
  ]
1755
1816
  }
1756
1817
  )
@@ -1840,7 +1901,7 @@ function AdminPage({ title, description, breadcrumbs, actions, children }) {
1840
1901
  }
1841
1902
 
1842
1903
  // src/admin/components/studio/AdminStudioDashboardClient.tsx
1843
- import { startTransition, useEffect as useEffect7, useMemo as useMemo3, useState as useState7 } from "react";
1904
+ import { startTransition, useEffect as useEffect7, useMemo as useMemo3, useState as useState8 } from "react";
1844
1905
  import Link from "next/link";
1845
1906
  import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1846
1907
  var SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1e3;
@@ -2062,7 +2123,7 @@ function AdminStudioDashboardClient({
2062
2123
  children
2063
2124
  }) {
2064
2125
  const role = isRole(userRole) ? userRole : void 0;
2065
- const [state, setState] = useState7(
2126
+ const [state, setState] = useState8(
2066
2127
  () => formsEnabled && canReviewForms(role) ? {
2067
2128
  forms: { status: "loading" },
2068
2129
  media: { status: "loading" },
@@ -2667,13 +2728,13 @@ function AdminStudioDashboard(rawProps) {
2667
2728
  }
2668
2729
 
2669
2730
  // src/admin/components/studio/AdminStudioPagesListView.tsx
2670
- import { useEffect as useEffect9, useMemo as useMemo5, useState as useState10 } from "react";
2731
+ import { useEffect as useEffect9, useMemo as useMemo5, useState as useState11 } from "react";
2671
2732
  import Link2 from "next/link";
2672
2733
  import { usePathname as usePathname3 } from "next/navigation";
2673
2734
  import { useAuth as useAuth4 } from "@payloadcms/ui";
2674
2735
 
2675
2736
  // src/admin/components/studio/AdminStudioNewPageView.tsx
2676
- import { useState as useState8 } from "react";
2737
+ import { useState as useState9 } from "react";
2677
2738
  import { useAuth as useAuth3 } from "@payloadcms/ui";
2678
2739
  import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
2679
2740
  var pageTemplates = ["standard", "landing", "services", "contact"];
@@ -2698,8 +2759,8 @@ function AdminStudioNewPageView(props) {
2698
2759
  const { user } = useAuth3();
2699
2760
  const adminBasePath = useAdminBasePath();
2700
2761
  const pagesCollectionSlug = getPropString3(props, "pagesCollectionSlug", "pages");
2701
- const [submitting, setSubmitting] = useState8(false);
2702
- const [error, setError] = useState8(null);
2762
+ const [submitting, setSubmitting] = useState9(false);
2763
+ const [error, setError] = useState9(null);
2703
2764
  if (!canManagePages(user)) {
2704
2765
  return /* @__PURE__ */ jsx18(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx18(
2705
2766
  AdminPage,
@@ -2794,7 +2855,7 @@ function AdminStudioNewPageView(props) {
2794
2855
  }
2795
2856
 
2796
2857
  // src/admin/components/studio/AdminStudioPageEditView.tsx
2797
- import { useEffect as useEffect8, useMemo as useMemo4, useRef as useRef3, useState as useState9 } from "react";
2858
+ import { useEffect as useEffect8, useMemo as useMemo4, useRef as useRef3, useState as useState10 } from "react";
2798
2859
  import { SetStepNav } from "@payloadcms/ui";
2799
2860
  import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
2800
2861
  var getPropString4 = (props, key, fallback) => {
@@ -2829,8 +2890,8 @@ function AdminStudioPageEditView(props) {
2829
2890
  const builderBasePath = getPropString4(props, "builderBasePath", "/builder");
2830
2891
  const pagesPath = resolveAdminPath(adminBasePath, "/pages");
2831
2892
  const pageIDFromParams = useMemo4(() => getParam(props.params, "id"), [props.params]);
2832
- const [pageID, setPageID] = useState9(pageIDFromParams);
2833
- const [didResolvePathFallback, setDidResolvePathFallback] = useState9(false);
2893
+ const [pageID, setPageID] = useState10(pageIDFromParams);
2894
+ const [didResolvePathFallback, setDidResolvePathFallback] = useState10(false);
2834
2895
  useEffect8(() => {
2835
2896
  if (pageIDFromParams) {
2836
2897
  setPageID(pageIDFromParams);
@@ -2932,9 +2993,9 @@ function AdminStudioPagesIndexView({
2932
2993
  const { user } = useAuth4();
2933
2994
  const pagesCollectionSlug = getPropString5(props, "pagesCollectionSlug", "pages");
2934
2995
  const newPagePath = resolveAdminPath(adminBasePath, "/pages/new");
2935
- const [loading, setLoading] = useState10(true);
2936
- const [error, setError] = useState10(null);
2937
- const [docs, setDocs] = useState10([]);
2996
+ const [loading, setLoading] = useState11(true);
2997
+ const [error, setError] = useState11(null);
2998
+ const [docs, setDocs] = useState11([]);
2938
2999
  const apiURL = useMemo5(() => {
2939
3000
  const params = new URLSearchParams({
2940
3001
  depth: "0",
@@ -3056,7 +3117,7 @@ function AdminStudioGlobalsView(props) {
3056
3117
  }
3057
3118
 
3058
3119
  // src/admin/components/studio/AdminStudioSiteSettingsGlobalView.tsx
3059
- import { useEffect as useEffect10, useMemo as useMemo6, useState as useState11 } from "react";
3120
+ import { useEffect as useEffect10, useMemo as useMemo6, useState as useState12 } from "react";
3060
3121
  import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
3061
3122
  var getPropString6 = (props, key, fallback) => {
3062
3123
  if (!props || typeof props !== "object") return fallback;
@@ -3142,12 +3203,12 @@ function AdminStudioSiteSettingsGlobalView(props) {
3142
3203
  const mediaCollectionSlug = getPropString6(props, "mediaCollectionSlug", "media");
3143
3204
  const adminBasePath = useAdminBasePath();
3144
3205
  const resolvedGlobalsBasePath = resolveAdminPath(adminBasePath, globalsBasePath);
3145
- const [loading, setLoading] = useState11(true);
3146
- const [saving, setSaving] = useState11(false);
3147
- const [error, setError] = useState11(null);
3148
- const [savedMessage, setSavedMessage] = useState11(null);
3149
- const [globalData, setGlobalData] = useState11({});
3150
- const [mediaOptions, setMediaOptions] = useState11([]);
3206
+ const [loading, setLoading] = useState12(true);
3207
+ const [saving, setSaving] = useState12(false);
3208
+ const [error, setError] = useState12(null);
3209
+ const [savedMessage, setSavedMessage] = useState12(null);
3210
+ const [globalData, setGlobalData] = useState12({});
3211
+ const [mediaOptions, setMediaOptions] = useState12([]);
3151
3212
  useEffect10(() => {
3152
3213
  let cancelled = false;
3153
3214
  const run = async () => {
@@ -3432,7 +3493,7 @@ function AdminStudioSiteSettingsGlobalView(props) {
3432
3493
  }
3433
3494
 
3434
3495
  // src/admin/components/studio/AdminStudioSocialMediaGlobalView.tsx
3435
- import { useEffect as useEffect11, useMemo as useMemo7, useState as useState12 } from "react";
3496
+ import { useEffect as useEffect11, useMemo as useMemo7, useState as useState13 } from "react";
3436
3497
 
3437
3498
  // src/shared/socialMedia.ts
3438
3499
  var SOCIAL_MEDIA_PLATFORM_LABELS = {
@@ -3569,11 +3630,11 @@ function AdminStudioSocialMediaGlobalView(props) {
3569
3630
  const globalsBasePath = getPropString7(props, "globalsBasePath", "/globals");
3570
3631
  const adminBasePath = useAdminBasePath();
3571
3632
  const resolvedGlobalsBasePath = resolveAdminPath(adminBasePath, globalsBasePath);
3572
- const [loading, setLoading] = useState12(true);
3573
- const [saving, setSaving] = useState12(false);
3574
- const [error, setError] = useState12(null);
3575
- const [savedMessage, setSavedMessage] = useState12(null);
3576
- const [globalData, setGlobalData] = useState12({});
3633
+ const [loading, setLoading] = useState13(true);
3634
+ const [saving, setSaving] = useState13(false);
3635
+ const [error, setError] = useState13(null);
3636
+ const [savedMessage, setSavedMessage] = useState13(null);
3637
+ const [globalData, setGlobalData] = useState13({});
3577
3638
  useEffect11(() => {
3578
3639
  let cancelled = false;
3579
3640
  const run = async () => {
@@ -3713,7 +3774,7 @@ function AdminStudioSocialMediaGlobalView(props) {
3713
3774
  }
3714
3775
 
3715
3776
  // src/admin/components/studio/AdminStudioHeaderGlobalView.tsx
3716
- import { useEffect as useEffect12, useMemo as useMemo8, useState as useState13 } from "react";
3777
+ import { useEffect as useEffect12, useMemo as useMemo8, useState as useState14 } from "react";
3717
3778
  import { SetStepNav as SetStepNav2 } from "@payloadcms/ui";
3718
3779
 
3719
3780
  // src/nextjs/utilities/socialMedia.ts
@@ -3809,15 +3870,15 @@ function AdminStudioHeaderGlobalView(props) {
3809
3870
  const adminBasePath = useAdminBasePath();
3810
3871
  const resolvedGlobalsBasePath = resolveAdminPath(adminBasePath, globalsBasePath);
3811
3872
  const rawGlobalPath = resolveAdminPath(adminBasePath, `/globals/${globalSlug}`);
3812
- const [loading, setLoading] = useState13(true);
3813
- const [saving, setSaving] = useState13(false);
3814
- const [error, setError] = useState13(null);
3815
- const [savedMessage, setSavedMessage] = useState13(null);
3816
- const [initialItems, setInitialItems] = useState13([]);
3817
- const [liveItems, setLiveItems] = useState13([]);
3818
- const [pages, setPages] = useState13([]);
3819
- const [siteSettings, setSiteSettings] = useState13({});
3820
- const [socialMedia, setSocialMedia] = useState13({});
3873
+ const [loading, setLoading] = useState14(true);
3874
+ const [saving, setSaving] = useState14(false);
3875
+ const [error, setError] = useState14(null);
3876
+ const [savedMessage, setSavedMessage] = useState14(null);
3877
+ const [initialItems, setInitialItems] = useState14([]);
3878
+ const [liveItems, setLiveItems] = useState14([]);
3879
+ const [pages, setPages] = useState14([]);
3880
+ const [siteSettings, setSiteSettings] = useState14({});
3881
+ const [socialMedia, setSocialMedia] = useState14({});
3821
3882
  useEffect12(() => {
3822
3883
  let cancelled = false;
3823
3884
  const run = async () => {
@@ -3984,7 +4045,7 @@ function AdminStudioHeaderGlobalView(props) {
3984
4045
  }
3985
4046
 
3986
4047
  // src/admin/components/studio/AdminStudioFooterGlobalView.tsx
3987
- import { useEffect as useEffect13, useMemo as useMemo9, useState as useState14 } from "react";
4048
+ import { useEffect as useEffect13, useMemo as useMemo9, useState as useState15 } from "react";
3988
4049
  import { SetStepNav as SetStepNav3 } from "@payloadcms/ui";
3989
4050
  import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
3990
4051
  var getPropString9 = (props, key, fallback) => {
@@ -4092,17 +4153,17 @@ function AdminStudioFooterGlobalView(props) {
4092
4153
  const adminBasePath = useAdminBasePath();
4093
4154
  const resolvedGlobalsBasePath = resolveAdminPath(adminBasePath, globalsBasePath);
4094
4155
  const rawGlobalPath = resolveAdminPath(adminBasePath, `/globals/${globalSlug}`);
4095
- const [loading, setLoading] = useState14(true);
4096
- const [saving, setSaving] = useState14(false);
4097
- const [error, setError] = useState14(null);
4098
- const [savedMessage, setSavedMessage] = useState14(null);
4099
- const [doc, setDoc] = useState14({
4156
+ const [loading, setLoading] = useState15(true);
4157
+ const [saving, setSaving] = useState15(false);
4158
+ const [error, setError] = useState15(null);
4159
+ const [savedMessage, setSavedMessage] = useState15(null);
4160
+ const [doc, setDoc] = useState15({
4100
4161
  contactEmail: "",
4101
4162
  contactPhone: "",
4102
4163
  copyright: ""
4103
4164
  });
4104
- const [siteSettings, setSiteSettings] = useState14({});
4105
- const [socialMedia, setSocialMedia] = useState14({});
4165
+ const [siteSettings, setSiteSettings] = useState15({});
4166
+ const [socialMedia, setSocialMedia] = useState15({});
4106
4167
  useEffect13(() => {
4107
4168
  let cancelled = false;
4108
4169
  const run = async () => {
@@ -4359,7 +4420,7 @@ function AdminStudioFooterGlobalView(props) {
4359
4420
  }
4360
4421
 
4361
4422
  // src/admin/components/studio/AdminStudioContactFormView.tsx
4362
- import { useEffect as useEffect14, useMemo as useMemo10, useState as useState15 } from "react";
4423
+ import { useEffect as useEffect14, useMemo as useMemo10, useState as useState16 } from "react";
4363
4424
  import { SetStepNav as SetStepNav4 } from "@payloadcms/ui";
4364
4425
  import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
4365
4426
  var defaultDoc = {
@@ -4450,11 +4511,11 @@ function AdminStudioContactFormView(props) {
4450
4511
  const adminBasePath = useAdminBasePath();
4451
4512
  const resolvedGlobalsBasePath = resolveAdminPath(adminBasePath, globalsBasePath);
4452
4513
  const rawGlobalPath = resolveAdminPath(adminBasePath, `/globals/${globalSlug}`);
4453
- const [doc, setDoc] = useState15(defaultDoc);
4454
- const [error, setError] = useState15(null);
4455
- const [isLoading, setIsLoading] = useState15(true);
4456
- const [isSaving, setIsSaving] = useState15(false);
4457
- const [savedMessage, setSavedMessage] = useState15(null);
4514
+ const [doc, setDoc] = useState16(defaultDoc);
4515
+ const [error, setError] = useState16(null);
4516
+ const [isLoading, setIsLoading] = useState16(true);
4517
+ const [isSaving, setIsSaving] = useState16(false);
4518
+ const [savedMessage, setSavedMessage] = useState16(null);
4458
4519
  useEffect14(() => {
4459
4520
  let mounted = true;
4460
4521
  const load = async () => {
@@ -4685,7 +4746,7 @@ function AdminStudioContactFormView(props) {
4685
4746
  }
4686
4747
 
4687
4748
  // src/admin/components/studio/AdminStudioMediaView.tsx
4688
- import { useEffect as useEffect15, useMemo as useMemo11, useState as useState16 } from "react";
4749
+ import { useEffect as useEffect15, useMemo as useMemo11, useState as useState17 } from "react";
4689
4750
  import { jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
4690
4751
  var MEDIA_LIBRARY_SYNC_EVENT = "orion-media-library-updated";
4691
4752
  var getPropString11 = (props, key, fallback) => {
@@ -4702,9 +4763,9 @@ var getPropString11 = (props, key, fallback) => {
4702
4763
  function AdminStudioMediaView(props) {
4703
4764
  const mediaCollectionSlug = getPropString11(props, "mediaCollectionSlug", "media");
4704
4765
  const adminBasePath = useAdminBasePath();
4705
- const [docs, setDocs] = useState16([]);
4706
- const [loading, setLoading] = useState16(true);
4707
- const [error, setError] = useState16(null);
4766
+ const [docs, setDocs] = useState17([]);
4767
+ const [loading, setLoading] = useState17(true);
4768
+ const [error, setError] = useState17(null);
4708
4769
  const apiURL = useMemo11(() => {
4709
4770
  const params = new URLSearchParams({
4710
4771
  depth: "0",
@@ -4794,7 +4855,7 @@ function AdminStudioMediaView(props) {
4794
4855
  }
4795
4856
 
4796
4857
  // src/admin/components/studio/AdminStudioMediaItemView.tsx
4797
- import { useEffect as useEffect16, useMemo as useMemo12, useState as useState17 } from "react";
4858
+ import { useEffect as useEffect16, useMemo as useMemo12, useState as useState18 } from "react";
4798
4859
  import { jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
4799
4860
  var getPropString12 = (props, key, fallback) => {
4800
4861
  if (!props || typeof props !== "object") return fallback;
@@ -4826,11 +4887,11 @@ function AdminStudioMediaItemView(props) {
4826
4887
  const adminBasePath = useAdminBasePath();
4827
4888
  const mediaPath = resolveAdminPath(adminBasePath, "/media");
4828
4889
  const mediaIDFromParams = useMemo12(() => getParam2(props.params, "id"), [props.params]);
4829
- const [mediaID, setMediaID] = useState17(mediaIDFromParams);
4830
- const [doc, setDoc] = useState17(null);
4831
- const [loading, setLoading] = useState17(true);
4832
- const [error, setError] = useState17(null);
4833
- const [savedMessage, setSavedMessage] = useState17(null);
4890
+ const [mediaID, setMediaID] = useState18(mediaIDFromParams);
4891
+ const [doc, setDoc] = useState18(null);
4892
+ const [loading, setLoading] = useState18(true);
4893
+ const [error, setError] = useState18(null);
4894
+ const [savedMessage, setSavedMessage] = useState18(null);
4834
4895
  useEffect16(() => {
4835
4896
  if (mediaIDFromParams) {
4836
4897
  setMediaID(mediaIDFromParams);
@@ -4942,7 +5003,7 @@ function AdminStudioMediaItemView(props) {
4942
5003
 
4943
5004
  // src/admin/components/studio/AdminStudioFormsView.tsx
4944
5005
  import Link3 from "next/link";
4945
- import { useEffect as useEffect17, useMemo as useMemo13, useState as useState18 } from "react";
5006
+ import { useEffect as useEffect17, useMemo as useMemo13, useState as useState19 } from "react";
4946
5007
  import { useAuth as useAuth5 } from "@payloadcms/ui";
4947
5008
  import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
4948
5009
  var FORM_TONES = [
@@ -5172,10 +5233,10 @@ function AdminStudioFormsView(props) {
5172
5233
  const studioFormsPath = resolveAdminPath(adminBasePath, "/forms");
5173
5234
  const studioSubmissionsPath = resolveAdminPath(adminBasePath, "/forms/submissions");
5174
5235
  const studioUploadsPath = resolveAdminPath(adminBasePath, "/forms/uploads");
5175
- const [forms, setForms] = useState18([]);
5176
- const [submissions, setSubmissions] = useState18([]);
5177
- const [loading, setLoading] = useState18(true);
5178
- const [error, setError] = useState18(null);
5236
+ const [forms, setForms] = useState19([]);
5237
+ const [submissions, setSubmissions] = useState19([]);
5238
+ const [loading, setLoading] = useState19(true);
5239
+ const [error, setError] = useState19(null);
5179
5240
  useEffect17(() => {
5180
5241
  if (!canReviewForms2(user)) {
5181
5242
  return;
@@ -5472,7 +5533,7 @@ function AdminStudioFormsView(props) {
5472
5533
 
5473
5534
  // src/admin/components/studio/AdminStudioFormDetailView.tsx
5474
5535
  import Link4 from "next/link";
5475
- import { useEffect as useEffect18, useMemo as useMemo14, useState as useState19 } from "react";
5536
+ import { useEffect as useEffect18, useMemo as useMemo14, useState as useState20 } from "react";
5476
5537
 
5477
5538
  // src/admin/components/studio/formsStudioShared.ts
5478
5539
  var FORM_TONES2 = [
@@ -5807,15 +5868,15 @@ function AdminStudioFormDetailView(props) {
5807
5868
  const adminBasePath = useAdminBasePath();
5808
5869
  const formsPath = resolveAdminPath(adminBasePath, "/forms");
5809
5870
  const formIDFromParams = useMemo14(() => getParam3(props.params, "id"), [props.params]);
5810
- const [formID, setFormID] = useState19(formIDFromParams);
5811
- const [didResolvePathFallback, setDidResolvePathFallback] = useState19(false);
5812
- const [doc, setDoc] = useState19(null);
5813
- const [submissions, setSubmissions] = useState19([]);
5814
- const [editorState, setEditorState] = useState19(null);
5815
- const [loading, setLoading] = useState19(true);
5816
- const [error, setError] = useState19(null);
5817
- const [saving, setSaving] = useState19(false);
5818
- const [savedMessage, setSavedMessage] = useState19(null);
5871
+ const [formID, setFormID] = useState20(formIDFromParams);
5872
+ const [didResolvePathFallback, setDidResolvePathFallback] = useState20(false);
5873
+ const [doc, setDoc] = useState20(null);
5874
+ const [submissions, setSubmissions] = useState20([]);
5875
+ const [editorState, setEditorState] = useState20(null);
5876
+ const [loading, setLoading] = useState20(true);
5877
+ const [error, setError] = useState20(null);
5878
+ const [saving, setSaving] = useState20(false);
5879
+ const [savedMessage, setSavedMessage] = useState20(null);
5819
5880
  useEffect18(() => {
5820
5881
  if (formIDFromParams) {
5821
5882
  setFormID(formIDFromParams);
@@ -6597,7 +6658,7 @@ function AdminStudioFormDetailView(props) {
6597
6658
 
6598
6659
  // src/admin/components/studio/AdminStudioFormSubmissionView.tsx
6599
6660
  import Link5 from "next/link";
6600
- import { useEffect as useEffect19, useMemo as useMemo15, useState as useState20 } from "react";
6661
+ import { useEffect as useEffect19, useMemo as useMemo15, useState as useState21 } from "react";
6601
6662
  import { Fragment as Fragment6, jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
6602
6663
  var sectionGridStyle2 = {
6603
6664
  display: "grid",
@@ -6657,14 +6718,14 @@ function AdminStudioFormSubmissionView(props) {
6657
6718
  const adminBasePath = useAdminBasePath();
6658
6719
  const formsPath = resolveAdminPath(adminBasePath, "/forms");
6659
6720
  const submissionIDFromParams = useMemo15(() => getParam3(props.params, "id"), [props.params]);
6660
- const [submissionID, setSubmissionID] = useState20(submissionIDFromParams);
6661
- const [didResolvePathFallback, setDidResolvePathFallback] = useState20(false);
6662
- const [doc, setDoc] = useState20(null);
6663
- const [formDoc, setFormDoc] = useState20(null);
6664
- const [loading, setLoading] = useState20(true);
6665
- const [error, setError] = useState20(null);
6666
- const [confirmDelete, setConfirmDelete] = useState20(false);
6667
- const [deleting, setDeleting] = useState20(false);
6721
+ const [submissionID, setSubmissionID] = useState21(submissionIDFromParams);
6722
+ const [didResolvePathFallback, setDidResolvePathFallback] = useState21(false);
6723
+ const [doc, setDoc] = useState21(null);
6724
+ const [formDoc, setFormDoc] = useState21(null);
6725
+ const [loading, setLoading] = useState21(true);
6726
+ const [error, setError] = useState21(null);
6727
+ const [confirmDelete, setConfirmDelete] = useState21(false);
6728
+ const [deleting, setDeleting] = useState21(false);
6668
6729
  useEffect19(() => {
6669
6730
  if (submissionIDFromParams) {
6670
6731
  setSubmissionID(submissionIDFromParams);
@@ -6881,7 +6942,7 @@ function AdminStudioFormSubmissionView(props) {
6881
6942
  }
6882
6943
 
6883
6944
  // src/admin/components/studio/AdminStudioFormUploadView.tsx
6884
- import { useEffect as useEffect20, useMemo as useMemo16, useState as useState21 } from "react";
6945
+ import { useEffect as useEffect20, useMemo as useMemo16, useState as useState22 } from "react";
6885
6946
  import { Fragment as Fragment7, jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
6886
6947
  var previewStyle = {
6887
6948
  borderRadius: 14,
@@ -6898,15 +6959,15 @@ function AdminStudioFormUploadView(props) {
6898
6959
  const adminBasePath = useAdminBasePath();
6899
6960
  const formsPath = resolveAdminPath(adminBasePath, "/forms");
6900
6961
  const uploadIDFromParams = useMemo16(() => getParam3(props.params, "id"), [props.params]);
6901
- const [uploadID, setUploadID] = useState21(uploadIDFromParams);
6902
- const [didResolvePathFallback, setDidResolvePathFallback] = useState21(false);
6903
- const [doc, setDoc] = useState21(null);
6904
- const [loading, setLoading] = useState21(true);
6905
- const [error, setError] = useState21(null);
6906
- const [savedMessage, setSavedMessage] = useState21(null);
6907
- const [saving, setSaving] = useState21(false);
6908
- const [confirmDelete, setConfirmDelete] = useState21(false);
6909
- const [deleting, setDeleting] = useState21(false);
6962
+ const [uploadID, setUploadID] = useState22(uploadIDFromParams);
6963
+ const [didResolvePathFallback, setDidResolvePathFallback] = useState22(false);
6964
+ const [doc, setDoc] = useState22(null);
6965
+ const [loading, setLoading] = useState22(true);
6966
+ const [error, setError] = useState22(null);
6967
+ const [savedMessage, setSavedMessage] = useState22(null);
6968
+ const [saving, setSaving] = useState22(false);
6969
+ const [confirmDelete, setConfirmDelete] = useState22(false);
6970
+ const [deleting, setDeleting] = useState22(false);
6910
6971
  useEffect20(() => {
6911
6972
  if (uploadIDFromParams) {
6912
6973
  setUploadID(uploadIDFromParams);
@@ -7097,7 +7158,7 @@ function AdminStudioFormUploadView(props) {
7097
7158
  }
7098
7159
 
7099
7160
  // src/admin/components/studio/AdminStudioToolsView.tsx
7100
- import { useEffect as useEffect21, useState as useState22 } from "react";
7161
+ import { useEffect as useEffect21, useState as useState23 } from "react";
7101
7162
  import { useAuth as useAuth6 } from "@payloadcms/ui";
7102
7163
  import { jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
7103
7164
  var userRoles = ["admin", "developer", "editor", "client"];
@@ -7110,12 +7171,12 @@ var normalizeRole = (value) => userRoles.includes(value) ? value : "editor";
7110
7171
  function AdminStudioToolsView(props) {
7111
7172
  const { user } = useAuth6();
7112
7173
  const adminBasePath = useAdminBasePath();
7113
- const [docs, setDocs] = useState22([]);
7114
- const [loading, setLoading] = useState22(true);
7115
- const [error, setError] = useState22(null);
7116
- const [savedMessage, setSavedMessage] = useState22(null);
7117
- const [createSubmitting, setCreateSubmitting] = useState22(false);
7118
- const [updatingUserID, setUpdatingUserID] = useState22(null);
7174
+ const [docs, setDocs] = useState23([]);
7175
+ const [loading, setLoading] = useState23(true);
7176
+ const [error, setError] = useState23(null);
7177
+ const [savedMessage, setSavedMessage] = useState23(null);
7178
+ const [createSubmitting, setCreateSubmitting] = useState23(false);
7179
+ const [updatingUserID, setUpdatingUserID] = useState23(null);
7119
7180
  if (!hasAdminAccess3(user)) {
7120
7181
  return /* @__PURE__ */ jsx33(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx33(
7121
7182
  AdminPage,
@@ -7389,7 +7450,7 @@ function StudioDocumentRedirect({
7389
7450
  }
7390
7451
 
7391
7452
  // src/admin/components/studio/StudioBackBreadcrumb.tsx
7392
- import { useEffect as useEffect24, useState as useState23 } from "react";
7453
+ import { useEffect as useEffect24, useState as useState24 } from "react";
7393
7454
  import { SetStepNav as SetStepNav5 } from "@payloadcms/ui";
7394
7455
  import { jsx as jsx37 } from "react/jsx-runtime";
7395
7456
  var toTitle = (slug) => slug.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
@@ -7436,7 +7497,7 @@ var buildNav = (pathname, adminBasePath) => {
7436
7497
  };
7437
7498
  function StudioBackBreadcrumb() {
7438
7499
  const adminBasePath = useAdminBasePath();
7439
- const [pathname, setPathname] = useState23("");
7500
+ const [pathname, setPathname] = useState24("");
7440
7501
  useEffect24(() => {
7441
7502
  const update = () => setPathname(window.location.pathname);
7442
7503
  update();
@@ -111,6 +111,14 @@ function NavIcon({ name }) {
111
111
  return null;
112
112
  }
113
113
  }
114
+ function LogoutIcon() {
115
+ const props = { width: iconSize, height: iconSize, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", style: iconStyle };
116
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...props, "aria-hidden": "true", children: [
117
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
118
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "8 17 3 12 8 7" }),
119
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "3", y1: "12", x2: "15", y2: "12" })
120
+ ] });
121
+ }
114
122
  function AdminShellClient({
115
123
  children,
116
124
  brandName,
@@ -189,7 +197,10 @@ function AdminShellClient({
189
197
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "orion-admin-user-label", children: "Signed in as" }),
190
198
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "orion-admin-user-email", children: userEmail })
191
199
  ] }) : null,
192
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "orion-admin-logout", disabled: loggingOut, onClick: handleLogout, type: "button", children: loggingOut ? "..." : "Log out" })
200
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { className: "orion-admin-logout", disabled: loggingOut, onClick: handleLogout, type: "button", children: [
201
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LogoutIcon, {}),
202
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: loggingOut ? "Logging out..." : "Log out" })
203
+ ] })
193
204
  ] })
194
205
  ] }),
195
206
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("main", { className: "orion-admin-main", children })
@@ -8,7 +8,7 @@ import {
8
8
  MediaUploadForm,
9
9
  SiteFooterPreview,
10
10
  SiteHeaderPreview
11
- } from "../chunk-3ZKXHSG5.mjs";
11
+ } from "../chunk-I7IBEYC5.mjs";
12
12
  import "../chunk-ROTPP5CU.mjs";
13
13
 
14
14
  // src/admin-app/components/PageEditorFrame.tsx
@@ -299,16 +299,34 @@
299
299
  }
300
300
 
301
301
  .orion-admin-logout {
302
+ align-items: center;
302
303
  background: transparent;
303
304
  border: 1px solid var(--orion-admin-border);
304
305
  border-radius: var(--orion-admin-radius-xs);
305
306
  color: var(--orion-admin-text);
306
307
  cursor: pointer;
308
+ display: inline-flex;
307
309
  font-weight: 700;
310
+ gap: 0.45rem;
311
+ justify-content: center;
308
312
  margin-top: 0.6rem;
309
313
  padding: 0.4rem 0.65rem;
310
314
  }
311
315
 
316
+ .orion-admin-logout svg {
317
+ flex: 0 0 auto;
318
+ }
319
+
320
+ .is-collapsed .orion-admin-logout {
321
+ height: 48px;
322
+ padding: 0;
323
+ width: 48px;
324
+ }
325
+
326
+ .is-collapsed .orion-admin-logout span {
327
+ display: none;
328
+ }
329
+
312
330
  .orion-admin-logout:hover:not(:disabled) {
313
331
  background: var(--orion-admin-control-hover-bg);
314
332
  }
@@ -92,6 +92,14 @@ function NavIcon({ name }) {
92
92
  return null;
93
93
  }
94
94
  }
95
+ function LogoutIcon() {
96
+ const props = { width: iconSize, height: iconSize, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", style: iconStyle };
97
+ return /* @__PURE__ */ jsxs("svg", { ...props, "aria-hidden": "true", children: [
98
+ /* @__PURE__ */ jsx("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
99
+ /* @__PURE__ */ jsx("polyline", { points: "8 17 3 12 8 7" }),
100
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "12", x2: "15", y2: "12" })
101
+ ] });
102
+ }
95
103
  function AdminShellClient({
96
104
  children,
97
105
  brandName,
@@ -170,7 +178,10 @@ function AdminShellClient({
170
178
  /* @__PURE__ */ jsx("div", { className: "orion-admin-user-label", children: "Signed in as" }),
171
179
  /* @__PURE__ */ jsx("div", { className: "orion-admin-user-email", children: userEmail })
172
180
  ] }) : null,
173
- /* @__PURE__ */ jsx("button", { className: "orion-admin-logout", disabled: loggingOut, onClick: handleLogout, type: "button", children: loggingOut ? "..." : "Log out" })
181
+ /* @__PURE__ */ jsxs("button", { className: "orion-admin-logout", disabled: loggingOut, onClick: handleLogout, type: "button", children: [
182
+ /* @__PURE__ */ jsx(LogoutIcon, {}),
183
+ /* @__PURE__ */ jsx("span", { children: loggingOut ? "Logging out..." : "Log out" })
184
+ ] })
174
185
  ] })
175
186
  ] }),
176
187
  /* @__PURE__ */ jsx("main", { className: "orion-admin-main", children })
@@ -723,13 +734,124 @@ function HeaderNavEditorWithPreview({
723
734
  ] });
724
735
  }
725
736
 
726
- // src/admin-app/components/MediaListItem.tsx
737
+ // src/admin-app/components/MediaDetailPanel.tsx
738
+ import { useState as useState4 } from "react";
727
739
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
728
740
  function formatFileSize(bytes) {
729
741
  if (bytes < 1024) return `${bytes} B`;
730
742
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
731
743
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
732
744
  }
745
+ function MediaDetailPanel({
746
+ id,
747
+ filename,
748
+ alt,
749
+ url,
750
+ filesize,
751
+ width,
752
+ height,
753
+ mimeType,
754
+ createdAt,
755
+ updateAction,
756
+ deleteAction
757
+ }) {
758
+ const [copied, setCopied] = useState4(false);
759
+ const [confirmDelete, setConfirmDelete] = useState4(false);
760
+ const copyUrl = async () => {
761
+ if (!url) return;
762
+ try {
763
+ await navigator.clipboard.writeText(url);
764
+ setCopied(true);
765
+ setTimeout(() => setCopied(false), 2e3);
766
+ } catch {
767
+ const input = document.createElement("input");
768
+ input.value = url;
769
+ document.body.appendChild(input);
770
+ input.select();
771
+ document.execCommand("copy");
772
+ document.body.removeChild(input);
773
+ setCopied(true);
774
+ setTimeout(() => setCopied(false), 2e3);
775
+ }
776
+ };
777
+ const metaRows = [];
778
+ if (filename) metaRows.push({ label: "Filename", value: filename });
779
+ if (typeof filesize === "number") metaRows.push({ label: "File size", value: formatFileSize(filesize) });
780
+ if (typeof width === "number" && typeof height === "number") metaRows.push({ label: "Dimensions", value: `${width} \xD7 ${height} px` });
781
+ if (mimeType) metaRows.push({ label: "Type", value: mimeType });
782
+ if (createdAt) {
783
+ try {
784
+ metaRows.push({ label: "Uploaded", value: new Date(createdAt).toLocaleDateString() });
785
+ } catch {
786
+ metaRows.push({ label: "Uploaded", value: createdAt });
787
+ }
788
+ }
789
+ return /* @__PURE__ */ jsxs5("div", { className: "orion-admin-grid", style: { alignItems: "start" }, children: [
790
+ /* @__PURE__ */ jsxs5("div", { children: [
791
+ /* @__PURE__ */ jsx5("div", { className: "orion-admin-card", children: url ? /* @__PURE__ */ jsx5("img", { alt: alt || filename || "Media", src: url, style: { borderRadius: 12, width: "100%" } }) : /* @__PURE__ */ jsx5("span", { children: "No preview available." }) }),
792
+ url ? /* @__PURE__ */ jsx5(
793
+ "button",
794
+ {
795
+ className: "orion-admin-action-button",
796
+ onClick: copyUrl,
797
+ style: { marginTop: "0.6rem", width: "100%" },
798
+ type: "button",
799
+ children: copied ? "Copied!" : "Copy URL"
800
+ }
801
+ ) : null
802
+ ] }),
803
+ /* @__PURE__ */ jsxs5("div", { style: { display: "grid", gap: "0.8rem" }, children: [
804
+ metaRows.length > 0 ? /* @__PURE__ */ jsx5("div", { className: "orion-admin-card orion-admin-meta-table", children: metaRows.map((row) => /* @__PURE__ */ jsxs5("div", { className: "orion-admin-meta-row", children: [
805
+ /* @__PURE__ */ jsx5("span", { className: "orion-admin-meta-label", children: row.label }),
806
+ /* @__PURE__ */ jsx5("span", { className: "orion-admin-meta-value", children: row.value })
807
+ ] }, row.label)) }) : null,
808
+ /* @__PURE__ */ jsxs5("form", { action: updateAction, className: "orion-admin-form", children: [
809
+ /* @__PURE__ */ jsx5("input", { name: "id", type: "hidden", value: id }),
810
+ /* @__PURE__ */ jsxs5("label", { children: [
811
+ "Alt text",
812
+ /* @__PURE__ */ jsx5("input", { defaultValue: alt || "", name: "alt", required: true, type: "text" })
813
+ ] }),
814
+ /* @__PURE__ */ jsx5("button", { type: "submit", children: "Save" })
815
+ ] }),
816
+ confirmDelete ? /* @__PURE__ */ jsxs5("div", { className: "orion-admin-form", style: { borderColor: "#b42318" }, children: [
817
+ /* @__PURE__ */ jsx5("p", { style: { fontWeight: 700, margin: 0 }, children: "Are you sure you want to delete this asset?" }),
818
+ /* @__PURE__ */ jsx5("p", { style: { color: "var(--orion-admin-muted)", fontSize: "0.9rem", margin: 0 }, children: "This action cannot be undone." }),
819
+ /* @__PURE__ */ jsxs5("div", { style: { display: "flex", gap: "0.5rem" }, children: [
820
+ /* @__PURE__ */ jsxs5("form", { action: deleteAction, style: { flex: 1 }, children: [
821
+ /* @__PURE__ */ jsx5("input", { name: "id", type: "hidden", value: id }),
822
+ /* @__PURE__ */ jsx5("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" })
823
+ ] }),
824
+ /* @__PURE__ */ jsx5(
825
+ "button",
826
+ {
827
+ onClick: () => setConfirmDelete(false),
828
+ style: { background: "transparent", border: "1px solid var(--orion-admin-border)", borderRadius: 10, cursor: "pointer", flex: 1, fontWeight: 700, padding: "0.55rem 0.8rem" },
829
+ type: "button",
830
+ children: "Cancel"
831
+ }
832
+ )
833
+ ] })
834
+ ] }) : /* @__PURE__ */ jsx5(
835
+ "button",
836
+ {
837
+ className: "orion-admin-action-button",
838
+ onClick: () => setConfirmDelete(true),
839
+ style: { background: "#b42318" },
840
+ type: "button",
841
+ children: "Delete Asset"
842
+ }
843
+ )
844
+ ] })
845
+ ] });
846
+ }
847
+
848
+ // src/admin-app/components/MediaListItem.tsx
849
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
850
+ function formatFileSize2(bytes) {
851
+ if (bytes < 1024) return `${bytes} B`;
852
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
853
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
854
+ }
733
855
  function MediaListItem({
734
856
  id,
735
857
  filename,
@@ -744,26 +866,26 @@ function MediaListItem({
744
866
  const label = filename || `Media ${id}`;
745
867
  const altText = alt || "";
746
868
  const metaParts = [];
747
- if (typeof filesize === "number") metaParts.push(formatFileSize(filesize));
869
+ if (typeof filesize === "number") metaParts.push(formatFileSize2(filesize));
748
870
  if (typeof width === "number" && typeof height === "number") metaParts.push(`${width}\xD7${height}`);
749
871
  if (typeof mimeType === "string") metaParts.push(mimeType);
750
- return /* @__PURE__ */ jsxs5("a", { className: "orion-admin-list-item", href, children: [
751
- /* @__PURE__ */ jsxs5("div", { style: { alignItems: "center", display: "flex", gap: "0.8rem" }, children: [
752
- url ? /* @__PURE__ */ jsx5("img", { alt: altText || label, className: "orion-admin-media-preview", src: url }) : null,
753
- /* @__PURE__ */ jsxs5("div", { children: [
754
- /* @__PURE__ */ jsx5("strong", { children: label }),
755
- /* @__PURE__ */ jsx5("div", { className: "orion-admin-list-meta", children: altText || "No alt text" }),
756
- metaParts.length > 0 ? /* @__PURE__ */ jsx5("div", { className: "orion-admin-list-meta", style: { marginTop: "0.15rem" }, children: metaParts.join(" \xB7 ") }) : null
872
+ return /* @__PURE__ */ jsxs6("a", { className: "orion-admin-list-item", href, children: [
873
+ /* @__PURE__ */ jsxs6("div", { style: { alignItems: "center", display: "flex", gap: "0.8rem" }, children: [
874
+ url ? /* @__PURE__ */ jsx6("img", { alt: altText || label, className: "orion-admin-media-preview", src: url }) : null,
875
+ /* @__PURE__ */ jsxs6("div", { children: [
876
+ /* @__PURE__ */ jsx6("strong", { children: label }),
877
+ /* @__PURE__ */ jsx6("div", { className: "orion-admin-list-meta", children: altText || "No alt text" }),
878
+ metaParts.length > 0 ? /* @__PURE__ */ jsx6("div", { className: "orion-admin-list-meta", style: { marginTop: "0.15rem" }, children: metaParts.join(" \xB7 ") }) : null
757
879
  ] })
758
880
  ] }),
759
- /* @__PURE__ */ jsx5("span", { className: "orion-admin-list-meta", children: "Edit" })
881
+ /* @__PURE__ */ jsx6("span", { className: "orion-admin-list-meta", children: "Edit" })
760
882
  ] });
761
883
  }
762
884
 
763
885
  // src/admin-app/components/MediaUploadForm.tsx
764
- import { useState as useState4, useRef, useCallback } from "react";
886
+ import { useState as useState5, useRef, useCallback } from "react";
765
887
  import { useRouter } from "next/navigation";
766
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
888
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
767
889
  var MEDIA_LIBRARY_SYNC_EVENT = "orion-media-library-updated";
768
890
  var notifyMediaLibraryUpdated = () => {
769
891
  if (typeof window === "undefined") {
@@ -804,12 +926,12 @@ var parseUploadError = async (response) => {
804
926
  function MediaUploadForm() {
805
927
  const router = useRouter();
806
928
  const fileInputRef = useRef(null);
807
- const [alt, setAlt] = useState4("");
808
- const [file, setFile] = useState4(null);
809
- const [preview, setPreview] = useState4(null);
810
- const [dragging, setDragging] = useState4(false);
811
- const [submitting, setSubmitting] = useState4(false);
812
- const [error, setError] = useState4(null);
929
+ const [alt, setAlt] = useState5("");
930
+ const [file, setFile] = useState5(null);
931
+ const [preview, setPreview] = useState5(null);
932
+ const [dragging, setDragging] = useState5(false);
933
+ const [submitting, setSubmitting] = useState5(false);
934
+ const [error, setError] = useState5(null);
813
935
  const handleFile = useCallback((selectedFile) => {
814
936
  setFile(selectedFile);
815
937
  if (preview) {
@@ -877,10 +999,10 @@ function MediaUploadForm() {
877
999
  setSubmitting(false);
878
1000
  }
879
1001
  };
880
- return /* @__PURE__ */ jsxs6("form", { className: "orion-admin-upload-form", onSubmit: upload, children: [
881
- /* @__PURE__ */ jsxs6("label", { children: [
1002
+ return /* @__PURE__ */ jsxs7("form", { className: "orion-admin-upload-form", onSubmit: upload, children: [
1003
+ /* @__PURE__ */ jsxs7("label", { children: [
882
1004
  "Alt text",
883
- /* @__PURE__ */ jsx6(
1005
+ /* @__PURE__ */ jsx7(
884
1006
  "input",
885
1007
  {
886
1008
  onChange: (event) => setAlt(event.target.value),
@@ -890,7 +1012,7 @@ function MediaUploadForm() {
890
1012
  }
891
1013
  )
892
1014
  ] }),
893
- /* @__PURE__ */ jsxs6(
1015
+ /* @__PURE__ */ jsxs7(
894
1016
  "div",
895
1017
  {
896
1018
  className: `orion-admin-dropzone${dragging ? " is-dragging" : ""}${file ? " has-file" : ""}`,
@@ -899,14 +1021,14 @@ function MediaUploadForm() {
899
1021
  onDragOver,
900
1022
  onDrop,
901
1023
  children: [
902
- preview ? /* @__PURE__ */ jsxs6("div", { className: "orion-admin-dropzone-preview", children: [
903
- /* @__PURE__ */ jsx6("img", { alt: "Upload preview", src: preview }),
904
- /* @__PURE__ */ jsx6("span", { children: file?.name })
905
- ] }) : /* @__PURE__ */ jsxs6("div", { className: "orion-admin-dropzone-label", children: [
906
- /* @__PURE__ */ jsx6("strong", { children: "Drop an image here" }),
907
- /* @__PURE__ */ jsx6("span", { children: "or click to browse" })
1024
+ preview ? /* @__PURE__ */ jsxs7("div", { className: "orion-admin-dropzone-preview", children: [
1025
+ /* @__PURE__ */ jsx7("img", { alt: "Upload preview", src: preview }),
1026
+ /* @__PURE__ */ jsx7("span", { children: file?.name })
1027
+ ] }) : /* @__PURE__ */ jsxs7("div", { className: "orion-admin-dropzone-label", children: [
1028
+ /* @__PURE__ */ jsx7("strong", { children: "Drop an image here" }),
1029
+ /* @__PURE__ */ jsx7("span", { children: "or click to browse" })
908
1030
  ] }),
909
- /* @__PURE__ */ jsx6(
1031
+ /* @__PURE__ */ jsx7(
910
1032
  "input",
911
1033
  {
912
1034
  accept: "image/*",
@@ -919,119 +1041,8 @@ function MediaUploadForm() {
919
1041
  ]
920
1042
  }
921
1043
  ),
922
- error ? /* @__PURE__ */ jsx6("div", { className: "orion-admin-upload-error", children: error }) : null,
923
- /* @__PURE__ */ jsx6("button", { disabled: submitting, type: "submit", children: submitting ? "Uploading..." : "Upload" })
924
- ] });
925
- }
926
-
927
- // src/admin-app/components/MediaDetailPanel.tsx
928
- import { useState as useState5 } from "react";
929
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
930
- function formatFileSize2(bytes) {
931
- if (bytes < 1024) return `${bytes} B`;
932
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
933
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
934
- }
935
- function MediaDetailPanel({
936
- id,
937
- filename,
938
- alt,
939
- url,
940
- filesize,
941
- width,
942
- height,
943
- mimeType,
944
- createdAt,
945
- updateAction,
946
- deleteAction
947
- }) {
948
- const [copied, setCopied] = useState5(false);
949
- const [confirmDelete, setConfirmDelete] = useState5(false);
950
- const copyUrl = async () => {
951
- if (!url) return;
952
- try {
953
- await navigator.clipboard.writeText(url);
954
- setCopied(true);
955
- setTimeout(() => setCopied(false), 2e3);
956
- } catch {
957
- const input = document.createElement("input");
958
- input.value = url;
959
- document.body.appendChild(input);
960
- input.select();
961
- document.execCommand("copy");
962
- document.body.removeChild(input);
963
- setCopied(true);
964
- setTimeout(() => setCopied(false), 2e3);
965
- }
966
- };
967
- const metaRows = [];
968
- if (filename) metaRows.push({ label: "Filename", value: filename });
969
- if (typeof filesize === "number") metaRows.push({ label: "File size", value: formatFileSize2(filesize) });
970
- if (typeof width === "number" && typeof height === "number") metaRows.push({ label: "Dimensions", value: `${width} \xD7 ${height} px` });
971
- if (mimeType) metaRows.push({ label: "Type", value: mimeType });
972
- if (createdAt) {
973
- try {
974
- metaRows.push({ label: "Uploaded", value: new Date(createdAt).toLocaleDateString() });
975
- } catch {
976
- metaRows.push({ label: "Uploaded", value: createdAt });
977
- }
978
- }
979
- return /* @__PURE__ */ jsxs7("div", { className: "orion-admin-grid", style: { alignItems: "start" }, children: [
980
- /* @__PURE__ */ jsxs7("div", { children: [
981
- /* @__PURE__ */ jsx7("div", { className: "orion-admin-card", children: url ? /* @__PURE__ */ jsx7("img", { alt: alt || filename || "Media", src: url, style: { borderRadius: 12, width: "100%" } }) : /* @__PURE__ */ jsx7("span", { children: "No preview available." }) }),
982
- url ? /* @__PURE__ */ jsx7(
983
- "button",
984
- {
985
- className: "orion-admin-action-button",
986
- onClick: copyUrl,
987
- style: { marginTop: "0.6rem", width: "100%" },
988
- type: "button",
989
- children: copied ? "Copied!" : "Copy URL"
990
- }
991
- ) : null
992
- ] }),
993
- /* @__PURE__ */ jsxs7("div", { style: { display: "grid", gap: "0.8rem" }, children: [
994
- metaRows.length > 0 ? /* @__PURE__ */ jsx7("div", { className: "orion-admin-card orion-admin-meta-table", children: metaRows.map((row) => /* @__PURE__ */ jsxs7("div", { className: "orion-admin-meta-row", children: [
995
- /* @__PURE__ */ jsx7("span", { className: "orion-admin-meta-label", children: row.label }),
996
- /* @__PURE__ */ jsx7("span", { className: "orion-admin-meta-value", children: row.value })
997
- ] }, row.label)) }) : null,
998
- /* @__PURE__ */ jsxs7("form", { action: updateAction, className: "orion-admin-form", children: [
999
- /* @__PURE__ */ jsx7("input", { name: "id", type: "hidden", value: id }),
1000
- /* @__PURE__ */ jsxs7("label", { children: [
1001
- "Alt text",
1002
- /* @__PURE__ */ jsx7("input", { defaultValue: alt || "", name: "alt", required: true, type: "text" })
1003
- ] }),
1004
- /* @__PURE__ */ jsx7("button", { type: "submit", children: "Save" })
1005
- ] }),
1006
- confirmDelete ? /* @__PURE__ */ jsxs7("div", { className: "orion-admin-form", style: { borderColor: "#b42318" }, children: [
1007
- /* @__PURE__ */ jsx7("p", { style: { fontWeight: 700, margin: 0 }, children: "Are you sure you want to delete this asset?" }),
1008
- /* @__PURE__ */ jsx7("p", { style: { color: "var(--orion-admin-muted)", fontSize: "0.9rem", margin: 0 }, children: "This action cannot be undone." }),
1009
- /* @__PURE__ */ jsxs7("div", { style: { display: "flex", gap: "0.5rem" }, children: [
1010
- /* @__PURE__ */ jsxs7("form", { action: deleteAction, style: { flex: 1 }, children: [
1011
- /* @__PURE__ */ jsx7("input", { name: "id", type: "hidden", value: id }),
1012
- /* @__PURE__ */ jsx7("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" })
1013
- ] }),
1014
- /* @__PURE__ */ jsx7(
1015
- "button",
1016
- {
1017
- onClick: () => setConfirmDelete(false),
1018
- style: { background: "transparent", border: "1px solid var(--orion-admin-border)", borderRadius: 10, cursor: "pointer", flex: 1, fontWeight: 700, padding: "0.55rem 0.8rem" },
1019
- type: "button",
1020
- children: "Cancel"
1021
- }
1022
- )
1023
- ] })
1024
- ] }) : /* @__PURE__ */ jsx7(
1025
- "button",
1026
- {
1027
- className: "orion-admin-action-button",
1028
- onClick: () => setConfirmDelete(true),
1029
- style: { background: "#b42318" },
1030
- type: "button",
1031
- children: "Delete Asset"
1032
- }
1033
- )
1034
- ] })
1044
+ error ? /* @__PURE__ */ jsx7("div", { className: "orion-admin-upload-error", children: error }) : null,
1045
+ /* @__PURE__ */ jsx7("button", { disabled: submitting, type: "submit", children: submitting ? "Uploading..." : "Upload" })
1035
1046
  ] });
1036
1047
  }
1037
1048
 
@@ -1043,7 +1054,7 @@ export {
1043
1054
  SiteHeaderPreview,
1044
1055
  SiteFooterPreview,
1045
1056
  HeaderNavEditorWithPreview,
1057
+ MediaDetailPanel,
1046
1058
  MediaListItem,
1047
- MediaUploadForm,
1048
- MediaDetailPanel
1059
+ MediaUploadForm
1049
1060
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orion-studios/payload-studio",
3
- "version": "0.6.0-beta.106",
3
+ "version": "0.6.0-beta.108",
4
4
  "description": "Base CMS, builder, and custom admin toolkit for Orion Studios websites",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",