@bison-lab/payload-blocks 3.21.0 → 3.23.0

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.mjs CHANGED
@@ -1,12 +1,114 @@
1
1
  "use client";
2
2
  import "./link-32261jXB.mjs";
3
- import { a as linkTypeOf, n as headerItemsFromBlocks, o as resolveAdminPreviewLink } from "./header-CV7K-3yB.mjs";
3
+ import { a as linkTypeOf, n as headerItemsFromBlocks, o as resolveAdminPreviewLink } from "./header-CTMSB4C0.mjs";
4
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
- import { FloatingNavBlock } from "@bison-lab/ui";
6
- import { ArrayField, FieldDescription, FieldError, FieldLabel, FieldPathContext, toast, useConfig, useField, useFieldPath, useForm, useTranslation } from "@payloadcms/ui";
5
+ import { ArrayField, DefaultEditView, FieldDescription, FieldError, FieldLabel, FieldPathContext, toast, useConfig, useField, useFieldPath, useForm, useTranslation } from "@payloadcms/ui";
7
6
  import { useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
8
- import { ConfirmDialog, LinkGlyph, MegaGlyph, TypeCard, TypeCards } from "@bison-lab/admin-ui";
9
- import { themeHeadFromDoc } from "@bison-lab/payload-core/theme";
7
+ import { Button, Canvas, Checkbox, ConfirmDialog, Dialog, Field, Fold, Input, ItemRail, Kicker, KindGlyph, KitProvider, Label, MainHead, RailSlot, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Stack, Textarea, TypeCard, TypeCards } from "@bison-lab/admin-ui";
8
+ import { resolveThemeIdentity, themeHeadFromDoc } from "@bison-lab/payload-core/theme";
9
+ //#region src/admin/workspace-css.ts
10
+ /**
11
+ * Payload Edit View → mockup workspace. Scoped to the document that
12
+ * opted in (Header first). Theme, Pages, and other collections stay
13
+ * Payload's form. Hex is the approved mockup, not Payload elevation.
14
+ *
15
+ * A second kit editor reuses this file by opting into the same view;
16
+ * do not copy Header selectors into that editor.
17
+ */
18
+ const ADMIN_WORKSPACE_CSS = `
19
+ .global-edit--navigation{
20
+ --bg:#0f1012;--panel:#141518;--panel2:#1b1d22;--panel3:#22252b;--line:#30333b;--line2:#444854;
21
+ --text:#f6f7f9;--muted:#989daa;--muted2:#727887;--pink:#e60088;--pink2:#ff2da5;--bl-kit-accent:var(--pink);--danger:#ff8aa9;
22
+ --theme-elevation-0:var(--panel);--theme-elevation-50:var(--panel2);--theme-elevation-100:var(--panel3);
23
+ --theme-elevation-150:var(--line);--theme-elevation-250:var(--line2);--theme-elevation-500:var(--muted);
24
+ --theme-elevation-800:var(--text);--theme-input-bg:#1d1f24;--theme-bg:var(--bg);--theme-text:var(--text);
25
+ --brand-primary:var(--pink);
26
+ --gutter-h:0;--main-gutter-h-left:0;--main-gutter-h-right:0;
27
+ --sidebar-gutter-h-left:0;--sidebar-gutter-h-right:0;
28
+ background:var(--bg);color:var(--text);
29
+ display:flex;flex-direction:column;flex:1;min-height:0;height:auto;
30
+ overflow:hidden;
31
+ }
32
+ /* Own the viewport with flex. The edit view already sits under
33
+ AppHeader inside the wrap; a viewport height here pushes the
34
+ Header button past the fold. */
35
+ .template-default:has(.global-edit--navigation){
36
+ height:100dvh;max-height:100dvh;min-height:0;overflow:hidden;
37
+ }
38
+ .template-default:has(.global-edit--navigation) .template-default__wrap{
39
+ display:flex;flex-direction:column;min-height:0;height:100%;overflow:hidden;
40
+ }
41
+ .template-default:has(.global-edit--navigation) .app-header{
42
+ flex:none;
43
+ }
44
+ .global-edit--navigation form,.global-edit--navigation .gutter--left,.global-edit--navigation .gutter--right{
45
+ padding:0;margin:0;
46
+ }
47
+ .global-edit--navigation form{
48
+ flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden;height:100%;
49
+ }
50
+ /* Payload's main pane is content-sized. Stretch it — and only the kit
51
+ field — so the rail and canvas reach the bottom of the browser.
52
+ Do not flex every .field-type: hidden cta/bar siblings would steal
53
+ height, and height:100% beats a viewport min-height on .bl-nav-items. */
54
+ .global-edit--navigation .doc-controls + div,
55
+ .global-edit--navigation .doc-controls + div > div,
56
+ .global-edit--navigation .document-fields,
57
+ .global-edit--navigation .document-fields__main,
58
+ .global-edit--navigation .document-fields__edit,
59
+ .global-edit--navigation .document-fields__fields,
60
+ .global-edit--navigation .render-fields:has(.bl-nav-items),
61
+ .global-edit--navigation .group-field:has(.bl-nav-items),
62
+ .global-edit--navigation .group-field:has(.bl-nav-items) .group-field__wrap{
63
+ display:flex;flex-direction:column;flex:1;min-height:0;height:100%;
64
+ overflow:hidden;padding:0;margin:0;border:0;max-width:none;width:100%;
65
+ }
66
+ .global-edit--navigation .render-fields:has(.bl-nav-items){gap:0}
67
+ .global-edit--navigation .field-label,.global-edit--navigation .field-label__label,
68
+ .global-edit--navigation .field-description,.global-edit--navigation .field__description,
69
+ .global-edit--navigation .group-field__title,.global-edit--navigation .tabs-field{display:none}
70
+ .global-edit--navigation .bl-nav-items .field-label,.global-edit--navigation .bl-nav-items .field-label__label{display:block}
71
+ .global-edit--navigation .live-preview,.global-edit--navigation .live-preview-window,
72
+ .global-edit--navigation [class*="LivePreview"]{display:none !important}
73
+ .global-edit--navigation .doc-header{
74
+ background:var(--bg);border-bottom:1px solid var(--line);padding:10px 24px;min-height:0;flex:none;
75
+ }
76
+ .global-edit--navigation .doc-controls{
77
+ background:var(--bg);border-bottom:1px solid var(--line);padding:12px;min-height:0;
78
+ flex:none;position:sticky;top:0;z-index:6;
79
+ }
80
+ .global-edit--navigation .doc-controls:before,.global-edit--navigation .doc-controls:after{
81
+ display:none;content:none;backdrop-filter:none;
82
+ }
83
+ .global-edit--navigation .doc-controls__wrapper{height:auto;min-height:0}
84
+ .global-edit--navigation .doc-controls__content{padding:0}
85
+ .global-edit--navigation .doc-controls__controls-wrapper{background:var(--bg);border-top-color:var(--line)}
86
+ .global-edit--navigation .doc-header__title,.global-edit--navigation .doc-controls .doc-title{font-size:16px;font-weight:700;color:var(--text)}
87
+ .global-edit--navigation .btn--style-primary,.global-edit--navigation .btn.btn--style-primary{
88
+ background:var(--pink);border-color:var(--pink);color:#fff;
89
+ }
90
+ .global-edit--navigation .bl-nav-items{
91
+ display:grid;grid-template-columns:300px minmax(0,1fr);
92
+ grid-template-rows:minmax(0,1fr);
93
+ flex:1;min-height:0;height:100%;overflow:hidden;align-self:stretch;
94
+ }
95
+ @media(max-width:1280px){.global-edit--navigation .bl-nav-items{grid-template-columns:250px minmax(0,1fr)}}
96
+ @media(max-width:850px){.global-edit--navigation .bl-nav-items{grid-template-columns:1fr}}
97
+ `;
98
+ //#endregion
99
+ //#region src/admin/admin-workspace.tsx
100
+ /**
101
+ * Wraps Payload's DefaultEditView so Header (and later kit editors)
102
+ * become the mockup workspace. Does not mount a second Form.
103
+ */
104
+ function AdminWorkspace(props) {
105
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("style", {
106
+ href: "bl-admin-workspace",
107
+ precedence: "high",
108
+ children: ADMIN_WORKSPACE_CSS
109
+ }), /* @__PURE__ */ jsx(DefaultEditView, { ...props })] });
110
+ }
111
+ //#endregion
10
112
  //#region src/admin/link-field.tsx
11
113
  /**
12
114
  * The link picker: one box in place of a link's `type`, `page` and `href`.
@@ -536,7 +638,17 @@ const THEME_SEED = {
536
638
  };
537
639
  const THEME_SCOPE = ".bl-nav-items";
538
640
  function scopeThemeCss(css) {
539
- return css.replace(/:root/g, THEME_SCOPE).replace(/\[data-theme="dark"\]/g, `${THEME_SCOPE}[data-theme="dark"]`);
641
+ return css.replace(/:root/g, THEME_SCOPE).replace(/\[data-theme="dark"\]/g, `${THEME_SCOPE}[data-theme="dark"], ${THEME_SCOPE} [data-theme="dark"]`);
642
+ }
643
+ function identityFallbackFromConfig(config) {
644
+ return config.globals?.find((global) => global.slug === "theme")?.admin?.custom?.identityFallback;
645
+ }
646
+ function lockupSrc(asset, serverURL) {
647
+ if (!asset?.url) return null;
648
+ return {
649
+ url: /^https?:\/\//.test(asset.url) || asset.url.startsWith("/") ? asset.url : `${serverURL}/${asset.url}`,
650
+ alt: asset.alt
651
+ };
540
652
  }
541
653
  function pageIdOf(value) {
542
654
  if (value == null) return null;
@@ -546,12 +658,16 @@ function pageIdOf(value) {
546
658
  }
547
659
  return String(value);
548
660
  }
549
- function collectPageIds(items) {
661
+ function ctaPathFromItems(itemsPath) {
662
+ return itemsPath.endsWith(".items") ? `${itemsPath.slice(0, -6)}.cta` : "header.cta";
663
+ }
664
+ function collectPageIds(items, extra) {
550
665
  const ids = /* @__PURE__ */ new Set();
551
666
  const take = (link) => {
552
667
  const id = pageIdOf(link?.page);
553
668
  if (id) ids.add(id);
554
669
  };
670
+ take(extra);
555
671
  for (const row of items) {
556
672
  take(row);
557
673
  const panel = row.panel;
@@ -575,40 +691,44 @@ function ComposedLinkField({ path, parentPath, readOnly }) {
575
691
  });
576
692
  }
