@orion-studios/payload-studio 0.5.0-beta.113 → 0.5.0-beta.115

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.
Files changed (42) hide show
  1. package/dist/admin/client.js +1880 -502
  2. package/dist/admin/client.mjs +1164 -329
  3. package/dist/admin/index.d.mts +2 -1
  4. package/dist/admin/index.d.ts +2 -1
  5. package/dist/admin/index.js +267 -59
  6. package/dist/admin/index.mjs +1 -1
  7. package/dist/admin-app/client.d.mts +1 -0
  8. package/dist/admin-app/client.d.ts +1 -0
  9. package/dist/admin-app/client.js +266 -105
  10. package/dist/admin-app/client.mjs +105 -456
  11. package/dist/admin-app/index.d.mts +2 -1
  12. package/dist/admin-app/index.d.ts +2 -1
  13. package/dist/admin-app/styles.css +351 -0
  14. package/dist/admin.css +9 -0
  15. package/dist/chunk-6NE7GIVT.mjs +555 -0
  16. package/dist/{chunk-DAIZDGHL.mjs → chunk-T5PBXPES.mjs} +267 -59
  17. package/dist/{chunk-3T2P6SDM.mjs → chunk-XKUTZ7IU.mjs} +215 -6
  18. package/dist/index-3jBpt6ZT.d.ts +385 -0
  19. package/dist/index-C3FgxbEL.d.mts +385 -0
  20. package/dist/{index-DUi_XND6.d.ts → index-Crx_MtPw.d.ts} +33 -3
  21. package/dist/{index-gLl_358v.d.mts → index-Cv-6qnrw.d.mts} +33 -3
  22. package/dist/{index-BzKOThsI.d.mts → index-DWmudwDm.d.mts} +1 -1
  23. package/dist/{index-BzKOThsI.d.ts → index-DWmudwDm.d.ts} +1 -1
  24. package/dist/{index-7lxTrxSG.d.mts → index-c5-qTRbH.d.mts} +7 -1
  25. package/dist/{index-7lxTrxSG.d.ts → index-yfpxsgUu.d.ts} +7 -1
  26. package/dist/index.d.mts +5 -4
  27. package/dist/index.d.ts +5 -4
  28. package/dist/index.js +473 -65
  29. package/dist/index.mjs +6 -6
  30. package/dist/nextjs/index.mjs +2 -2
  31. package/dist/sitePreviewTypes-BECnq9xI.d.mts +41 -0
  32. package/dist/sitePreviewTypes-BECnq9xI.d.ts +41 -0
  33. package/dist/studio/index.d.mts +1 -1
  34. package/dist/studio/index.d.ts +1 -1
  35. package/dist/studio-pages/index.d.mts +3 -3
  36. package/dist/studio-pages/index.d.ts +3 -3
  37. package/dist/studio-pages/index.js +330 -7
  38. package/dist/studio-pages/index.mjs +10 -3
  39. package/package.json +1 -1
  40. package/dist/index-B7QvY3yF.d.mts +0 -245
  41. package/dist/index-BK03FiEM.d.ts +0 -245
  42. package/dist/{chunk-BET2YLAS.mjs → chunk-OTHERBGX.mjs} +3 -3