577
693
  const NavItemsField = ({ field, path, readOnly }) => {
578
- const itemsField = useField({ path });
579
- const items = Array.isArray(itemsField.value) ? itemsField.value : [];
580
- const { addFieldRow, replaceFieldRow, removeFieldRow, moveFieldRow } = useForm();
694
+ const itemsField = useField({
695
+ path,
696
+ hasRows: true
697
+ });
698
+ const { addFieldRow, replaceFieldRow, getDataByPath } = useForm();
699
+ Array.isArray(itemsField.rows) ? itemsField.rows.length : itemsField.value;
700
+ const fromPath = getDataByPath?.(path);
701
+ const items = Array.isArray(fromPath) ? fromPath : Array.isArray(itemsField.value) ? itemsField.value : [];
702
+ const ctaPath = ctaPathFromItems(path);
703
+ const ctaField = useField({ path: ctaPath });
704
+ const ctaEnabled = useField({ path: `${ctaPath}.enabled` });
705
+ const ctaLabel = useField({ path: `${ctaPath}.label` });
706
+ const ctaPage = useField({ path: `${ctaPath}.page` });
707
+ const ctaHrefField = useField({ path: `${ctaPath}.href` });
708
+ const ctaType = useField({ path: `${ctaPath}.type` });
709
+ const ctaSnapshot = ctaField.value ?? {};
710
+ const cta = {
711
+ ...ctaSnapshot,
712
+ enabled: ctaEnabled.value ?? ctaSnapshot.enabled,
713
+ label: ctaLabel.value ?? ctaSnapshot.label,
714
+ page: ctaPage.value ?? ctaSnapshot.page,
715
+ href: ctaHrefField.value ?? ctaSnapshot.href,
716
+ type: ctaType.value ?? ctaSnapshot.type
717
+ };
718
+ const ctaOn = cta.enabled !== false && Boolean(cta.label || cta.page || cta.href || cta.enabled);
581
719
  const { config } = useConfig();
582
720
  const endpoint = `${config.serverURL}${config.routes.api}`;
583
721
  const [selected, setSelected] = useState(0);
584
722
  const [adding, setAdding] = useState(false);
585
723
  const [confirmSwitch, setConfirmSwitch] = useState(false);
586
- const [menu, setMenu] = useState(null);
587
- const [atTop, setAtTop] = useState(true);
588
- const sentinel = useRef(null);
724
+ const [previewDark, setPreviewDark] = useState(true);
725
+ const identityFallback = identityFallbackFromConfig(config);
589
726
  useEffect(() => {
590
727
  if (selected >= items.length) setSelected(Math.max(0, items.length - 1));
591
728
  }, [items.length, selected]);
592
- useEffect(() => {
593
- const el = sentinel.current;
594
- if (!el) return;
595
- const leave = () => setAtTop(false);
596
- const enter = () => setAtTop(true);
597
- el.addEventListener("nav-items-preview-leave", leave);
598
- el.addEventListener("nav-items-preview-enter", enter);
599
- const io = new IntersectionObserver(([entry]) => {
600
- if (entry) setAtTop(entry.isIntersecting);
601
- });
602
- io.observe(el);
603
- return () => {
604
- el.removeEventListener("nav-items-preview-leave", leave);
605
- el.removeEventListener("nav-items-preview-enter", enter);
606
- io.disconnect();
607
- };
608
- }, []);
609
729
  const current = items[selected];
610
730
  const [pages, setPages] = useState(() => /* @__PURE__ */ new Map());
611
- const pageIds = useMemo(() => collectPageIds(items).sort().join(","), [items]);
731
+ const pageIds = useMemo(() => collectPageIds(items, cta).sort().join(","), [items, cta]);
612
732
  useEffect(() => {
613
733
  const ids = pageIds ? pageIds.split(",") : [];
614
734
  if (ids.length === 0) return;
@@ -626,7 +746,10 @@ const NavItemsField = ({ field, path, readOnly }) => {
626
746
  };
627
747
  }, [pageIds, endpoint]);
628
748
  const previewItems = useMemo(() => headerItemsFromBlocks(items, { resolveLink: (link) => resolveAdminPreviewLink(link, pages) }), [items, pages]);
629
- const openItem = atTop && current?.blockType === "megaMenu" && current.label ? current.label : void 0;
749
+ const [hoverItem, setHoverItem] = useState(null);
750
+ const openItem = hoverItem && items.some((row) => row.label === hoverItem && row.blockType === "megaMenu") ? hoverItem : void 0;
751
+ const openRow = items.find((row) => row.label === openItem && row.blockType === "megaMenu");
752
+ const openIndex = openRow ? items.indexOf(openRow) : -1;
630
753
  function add(blockType) {
631
754
  const seed = blockType === "navLink" ? emptyLink() : emptyMega();
632
755
  addFieldRow({
@@ -701,44 +824,36 @@ const NavItemsField = ({ field, path, readOnly }) => {
701
824
  }
702
825
  switchToMega();
703
826
  }
704
- function setRow(name, value) {
705
- itemsField.setValue(items.map((row, i) => i === selected ? {
706
- ...row,
707
- [name]: value
708
- } : row));
709
- }
710
- function setPanel(patch) {
711
- if (current?.blockType !== "megaMenu") return;
712
- setRow("panel", {
713
- ...current.panel ?? emptyPanel(),
714
- ...patch
715
- });
716
- }
717
- function setColumns(columns) {
718
- setPanel({ columns: columns.map((column, i) => i === 0 ? {
719
- ...column,
720
- divider: false
721
- } : column) });
722
- }
723
827
  function onPreviewClick(event) {
724
828
  const target = event.target;
725
- const label = target.closest("[data-preview-item]")?.getAttribute("data-preview-item") ?? items.find((row) => row.label && target.textContent?.includes(row.label))?.label;
829
+ if (target.closest("a[href]")) event.preventDefault();
830
+ const label = target.closest("[data-preview-item]")?.getAttribute("data-preview-item");
726
831
  if (!label) return;
727
832
  const index = items.findIndex((row) => row.label === label);
728
- if (index >= 0) setSelected(index);
833
+ if (index >= 0) {
834
+ setSelected(index);
835
+ setHoverItem(label);
836
+ }
729
837
  }
730
838
  const [themeCss, setThemeCss] = useState("");
839
+ const [lockup, setLockup] = useState(() => lockupSrc(identityFallback?.lockup, config.serverURL));
731
840
  useEffect(() => {
732
841
  let cancelled = false;
733
842
  fetch(`${endpoint}/globals/theme?depth=1`, { credentials: "include" }).then((response) => response.ok ? response.json() : null).then((doc) => {
734
- if (cancelled || !doc) return;
735
- setThemeCss(scopeThemeCss(themeHeadFromDoc(doc, THEME_SEED).css));
843
+ if (cancelled) return;
844
+ if (doc) setThemeCss(scopeThemeCss(themeHeadFromDoc(doc, THEME_SEED).css));
845
+ setLockup(lockupSrc(resolveThemeIdentity(doc, identityFallback).lockup, config.serverURL));
736
846
  }).catch(() => void 0);
737
847
  return () => {
738
848
  cancelled = true;
739
849
  };
740
- }, [endpoint]);
741
- return /* @__PURE__ */ jsxs("div", {
850
+ }, [
851
+ config.serverURL,
852
+ endpoint,
853
+ identityFallback
854
+ ]);
855
+ const ctaHref = resolveAdminPreviewLink(cta, pages);
856
+ return /* @__PURE__ */ jsx(KitProvider, { children: /* @__PURE__ */ jsxs("div", {
742
857
  className: "bl-nav-items field-type",
743
858
  children: [
744
859
  /* @__PURE__ */ jsx("style", {
@@ -751,188 +866,150 @@ const NavItemsField = ({ field, path, readOnly }) => {
751
866
  precedence: "default",
752
867
  children: themeCss
753
868
  }) : null,
754
- /* @__PURE__ */ jsxs("aside", {
755
- className: "bl-nav-items__rail",
756
- children: [
757
- /* @__PURE__ */ jsxs("div", {
758
- className: "bl-nav-items__rail-head",
759
- children: [/* @__PURE__ */ jsx("p", {
760
- className: "bl-nav-items__kicker",
761
- children: "Header navigation"
762
- }), /* @__PURE__ */ jsx("h2", { children: "Menu items" })]
763
- }),
764
- /* @__PURE__ */ jsx("ul", {
765
- className: "bl-nav-items__list",
766
- "aria-label": "Menu items",
767
- children: items.map((row, index) => /* @__PURE__ */ jsxs("li", {
768
- "data-selected": index === selected ? "true" : "false",
769
- children: [/* @__PURE__ */ jsxs("div", {
770
- className: "bl-nav-items__rail-row",
771
- children: [
772
- /* @__PURE__ */ jsx("span", {
773
- className: "bl-nav-items__badge",
774
- "data-kind": row.blockType,
775
- "aria-hidden": true,
776
- children: row.blockType === "megaMenu" ? /* @__PURE__ */ jsx(MegaGlyph, {}) : /* @__PURE__ */ jsx(LinkGlyph, {})
777
- }),
778
- /* @__PURE__ */ jsx("button", {
779
- type: "button",
780
- className: "bl-nav-items__rail-label",
781
- onClick: () => setSelected(index),
782
- children: row.label || "Untitled"
783
- }),
784
- readOnly ? null : /* @__PURE__ */ jsxs("div", {
785
- className: "bl-nav-items__menu",
786
- children: [/* @__PURE__ */ jsx("button", {
787
- type: "button",
788
- "aria-label": `${row.label || "Item"} actions`,
789
- onClick: () => setMenu(menu === index ? null : index),
790
- children: "⋯"
791
- }), menu === index ? /* @__PURE__ */ jsxs("div", {
792
- className: "bl-nav-items__menu-pop",
793
- children: [
794
- /* @__PURE__ */ jsx("button", {
795
- type: "button",
796
- disabled: index === 0,
797
- onClick: () => {
798
- moveFieldRow({
799
- path,
800
- moveFromIndex: index,
801
- moveToIndex: index - 1
802
- });
803
- setSelected(index - 1);
804
- setMenu(null);
805
- },
806
- children: "Move up"
807
- }),
808
- /* @__PURE__ */ jsx("button", {
809
- type: "button",
810
- disabled: index === items.length - 1,
811
- onClick: () => {
812
- moveFieldRow({
813
- path,
814
- moveFromIndex: index,
815
- moveToIndex: index + 1
816
- });
817
- setSelected(index + 1);
818
- setMenu(null);
819
- },
820
- children: "Move down"
821
- }),
822
- /* @__PURE__ */ jsx("button", {
823
- type: "button",
824
- className: "bl-nav-kit__danger",
825
- onClick: () => {
826
- removeFieldRow({
827
- path,
828
- rowIndex: index
829
- });
830
- setMenu(null);
831
- },
832
- children: "Delete"
833
- })
834
- ]
835
- }) : null]
836
- })
837
- ]
838
- }), index === selected ? /* @__PURE__ */ jsxs("div", {
839
- className: "bl-nav-items__rail-edit",
840
- children: [/* @__PURE__ */ jsxs(TypeCards, {
841
- compact: true,
842
- children: [/* @__PURE__ */ jsx(TypeCard, {
843
- icon: /* @__PURE__ */ jsx(LinkGlyph, {}),
844
- label: "Link",
845
- onClick: () => requestType("navLink")
846
- }), /* @__PURE__ */ jsx(TypeCard, {
847
- icon: /* @__PURE__ */ jsx(MegaGlyph, {}),
848
- label: "Mega",
849
- onClick: () => requestType("megaMenu")
850
- })]
851
- }), /* @__PURE__ */ jsx(ItemBasics, {
852
- path,
869
+ /* @__PURE__ */ jsxs(ItemRail, { children: [/* @__PURE__ */ jsxs("div", {
870
+ className: "bl-nav-items__rail-body",
871
+ children: [/* @__PURE__ */ jsx("ul", {
872
+ className: "bl-nav-items__list",
873
+ "aria-label": "Menu items",
874
+ children: items.map((row, index) => /* @__PURE__ */ jsxs("li", {
875
+ "data-selected": index === selected ? "true" : "false",
876
+ children: [/* @__PURE__ */ jsxs("div", {
877
+ className: "bl-nav-items__rail-row",
878
+ children: [
879
+ /* @__PURE__ */ jsx(KindGlyph, { kind: row.blockType === "megaMenu" ? "megaMenu" : "navLink" }),
880
+ /* @__PURE__ */ jsx("button", {
881
+ type: "button",
882
+ className: "bl-nav-items__rail-label",
883
+ onClick: () => setSelected(index),
884
+ children: row.label || "Untitled"
885
+ }),
886
+ readOnly ? null : /* @__PURE__ */ jsx(RowMenu, {
887
+ label: row.label || "Item",
853
888
  index,
854
- readOnly
889
+ count: items.length,
890
+ path,
891
+ onMoved: (to) => setSelected(to)
892
+ })
893
+ ]
894
+ }), index === selected ? /* @__PURE__ */ jsxs("div", {
895
+ className: "bl-nav-items__rail-edit",
896
+ children: [/* @__PURE__ */ jsxs(TypeCards, {
897
+ compact: true,
898
+ children: [/* @__PURE__ */ jsx(TypeCard, {
899
+ icon: /* @__PURE__ */ jsx(KindGlyph, { kind: "navLink" }),
900
+ label: "Link",
901
+ active: row.blockType === "navLink",
902
+ onClick: () => requestType("navLink")
903
+ }), /* @__PURE__ */ jsx(TypeCard, {
904
+ icon: /* @__PURE__ */ jsx(KindGlyph, { kind: "megaMenu" }),
905
+ label: "Mega",
906
+ active: row.blockType === "megaMenu",
907
+ onClick: () => requestType("megaMenu")
855
908
  })]
856
- }) : null]
857
- }, String(row.id ?? index)))
858
- }),
859
- readOnly ? null : /* @__PURE__ */ jsx("button", {
860
- type: "button",
861
- className: "bl-nav-items__add",
862
- onClick: () => setAdding(true),
863
- children: "Add item"
864
- })
865
- ]
866
- }),
867
- /* @__PURE__ */ jsxs("div", {
868
- className: "bl-nav-items__main",
869
- children: [
870
- /* @__PURE__ */ jsx("div", {
871
- className: "bl-nav-items__sentinel",
872
- "data-testid": "nav-items-preview-sentinel",
873
- ref: sentinel,
874
- "aria-hidden": true
875
- }),
876
- /* @__PURE__ */ jsx("div", {
877
- "data-preview-chrome": true,
878
- "data-sticky": "true",
909
+ }), /* @__PURE__ */ jsx(ItemBasics, {
910
+ path,
911
+ index,
912
+ readOnly
913
+ })]
914
+ }) : null]
915
+ }, String(row.id ?? index)))
916
+ }), readOnly ? null : /* @__PURE__ */ jsx(Button, {
917
+ variant: "outline",
918
+ className: "bl-nav-items__add",
919
+ onClick: () => setAdding(true),
920
+ children: "Add item"
921
+ })]
922
+ }), /* @__PURE__ */ jsx(RailSlot, { children: /* @__PURE__ */ jsx(HeaderCta, {
923
+ path: ctaPath,
924
+ readOnly
925
+ }) })] }),
926
+ /* @__PURE__ */ jsxs(Canvas, { children: [
927
+ current?.blockType === "megaMenu" ? /* @__PURE__ */ jsx(MainHead, {
928
+ kicker: "Editing mega menu",
929
+ title: current.label || "Menu items",
930
+ description: "Configure the dropdown layout, sections, links, and footer."
931
+ }) : items.length === 0 ? /* @__PURE__ */ jsx(MainHead, {
932
+ kicker: "Header",
933
+ title: "Menu items",
934
+ description: "Add a link or a mega menu to start the header."
935
+ }) : null,
936
+ /* @__PURE__ */ jsxs("div", {
937
+ className: "bl-nav-items__preview-block",
938
+ "data-preview-chrome": true,
939
+ "data-sticky": "true",
940
+ "data-theme": previewDark ? "dark" : "light",
941
+ onClick: onPreviewClick,
942
+ onMouseLeave: (event) => {
943
+ const next = event.relatedTarget;
944
+ if (next instanceof Node && event.currentTarget.contains(next)) return;
945
+ setHoverItem(null);
946
+ },
947
+ children: [/* @__PURE__ */ jsxs("div", {
879
948
  className: "bl-nav-items__preview",
880
- onClick: onPreviewClick,
881
- children: /* @__PURE__ */ jsx(FloatingNavBlock, {
882
- items: previewItems,
883
- hideOnScroll: false,
884
- breakpoint: "lg",
949
+ children: [/* @__PURE__ */ jsx(Kicker, { children: "This is just a preview" }), /* @__PURE__ */ jsx(PreviewNav, {
950
+ items: items.filter((row) => row.label).map((row) => {
951
+ const mapped = previewItems.find((item) => item.label === row.label);
952
+ return {
953
+ label: row.label,
954
+ href: mapped?.href ?? resolveAdminPreviewLink(row, pages) ?? void 0,
955
+ content: row.blockType === "megaMenu" ? true : mapped?.content,
956
+ items: mapped?.items
957
+ };
958
+ }),
959
+ lockup,
960
+ onLockupError: () => {
961
+ const next = lockupSrc(identityFallback?.lockup, config.serverURL);
962
+ setLockup((current) => current?.url === next?.url ? null : next);
963
+ },
964
+ actions: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(PreviewThemeToggle, {
965
+ dark: previewDark,
966
+ onToggle: () => setPreviewDark((next) => !next)
967
+ }), ctaOn && ctaHref && cta.label ? /* @__PURE__ */ jsx("a", {
968
+ href: ctaHref,
969
+ className: "bl-nav-items__preview-cta",
970
+ children: cta.label
971
+ }) : null] }),
885
972
  openItem,
886
- className: "bl-nav-items__bar"
973
+ onItemEnter: (label) => setHoverItem(label)
974
+ })]
975
+ }), openRow ? /* @__PURE__ */ jsx("div", {
976
+ className: "bl-nav-items__preview-stage",
977
+ "data-testid": "nav-items-preview-mega",
978
+ onMouseEnter: () => openItem && setHoverItem(openItem),
979
+ children: /* @__PURE__ */ jsx(PreviewMega, {
980
+ path,
981
+ index: openIndex,
982
+ row: openRow,
983
+ pages
887
984
  })
888
- }),
889
- current?.blockType === "megaMenu" ? /* @__PURE__ */ jsx(MegaEditor, {
890
- path,
891
- index: selected,
892
- panel: current.panel ?? emptyPanel(),
893
- readOnly: Boolean(readOnly),
894
- onColumns: setColumns,
895
- onPanel: setPanel
896
- }) : current ? /* @__PURE__ */ jsx("p", {
897
- className: "bl-nav-items__empty",
898
- children: "A plain link is edited in the rail: label, destination, and new tab."
899
- }) : /* @__PURE__ */ jsx("p", {
900
- className: "bl-nav-items__empty",
901
- children: "Add a link or a mega menu to start the header."
902
- })
903
- ]
985
+ }) : null]
986
+ }),
987
+ current?.blockType === "megaMenu" ? /* @__PURE__ */ jsx(MegaEditor, {
988
+ path,
989
+ index: selected,
990
+ panel: current.panel ?? emptyPanel(),
991
+ readOnly: Boolean(readOnly)
992
+ }) : items.length === 0 ? /* @__PURE__ */ jsx("p", {
993
+ className: "bl-nav-items__empty",
994
+ children: "Add a link or a mega menu to start the header."
995
+ }) : null
996
+ ] }),
997
+ /* @__PURE__ */ jsx(Dialog, {
998
+ open: adding,
999
+ title: "Add menu item",
1000
+ onCancel: () => setAdding(false),
1001
+ children: /* @__PURE__ */ jsxs(TypeCards, { children: [/* @__PURE__ */ jsx(TypeCard, {
1002
+ icon: /* @__PURE__ */ jsx(KindGlyph, { kind: "navLink" }),
1003
+ label: "Plain link",
1004
+ description: "A bar item that goes to a page or URL.",
1005
+ onClick: () => add("navLink")
1006
+ }), /* @__PURE__ */ jsx(TypeCard, {
1007
+ icon: /* @__PURE__ */ jsx(KindGlyph, { kind: "megaMenu" }),
1008
+ label: "Mega menu",
1009
+ description: "A dropdown of columns, sections, and an optional footer.",
1010
+ onClick: () => add("megaMenu")
1011
+ })] })
904
1012
  }),
905
- adding ? /* @__PURE__ */ jsx("div", {
906
- className: "bl-nav-kit__modal",
907
- role: "dialog",
908
- "aria-labelledby": "bl-nav-add-title",
909
- children: /* @__PURE__ */ jsxs("div", {
910
- className: "bl-nav-kit__modal-card",
911
- children: [
912
- /* @__PURE__ */ jsx("h2", {
913
- id: "bl-nav-add-title",
914
- children: "Add menu item"
915
- }),
916
- /* @__PURE__ */ jsxs(TypeCards, { children: [/* @__PURE__ */ jsx(TypeCard, {
917
- icon: /* @__PURE__ */ jsx(LinkGlyph, {}),
918
- label: "Plain link",
919
- description: "A bar item that goes to a page or URL.",
920
- onClick: () => add("navLink")
921
- }), /* @__PURE__ */ jsx(TypeCard, {
922
- icon: /* @__PURE__ */ jsx(MegaGlyph, {}),
923
- label: "Mega menu",
924
- description: "A dropdown of columns, sections, and an optional footer.",
925
- onClick: () => add("megaMenu")
926
- })] }),
927
- /* @__PURE__ */ jsx("button", {
928
- type: "button",
929
- className: "bl-nav-items__add",
930
- onClick: () => setAdding(false),
931
- children: "Cancel"
932
- })
933
- ]
934
- })
935
- }) : null,
936
1013
  /* @__PURE__ */ jsx(ConfirmDialog, {
937
1014
  open: confirmSwitch,
938
1015
  title: "Switch to a plain link?",
@@ -943,311 +1020,837 @@ const NavItemsField = ({ field, path, readOnly }) => {
943
1020
  children: "This drops the columns, sections, and footer. The label and destination stay."
944
1021
  })
945
1022
  ]
1023
+ }) });
1024
+ };
1025
+ function PreviewThemeToggle({ dark, onToggle }) {
1026
+ return /* @__PURE__ */ jsx("button", {
1027
+ type: "button",
1028
+ className: "bl-nav-items__preview-theme",
1029
+ "aria-label": dark ? "Switch to light mode" : "Switch to dark mode",
1030
+ onClick: (event) => {
1031
+ event.stopPropagation();
1032
+ onToggle();
1033
+ },
1034
+ children: dark ? /* @__PURE__ */ jsx("svg", {
1035
+ viewBox: "0 0 24 24",
1036
+ width: "18",
1037
+ height: "18",
1038
+ fill: "none",
1039
+ stroke: "currentColor",
1040
+ strokeWidth: "2",
1041
+ "aria-hidden": true,
1042
+ children: /* @__PURE__ */ jsx("path", { d: "M21 14.5A8.5 8.5 0 1 1 9.5 3 7 7 0 0 0 21 14.5z" })
1043
+ }) : /* @__PURE__ */ jsxs("svg", {
1044
+ viewBox: "0 0 24 24",
1045
+ width: "18",
1046
+ height: "18",
1047
+ fill: "none",
1048
+ stroke: "currentColor",
1049
+ strokeWidth: "2",
1050
+ "aria-hidden": true,
1051
+ children: [/* @__PURE__ */ jsx("circle", {
1052
+ cx: "12",
1053
+ cy: "12",
1054
+ r: "4"
1055
+ }), /* @__PURE__ */ jsx("path", { d: "M12 3v2M12 19v2M3 12h2M19 12h2M5.6 5.6l1.4 1.4M17 17l1.4 1.4M18.4 5.6 17 7M7 17l-1.4 1.4" })]
1056
+ })
1057
+ });
1058
+ }
1059
+ /**
1060
+ * Kit island, not `FloatingNavBlock`. Payload admin does not load the
1061
+ * site Tailwind preset or `BisonProvider`; the live block (and
1062
+ * `ThemeToggle`) throw or render unstyled there. Theme Identity still
1063
+ * comes from `/api/globals/theme`. The public header stays
1064
+ * `headerFromNavigation` → `FloatingNavBlock` (SPI-99).
1065
+ */
1066
+ function PreviewNav({ items, lockup, onLockupError, actions, openItem, onItemEnter }) {
1067
+ return /* @__PURE__ */ jsxs("nav", {
1068
+ "aria-label": "Main",
1069
+ className: "bl-nav-items__preview-nav",
1070
+ "data-open-item": openItem ?? "",
1071
+ "data-has-logo": lockup ? "yes" : "no",
1072
+ "data-has-actions": actions ? "yes" : "no",
1073
+ children: [
1074
+ /* @__PURE__ */ jsx("div", {
1075
+ className: "bl-nav-items__preview-logo",
1076
+ children: lockup ? /* @__PURE__ */ jsx("img", {
1077
+ src: lockup.url,
1078
+ alt: lockup.alt,
1079
+ height: 20,
1080
+ onError: onLockupError
1081
+ }) : null
1082
+ }),
1083
+ /* @__PURE__ */ jsx("div", {
1084
+ className: "bl-nav-items__preview-links",
1085
+ children: items.map((item) => /* @__PURE__ */ jsxs("button", {
1086
+ type: "button",
1087
+ className: openItem === item.label ? "bl-nav-items__preview-link is-open" : "bl-nav-items__preview-link",
1088
+ "data-preview-item": item.label,
1089
+ "data-href": item.href ?? "",
1090
+ "aria-label": `Preview ${item.label}`,
1091
+ onMouseEnter: () => onItemEnter?.(item.label),
1092
+ children: [item.label, item.content || item.items?.length ? /* @__PURE__ */ jsx(PreviewChevron, {}) : null]
1093
+ }, item.label))
1094
+ }),
1095
+ /* @__PURE__ */ jsx("div", {
1096
+ className: "bl-nav-items__preview-actions",
1097
+ children: actions
1098
+ })
1099
+ ]
946
1100
  });
1101
+ }
1102
+ const PREVIEW_MAX_WIDTH = {
1103
+ narrow: "22rem",
1104
+ standard: "42rem",
1105
+ wide: "48rem"
947
1106
  };
1107
+ const PREVIEW_TRACKS = {
1108
+ "25": 3,
1109
+ "33": 4,
1110
+ "50": 6,
1111
+ "66": 8,
1112
+ "75": 9,
1113
+ "100": 12
1114
+ };
1115
+ function previewColumnTrack(width) {
1116
+ const key = String(width ?? "100");
1117
+ return `minmax(0, ${PREVIEW_TRACKS[key] ?? Math.max(1, Number(key) || 1)}fr)`;
1118
+ }
1119
+ function PreviewMega({ path, index, row, pages }) {
1120
+ const panel = row.panel;
1121
+ const columns = panel?.columns ?? [];
1122
+ const maxWidthField = useField({ path: `${path}.${index}.panel.maxWidth` });
1123
+ const width0 = useField({ path: `${path}.${index}.panel.columns.0.width` });
1124
+ const width1 = useField({ path: `${path}.${index}.panel.columns.1.width` });
1125
+ const width2 = useField({ path: `${path}.${index}.panel.columns.2.width` });
1126
+ const width3 = useField({ path: `${path}.${index}.panel.columns.3.width` });
1127
+ const divider1 = useField({ path: `${path}.${index}.panel.columns.1.divider` });
1128
+ const divider2 = useField({ path: `${path}.${index}.panel.columns.2.divider` });
1129
+ const divider3 = useField({ path: `${path}.${index}.panel.columns.3.divider` });
1130
+ const liveWidths = [
1131
+ width0.value,
1132
+ width1.value,
1133
+ width2.value,
1134
+ width3.value
1135
+ ];
1136
+ const liveDividers = [
1137
+ void 0,
1138
+ divider1.value,
1139
+ divider2.value,
1140
+ divider3.value
1141
+ ];
1142
+ const maxWidth = PREVIEW_MAX_WIDTH[maxWidthField.value ?? panel?.maxWidth ?? "standard"] ?? PREVIEW_MAX_WIDTH.standard;
1143
+ const complete = columns.some((column) => (column.sections ?? []).some((section) => (section.links ?? []).some((link) => {
1144
+ const item = link;
1145
+ return Boolean(item.label && resolveAdminPreviewLink(item, pages));
1146
+ })));
1147
+ const overview = panel?.footer?.overview;
1148
+ const cta = panel?.footer?.cta;
1149
+ const overviewHref = overview ? resolveAdminPreviewLink(overview, pages) : null;
1150
+ const ctaHref = cta ? resolveAdminPreviewLink(cta, pages) : null;
1151
+ const showFooter = Boolean(overview?.label && overviewHref || cta?.label && ctaHref);
1152
+ return /* @__PURE__ */ jsxs("div", {
1153
+ className: "bl-nav-items__mega-preview",
1154
+ style: { maxWidth },
1155
+ children: [complete ? /* @__PURE__ */ jsx("div", {
1156
+ className: "bl-nav-items__preview-columns",
1157
+ style: { gridTemplateColumns: columns.map((column, columnIndex) => previewColumnTrack(liveWidths[columnIndex] ?? column.width)).join(" ") },
1158
+ children: columns.map((column, columnIndex) => /* @__PURE__ */ jsx("div", {
1159
+ className: columnIndex > 0 && Boolean(liveDividers[columnIndex] ?? column.divider) ? "bl-nav-items__preview-col has-border" : "bl-nav-items__preview-col",
1160
+ children: (column.sections ?? []).map((section, sectionIndex) => {
1161
+ const links = (section.links ?? []).flatMap((link, linkIndex) => {
1162
+ const item = link;
1163
+ const href = resolveAdminPreviewLink(item, pages);
1164
+ if (!item.label || !href) return [];
1165
+ const featured = section.display === "featured";
1166
+ return [/* @__PURE__ */ jsx("div", {
1167
+ className: featured ? "bl-nav-items__preview-featured" : "bl-nav-items__preview-list-row",
1168
+ children: featured ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
1169
+ className: "title",
1170
+ children: item.label
1171
+ }), item.description ? /* @__PURE__ */ jsx("small", { children: item.description }) : null] }) : /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("strong", { children: item.label }), item.description ? /* @__PURE__ */ jsx("small", { children: item.description }) : null] })
1172
+ }, `${sectionIndex}-${linkIndex}`)];
1173
+ });
1174
+ return /* @__PURE__ */ jsxs("div", { children: [section.eyebrow ? /* @__PURE__ */ jsx("div", {
1175
+ className: "bl-nav-items__preview-eyebrow",
1176
+ children: section.eyebrow
1177
+ }) : null, links.length ? links : /* @__PURE__ */ jsx("div", {
1178
+ className: "bl-nav-items__preview-empty",
1179
+ children: "Empty section"
1180
+ })] }, sectionIndex);
1181
+ })
1182
+ }, columnIndex))
1183
+ }) : /* @__PURE__ */ jsx("div", {
1184
+ className: "bl-nav-items__preview-empty",
1185
+ children: "No complete links in this menu yet."
1186
+ }), showFooter ? /* @__PURE__ */ jsxs("div", {
1187
+ className: "bl-nav-items__preview-footer",
1188
+ children: [overview?.label && overviewHref ? /* @__PURE__ */ jsx("a", {
1189
+ href: overviewHref,
1190
+ children: overview.label
1191
+ }) : /* @__PURE__ */ jsx("span", {}), cta?.label && ctaHref ? /* @__PURE__ */ jsx("span", {
1192
+ className: "cta",
1193
+ children: cta.label
1194
+ }) : null]
1195
+ }) : null]
1196
+ });
1197
+ }
1198
+ function HeaderCta({ path, readOnly }) {
1199
+ const group = useField({ path });
1200
+ const enabled = useField({ path: `${path}.enabled` });
1201
+ const label = useField({ path: `${path}.label` });
1202
+ const page = useField({ path: `${path}.page` });
1203
+ const href = useField({ path: `${path}.href` });
1204
+ const newTab = useField({ path: `${path}.newTab` });
1205
+ const on = enabled.value === true || enabled.value !== false && Boolean(label.value || page.value || href.value);
1206
+ function setEnabled(next) {
1207
+ enabled.setValue(next);
1208
+ if (!next) {
1209
+ label.setValue("");
1210
+ page.setValue(null);
1211
+ href.setValue(null);
1212
+ newTab.setValue(false);
1213
+ }
1214
+ }
1215
+ return /* @__PURE__ */ jsxs("fieldset", {
1216
+ className: "bl-nav-items__header-cta",
1217
+ "aria-label": "Header button",
1218
+ children: [
1219
+ /* @__PURE__ */ jsx("div", {
1220
+ className: "bl-nav-items__header-cta-head",
1221
+ children: /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", { children: "Header button" }), /* @__PURE__ */ jsx("p", { children: "The pill on the right of the bar." })] })
1222
+ }),
1223
+ /* @__PURE__ */ jsx(CheckLabel, {
1224
+ className: "bl-nav-items__header-cta-toggle",
1225
+ checked: on,
1226
+ disabled: readOnly,
1227
+ onCheckedChange: setEnabled,
1228
+ children: "Show Header button"
1229
+ }),
1230
+ on ? /* @__PURE__ */ jsxs(Fragment, { children: [
1231
+ /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsxs(Label, { children: [
1232
+ "Label",
1233
+ " ",
1234
+ /* @__PURE__ */ jsx("span", {
1235
+ className: "bl-nav-items__req",
1236
+ "aria-hidden": true,
1237
+ children: "*"
1238
+ })
1239
+ ] }), /* @__PURE__ */ jsx(Input, {
1240
+ value: label.value ?? "",
1241
+ disabled: readOnly,
1242
+ onChange: (event) => label.setValue(event.target.value)
1243
+ })] }),
1244
+ /* @__PURE__ */ jsx(ComposedLinkField, {
1245
+ path: `${path}._index-0`,
1246
+ parentPath: path,
1247
+ readOnly
1248
+ }),
1249
+ /* @__PURE__ */ jsx(CheckLabel, {
1250
+ checked: Boolean(newTab.value),
1251
+ disabled: readOnly,
1252
+ onCheckedChange: (checked) => newTab.setValue(checked),
1253
+ children: "Open in a new tab"
1254
+ })
1255
+ ] }) : null,
1256
+ /* @__PURE__ */ jsx(FieldError, {
1257
+ path: group.path,
1258
+ showError: group.showError,
1259
+ message: group.errorMessage
1260
+ })
1261
+ ]
1262
+ });
1263
+ }
948
1264
  function ItemBasics({ path, index, readOnly }) {
949
1265
  const label = useField({ path: `${path}.${index}.label` });
950
1266
  const newTab = useField({ path: `${path}.${index}.newTab` });
951
1267
  return /* @__PURE__ */ jsxs("div", {
952
1268
  className: "bl-nav-items__basics",
953
1269
  children: [
954
- /* @__PURE__ */ jsxs("label", {
955
- className: "bl-nav-items__field",
956
- children: [/* @__PURE__ */ jsx("span", { children: "Label" }), /* @__PURE__ */ jsx("input", {
957
- value: label.value ?? "",
958
- disabled: readOnly,
959
- onChange: (event) => label.setValue(event.target.value)
960
- })]
961
- }),
1270
+ /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(Label, { children: "Label" }), /* @__PURE__ */ jsx(Input, {
1271
+ value: label.value ?? "",
1272
+ disabled: readOnly,
1273
+ onChange: (event) => label.setValue(event.target.value)
1274
+ })] }),
962
1275
  /* @__PURE__ */ jsx(ComposedLinkField, {
963
1276
  path: `${path}.${index}._index-0`,
964
1277
  parentPath: `${path}.${index}`,
965
1278
  readOnly
966
1279
  }),
967
- /* @__PURE__ */ jsxs("label", {
968
- className: "bl-nav-items__check",
969
- children: [/* @__PURE__ */ jsx("input", {
970
- type: "checkbox",
971
- checked: Boolean(newTab.value),
972
- disabled: readOnly,
973
- onChange: (event) => newTab.setValue(event.target.checked)
974
- }), "Open in a new tab"]
1280
+ /* @__PURE__ */ jsx(CheckLabel, {
1281
+ checked: Boolean(newTab.value),
1282
+ disabled: readOnly,
1283
+ onCheckedChange: (checked) => newTab.setValue(checked),
1284
+ children: "Open in a new tab"
975
1285
  })
976
1286
  ]
977
1287
  });