@@ -0,0 +1,555 @@
1
+ 'use client';
2
+
3
+ // src/admin-app/components/HeaderNavItemsEditor.tsx
4
+ import { useEffect, useMemo, useState } from "react";
5
+
6
+ // src/admin-app/navigationLinks.ts
7
+ var fallbackHomeOption = {
8
+ href: "/",
9
+ label: "Home",
10
+ title: "Home"
11
+ };
12
+ var buildAdminPageLinkOptions = (pages) => {
13
+ const options = pages.map((page) => {
14
+ const href = typeof page.path === "string" ? page.path.trim() : "";
15
+ const title = typeof page.title === "string" && page.title.trim().length > 0 ? page.title.trim() : "Untitled Page";
16
+ if (!href) {
17
+ return null;
18
+ }
19
+ const depth = href === "/" ? 0 : href.split("/").filter(Boolean).length;
20
+ const indentLevel = Math.max(depth - 1, 0);
21
+ const indent = indentLevel > 0 ? `${"\u21B3 ".repeat(indentLevel)}` : "";
22
+ return {
23
+ href,
24
+ label: `${indent}${title}`,
25
+ title
26
+ };
27
+ }).filter((option) => option !== null).sort((a, b) => {
28
+ if (a.href === "/" && b.href !== "/") return -1;
29
+ if (b.href === "/" && a.href !== "/") return 1;
30
+ return a.href.localeCompare(b.href);
31
+ });
32
+ if (options.length === 0) {
33
+ return [fallbackHomeOption];
34
+ }
35
+ return options;
36
+ };
37
+ var normalizeAdminNavInputs = (rows, pageOptions) => {
38
+ const allowedLinks = new Map(pageOptions.map((option) => [option.href, option.title]));
39
+ const deduped = [];
40
+ const seen = /* @__PURE__ */ new Set();
41
+ for (const row of rows) {
42
+ const href = typeof row.href === "string" ? row.href.trim() : "";
43
+ const defaultLabel = allowedLinks.get(href);
44
+ const explicitLabel = typeof row.label === "string" ? row.label.trim() : "";
45
+ const parentHref = typeof row.parentHref === "string" ? row.parentHref.trim() : "";
46
+ if (!href || !defaultLabel || seen.has(href)) {
47
+ continue;
48
+ }
49
+ seen.add(href);
50
+ deduped.push({
51
+ href,
52
+ label: explicitLabel.length > 0 ? explicitLabel : defaultLabel,
53
+ ...parentHref.length > 0 ? { parentHref } : {}
54
+ });
55
+ }
56
+ const hrefs = new Set(deduped.map((item) => item.href));
57
+ const parentByHref = new Map(deduped.map((item) => [item.href, item.parentHref || ""]));
58
+ const createsCycle = (href, parentHref) => {
59
+ const visited = /* @__PURE__ */ new Set([href]);
60
+ let current = parentHref;
61
+ while (current) {
62
+ if (visited.has(current)) {
63
+ return true;
64
+ }
65
+ visited.add(current);
66
+ current = parentByHref.get(current) || "";
67
+ }
68
+ return false;
69
+ };
70
+ return deduped.map((item) => {
71
+ const parentHref = item.parentHref;
72
+ if (!parentHref || parentHref === item.href || !hrefs.has(parentHref) || createsCycle(item.href, parentHref)) {
73
+ return {
74
+ href: item.href,
75
+ label: item.label
76
+ };
77
+ }
78
+ return item;
79
+ });
80
+ };
81
+
82
+ // src/admin-app/components/HeaderNavItemsEditor.tsx
83
+ import { jsx, jsxs } from "react/jsx-runtime";
84
+ var toRow = (item, index) => ({
85
+ id: `row-${index}-${item.href || "empty"}`,
86
+ href: item.href || "",
87
+ label: item.label || "",
88
+ parentHref: item.parentHref || ""
89
+ });
90
+ var moveRow = (rows, fromIndex, toIndex) => {
91
+ if (fromIndex === toIndex || fromIndex < 0 || toIndex < 0 || fromIndex >= rows.length || toIndex >= rows.length) {
92
+ return rows;
93
+ }
94
+ const next = [...rows];
95
+ const [moved] = next.splice(fromIndex, 1);
96
+ if (!moved) {
97
+ return rows;
98
+ }
99
+ next.splice(toIndex, 0, moved);
100
+ return next;
101
+ };
102
+ function HeaderNavItemsEditor({ initialItems, pageOptions, onItemsChange }) {
103
+ const [rows, setRows] = useState(() => initialItems.map(toRow));
104
+ const [nextRowID, setNextRowID] = useState(initialItems.length);
105
+ const [draggingRowID, setDraggingRowID] = useState(null);
106
+ const [dragOverRowID, setDragOverRowID] = useState(null);
107
+ const pageOptionByHref = useMemo(() => new Map(pageOptions.map((option) => [option.href, option])), [pageOptions]);
108
+ const serializedState = useMemo(
109
+ () => JSON.stringify(
110
+ rows.map((row) => ({
111
+ href: row.href.trim(),
112
+ label: row.label.trim(),
113
+ parentHref: row.parentHref.trim() || void 0
114
+ }))
115
+ ),
116
+ [rows]
117
+ );
118
+ const normalizedItems = useMemo(() => {
119
+ const inputs = rows.map((row) => ({
120
+ href: row.href,
121
+ label: row.label,
122
+ parentHref: row.parentHref
123
+ }));
124
+ return normalizeAdminNavInputs(inputs, pageOptions);
125
+ }, [rows, pageOptions]);
126
+ useEffect(() => {
127
+ onItemsChange?.(normalizedItems);
128
+ }, [normalizedItems, onItemsChange]);
129
+ const setRowValue = (rowID, changes) => {
130
+ setRows(
131
+ (currentRows) => currentRows.map((row) => {
132
+ if (row.id !== rowID) {
133
+ return row;
134
+ }
135
+ const nextRow = { ...row, ...changes };
136
+ if (nextRow.parentHref === nextRow.href) {
137
+ nextRow.parentHref = "";
138
+ }
139
+ return nextRow;
140
+ })
141
+ );
142
+ };
143
+ const removeRow = (rowID) => {
144
+ setRows((currentRows) => {
145
+ const removedRow = currentRows.find((candidate) => candidate.id === rowID);
146
+ const removedHref = removedRow?.href || "";
147
+ return currentRows.filter((row) => row.id !== rowID).map((row) => removedHref && row.parentHref === removedHref ? { ...row, parentHref: "" } : row);
148
+ });
149
+ };
150
+ const addRow = () => {
151
+ setRows((currentRows) => [
152
+ ...currentRows,
153
+ {
154
+ id: `row-new-${nextRowID}`,
155
+ href: "",
156
+ label: "",
157
+ parentHref: ""
158
+ }
159
+ ]);
160
+ setNextRowID((current) => current + 1);
161
+ };
162
+ return /* @__PURE__ */ jsxs("div", { className: "orion-admin-nav-editor", children: [
163
+ /* @__PURE__ */ jsx("input", { name: "navItemsState", readOnly: true, type: "hidden", value: serializedState }),
164
+ /* @__PURE__ */ jsxs("div", { className: "orion-admin-nav-editor-head", children: [
165
+ /* @__PURE__ */ jsx("div", { className: "orion-admin-nav-editor-title", children: "Navigation Items" }),
166
+ /* @__PURE__ */ jsx("button", { className: "orion-admin-nav-editor-add", onClick: addRow, type: "button", children: "Add Item" })
167
+ ] }),
168
+ /* @__PURE__ */ jsx("div", { className: "orion-admin-nav-editor-help", children: "Add only links you want in the menu. Drag rows to reorder. Set a parent to create dropdown items." }),
169
+ rows.length === 0 ? /* @__PURE__ */ jsx("div", { className: "orion-admin-nav-editor-empty", children: 'No navigation items yet. Click "Add Item" to start.' }) : null,
170
+ /* @__PURE__ */ jsx("div", { className: "orion-admin-nav-editor-list", children: rows.map((row, rowIndex) => {
171
+ const parentCandidates = rows.filter((candidate) => candidate.id !== row.id && candidate.href.trim().length > 0).map((candidate) => {
172
+ const resolved = pageOptionByHref.get(candidate.href);
173
+ return {
174
+ href: candidate.href,
175
+ label: candidate.label.trim() || resolved?.title || candidate.href
176
+ };
177
+ });
178
+ const selectedPage = pageOptionByHref.get(row.href);
179
+ const labelPlaceholder = selectedPage?.title || "Navigation Label";
180
+ return /* @__PURE__ */ jsxs(
181
+ "div",
182
+ {
183
+ className: `orion-admin-nav-editor-row${draggingRowID === row.id ? " is-dragging" : ""}${dragOverRowID === row.id && draggingRowID !== row.id ? " is-drop-target" : ""}`,
184
+ draggable: true,
185
+ onDragEnd: () => {
186
+ setDraggingRowID(null);
187
+ setDragOverRowID(null);
188
+ },
189
+ onDragEnter: () => {
190
+ if (draggingRowID && draggingRowID !== row.id) {
191
+ setDragOverRowID(row.id);
192
+ }
193
+ },
194
+ onDragLeave: () => {
195
+ if (dragOverRowID === row.id) {
196
+ setDragOverRowID(null);
197
+ }
198
+ },
199
+ onDragOver: (event) => {
200
+ event.preventDefault();
201
+ if (draggingRowID && draggingRowID !== row.id && dragOverRowID !== row.id) {
202
+ setDragOverRowID(row.id);
203
+ }
204
+ },
205
+ onDragStart: (event) => {
206
+ setDraggingRowID(row.id);
207
+ event.dataTransfer.effectAllowed = "move";
208
+ },
209
+ onDrop: (event) => {
210
+ event.preventDefault();
211
+ if (!draggingRowID || draggingRowID === row.id) {
212
+ return;
213
+ }
214
+ setRows((currentRows) => {
215
+ const fromIndex = currentRows.findIndex((entry) => entry.id === draggingRowID);
216
+ const toIndex = currentRows.findIndex((entry) => entry.id === row.id);
217
+ return moveRow(currentRows, fromIndex, toIndex);
218
+ });
219
+ setDraggingRowID(null);
220
+ setDragOverRowID(null);
221
+ },
222
+ children: [
223
+ /* @__PURE__ */ jsxs("div", { className: "orion-admin-nav-editor-row-head", children: [
224
+ /* @__PURE__ */ jsx("span", { className: "orion-admin-nav-editor-drag", children: "Drag" }),
225
+ /* @__PURE__ */ jsxs("span", { className: "orion-admin-nav-editor-row-index", children: [
226
+ "#",
227
+ rowIndex + 1
228
+ ] }),
229
+ /* @__PURE__ */ jsx("button", { className: "orion-admin-nav-editor-remove", onClick: () => removeRow(row.id), type: "button", children: "Remove" })
230
+ ] }),
231
+ /* @__PURE__ */ jsxs("div", { className: "orion-admin-nav-editor-row-grid", children: [
232
+ /* @__PURE__ */ jsxs("label", { children: [
233
+ "Label",
234
+ /* @__PURE__ */ jsx(
235
+ "input",
236
+ {
237
+ name: `navLabel_${rowIndex}`,
238
+ onChange: (event) => setRowValue(row.id, { label: event.target.value }),
239
+ placeholder: labelPlaceholder,
240
+ type: "text",
241
+ value: row.label
242
+ }
243
+ )
244
+ ] }),
245
+ /* @__PURE__ */ jsxs("label", { children: [
246
+ "Page",
247
+ /* @__PURE__ */ jsxs(
248
+ "select",
249
+ {
250
+ name: `navPage_${rowIndex}`,
251
+ onChange: (event) => {
252
+ const nextHref = event.target.value;
253
+ const nextParent = row.parentHref && row.parentHref === nextHref ? "" : row.parentHref;
254
+ setRowValue(row.id, { href: nextHref, parentHref: nextParent });
255
+ },
256
+ value: row.href,
257
+ children: [
258
+ /* @__PURE__ */ jsx("option", { value: "", children: "Select page..." }),
259
+ pageOptions.map((pageOption) => /* @__PURE__ */ jsx("option", { value: pageOption.href, children: pageOption.label }, `${pageOption.href}-${pageOption.title}`))
260
+ ]
261
+ }
262
+ )
263
+ ] }),
264
+ /* @__PURE__ */ jsxs("label", { children: [
265
+ "Parent (dropdown under)",
266
+ /* @__PURE__ */ jsxs(
267
+ "select",
268
+ {
269
+ name: `navParentHref_${rowIndex}`,
270
+ onChange: (event) => setRowValue(row.id, { parentHref: event.target.value }),
271
+ value: row.parentHref,
272
+ children: [
273
+ /* @__PURE__ */ jsx("option", { value: "", children: "Top-level item" }),
274
+ parentCandidates.map((candidate) => /* @__PURE__ */ jsx("option", { value: candidate.href, children: candidate.label }, `${row.id}-parent-${candidate.href}`))
275
+ ]
276
+ }
277
+ )
278
+ ] })
279
+ ] })
280
+ ]
281
+ },
282
+ row.id
283
+ );
284
+ }) })
285
+ ] });
286
+ }
287
+
288
+ // src/admin-app/components/SitePreview.tsx
289
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
290
+ var fallbackHeaderNav = [{ href: "/", label: "Home" }];
291
+ var socialGlyphByPlatform = {
292
+ facebook: "f",
293
+ instagram: "ig",
294
+ linkedin: "in",
295
+ pinterest: "p",
296
+ snapchat: "sc",
297
+ tiktok: "tt",
298
+ x: "x",
299
+ youtube: "yt"
300
+ };
301
+ var getInitials = (value) => {
302
+ const initials = value.trim().split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]?.toUpperCase() || "").join("");
303
+ return initials || "OS";
304
+ };
305
+ var getSocialGlyph = (platform) => {
306
+ const normalized = platform.trim().toLowerCase();
307
+ return socialGlyphByPlatform[normalized] || normalized.slice(0, 2).toUpperCase() || "\u2022";
308
+ };
309
+ var getTaglineLines = (tagline) => {
310
+ const parts = (tagline || "").split(".").map((part) => part.trim()).filter(Boolean);
311
+ const first = parts[0] ? `${parts[0]}.` : "Warm Gifts.";
312
+ const second = parts[1] ? `${parts[1]}.` : "Local Heart.";
313
+ return [first, second];
314
+ };
315
+ function PreviewSocialLinks({
316
+ links,
317
+ variant
318
+ }) {
319
+ if (links.length === 0) {
320
+ return null;
321
+ }
322
+ return /* @__PURE__ */ jsx2(
323
+ "div",
324
+ {
325
+ className: variant === "header" ? "orion-admin-site-preview-social-list" : "orion-admin-site-preview-social-list orion-admin-site-preview-social-list--footer",
326
+ children: links.map((item) => /* @__PURE__ */ jsx2(
327
+ "a",
328
+ {
329
+ className: variant === "header" ? "orion-admin-site-preview-social-badge" : "orion-admin-site-preview-social-badge orion-admin-site-preview-social-badge--footer",
330
+ href: item.url,
331
+ tabIndex: -1,
332
+ children: getSocialGlyph(item.platform)
333
+ },
334
+ `${item.platform}-${item.url}`
335
+ ))
336
+ }
337
+ );
338
+ }
339
+ function PreviewLogo({
340
+ className,
341
+ logoUrl,
342
+ siteName
343
+ }) {
344
+ if (logoUrl && logoUrl.trim().length > 0) {
345
+ return /* @__PURE__ */ jsx2("img", { alt: `${siteName} logo`, className, src: logoUrl });
346
+ }
347
+ return /* @__PURE__ */ jsx2("div", { className: `${className} orion-admin-site-preview-logo-fallback`, children: getInitials(siteName) });
348
+ }
349
+ function SiteHeaderPreview({ site }) {
350
+ const navItems = site.navItems.length > 0 ? site.navItems : fallbackHeaderNav;
351
+ const [taglineLineOne, taglineLineTwo] = getTaglineLines(site.tagline);
352
+ const socialLinks = site.socialLinks?.slice(0, 4) || [];
353
+ const activePath = site.activePath || navItems[0]?.href || "/";
354
+ return /* @__PURE__ */ jsxs2("div", { "aria-hidden": "true", className: "orion-admin-site-preview orion-admin-site-preview--header", children: [
355
+ /* @__PURE__ */ jsx2("div", { className: "orion-admin-site-preview-header-bar", children: /* @__PURE__ */ jsxs2("div", { className: "orion-admin-site-preview-shell orion-admin-site-preview-shell--utility", children: [
356
+ /* @__PURE__ */ jsx2("p", { className: "orion-admin-site-preview-utility-copy", children: site.locationSummary?.address?.trim() || "Neighborhood gift shop" }),
357
+ /* @__PURE__ */ jsxs2("div", { className: "orion-admin-site-preview-utility-meta", children: [
358
+ site.locationSummary?.hours?.trim() ? /* @__PURE__ */ jsx2("p", { className: "orion-admin-site-preview-utility-copy", children: site.locationSummary.hours.trim() }) : null,
359
+ /* @__PURE__ */ jsx2(PreviewSocialLinks, { links: socialLinks, variant: "header" }),
360
+ /* @__PURE__ */ jsx2("a", { className: "orion-admin-site-preview-header-action", href: site.actionHref || "/contact", tabIndex: -1, children: site.actionLabel || "Visit Today" })
361
+ ] })
362
+ ] }) }),
363
+ /* @__PURE__ */ jsx2("div", { className: "orion-admin-site-preview-header-main", children: /* @__PURE__ */ jsxs2("div", { className: "orion-admin-site-preview-shell orion-admin-site-preview-shell--main", children: [
364
+ /* @__PURE__ */ jsxs2("a", { className: "orion-admin-site-preview-brand", href: "/", tabIndex: -1, children: [
365
+ /* @__PURE__ */ jsx2(
366
+ PreviewLogo,
367
+ {
368
+ className: "orion-admin-site-preview-header-logo",
369
+ logoUrl: site.logoUrl,
370
+ siteName: site.siteName
371
+ }
372
+ ),
373
+ /* @__PURE__ */ jsxs2("div", { className: "orion-admin-site-preview-tagline", children: [
374
+ /* @__PURE__ */ jsx2("p", { className: "orion-admin-site-preview-tagline-line", children: taglineLineOne }),
375
+ /* @__PURE__ */ jsx2("p", { className: "orion-admin-site-preview-tagline-line", children: taglineLineTwo })
376
+ ] })
377
+ ] }),
378
+ /* @__PURE__ */ jsx2("nav", { className: "orion-admin-site-preview-nav", children: navItems.map((item) => /* @__PURE__ */ jsx2(
379
+ "a",
380
+ {
381
+ className: item.href === activePath ? "is-active" : void 0,
382
+ href: item.href,
383
+ tabIndex: -1,
384
+ children: item.label
385
+ },
386
+ `${item.href}-${item.label}`
387
+ )) }),
388
+ /* @__PURE__ */ jsxs2("div", { className: "orion-admin-site-preview-mobile-toggle", children: [
389
+ /* @__PURE__ */ jsx2("span", {}),
390
+ /* @__PURE__ */ jsx2("span", {}),
391
+ /* @__PURE__ */ jsx2("span", {})
392
+ ] })
393
+ ] }) })
394
+ ] });
395
+ }
396
+ function SiteFooterPreview({ site }) {
397
+ const description = site.description?.trim() || site.tagline?.trim() || "Thoughtful gifts, warm local service, and a beautifully stocked neighborhood shop.";
398
+ const socialLinks = site.socialLinks?.slice(0, 4) || [];
399
+ const builtByLabel = site.builtByLabel || "Built by Orion Studios";
400
+ const builtByHref = site.builtByHref || "https://orionstudios.dev";
401
+ return /* @__PURE__ */ jsx2("div", { "aria-hidden": "true", className: "orion-admin-site-preview orion-admin-site-preview--footer", children: /* @__PURE__ */ jsxs2("div", { className: "orion-admin-site-preview-footer-shell", children: [
402
+ /* @__PURE__ */ jsxs2("div", { className: "orion-admin-site-preview-footer-grid", children: [
403
+ /* @__PURE__ */ jsxs2("div", { children: [
404
+ /* @__PURE__ */ jsxs2("div", { className: "orion-admin-site-preview-footer-brand", children: [
405
+ /* @__PURE__ */ jsx2(
406
+ PreviewLogo,
407
+ {
408
+ className: "orion-admin-site-preview-footer-logo",
409
+ logoUrl: site.logoUrl,
410
+ siteName: site.siteName
411
+ }
412
+ ),
413
+ /* @__PURE__ */ jsx2("p", { className: "orion-admin-site-preview-footer-name", children: site.siteName })
414
+ ] }),
415
+ /* @__PURE__ */ jsx2("p", { className: "orion-admin-site-preview-footer-description", children: description })
416
+ ] }),
417
+ /* @__PURE__ */ jsxs2("div", { children: [
418
+ /* @__PURE__ */ jsx2("p", { className: "orion-admin-site-preview-footer-eyebrow", children: "Shop focus" }),
419
+ /* @__PURE__ */ jsx2("div", { className: "orion-admin-site-preview-footer-list", children: site.footerCategories.map((item) => /* @__PURE__ */ jsx2("p", { children: item }, item)) })
420
+ ] }),
421
+ /* @__PURE__ */ jsxs2("div", { children: [
422
+ /* @__PURE__ */ jsx2("p", { className: "orion-admin-site-preview-footer-eyebrow", children: "Explore" }),
423
+ /* @__PURE__ */ jsx2("div", { className: "orion-admin-site-preview-footer-list", children: site.footerLinks.map((item) => /* @__PURE__ */ jsx2("a", { href: item.href, tabIndex: -1, children: item.label }, `${item.href}-${item.label}`)) })
424
+ ] }),
425
+ /* @__PURE__ */ jsxs2("div", { children: [
426
+ /* @__PURE__ */ jsx2("p", { className: "orion-admin-site-preview-footer-eyebrow", children: "Visit" }),
427
+ /* @__PURE__ */ jsxs2("div", { className: "orion-admin-site-preview-footer-contact", children: [
428
+ site.locationSummary.address?.trim() ? /* @__PURE__ */ jsx2("p", { children: site.locationSummary.address.trim() }) : null,
429
+ site.locationSummary.hours?.trim() ? /* @__PURE__ */ jsx2("p", { children: site.locationSummary.hours.trim() }) : null,
430
+ site.locationSummary.phone?.trim() ? /* @__PURE__ */ jsx2("a", { href: `tel:${site.locationSummary.phone.trim()}`, tabIndex: -1, children: site.locationSummary.phone.trim() }) : null,
431
+ /* @__PURE__ */ jsx2("a", { href: `mailto:${site.contactEmail}`, tabIndex: -1, children: site.contactEmail })
432
+ ] }),
433
+ /* @__PURE__ */ jsx2(PreviewSocialLinks, { links: socialLinks, variant: "footer" })
434
+ ] })
435
+ ] }),
436
+ /* @__PURE__ */ jsxs2("div", { className: "orion-admin-site-preview-footer-meta", children: [
437
+ /* @__PURE__ */ jsx2("span", { children: site.copyright }),
438
+ /* @__PURE__ */ jsx2("a", { href: builtByHref, tabIndex: -1, children: builtByLabel })
439
+ ] })
440
+ ] }) });
441
+ }
442
+
443
+ // src/admin-app/components/HeaderNavEditorWithPreview.tsx
444
+ import { useMemo as useMemo2, useState as useState2 } from "react";
445
+
446
+ // src/admin-app/nestedNavigation.ts
447
+ var normalizeNestedNavItems = (items) => {
448
+ const deduped = [];
449
+ const seen = /* @__PURE__ */ new Set();
450
+ for (const item of items) {
451
+ const href = typeof item.href === "string" ? item.href.trim() : "";
452
+ const label = typeof item.label === "string" ? item.label.trim() : "";
453
+ const parentHref = typeof item.parentHref === "string" ? item.parentHref.trim() : "";
454
+ if (!href || !label || seen.has(href)) {
455
+ continue;
456
+ }
457
+ seen.add(href);
458
+ deduped.push({
459
+ href,
460
+ label,
461
+ ...parentHref ? { parentHref } : {}
462
+ });
463
+ }
464
+ const hrefs = new Set(deduped.map((item) => item.href));
465
+ return deduped.map((item) => ({
466
+ href: item.href,
467
+ label: item.label,
468
+ ...item.parentHref && item.parentHref !== item.href && hrefs.has(item.parentHref) ? { parentHref: item.parentHref } : {}
469
+ }));
470
+ };
471
+ var buildNestedNavTree = (items) => {
472
+ const childrenByParent = /* @__PURE__ */ new Map();
473
+ const topLevel = [];
474
+ for (const item of items) {
475
+ if (!item.parentHref) {
476
+ topLevel.push(item);
477
+ continue;
478
+ }
479
+ const children = childrenByParent.get(item.parentHref) || [];
480
+ children.push(item);
481
+ childrenByParent.set(item.parentHref, children);
482
+ }
483
+ if (topLevel.length === 0 && items.length > 0) {
484
+ return {
485
+ topLevel: items.map((item) => ({ href: item.href, label: item.label })),
486
+ childrenByParent: /* @__PURE__ */ new Map()
487
+ };
488
+ }
489
+ return { childrenByParent, topLevel };
490
+ };
491
+
492
+ // src/admin-app/components/HeaderNavEditorWithPreview.tsx
493
+ import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
494
+ var fallbackNav = [{ href: "/", label: "Home" }];
495
+ function HeaderNavEditorWithPreview({
496
+ activePath,
497
+ actionHref,
498
+ actionLabel,
499
+ brandName,
500
+ initialItems,
501
+ locationSummary,
502
+ logoUrl,
503
+ onItemsChange,
504
+ pageOptions,
505
+ socialLinks,
506
+ tagline = ""
507
+ }) {
508
+ const [liveItems, setLiveItems] = useState2(initialItems);
509
+ const previewItems = useMemo2(() => {
510
+ const normalized = normalizeNestedNavItems(liveItems);
511
+ const tree = buildNestedNavTree(normalized);
512
+ return tree.topLevel.length > 0 ? tree : buildNestedNavTree(fallbackNav);
513
+ }, [liveItems]);
514
+ return /* @__PURE__ */ jsxs3(Fragment, { children: [
515
+ /* @__PURE__ */ jsx3(
516
+ HeaderNavItemsEditor,
517
+ {
518
+ initialItems,
519
+ onItemsChange: (items) => {
520
+ setLiveItems(items);
521
+ onItemsChange?.(items);
522
+ },
523
+ pageOptions
524
+ }
525
+ ),
526
+ /* @__PURE__ */ jsx3("div", { className: "orion-admin-preview-label", children: "Header Preview" }),
527
+ /* @__PURE__ */ jsx3("div", { className: "orion-admin-preview-frame", children: /* @__PURE__ */ jsx3("div", { className: "orion-admin-preview-surface", children: /* @__PURE__ */ jsx3(
528
+ SiteHeaderPreview,
529
+ {
530
+ site: {
531
+ activePath,
532
+ actionHref,
533
+ actionLabel,
534
+ locationSummary,
535
+ logoUrl,
536
+ navItems: previewItems.topLevel.map((item) => ({
537
+ href: item.href,
538
+ label: item.label
539
+ })),
540
+ siteName: brandName,
541
+ socialLinks,
542
+ tagline
543
+ }
544
+ }
545
+ ) }) })
546
+ ] });
547
+ }
548
+
549
+ export {
550
+ buildAdminPageLinkOptions,
551
+ HeaderNavItemsEditor,
552
+ SiteHeaderPreview,
553
+ SiteFooterPreview,
554
+ HeaderNavEditorWithPreview
555
+ };