978
1288
  }
979
- function MegaEditor({ path, index, panel, readOnly, onColumns, onPanel }) {
1289
+ function MegaEditor({ path, index, panel, readOnly }) {
1290
+ const { addFieldRow } = useForm();
980
1291
  const columns = panel.columns ?? [];
981
1292
  const columnsError = useField({ path: `${path}.${index}.panel.columns` });
1293
+ const columnsPath = `${path}.${index}.panel.columns`;
1294
+ const maxWidth = useField({ path: `${path}.${index}.panel.maxWidth` });
982
1295
  return /* @__PURE__ */ jsxs("div", {
983
1296
  className: "bl-nav-items__mega",
984
1297
  children: [
985
- /* @__PURE__ */ jsxs("label", {
986
- className: "bl-nav-items__field",
987
- children: [/* @__PURE__ */ jsx("span", { children: "Dropdown width" }), /* @__PURE__ */ jsxs("select", {
988
- value: panel.maxWidth ?? "standard",
989
- disabled: readOnly,
990
- onChange: (event) => onPanel({ maxWidth: event.target.value }),
991
- children: [
992
- /* @__PURE__ */ jsx("option", {
993
- value: "narrow",
994
- children: "Narrow"
995
- }),
996
- /* @__PURE__ */ jsx("option", {
997
- value: "standard",
998
- children: "Standard"
999
- }),
1000
- /* @__PURE__ */ jsx("option", {
1001
- value: "wide",
1002
- children: "Wide"
1003
- })
1004
- ]
1298
+ /* @__PURE__ */ jsxs("div", {
1299
+ className: "bl-nav-items__builder-head",
1300
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h2", { children: "Menu content" }), /* @__PURE__ */ jsx("p", { children: "Set each column’s width here. The header preview is what shows the live layout." })] }), /* @__PURE__ */ jsxs("label", {
1301
+ className: "bl-nav-items__tool",
1302
+ children: ["Panel width", /* @__PURE__ */ jsxs(Select, {
1303
+ value: maxWidth.value ?? panel.maxWidth ?? "standard",
1304
+ disabled: readOnly,
1305
+ onValueChange: (value) => maxWidth.setValue(value),
1306
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
1307
+ "aria-label": "Panel width",
1308
+ children: /* @__PURE__ */ jsx(SelectValue, {})
1309
+ }), /* @__PURE__ */ jsxs(SelectContent, { children: [
1310
+ /* @__PURE__ */ jsx(SelectItem, {
1311
+ value: "narrow",
1312
+ children: "Narrow"
1313
+ }),
1314
+ /* @__PURE__ */ jsx(SelectItem, {
1315
+ value: "standard",
1316
+ children: "Standard"
1317
+ }),
1318
+ /* @__PURE__ */ jsx(SelectItem, {
1319
+ value: "wide",
1320
+ children: "Wide"
1321
+ })
1322
+ ] })]
1323
+ })]
1005
1324
  })]
1006
1325
  }),
1007
1326
  /* @__PURE__ */ jsx("div", {
1008
1327
  className: "bl-nav-items__columns",
1009
1328
  "data-testid": "nav-items-columns",
1010
1329
  style: { gridTemplateColumns: "repeat(2, minmax(0, 1fr))" },
1011
- children: columns.map((column, columnIndex) => /* @__PURE__ */ jsxs("fieldset", {
1012
- className: "bl-nav-items__column",
1013
- "aria-label": `Column ${columnIndex + 1}`,
1014
- children: [
1015
- /* @__PURE__ */ jsxs("legend", { children: ["Column ", columnIndex + 1] }),
1016
- /* @__PURE__ */ jsxs("div", {
1017
- className: "bl-nav-items__column-settings",
1018
- children: [/* @__PURE__ */ jsxs("label", {
1019
- className: "bl-nav-items__field",
1020
- children: [/* @__PURE__ */ jsx("span", { children: "Width" }), /* @__PURE__ */ jsx("select", {
1021
- value: column.width ?? "100",
1022
- disabled: readOnly,
1023
- onChange: (event) => onColumns(columns.map((row, i) => i === columnIndex ? {
1024
- ...row,
1025
- width: event.target.value
1026
- } : row)),
1027
- children: WIDTHS.map((width) => /* @__PURE__ */ jsxs("option", {
1028
- value: width,
1029
- children: [width, "%"]
1030
- }, width))
1031
- })]
1032
- }), columnIndex > 0 ? /* @__PURE__ */ jsxs("label", {
1033
- className: "bl-nav-items__check",
1034
- children: [/* @__PURE__ */ jsx("input", {
1035
- type: "checkbox",
1036
- checked: Boolean(column.divider),
1037
- disabled: readOnly,
1038
- onChange: (event) => onColumns(columns.map((row, i) => i === columnIndex ? {
1039
- ...row,
1040
- divider: event.target.checked
1041
- } : row))
1042
- }), "Draw a line on the left of this column"]
1043
- }) : null]
1044
- }),
1045
- (column.sections ?? []).map((section, sectionIndex) => /* @__PURE__ */ jsx(SectionEditor, {
1046
- path,
1047
- itemIndex: index,
1048
- columnIndex,
1049
- sectionIndex,
1050
- section,
1051
- readOnly,
1052
- onChange: (next) => onColumns(columns.map((row, i) => i === columnIndex ? {
1053
- ...row,
1054
- sections: (row.sections ?? []).map((entry, j) => j === sectionIndex ? next : entry)
1055
- } : row))
1056
- }, sectionIndex)),
1057
- readOnly || (column.sections?.length ?? 0) >= 8 ? null : /* @__PURE__ */ jsx("button", {
1058
- type: "button",
1059
- className: "bl-nav-items__add",
1060
- onClick: () => onColumns(columns.map((row, i) => i === columnIndex ? {
1061
- ...row,
1062
- sections: [...row.sections ?? [], emptySection()]
1063
- } : row)),
1064
- children: "Add section"
1065
- })
1066
- ]
1330
+ children: columns.map((column, columnIndex) => /* @__PURE__ */ jsx(ColumnEditor, {
1331
+ path,
1332
+ itemIndex: index,
1333
+ columnIndex,
1334
+ column,
1335
+ readOnly,
1336
+ columnCount: columns.length
1067
1337
  }, columnIndex))
1068
1338
  }),
1069
- readOnly || columns.length >= 4 ? null : /* @__PURE__ */ jsx("button", {
1070
- type: "button",
1071
- className: "bl-nav-items__add",
1072
- onClick: () => onColumns([...columns, {
1073
- ...emptyColumn(),
1074
- width: "25"
1075
- }]),
1076
- children: "Add column"
1339
+ readOnly || columns.length >= 4 ? null : /* @__PURE__ */ jsx(Button, {
1340
+ variant: "outline",
1341
+ className: "bl-nav-items__add-column",
1342
+ onClick: () => {
1343
+ addFieldRow({
1344
+ path: columnsPath,
1345
+ schemaPath: columnsPath,
1346
+ subFieldState: {
1347
+ width: {
1348
+ value: "25",
1349
+ valid: true
1350
+ },
1351
+ divider: {
1352
+ value: true,
1353
+ valid: true
1354
+ }
1355
+ }
1356
+ });
1357
+ addFieldRow({
1358
+ path: `${columnsPath}.${columns.length}.sections`,
1359
+ schemaPath: `${columnsPath}.${columns.length}.sections`,
1360
+ subFieldState: {
1361
+ display: {
1362
+ value: "list",
1363
+ valid: true
1364
+ },
1365
+ hideDescriptionsOnMobile: {
1366
+ value: true,
1367
+ valid: true
1368
+ }
1369
+ }
1370
+ });
1371
+ },
1372
+ children: "+ Add column"
1077
1373
  }),
1078
1374
  /* @__PURE__ */ jsx(FieldError, {
1079
1375
  path: columnsError.path,
1080
1376
  showError: columnsError.showError,
1081
1377
  message: columnsError.errorMessage
1082
1378
  }),
1083
- /* @__PURE__ */ jsxs("div", {
1379
+ /* @__PURE__ */ jsxs("section", {
1084
1380
  className: "bl-nav-items__footer",
1085
- children: [/* @__PURE__ */ jsx("h3", { children: "Footer" }), /* @__PURE__ */ jsxs("div", {
1086
- className: "bl-nav-items__footer-grid",
1087
- children: [/* @__PURE__ */ jsxs("div", { children: [
1088
- /* @__PURE__ */ jsx("h4", { children: "Overview link" }),
1089
- /* @__PURE__ */ jsx(ComposedLinkField, {
1090
- path: `${path}.${index}.panel.footer.overview._index-0`,
1091
- parentPath: `${path}.${index}.panel.footer.overview`,
1092
- readOnly
1093
- }),
1094
- /* @__PURE__ */ jsxs("label", {
1095
- className: "bl-nav-items__field",
1096
- children: [/* @__PURE__ */ jsx("span", { children: "Label" }), /* @__PURE__ */ jsx(FooterText, {
1381
+ children: [/* @__PURE__ */ jsx("div", {
1382
+ className: "bl-nav-items__footer-head",
1383
+ children: /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", { children: "Footer" }), /* @__PURE__ */ jsx("p", { children: "Optional links displayed below the menu columns. The overview is the section’s own landing page so it stays reachable from the bar." })] })
1384
+ }), /* @__PURE__ */ jsxs("div", {
1385
+ className: "bl-nav-items__footer-body",
1386
+ children: [/* @__PURE__ */ jsxs("div", {
1387
+ className: "bl-nav-items__footer-card",
1388
+ children: [
1389
+ /* @__PURE__ */ jsx("h4", { children: "Overview link" }),
1390
+ /* @__PURE__ */ jsx(ComposedLinkField, {
1391
+ path: `${path}.${index}.panel.footer.overview._index-0`,
1392
+ parentPath: `${path}.${index}.panel.footer.overview`,
1393
+ readOnly
1394
+ }),
1395
+ /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(Label, { children: "Label" }), /* @__PURE__ */ jsx(FooterText, {
1097
1396
  path: `${path}.${index}.panel.footer.overview.label`,
1098
1397
  readOnly
1099
- })]
1100
- })
1101
- ] }), /* @__PURE__ */ jsxs("div", { children: [
1102
- /* @__PURE__ */ jsx("h4", { children: "Call to action" }),
1103
- /* @__PURE__ */ jsx(ComposedLinkField, {
1104
- path: `${path}.${index}.panel.footer.cta._index-0`,
1105
- parentPath: `${path}.${index}.panel.footer.cta`,
1106
- readOnly
1107
- }),
1108
- /* @__PURE__ */ jsxs("label", {
1109
- className: "bl-nav-items__field",
1110
- children: [/* @__PURE__ */ jsx("span", { children: "Label" }), /* @__PURE__ */ jsx(FooterText, {
1398
+ })] })
1399
+ ]
1400
+ }), /* @__PURE__ */ jsxs("div", {
1401
+ className: "bl-nav-items__footer-card",
1402
+ children: [
1403
+ /* @__PURE__ */ jsx("h4", { children: "Call to action" }),
1404
+ /* @__PURE__ */ jsx(ComposedLinkField, {
1405
+ path: `${path}.${index}.panel.footer.cta._index-0`,
1406
+ parentPath: `${path}.${index}.panel.footer.cta`,
1407
+ readOnly
1408
+ }),
1409
+ /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(Label, { children: "Label" }), /* @__PURE__ */ jsx(FooterText, {
1111
1410
  path: `${path}.${index}.panel.footer.cta.label`,
1112
1411
  readOnly
1113
- })]
1114
- })
1115
- ] })]
1412
+ })] })
1413
+ ]
1414
+ })]
1116
1415
  })]
1117
1416
  })
1118
1417
  ]
1119
1418
  });
1120
1419
  }
1420
+ function RowMenu({ label, index, count, path, allowRemove = true, onMoved }) {
1421
+ const [open, setOpen] = useState(false);
1422
+ const { moveFieldRow, removeFieldRow } = useForm();
1423
+ return /* @__PURE__ */ jsxs("div", {
1424
+ className: "bl-nav-items__menu",
1425
+ children: [/* @__PURE__ */ jsx("button", {
1426
+ type: "button",
1427
+ "aria-label": `${label} actions`,
1428
+ onClick: () => setOpen((next) => !next),
1429
+ children: "⋯"
1430
+ }), open ? /* @__PURE__ */ jsxs("div", {
1431
+ className: "bl-nav-items__menu-pop",
1432
+ children: [
1433
+ /* @__PURE__ */ jsx("button", {
1434
+ type: "button",
1435
+ disabled: index === 0,
1436
+ onClick: () => {
1437
+ moveFieldRow({
1438
+ path,
1439
+ moveFromIndex: index,
1440
+ moveToIndex: index - 1
1441
+ });
1442
+ onMoved?.(index - 1);
1443
+ setOpen(false);
1444
+ },
1445
+ children: "Move up"
1446
+ }),
1447
+ /* @__PURE__ */ jsx("button", {
1448
+ type: "button",
1449
+ disabled: index === count - 1,
1450
+ onClick: () => {
1451
+ moveFieldRow({
1452
+ path,
1453
+ moveFromIndex: index,
1454
+ moveToIndex: index + 1
1455
+ });
1456
+ onMoved?.(index + 1);
1457
+ setOpen(false);
1458
+ },
1459
+ children: "Move down"
1460
+ }),
1461
+ allowRemove ? /* @__PURE__ */ jsx("button", {
1462
+ type: "button",
1463
+ className: "bl-nav-kit__danger",
1464
+ onClick: () => {
1465
+ removeFieldRow({
1466
+ path,
1467
+ rowIndex: index
1468
+ });
1469
+ setOpen(false);
1470
+ },
1471
+ children: "Delete"
1472
+ }) : null
1473
+ ]
1474
+ }) : null]
1475
+ });
1476
+ }
1477
+ function useRowActions({ index, count, path, allowRemove = true, onMoved, readOnly }) {
1478
+ const { moveFieldRow, removeFieldRow } = useForm();
1479
+ if (readOnly) return void 0;
1480
+ const actions = [{
1481
+ label: "Move up",
1482
+ disabled: index === 0,
1483
+ onClick: () => {
1484
+ moveFieldRow({
1485
+ path,
1486
+ moveFromIndex: index,
1487
+ moveToIndex: index - 1
1488
+ });
1489
+ onMoved?.(index - 1);
1490
+ }
1491
+ }, {
1492
+ label: "Move down",
1493
+ disabled: index === count - 1,
1494
+ onClick: () => {
1495
+ moveFieldRow({
1496
+ path,
1497
+ moveFromIndex: index,
1498
+ moveToIndex: index + 1
1499
+ });
1500
+ onMoved?.(index + 1);
1501
+ }
1502
+ }];
1503
+ if (allowRemove) actions.push({
1504
+ label: "Delete",
1505
+ danger: true,
1506
+ onClick: () => removeFieldRow({
1507
+ path,
1508
+ rowIndex: index
1509
+ })
1510
+ });
1511
+ return actions;
1512
+ }
1513
+ function MegaLinkEditor({ path, arrayPath, index, count, label, readOnly }) {
1514
+ const description = useField({ path: `${path}.description` });
1515
+ const newTab = useField({ path: `${path}.newTab` });
1516
+ return /* @__PURE__ */ jsxs(Fold, {
1517
+ title: label?.trim() || "Untitled",
1518
+ tone: "dark",
1519
+ actions: useRowActions({
1520
+ index,
1521
+ count,
1522
+ path: arrayPath,
1523
+ readOnly
1524
+ }),
1525
+ children: [
1526
+ /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(Label, { children: "Label" }), /* @__PURE__ */ jsx(FooterText, {
1527
+ path: `${path}.label`,
1528
+ readOnly
1529
+ })] }),
1530
+ /* @__PURE__ */ jsx(ComposedLinkField, {
1531
+ path: `${path}._index-0`,
1532
+ parentPath: path,
1533
+ readOnly
1534
+ }),
1535
+ /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(Label, { children: "Description" }), /* @__PURE__ */ jsx(Textarea, {
1536
+ value: description.value ?? "",
1537
+ disabled: readOnly,
1538
+ rows: 2,
1539
+ onChange: (event) => description.setValue(event.target.value)
1540
+ })] }),
1541
+ /* @__PURE__ */ jsx(CheckLabel, {
1542
+ checked: Boolean(newTab.value),
1543
+ disabled: readOnly,
1544
+ onCheckedChange: (checked) => newTab.setValue(checked),
1545
+ children: "Open in a new tab"
1546
+ })
1547
+ ]
1548
+ });
1549
+ }
1121
1550
  function FooterText({ path, readOnly }) {
1122
1551
  const field = useField({ path });
1123
- return /* @__PURE__ */ jsx("input", {
1552
+ return /* @__PURE__ */ jsx(Input, {
1124
1553
  value: field.value ?? "",
1125
1554
  disabled: readOnly,
1126
1555
  onChange: (event) => field.setValue(event.target.value)
1127
1556
  });
1128
1557
  }
1129
- function SectionEditor({ path, itemIndex, columnIndex, sectionIndex, section, readOnly, onChange }) {
1130
- const links = section.links ?? [];
1131
- return /* @__PURE__ */ jsxs("div", {
1132
- className: "bl-nav-items__section",
1133
- children: [
1134
- /* @__PURE__ */ jsxs("label", {
1135
- className: "bl-nav-items__field",
1136
- children: [/* @__PURE__ */ jsx("span", { children: "Eyebrow" }), /* @__PURE__ */ jsx("input", {
1137
- value: section.eyebrow ?? "",
1138
- disabled: readOnly,
1139
- onChange: (event) => onChange({
1140
- ...section,
1141
- eyebrow: event.target.value
1142
- })
1143
- })]
1144
- }),
1145
- /* @__PURE__ */ jsxs(TypeCards, {
1146
- compact: true,
1147
- children: [/* @__PURE__ */ jsx(TypeCard, {
1148
- label: "Featured",
1149
- active: section.display === "featured",
1558
+ function PreviewChevron() {
1559
+ return /* @__PURE__ */ jsx("svg", {
1560
+ className: "bl-nav-items__preview-chevron",
1561
+ viewBox: "0 0 24 24",
1562
+ width: "12",
1563
+ height: "12",
1564
+ fill: "none",
1565
+ stroke: "currentColor",
1566
+ strokeWidth: "2",
1567
+ strokeLinecap: "round",
1568
+ strokeLinejoin: "round",
1569
+ "aria-hidden": true,
1570
+ children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
1571
+ });
1572
+ }
1573
+ function CheckLabel({ checked, disabled, onCheckedChange, children, className }) {
1574
+ return /* @__PURE__ */ jsxs("label", {
1575
+ className: ["bl-nav-items__check", className].filter(Boolean).join(" "),
1576
+ children: [/* @__PURE__ */ jsx(Checkbox, {
1577
+ checked,
1578
+ disabled,
1579
+ onCheckedChange: (value) => onCheckedChange(value === true)
1580
+ }), children]
1581
+ });
1582
+ }
1583
+ function ColumnEditor({ path, itemIndex, columnIndex, column, readOnly, columnCount }) {
1584
+ const { addFieldRow } = useForm();
1585
+ const width = useField({ path: `${path}.${itemIndex}.panel.columns.${columnIndex}.width` });
1586
+ const divider = useField({ path: `${path}.${itemIndex}.panel.columns.${columnIndex}.divider` });
1587
+ const columnsPath = `${path}.${itemIndex}.panel.columns`;
1588
+ const sectionsPath = `${path}.${itemIndex}.panel.columns.${columnIndex}.sections`;
1589
+ const sections = column.sections ?? [];
1590
+ const columnName = `Column ${columnIndex + 1}`;
1591
+ const actions = useRowActions({
1592
+ index: columnIndex,
1593
+ count: columnCount,
1594
+ path: columnsPath,
1595
+ allowRemove: columnCount > 1,
1596
+ readOnly
1597
+ });
1598
+ return /* @__PURE__ */ jsx(Fold, {
1599
+ title: columnName,
1600
+ tone: "light",
1601
+ badge: `${width.value ?? column.width ?? "100"}%`,
1602
+ meta: (open) => open ? null : /* @__PURE__ */ jsxs("small", { children: [
1603
+ sections.length,
1604
+ " ",
1605
+ sections.length === 1 ? "section" : "sections"
1606
+ ] }),
1607
+ actions,
1608
+ children: /* @__PURE__ */ jsxs(Stack, { children: [
1609
+ /* @__PURE__ */ jsxs("div", {
1610
+ className: "bl-nav-items__column-settings",
1611
+ children: [/* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(Label, { children: "Width" }), /* @__PURE__ */ jsxs(Select, {
1612
+ value: width.value ?? column.width ?? "100",
1150
1613
  disabled: readOnly,
1151
- onClick: () => onChange({
1152
- ...section,
1153
- display: "featured"
1154
- })
1155
- }), /* @__PURE__ */ jsx(TypeCard, {
1156
- label: "List",
1157
- active: section.display !== "featured",
1614
+ onValueChange: (value) => width.setValue(value),
1615
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
1616
+ "aria-label": "Width",
1617
+ children: /* @__PURE__ */ jsx(SelectValue, {})
1618
+ }), /* @__PURE__ */ jsx(SelectContent, { children: WIDTHS.map((option) => /* @__PURE__ */ jsxs(SelectItem, {
1619
+ value: option,
1620
+ children: [option, "%"]
1621
+ }, option)) })]
1622
+ })] }), columnIndex > 0 ? /* @__PURE__ */ jsx(CheckLabel, {
1623
+ checked: Boolean(divider.value ?? column.divider),
1158
1624
  disabled: readOnly,
1159
- onClick: () => onChange({
1160
- ...section,
1161
- display: "list"
1162
- })
1163
- })]
1625
+ onCheckedChange: (checked) => divider.setValue(checked),
1626
+ children: "Draw a line on the left"
1627
+ }) : null]
1164
1628
  }),
1165
- /* @__PURE__ */ jsxs("label", {
1166
- className: "bl-nav-items__check",
1167
- children: [/* @__PURE__ */ jsx("input", {
1168
- type: "checkbox",
1169
- checked: section.hideDescriptionsOnMobile !== false,
1170
- disabled: readOnly,
1171
- onChange: (event) => onChange({
1172
- ...section,
1173
- hideDescriptionsOnMobile: event.target.checked
1629
+ sections.map((section, sectionIndex) => /* @__PURE__ */ jsx(SectionEditor, {
1630
+ path,
1631
+ itemIndex,
1632
+ columnIndex,
1633
+ sectionIndex,
1634
+ section,
1635
+ readOnly,
1636
+ sectionCount: sections.length
1637
+ }, sectionIndex)),
1638
+ readOnly || sections.length >= 8 ? null : /* @__PURE__ */ jsx(Button, {
1639
+ variant: "outline",
1640
+ className: "bl-nav-items__add-section",
1641
+ onClick: () => addFieldRow({
1642
+ path: sectionsPath,
1643
+ schemaPath: sectionsPath,
1644
+ subFieldState: {
1645
+ display: {
1646
+ value: "list",
1647
+ valid: true
1648
+ },
1649
+ hideDescriptionsOnMobile: {
1650
+ value: true,
1651
+ valid: true
1652
+ }
1653
+ }
1654
+ }),
1655
+ children: "+ Add section to this column"
1656
+ })
1657
+ ] })
1658
+ });
1659
+ }
1660
+ function SectionEditor({ path, itemIndex, columnIndex, sectionIndex, section, readOnly, sectionCount }) {
1661
+ const { addFieldRow } = useForm();
1662
+ const base = `${path}.${itemIndex}.panel.columns.${columnIndex}.sections.${sectionIndex}`;
1663
+ const sectionsPath = `${path}.${itemIndex}.panel.columns.${columnIndex}.sections`;
1664
+ const display = useField({ path: `${base}.display` });
1665
+ const eyebrow = useField({ path: `${base}.eyebrow` });
1666
+ const hideMobile = useField({ path: `${base}.hideDescriptionsOnMobile` });
1667
+ const links = section.links ?? [];
1668
+ const featured = (display.value ?? section.display) === "featured";
1669
+ return /* @__PURE__ */ jsx(Fold, {
1670
+ title: eyebrow.value || section.eyebrow || "Untitled section",
1671
+ tone: "dark",
1672
+ meta: (open) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("small", { children: featured ? "featured" : "list" }), open ? null : /* @__PURE__ */ jsxs("small", { children: [
1673
+ links.length,
1674
+ " ",
1675
+ links.length === 1 ? "link" : "links"
1676
+ ] })] }),
1677
+ actions: useRowActions({
1678
+ index: sectionIndex,
1679
+ count: sectionCount,
1680
+ path: sectionsPath,
1681
+ readOnly
1682
+ }),
1683
+ children: /* @__PURE__ */ jsxs(Stack, { children: [
1684
+ /* @__PURE__ */ jsxs("div", {
1685
+ className: "bl-nav-items__section-settings",
1686
+ children: [
1687
+ /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(Label, { children: "Eyebrow" }), /* @__PURE__ */ jsx(Input, {
1688
+ value: eyebrow.value ?? section.eyebrow ?? "",
1689
+ disabled: readOnly,
1690
+ placeholder: "Optional heading",
1691
+ onChange: (event) => eyebrow.setValue(event.target.value)
1692
+ })] }),
1693
+ /* @__PURE__ */ jsxs(Field, {
1694
+ as: "div",
1695
+ children: [/* @__PURE__ */ jsx(Label, { children: "Display" }), /* @__PURE__ */ jsxs("div", {
1696
+ className: "bl-nav-items__seg",
1697
+ children: [/* @__PURE__ */ jsx("button", {
1698
+ type: "button",
1699
+ className: featured ? "is-active" : void 0,
1700
+ disabled: readOnly,
1701
+ onClick: () => display.setValue("featured"),
1702
+ children: "Featured"
1703
+ }), /* @__PURE__ */ jsx("button", {
1704
+ type: "button",
1705
+ className: !featured ? "is-active" : void 0,
1706
+ disabled: readOnly,
1707
+ onClick: () => display.setValue("list"),
1708
+ children: "List"
1709
+ })]
1710
+ })]
1711
+ }),
1712
+ /* @__PURE__ */ jsx(CheckLabel, {
1713
+ checked: (hideMobile.value ?? section.hideDescriptionsOnMobile) !== false,
1714
+ disabled: readOnly,
1715
+ onCheckedChange: (checked) => hideMobile.setValue(checked),
1716
+ children: "Hide descriptions on mobile"
1174
1717
  })
1175
- }), "Hide descriptions on mobile"]
1718
+ ]
1176
1719
  }),
1177
- links.map((link, linkIndex) => /* @__PURE__ */ jsxs("div", {
1178
- className: "bl-nav-items__link",
1179
- children: [/* @__PURE__ */ jsxs("label", {
1180
- className: "bl-nav-items__field",
1181
- children: [/* @__PURE__ */ jsx("span", { children: "Label" }), /* @__PURE__ */ jsx("input", {
1182
- value: String(link.label ?? ""),
1183
- disabled: readOnly,
1184
- onChange: (event) => onChange({
1185
- ...section,
1186
- links: links.map((row, i) => i === linkIndex ? {
1187
- ...row,
1188
- label: event.target.value
1189
- } : row)
1190
- })
1191
- })]
1192
- }), /* @__PURE__ */ jsx(ComposedLinkField, {
1193
- path: `${path}.${itemIndex}.panel.columns.${columnIndex}.sections.${sectionIndex}.links.${linkIndex}._index-0`,
1194
- parentPath: `${path}.${itemIndex}.panel.columns.${columnIndex}.sections.${sectionIndex}.links.${linkIndex}`,
1195
- readOnly
1196
- })]
1720
+ links.map((link, linkIndex) => /* @__PURE__ */ jsx(MegaLinkEditor, {
1721
+ path: `${base}.links.${linkIndex}`,
1722
+ arrayPath: `${base}.links`,
1723
+ index: linkIndex,
1724
+ count: links.length,
1725
+ label: link.label,
1726
+ readOnly
1197
1727
  }, linkIndex)),
1198
- readOnly ? null : /* @__PURE__ */ jsx("button", {
1199
- type: "button",
1200
- className: "bl-nav-items__add",
1201
- onClick: () => onChange({
1202
- ...section,
1203
- links: [...links, {
1204
- label: "New link",
1205
- type: "page",
1206
- page: null,
1207
- href: null
1208
- }]
1728
+ readOnly ? null : /* @__PURE__ */ jsx(Button, {
1729
+ variant: "outline",
1730
+ className: "bl-nav-items__inline-add",
1731
+ onClick: () => addFieldRow({
1732
+ path: `${base}.links`,
1733
+ schemaPath: `${base}.links`,
1734
+ subFieldState: {
1735
+ label: {
1736
+ value: "New link",
1737
+ valid: true
1738
+ },
1739
+ type: {
1740
+ value: "page",
1741
+ valid: true
1742
+ }
1743
+ }
1209
1744
  }),
1210
- children: "Add link"
1745
+ children: "Add link"
1211
1746
  })
1212
- ]
1747
+ ] })
1213
1748
  });
1214
1749
  }
1215
1750
  const CSS = `
1216
- .bl-nav-items{display:grid;grid-template-columns:minmax(16rem,20rem) minmax(0,1fr);gap:0;border:1px solid var(--theme-elevation-150);border-radius:var(--style-radius-s);background:var(--theme-elevation-0);color:var(--theme-elevation-800);font-family:var(--font-body)}
1217
- .bl-nav-items__rail{border-right:1px solid var(--theme-elevation-150);padding:1rem;min-width:0}
1218
- .bl-nav-items__rail-head h2{margin:.15rem 0 0;font-size:14px}
1219
- .bl-nav-items__kicker{margin:0;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--theme-elevation-500)}
1751
+ .bl-nav-items{--bg:#0f1012;--panel:#141518;--panel2:#1b1d22;--line:#30333b;--line2:#444854;--text:#f6f7f9;--muted:#989daa;--pink:#e60088;--bl-kit-accent:var(--pink);display:grid;grid-template-columns:300px minmax(0,1fr);grid-template-rows:minmax(0,1fr);min-height:0;background:var(--bg);color:var(--text);font:14px/1.45 Inter,ui-sans-serif,system-ui,sans-serif}
1752
+ .bl-nav-items button:not([class*="bl-nav-kit"]),.bl-nav-items input:not([class*="bl-nav-kit"]),.bl-nav-items select:not([class*="bl-nav-kit"]),.bl-nav-items textarea:not([class*="bl-nav-kit"]){font:inherit;color:inherit}
1753
+ .bl-workspace__rail{border-right:1px solid var(--line);background:#121316;min-width:0;min-height:0;height:100%;display:flex;flex-direction:column;overflow:hidden}
1754
+ .bl-nav-items__rail-body{padding:12px;flex:1;min-height:0;overflow:auto}
1755
+ .bl-workspace__rail-slot{flex:none;min-height:0;max-height:100%;overflow:auto;border-top:1px solid var(--line);background:#101115;padding:14px 12px 16px}
1756
+ .bl-nav-items__header-cta{margin:0;padding:0;border:0;min-width:0}
1757
+ .bl-nav-items__header-cta-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px}
1758
+ .bl-nav-items__header-cta-head h3{margin:0;font-size:14px}
1759
+ .bl-nav-items__header-cta-head p{margin:3px 0 0;color:var(--muted);font-size:12px}
1760
+ .bl-nav-items__req{color:var(--pink)}
1220
1761
  .bl-nav-items__list{list-style:none;margin:0;padding:0}
1221
- .bl-nav-items__list li{border:1px solid transparent;border-radius:8px;margin:.4rem 0}
1222
- .bl-nav-items__list li[data-selected="true"]{border-color:var(--theme-elevation-250);background:var(--theme-elevation-50)}
1223
- .bl-nav-items__rail-row{display:grid;grid-template-columns:28px 1fr auto;gap:.5rem;align-items:center;padding:.5rem}
1762
+ .bl-nav-items__list li{border:1px solid transparent;border-radius:9px;margin-bottom:7px}
1763
+ .bl-nav-items__list li[data-selected="true"]{border-color:#414550;background:#1b1d22}
1764
+ .bl-nav-items__rail-row{display:grid;grid-template-columns:20px 1fr auto;gap:8px;align-items:center;padding:6px 8px}
1224
1765
  .bl-nav-items__rail-label{border:0;background:transparent;text-align:left;font:inherit;font-weight:650;color:inherit;cursor:pointer;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1225
- .bl-nav-items__badge{width:28px;height:28px;display:grid;place-items:center;border-radius:7px;background:var(--theme-elevation-100);color:var(--theme-elevation-600)}
1226
- .bl-nav-items__badge[data-kind="megaMenu"]{background:color-mix(in srgb,var(--brand-primary,var(--theme-success-500)) 16%,var(--theme-elevation-50));color:var(--brand-primary,var(--theme-success-500))}
1227
- .bl-nav-items__rail-edit{padding:0 .6rem .75rem}
1228
- .bl-nav-items__add{width:100%;margin-top:.6rem;border:1px dashed var(--theme-elevation-250);background:transparent;border-radius:8px;padding:.65rem;color:var(--theme-elevation-700);cursor:pointer}
1229
- .bl-nav-items__main{min-width:0;padding:1rem 1.25rem 2rem}
1230
- .bl-nav-items__sentinel{height:1px}
1231
- .bl-nav-items__preview{position:sticky;top:0;z-index:5;background:var(--theme-elevation-0);padding:.75rem 0 1rem}
1232
- .bl-nav-items__bar{position:relative !important;inset:auto !important;pointer-events:auto !important;transform:none !important}
1233
- .bl-nav-items__columns{display:grid;gap:.75rem;align-items:start}
1234
- .bl-nav-items__column{border:1px solid var(--theme-elevation-150);border-radius:10px;padding:.75rem;margin:0;min-width:0}
1235
- .bl-nav-items__column legend{font-weight:700;padding:0 .25rem}
1236
- .bl-nav-items__column-settings{display:grid;grid-template-columns:1fr auto;gap:.6rem;align-items:end;margin-bottom:.75rem}
1237
- .bl-nav-items__field{display:flex;flex-direction:column;gap:.35rem;font-size:12px;font-weight:700;margin:.5rem 0}
1238
- .bl-nav-items__field input,.bl-nav-items__field select{font:inherit;font-weight:400;padding:.5rem .6rem;border:1px solid var(--theme-elevation-150);border-radius:var(--style-radius-s);background:var(--theme-input-bg);color:inherit}
1239
- .bl-nav-items__check{display:flex;align-items:center;gap:.5rem;font-size:13px;font-weight:500}
1240
- .bl-nav-items__section,.bl-nav-items__link{border:1px solid var(--theme-elevation-100);border-radius:8px;padding:.6rem;margin:.5rem 0}
1241
- .bl-nav-items__footer{margin-top:1.25rem;border:1px solid var(--theme-elevation-150);border-radius:10px;padding:1rem}
1242
- .bl-nav-items__footer-grid{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
1243
- .bl-nav-items__empty{color:var(--theme-elevation-500)}
1766
+ .bl-nav-items__badge{width:28px;height:28px;display:grid;place-items:center;border-radius:7px;background:#292c33;color:#c9ccd4}
1767
+ .bl-nav-items__badge[data-kind="megaMenu"]{background:#32142a;color:#ff91ce}
1768
+ .bl-nav-items__rail-edit{display:block;border-top:1px solid var(--line);padding:10px}
1769
+ .bl-nav-items__add,.bl-nav-items__add-section,.bl-nav-items__add-column,.bl-nav-items__inline-add{width:100%}
1770
+ .bl-nav-items__add-column{margin-top:12px}
1771
+ .bl-workspace__canvas{min-width:0;min-height:0;height:100%;overflow:auto;padding:0 28px 44px;max-width:1250px;margin:0 auto;width:100%}
1772
+ .bl-workspace__main-head{padding:18px 0 14px;display:flex;justify-content:space-between;align-items:flex-start}
1773
+ .bl-workspace__main-head h1{font-size:20px;margin:2px 0 4px}
1774
+ .bl-workspace__main-head p{margin:0;color:var(--muted)}
1775
+ .bl-nav-items__preview-block{position:sticky;top:0;z-index:20;background:transparent;padding:0;overflow:visible}
1776
+ .bl-nav-items__preview{padding:16px;display:flex;flex-direction:column;gap:16px;background:var(--panel);border:1px solid var(--line);border-radius:12px;overflow:visible}
1777
+ .bl-nav-items__preview-theme{border:0;background:transparent;color:inherit;width:36px;height:36px;display:grid;place-items:center;border-radius:8px;cursor:pointer;flex:none}
1778
+ .bl-nav-items__preview-theme:hover{background:#24242b}
1779
+ .bl-nav-items__preview-block[data-theme="dark"] .bl-nav-items__preview-logo img{filter:invert(1) hue-rotate(180deg)}
1780
+ .bl-nav-items__preview-block[data-theme="light"] .bl-nav-items__preview-nav{background:rgba(255,255,255,.92);border-color:#d8dbe2}
1781
+ .bl-nav-items__preview-block[data-theme="light"] .bl-nav-items__preview-link{color:#1b1d22}
1782
+ .bl-nav-items__preview-block[data-theme="light"] .bl-nav-items__preview-link.is-open{background:#eceef2}
1783
+ .bl-nav-items__preview-block[data-theme="light"] .bl-nav-items__preview-theme{color:#1b1d22}
1784
+ .bl-nav-items__preview-block[data-theme="light"] .bl-nav-items__preview-theme:hover{background:#eceef2}
1785
+ .bl-nav-items__preview-block[data-theme="light"] .bl-nav-items__mega-preview{background:#fff;color:#1b1d22}
1786
+ .bl-nav-items__preview-block[data-theme="light"] .bl-nav-items__preview-footer{background:#f4f5f7}
1787
+ .bl-nav-items__preview-stage{position:absolute;left:0;right:0;top:100%;z-index:21;padding:8px 0 0;pointer-events:auto}
1788
+ .bl-nav-items__mega-preview{margin:0 auto;background:#18191d;border:1px solid var(--line);border-radius:8px;box-shadow:0 12px 32px rgba(0,0,0,.4);overflow:hidden}
1789
+ .bl-nav-items__preview-columns{display:grid;gap:24px;padding:16px}
1790
+ .bl-nav-items__preview-col{padding:0;min-width:0}
1791
+ .bl-nav-items__preview-col.has-border{border-left:1px solid var(--line);padding-left:24px}
1792
+ .bl-nav-items__preview-eyebrow{font-size:12px;font-weight:650;color:#afb3bd;text-transform:uppercase;letter-spacing:.04em;margin:0 8px 8px}
1793
+ .bl-nav-items__preview-list-row{display:flex;gap:12px;align-items:flex-start;padding:8px}
1794
+ .bl-nav-items__preview-list-row strong{display:block}
1795
+ .bl-nav-items__preview-list-row small,.bl-nav-items__preview-featured small{display:block;color:#aeb2bc;margin-top:2px}
1796
+ .bl-nav-items__preview-featured{padding:12px}
1797
+ .bl-nav-items__preview-featured .title{font-size:16px;font-weight:650}
1798
+ .bl-nav-items__preview-empty{color:var(--muted);font-size:13px;padding:28px;text-align:center}
1799
+ .bl-nav-items__preview-footer{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 16px;background:#1f2126;border-top:1px solid var(--line)}
1800
+ .bl-nav-items__preview-footer a{color:var(--pink2,#ff2da5);text-decoration:underline;text-underline-offset:2px;font-weight:650;font-size:13px}
1801
+ .bl-nav-items__preview-footer .cta{background:var(--pink);padding:8px 12px;border-radius:8px;color:#fff;font-weight:650;font-size:13px}
1802
+ .bl-nav-items__preview-nav{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:center;gap:24px;padding:12px 16px 12px 20px;overflow:hidden;border:1px solid var(--line);border-radius:12px;background:rgba(20,21,24,.85);box-shadow:0 10px 28px rgba(0,0,0,.28)}
1803
+ .bl-nav-items__preview-logo{justify-self:start;min-width:0;display:flex;align-items:center}
1804
+ .bl-nav-items__preview-logo img{height:20px;width:auto;display:block}
1805
+ .bl-nav-items__preview-links{display:flex;align-items:center;justify-content:center;gap:4px;min-width:0}
1806
+ .bl-nav-items__preview-link{display:inline-flex;align-items:center;gap:4px;color:#d7dae0;background:none;border:0;padding:8px 12px;border-radius:8px;font-weight:550;cursor:pointer;white-space:nowrap}
1807
+ .bl-nav-items__preview-link.is-open{background:#24242b}
1808
+ .bl-nav-items__preview-chevron{flex:none;width:12px;height:12px;transition:transform .2s}
1809
+ .bl-nav-items__preview-link.is-open .bl-nav-items__preview-chevron{transform:rotate(180deg)}
1810
+ .bl-nav-items__preview-actions{justify-self:end;display:flex;align-items:center;justify-content:flex-end;gap:8px}
1811
+ .bl-nav-items__preview-cta{flex:none;background:var(--pink);border:0;border-radius:8px;color:#fff;font-weight:650;font-size:13px;padding:8px 12px;white-space:nowrap;text-decoration:none}
1812
+ .bl-nav-items__builder-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin:26px 0 10px}
1813
+ .bl-nav-items__builder-head h2{font-size:18px;margin:0}
1814
+ .bl-nav-items__builder-head p{margin:3px 0 0;color:var(--muted);font-size:13px}
1815
+ .bl-nav-items__builder-tools{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
1816
+ .bl-nav-items__tool{display:flex;align-items:center;gap:8px;color:var(--muted);font-size:12px}
1817
+ .bl-nav-items__tool .bl-nav-kit__select-trigger{width:auto;min-width:160px}
1818
+ .bl-nav-items__columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:start}
1819
+ .bl-nav-items__columns:has(> :only-child){grid-template-columns:minmax(0,1fr)}
1820
+ .bl-nav-items__column-settings{display:grid;grid-template-columns:1fr;gap:10px;padding:10px;background:#101115;border:1px solid var(--line);border-radius:9px;align-items:center}
1821
+ .bl-nav-items__column-settings .bl-nav-kit__field{margin:0}
1822
+ .bl-nav-items__column-settings .bl-nav-kit__select-trigger{width:100%}
1823
+ .bl-nav-items__check{display:flex;align-items:center;gap:12px;font-size:13px;font-weight:500;color:#d8dbe1}
1824
+ .bl-nav-items__header-cta .bl-nav-items__check{gap:16px}
1825
+ .bl-nav-items__header-cta-toggle{margin-bottom:20px}
1826
+ .bl-nav-items__seg{display:grid;grid-template-columns:1fr 1fr;gap:6px}
1827
+ .bl-nav-items__seg button{border:1px solid var(--line2);background:#15171b;border-radius:7px;padding:8px 6px;font-size:12px;color:inherit;cursor:pointer}
1828
+ .bl-nav-items__seg button.is-active{border-color:var(--pink);background:#261722}
1829
+ .bl-nav-items__section-settings{padding:10px 12px;border:1px solid var(--line);background:#0e0f13;border-radius:9px}
1830
+ .bl-nav-items__footer,.bl-nav-items__panel{margin-top:18px;border:1px solid var(--line2);background:#141518;border-radius:12px;overflow:hidden}
1831
+ .bl-nav-items__footer-head,.bl-nav-items__panel-head{display:flex;align-items:flex-start;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--line);gap:12px}
1832
+ .bl-nav-items__footer-head h3,.bl-nav-items__panel-head h3{margin:0;font-size:16px}
1833
+ .bl-nav-items__footer-head p,.bl-nav-items__panel-head p{margin:3px 0 0;color:var(--muted);font-size:12px}
1834
+ .bl-nav-items__footer-body,.bl-nav-items__panel-body{padding:14px 16px}
1835
+ .bl-nav-items__footer-body{display:grid;grid-template-columns:1fr 1fr;gap:14px}
1836
+ .bl-nav-items__footer-card{background:#101115;border:1px solid var(--line);border-radius:10px;padding:14px}
1837
+ .bl-nav-items__footer-card h4{margin:0 0 12px;font-size:14px}
1838
+ .bl-nav-items__panel-body{max-width:480px}
1839
+ .bl-nav-items__empty{color:var(--muted);font-size:13px;padding:28px;text-align:center}
1244
1840
  .bl-nav-items__menu{position:relative}
1245
1841
  .bl-nav-items__menu > button{border:0;background:transparent;color:inherit;cursor:pointer}
1246
- .bl-nav-items__menu-pop{position:absolute;right:0;top:1.4rem;z-index:6;min-width:8rem;padding:.2rem;border:1px solid var(--theme-elevation-150);border-radius:8px;background:var(--theme-elevation-0);box-shadow:0 8px 24px var(--theme-overlay)}
1247
- .bl-nav-items__menu-pop button{display:block;width:100%;text-align:left;border:0;background:transparent;padding:.4rem .5rem;border-radius:6px;color:inherit;cursor:pointer}
1248
- @media(max-width:800px){.bl-nav-items{grid-template-columns:1fr}.bl-nav-items__footer-grid,.bl-nav-items__columns{grid-template-columns:minmax(0,1fr) !important}}
1842
+ .bl-nav-items__menu-pop{position:absolute;right:0;top:34px;z-index:12;min-width:140px;padding:4px;border:1px solid var(--line2);border-radius:8px;background:#1b1d22}
1843
+ .bl-nav-items__menu-pop button{display:block;width:100%;text-align:left;border:0;background:transparent;padding:7px 8px;border-radius:6px;color:#d8dbe1;cursor:pointer}
1844
+ .bl-nav-items .field-label,.bl-nav-items .field-label__label{display:block !important;margin:0;padding:0;font:12px/1.2 Inter,ui-sans-serif,system-ui,sans-serif;font-weight:700;color:inherit}
1845
+ .bl-nav-items .field-description,.bl-nav-items .field__description{display:none !important}
1846
+ .bl-nav-items .bl-link-field{display:flex;flex-direction:column;gap:8px;margin:0 0 16px}
1847
+ .bl-nav-items .bl-link-field__control{background:#1d1f24;border:1px solid #3a3d46;border-radius:8px;min-height:auto;padding:8px 10px;color:#fff;box-shadow:none}
1848
+ .bl-nav-items .bl-link-field__kind{background:#292c33;color:#c9ccd4;border-radius:999px;padding:3px 7px}
1849
+ .bl-nav-items .bl-link-field__kind:first-letter{text-transform:uppercase}
1850
+ @media(max-width:1280px){.bl-nav-items{grid-template-columns:250px minmax(0,1fr)}}
1851
+ @media(max-width:850px){.bl-nav-items{grid-template-columns:1fr}.bl-nav-items__footer-body,.bl-nav-items__columns,.bl-nav-items__columns:has(> :only-child){grid-template-columns:minmax(0,1fr) !important}}
1249
1852
  `;
1250
1853
  //#endregion
1251
- export { LinkField, MinRowsArrayField, NavItemsField };
1854
+ export { AdminWorkspace, LinkField, MinRowsArrayField, NavItemsField };
1252
1855
 
1253
1856
  //# sourceMappingURL=admin.mjs.map