@bettercms-ai/kit 2.0.0-next.2 → 2.0.0-next.3

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.
@@ -191,19 +191,22 @@ export interface LinkPickerProps {
191
191
  className?: string;
192
192
  }
193
193
  export declare function LinkPicker({ value, onChange, onPick, onEnter, onEscape, autoFocus, startSearching, id, "aria-label": ariaLabel, size, bare, lockedType, inlineList, types, invalid, "aria-describedby": describedBy, className, }: LinkPickerProps): import("react/jsx-runtime").JSX.Element;
194
- export declare function LinkOptions({ v, onChange, compact, disabled }: {
194
+ export declare function LinkOptions({ v, onChange, compact, disabled, hideNewTab, }: {
195
195
  v: LinkValue;
196
196
  onChange: (v: LinkValue) => void;
197
197
  compact?: boolean;
198
- disabled?: boolean;
198
+ disabled?: boolean; /** the place forbids a new tab (a rich-text field without allowTargetBlank) */
199
+ hideNewTab?: boolean;
199
200
  }): import("react/jsx-runtime").JSX.Element;
200
- export declare function LinkForm({ value, onChange, onEnter, hideOptions, types, autoFocus, readOnly, className, }: {
201
+ export declare function LinkForm({ value, onChange, onEnter, hideOptions, hideNewTab, types, autoFocus, readOnly, className, }: {
201
202
  value: LinkValue;
202
203
  onChange: (v: LinkValue) => void;
203
204
  /** Enter in the target with a value that can be saved */
204
205
  onEnter?: (v: LinkValue) => void;
205
206
  /** string-only values: no new tab / rel */
206
207
  hideOptions?: boolean;
208
+ /** no new tab here (rel stays) */
209
+ hideNewTab?: boolean;
207
210
  /** the link types this place allows. Default: all */
208
211
  types?: LinkType[];
209
212
  /** focus the Type control on open (D48: never the search) */
@@ -212,15 +215,19 @@ export declare function LinkForm({ value, onChange, onEnter, hideOptions, types,
212
215
  readOnly?: boolean;
213
216
  className?: string;
214
217
  }): import("react/jsx-runtime").JSX.Element;
215
- export declare function LinkPopoverBody({ initial, onSave, onDetach, onCancel, hideOptions, types, }: {
218
+ export declare function LinkPopoverBody({ initial, onSave, onDetach, onCancel, hideOptions, hideNewTab, types, dirty, }: {
216
219
  initial: LinkValue;
217
220
  onSave: (v: LinkValue) => void;
218
221
  onDetach?: () => void;
219
222
  onCancel?: () => void;
220
223
  /** string-only fields: no new tab / rel */
221
224
  hideOptions?: boolean;
225
+ /** no new tab here (rel stays): a rich-text field without allowTargetBlank */
226
+ hideNewTab?: boolean;
222
227
  /** the link types this place allows. Default: all */
223
228
  types?: LinkType[];
229
+ /** something the host draws beside the form changed (a button's label), so Apply has something to save */
230
+ dirty?: boolean;
224
231
  }): import("react/jsx-runtime").JSX.Element;
225
232
  export declare function LinkQuickEdit({ value, onCommit, onDone, ariaLabel, size, bare, types, }: {
226
233
  value: LinkValue;
@@ -673,7 +673,7 @@ function LinkPicker({ value, onChange, onPick, onEnter, onEscape, autoFocus, sta
673
673
  ]
674
674
  });
675
675
  }
676
- function LinkOptions({ v, onChange, compact, disabled }) {
676
+ function LinkOptions({ v, onChange, compact, disabled, hideNewTab }) {
677
677
  const tabId = React.useId();
678
678
  return /* @__PURE__ */ jsxs("div", {
679
679
  className: cn("flex flex-col", compact ? "gap-2" : "gap-2.5"),
@@ -694,7 +694,7 @@ function LinkOptions({ v, onChange, compact, disabled }) {
694
694
  className: "max-w-52"
695
695
  })]
696
696
  }) : null,
697
- /* @__PURE__ */ jsxs("label", {
697
+ hideNewTab ? null : /* @__PURE__ */ jsxs("label", {
698
698
  htmlFor: tabId,
699
699
  className: "flex min-h-7 items-center justify-between gap-3",
700
700
  children: [/* @__PURE__ */ jsx("span", {
@@ -733,7 +733,7 @@ function LinkOptions({ v, onChange, compact, disabled }) {
733
733
  ]
734
734
  });
735
735
  }
736
- function LinkForm({ value, onChange, onEnter, hideOptions, types, autoFocus, readOnly, className }) {
736
+ function LinkForm({ value, onChange, onEnter, hideOptions, hideNewTab, types, autoFocus, readOnly, className }) {
737
737
  const v = normLink(value);
738
738
  const { MediaPicker } = useKitServices();
739
739
  const allowed = LINK_TYPES.filter((t) => (!types || types.includes(t.type)) && (t.type !== "file" || MediaPicker || v.type === "file"));
@@ -852,12 +852,13 @@ function LinkForm({ value, onChange, onEnter, hideOptions, types, autoFocus, rea
852
852
  v,
853
853
  onChange,
854
854
  compact: true,
855
- disabled: readOnly
855
+ disabled: readOnly,
856
+ hideNewTab
856
857
  })
857
858
  ]
858
859
  });
859
860
  }
860
- function LinkPopoverBody({ initial, onSave, onDetach, onCancel, hideOptions, types }) {
861
+ function LinkPopoverBody({ initial, onSave, onDetach, onCancel, hideOptions, hideNewTab, types, dirty = false }) {
861
862
  const start = normLink(initial);
862
863
  const [v, setV] = React.useState(start);
863
864
  const { targets } = useLinkTargets();
@@ -866,7 +867,7 @@ function LinkPopoverBody({ initial, onSave, onDetach, onCancel, hideOptions, typ
866
867
  const f = finalizeLink(x);
867
868
  return f ? JSON.stringify(storedLink(f)) : "";
868
869
  };
869
- const changed = fin(v) !== fin(start);
870
+ const changed = dirty || fin(v) !== fin(start);
870
871
  const ok = hasLink(v) && !linkProblem(v);
871
872
  const apply = (n = v) => {
872
873
  const out = finalizeLink(n);
@@ -901,6 +902,7 @@ function LinkPopoverBody({ initial, onSave, onDetach, onCancel, hideOptions, typ
901
902
  onChange: setV,
902
903
  onEnter: (n) => apply(n),
903
904
  hideOptions,
905
+ hideNewTab,
904
906
  types,
905
907
  autoFocus: true
906
908
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"link.js","names":[],"sources":["../../src/controls/link.tsx"],"sourcesContent":["/**\n * LINK — the ONE link element of the product (V2 HEAD kit/controls/link.tsx, DESIGN §8.7, CPO D43 · D48 · D57).\n *\n * - <LinkForm> Type (Page · CMS item · URL · Email · Phone · Section · File) → the target for that type (search over\n * the host's pages and CMS items, paste detection, URL / email / phone / #anchor validation; File =\n * the host's media library) → Section on the picked page → options (new tab · rel · email subject).\n * - <LinkPopoverBody> the link panel: what it links to now + LinkForm + Remove link · Cancel · Apply.\n * - <LinkField> a link at rest (one bordered row): click edits in place (quick edit), the sliders icon opens the panel.\n * - <LinkPicker> the target input inside all of the above.\n * - <LinkLine> how a link READS at rest: page icon + title + path · external icon + domain · mail / phone.\n *\n * Where the targets come from. The kit never fetches: the host hands its own link-target query in as a React hook,\n * `KitServices.useLinkTargets` (KitLinkServices below), and the media library as `KitServices.MediaPicker`. With no hook a\n * page link is typed as a path and the list says so in words; with no media picker the File type is not offered.\n * Section anchors come from the host that knows the page (SectionAnchorsProvider); without one a section is typed (#faq).\n *\n * Stored shape (prod `link`, adapters/values.ts linkToProd / linkFromProd). The kit value is what the field already\n * stores: a STRING href stays a string (legacy fields and the sites that read `href={link}`), an object stays an object.\n * An empty field takes `field.valueShape` and, with none, the string (prod LinkField's default). In the string shape the\n * options (new tab, rel) need the object, so they hide — V2's `valueShape=\"string\"`. An object never carries `target`\n * (derived from newTab), `rel: \"follow\"` (follow = no rel) or `newTab: false`, so it reads back exactly as written.\n *\n * Deviations from V2, each because prod has no source for it: no \"From this entry\" {{token}} targets (no binding store\n * behind them), no seeded page anchors, no fabricated CDN address for a file (a file without a public url is refused).\n */\nimport * as React from \"react\";\nimport {\n IconAdjustmentsHorizontal, IconArrowUpRight, IconAt, IconCheck, IconChevronDown, IconExternalLink, IconFile, IconFileDatabase,\n IconFolderOpen, IconHash, IconLink, IconMail, IconPaperclip, IconPhone, IconWorld, IconX,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { isObj } from \"../lib/path\";\nimport { useKitEnv, useKitServices, type KitMediaAsset, type KitServices } from \"../context\";\nimport { Button, IconButton } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport { Switch } from \"../ui/controls\";\nimport { Autocomplete } from \"../ui/autocomplete\";\nimport { Select, type SelectOption } from \"../ui/select\";\nimport { Menu, MenuContent, MenuItem, MenuTrigger, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Tooltip } from \"../ui/overlay\";\nimport type { ControlProps } from \"../types\";\n\nexport type LinkType = \"page\" | \"url\" | \"section\" | \"email\" | \"phone\" | \"file\" | \"entry\";\nexport type LinkRel = \"follow\" | \"nofollow\" | \"ugc\" | \"sponsored\";\nexport type ButtonStyle = \"primary\" | \"secondary\" | \"outline\" | \"link\";\nexport interface LinkValue {\n type?: LinkType;\n href: string;\n /** button label / link text */\n label?: string;\n /** resolved title of the target (page or entry name) */\n title?: string;\n pageId?: string;\n entryId?: string;\n anchor?: string;\n assetId?: string;\n email?: string;\n subject?: string;\n phone?: string;\n /** legacy target: read as newTab, never written */\n target?: \"_self\" | \"_blank\";\n newTab?: boolean;\n rel?: LinkRel;\n /* button-only (controls/button.tsx) */\n style?: ButtonStyle;\n variant?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n arrow?: boolean;\n icon?: string;\n fullWidth?: boolean;\n}\n\n/* ── Host services ───────────────────────────────────────────────────── */\n/** A place a link can point at, as the host lists it. */\nexport interface LinkTarget {\n id: string;\n title: string;\n /** the public path (\"/about\", \"/blog/hello\") or a file's url */\n href: string;\n kind: \"page\" | \"entry\" | \"file\" | \"section\";\n /** collection name for an entry, file kind for a file */\n meta?: string;\n /** list group: \"Pages\", the collection's name, \"Files\", \"On this page\" */\n group: string;\n /** draft · published · scheduled · archived … (shown when it is not live) */\n status?: string;\n /** \"#faq\" anchors on that page, when the host knows them */\n anchors?: string[];\n /** a section without an anchor yet gets it when picked */\n onChoose?: () => void;\n}\n/**\n * The link services a host provides next to KitServices (registerKitServices / KitServicesProvider take them as is).\n * `useLinkTargets` is a React HOOK (called on every render of a link control), so a host passes the same function for\n * the life of the form.\n */\nexport type KitLinkServices = Pick<KitServices, \"useLinkTargets\">;\ntype LinkHost = { targets: LinkTarget[]; loading: boolean; error?: string; unavailable: boolean };\nconst NO_TARGETS: LinkTarget[] = [];\nconst useNoTargets = () => ({ targets: NO_TARGETS, loading: false, error: undefined as string | undefined });\n\n/** The host's pages, CMS items (and files, when it lists them). */\nexport function useLinkTargets(): LinkHost {\n const svc = useKitServices();\n const useHost = svc.useLinkTargets ?? useNoTargets;\n const r = useHost();\n return { targets: r.targets ?? NO_TARGETS, loading: !!r.loading, error: r.error, unavailable: !svc.useLinkTargets };\n}\n\n/** A section on the page being edited that a link can jump to (`id` on the block). */\nexport interface SectionAnchor {\n /** \"#faq\" */\n anchor: string;\n /** what a person reads: the block's name */\n label: string;\n /** the block has no anchor yet: give it this one when a link picks it */\n ensure?: () => void;\n}\nconst SectionAnchorsCtx = React.createContext<SectionAnchor[] | null>(null);\n/** The host that knows the page being edited lists its section anchors, so the Section type is a pick. */\nexport function SectionAnchorsProvider({ anchors, children }: { anchors: SectionAnchor[]; children: React.ReactNode }) {\n return <SectionAnchorsCtx.Provider value={anchors}>{children}</SectionAnchorsCtx.Provider>;\n}\nfunction useSectionTargets(): LinkTarget[] {\n const anchors = React.useContext(SectionAnchorsCtx);\n return React.useMemo(\n () =>\n (anchors ?? []).map((a) => ({\n id: `section:${a.anchor}`,\n title: a.label,\n href: a.anchor.startsWith(\"#\") ? a.anchor : `#${a.anchor}`,\n kind: \"section\" as const,\n group: \"On this page\",\n onChoose: a.ensure,\n })),\n [anchors],\n );\n}\n\n/** A file from the media library as a link target, or the reason it can't be one. */\nexport function fileTarget(a: Pick<KitMediaAsset, \"id\" | \"name\" | \"url\">): LinkTarget | { problem: string } {\n if (!a.url || a.url.startsWith(\"blob:\")) return { problem: \"This file has no public address yet. Wait for the upload to finish, then pick it again.\" };\n const name = a.name || fileName(a.url);\n return { id: a.id, title: name, href: a.url, kind: \"file\", meta: name.split(\".\").pop()?.toUpperCase(), group: \"Files\" };\n}\n\n/* ── Value helpers ───────────────────────────────────────────────────── */\nexport const normLink = (v: unknown): LinkValue => {\n const o: LinkValue = typeof v === \"string\" ? { href: v } : isObj(v) ? ({ ...(v as object), href: typeof v.href === \"string\" ? v.href : \"\" } as LinkValue) : { href: \"\" };\n if (o.newTab === undefined && o.target === \"_blank\") o.newTab = true;\n if (!o.type) o.type = detectType(o.href);\n return o;\n};\n\nexport function detectType(raw: string): LinkType {\n const s = raw.trim();\n if (!s) return \"page\";\n if (s.startsWith(\"#\")) return \"section\";\n if (/^mailto:/i.test(s) || /^[^\\s@/]+@[^\\s@]+\\.[^\\s@]+$/.test(s)) return \"email\";\n if (/^tel:/i.test(s) || /^\\+?[\\d\\s().-]{7,}$/.test(s)) return \"phone\";\n if (/\\.(pdf|zip|docx?|csv)$/i.test(s)) return \"file\";\n if (/^https?:\\/\\//i.test(s) || /^www\\./i.test(s) || /^[a-z0-9-]+(\\.[a-z0-9-]+)+(\\/|$)/i.test(s)) return \"url\";\n return \"page\";\n}\n\nexport const LINK_TYPES: { type: LinkType; label: string; icon: React.ReactNode; placeholder: string; target: string }[] = [\n { type: \"page\", label: \"Page\", icon: <IconFile stroke={1.5} />, placeholder: \"Search pages and CMS items, or paste a link\", target: \"Page\" },\n { type: \"entry\", label: \"CMS item\", icon: <IconFileDatabase stroke={1.5} />, placeholder: \"Search CMS items\", target: \"CMS item\" },\n { type: \"url\", label: \"URL\", icon: <IconWorld stroke={1.5} />, placeholder: \"https://example.com\", target: \"Address\" },\n { type: \"email\", label: \"Email\", icon: <IconAt stroke={1.5} />, placeholder: \"name@company.com\", target: \"Email address\" },\n { type: \"phone\", label: \"Phone\", icon: <IconPhone stroke={1.5} />, placeholder: \"+1 541 555 0182\", target: \"Phone number\" },\n { type: \"section\", label: \"Section\", icon: <IconHash stroke={1.5} />, placeholder: \"#section-on-this-page\", target: \"Section on this page\" },\n { type: \"file\", label: \"File\", icon: <IconPaperclip stroke={1.5} />, placeholder: \"Search files\", target: \"File\" },\n];\nconst typeMeta = (t?: string) => LINK_TYPES.find((x) => x.type === t) ?? LINK_TYPES[0];\n\n/** The target a value points at: by id first, then by an exact path (\"/about\" typed by hand still reads as About). */\nexport function findTarget(targets: LinkTarget[], v: LinkValue): LinkTarget | undefined {\n const byId = targets.find((t) => (v.pageId && t.id === v.pageId) || (v.entryId && t.id === v.entryId) || (v.assetId && t.id === v.assetId));\n if (byId) return byId;\n if (v.type === \"section\") return v.href ? targets.find((t) => t.kind === \"section\" && t.href === (v.href.startsWith(\"#\") ? v.href : `#${v.href}`)) : undefined;\n if (!v.href || (v.type !== \"page\" && v.type !== \"entry\" && v.type !== \"file\")) return undefined;\n if (v.type === \"file\") {\n const f = targets.find((t) => t.kind === \"file\" && t.href === v.href);\n // a file picked from the library reads as the file by the name stored with it\n return f ?? (v.title ? { id: v.assetId ?? v.href, title: v.title, href: v.href, kind: \"file\", group: \"Files\" } : undefined);\n }\n const path = v.href.replace(/[?#].*$/, \"\").replace(/\\/$/, \"\") || \"/\";\n return targets.find((t) => t.kind !== \"file\" && t.kind !== \"section\" && t.href === path);\n}\n\n/** The final href for a link value. */\nexport function hrefOf(v: LinkValue): string {\n switch (v.type) {\n case \"email\": {\n const addr = (v.email ?? v.href).replace(/^mailto:/i, \"\").replace(/\\?.*$/, \"\");\n return addr ? `mailto:${addr}${v.subject ? `?subject=${encodeURIComponent(v.subject)}` : \"\"}` : \"\";\n }\n case \"phone\": {\n const n = (v.phone ?? v.href).replace(/^tel:/i, \"\").replace(/[^\\d+]/g, \"\");\n return n ? `tel:${n}` : \"\";\n }\n case \"section\":\n return v.href.startsWith(\"#\") ? v.href : v.href ? `#${v.href}` : \"\";\n default: {\n // idempotent: a stored href already carries its anchor, so a changed or removed anchor replaces it\n const base = v.anchor !== undefined ? v.href.replace(/#.*$/, \"\") : v.href;\n return `${base}${v.anchor && v.anchor !== \"none\" ? v.anchor : \"\"}`;\n }\n }\n}\n\nconst BAD_URL = \"Enter a full address, like https://example.com.\";\n/** Why a link can't be saved yet, in plain words. Undefined when it is fine (or empty). */\nexport function linkProblem(v: LinkValue): string | undefined {\n if (!hasLink(v)) return undefined;\n const raw = (v.type === \"email\" ? v.email ?? v.href : v.type === \"phone\" ? v.phone ?? v.href : v.href).trim();\n if (/^(javascript|data|vbscript):/i.test(raw.replace(/[\\u0000- ]/g, \"\"))) return \"Script links aren't allowed.\";\n switch (v.type) {\n case \"url\": {\n if (raw.startsWith(\"/\") || raw.startsWith(\"#\")) return undefined;\n try {\n const u = new URL(/^[a-z][a-z0-9+.-]*:/i.test(raw) ? raw : `https://${raw}`);\n if (!/^https?:$/.test(u.protocol)) return BAD_URL;\n return /\\.[a-z]{2,}$/i.test(u.hostname) || u.hostname === \"localhost\" ? undefined : BAD_URL;\n } catch {\n return BAD_URL;\n }\n }\n case \"email\":\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$/.test(raw.replace(/^mailto:/i, \"\").replace(/\\?.*$/, \"\")) ? undefined : \"Enter an email address, like name@company.com.\";\n case \"phone\":\n return raw.replace(/^tel:/i, \"\").replace(/\\D/g, \"\").length >= 7 ? undefined : \"Enter a phone number with at least 7 digits.\";\n case \"section\":\n return /^#?[A-Za-z][\\w-]*$/.test(raw) ? undefined : \"Use letters, numbers and dashes, like #faq.\";\n case \"page\":\n case \"entry\":\n return raw.startsWith(\"/\") || raw.startsWith(\"#\") || v.pageId || v.entryId ? undefined : \"Pick a page, or start a path with /, like /about.\";\n default:\n return undefined;\n }\n}\n\n/** One list for every link editor (dropdown, never a segmented row — D40). */\nexport const REL_ITEMS: { value: LinkRel; label: string; description: string }[] = [\n { value: \"follow\", label: \"Do-follow\", description: \"Normal link. Search engines follow it.\" },\n { value: \"nofollow\", label: \"No-follow\", description: \"Search engines don't follow or credit it.\" },\n { value: \"sponsored\", label: \"Sponsored\", description: \"Paid, affiliate or ad link.\" },\n { value: \"ugc\", label: \"UGC\", description: \"Link added by users, e.g. comments.\" },\n];\n\nexport const hasLink = (v: LinkValue) => !!(v.href || v.email || v.phone);\nexport const TARGET_KEYS = { title: undefined, pageId: undefined, entryId: undefined, assetId: undefined, anchor: undefined } as const;\n\n/** The value a picked target produces (keeps label, style and options). */\nexport function withTarget(v: LinkValue, t: LinkTarget): LinkValue {\n return {\n ...v,\n ...TARGET_KEYS,\n email: undefined,\n phone: undefined,\n subject: undefined,\n type: t.kind === \"file\" ? \"file\" : t.kind === \"entry\" ? \"entry\" : t.kind === \"section\" ? \"section\" : \"page\",\n href: t.href,\n title: t.title,\n pageId: t.kind === \"page\" ? t.id : undefined,\n entryId: t.kind === \"entry\" ? t.id : undefined,\n assetId: t.kind === \"file\" ? t.id : undefined,\n };\n}\n/** The value typed text produces (auto-detects URL / email / phone / #section unless the type was chosen). */\nexport function withText(v: LinkValue, s: string, type?: LinkType): LinkValue {\n const t = type ?? detectType(s);\n const n: LinkValue = { ...v, ...TARGET_KEYS, type: t, email: undefined, phone: undefined };\n if (t === \"email\") Object.assign(n, { email: s.replace(/^mailto:/i, \"\"), href: s });\n else if (t === \"phone\") Object.assign(n, { phone: s.replace(/^tel:/i, \"\"), href: s });\n else n.href = s;\n return n;\n}\n/** Clean a value before it is stored: add https:// to bare domains, refuse script URLs, store the href the site renders. */\nexport function finalizeLink(v: LinkValue): LinkValue | null {\n const out: LinkValue = { ...v };\n if (/^(javascript|data|vbscript):/i.test(out.href.replace(/[\\u0000- ]/g, \"\"))) return null;\n if (out.type === \"url\" && out.href && !/^(https?:|\\/|#)/.test(out.href)) out.href = `https://${out.href.replace(/^\\/+/, \"\")}`;\n // the stored href is the one the site renders (mailto:, tel:, #anchor); every consumer reads `href` as is\n if (hasLink(out)) out.href = hrefOf(out);\n return out;\n}\n/**\n * The object as prod stores it, keyed like the value it replaces (`original`), so an edit changes only what was edited:\n * no undefined keys; no `rel: \"follow\"` (follow is no rel: the backend normalises it away and a button refuses it); no\n * `newTab: false` and no `target` unless the stored value had that key (a stored `target` is kept in sync with newTab,\n * and is then the one that carries it).\n */\nexport function storedLink<T extends LinkValue>(v: T, original?: unknown): T {\n const had = (k: string) => isObj(original) && k in original;\n const out: Record<string, unknown> = {};\n for (const [k, x] of Object.entries(v)) {\n if (x === undefined || k === \"target\") continue;\n if (k === \"rel\" && x === \"follow\") continue;\n if (k === \"newTab\" && !had(\"newTab\") && (x === false || had(\"target\"))) continue;\n out[k] = x;\n }\n if (had(\"target\")) out.target = v.newTab ? \"_blank\" : \"_self\";\n return out as T;\n}\n/** Text the picker's input shows for a value that has no picked target. */\nconst inputText = (v: LinkValue) =>\n v.type === \"email\" ? (v.email ?? v.href.replace(/^mailto:/i, \"\")) : v.type === \"phone\" ? (v.phone ?? v.href.replace(/^tel:/i, \"\")) : v.href;\n\nconst STATUS_LABEL: Record<string, string> = { draft: \"Draft\", changed: \"Edited\", scheduled: \"Scheduled\", review: \"In review\", archived: \"Archived\" };\n\n/* ── How a link reads ───────────────────────────────────────────────── */\nexport function linkIcon(v: LinkValue, target?: LinkTarget): React.ReactNode {\n if (!hasLink(v)) return <IconLink stroke={1.5} />;\n if (target) return target.kind === \"entry\" ? <IconFileDatabase stroke={1.5} /> : target.kind === \"file\" ? <IconPaperclip stroke={1.5} /> : target.kind === \"section\" ? <IconHash stroke={1.5} /> : <IconFile stroke={1.5} />;\n switch (v.type) {\n case \"url\": return <IconExternalLink stroke={1.5} />;\n case \"email\": return <IconMail stroke={1.5} />;\n case \"phone\": return <IconPhone stroke={1.5} />;\n case \"section\": return <IconHash stroke={1.5} />;\n case \"file\": return <IconPaperclip stroke={1.5} />;\n case \"entry\": return <IconFileDatabase stroke={1.5} />;\n default: return <IconFile stroke={1.5} />;\n }\n}\n/** Primary + secondary text: page title + path · domain + rest of the URL · address · number. */\nexport function describeLink(v: LinkValue, target?: LinkTarget): { primary: string; secondary?: string } {\n if (!hasLink(v)) return { primary: \"\" };\n const anchor = v.anchor && v.anchor !== \"none\" ? v.anchor : \"\";\n if (target) return { primary: target.title, secondary: target.kind === \"section\" ? `${target.href} on this page` : target.kind === \"file\" ? fileKind(target) : `${target.href}${anchor}` };\n switch (v.type) {\n case \"url\": {\n try {\n const u = new URL(/^https?:/i.test(v.href) ? v.href : `https://${v.href}`);\n const rest = `${u.pathname === \"/\" ? \"\" : u.pathname}${u.search}${u.hash}`;\n return { primary: u.hostname.replace(/^www\\./, \"\"), secondary: rest || undefined };\n } catch {\n return { primary: v.href };\n }\n }\n case \"email\": return { primary: v.email ?? v.href.replace(/^mailto:/i, \"\").replace(/\\?.*$/, \"\"), secondary: v.subject ? `Subject: ${v.subject}` : undefined };\n case \"phone\": return { primary: v.phone ?? v.href.replace(/^tel:/i, \"\") };\n case \"section\": return { primary: v.href, secondary: \"On this page\" };\n // a stored href already carries its anchor (finalizeLink)\n default: return { primary: v.title || v.href, secondary: v.title ? v.href : undefined };\n }\n}\n/** \"PDF file\": the name is already the title */\nconst fileKind = (t: LinkTarget) => `${t.meta ?? (fileName(t.href).split(\".\").pop() ?? \"\").toUpperCase()} file`.trim();\nfunction fileName(href: string) {\n const last = href.replace(/[?#].*$/, \"\").split(\"/\").pop() ?? href;\n try {\n return decodeURIComponent(last);\n } catch {\n return last;\n }\n}\n/** What a person reads for a link (one string — menus, aria labels, history). */\nexport const linkText = (v: LinkValue) => (hasLink(v) ? v.title || describeLink(v).primary : \"\");\n\n/** A link at rest: icon · title (fg) · path (fg-3) · new-tab mark. Empty → \"Add link\". */\nexport function LinkLine({ v, target, placeholder = \"Add link\", className }: { v: LinkValue; target?: LinkTarget; placeholder?: string; className?: string }) {\n const d = describeLink(v, target);\n const empty = !hasLink(v);\n return (\n <span className={cn(\"flex min-w-0 flex-1 items-center gap-2\", className)}>\n <span className={cn(\"flex shrink-0 [&_svg]:size-4\", empty ? \"text-kit-fg-3\" : \"text-kit-fg-2\")} aria-hidden>{linkIcon(v, target)}</span>\n <span className={cn(\"min-w-0 shrink truncate text-kit-sm\", empty ? \"text-kit-fg-3\" : \"text-kit-fg\")}>{empty ? placeholder : d.primary}</span>\n {d.secondary ? <span className=\"min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3\">{d.secondary}</span> : <span className=\"flex-1\" />}\n {!empty && v.newTab ? (\n <span className=\"inline-flex shrink-0 items-center gap-0.5 text-kit-2xs text-kit-fg-3\">\n <IconArrowUpRight className=\"size-3\" stroke={1.5} aria-hidden />\n New tab\n </span>\n ) : null}\n </span>\n );\n}\n\n/* ── The picker: ONE link input for the whole product ───────────────── */\ntype Row = { key: string; group: string; target: LinkTarget };\n\n/** While the media library is open from a picker, focus sits in its dialog: a quick edit must not close under it. */\nlet libraryOpen = false;\n/** Marks the floating results list, so a quick edit losing focus to it is not \"focus left the editor\". */\nconst LIST_ATTR = \"data-kit-link-list\";\n\nexport interface LinkPickerProps {\n value: LinkValue;\n /** every change: typed text, a picked target, a cleared value */\n onChange: (v: LinkValue) => void;\n /** a target was chosen from the list (quick editors commit here) */\n onPick?: (v: LinkValue) => void;\n /** Enter with no list row active */\n onEnter?: (v: LinkValue) => void;\n /** Escape with the list closed */\n onEscape?: () => void;\n autoFocus?: boolean;\n /** open straight into search (quick edit), even when a target is picked */\n startSearching?: boolean;\n id?: string;\n \"aria-label\"?: string;\n size?: \"sm\" | \"md\";\n /** no border of its own — it sits inside a unit that already draws one (button field) */\n bare?: boolean;\n /** the host shows its own type control (link panel): hide the inline type menu and search only this type */\n lockedType?: LinkType;\n /** results render in the flow under the input instead of a floating list — panels/popovers, never over them */\n inlineList?: boolean;\n /** the link types this place allows. Default: all of them */\n types?: LinkType[];\n /** the value can't be saved as it is (shown as the field's error state) */\n invalid?: boolean;\n \"aria-describedby\"?: string;\n className?: string;\n}\n\nexport function LinkPicker({\n value, onChange, onPick, onEnter, onEscape, autoFocus, startSearching, id, \"aria-label\": ariaLabel = \"Link to\", size = \"md\", bare, lockedType,\n inlineList, types, invalid, \"aria-describedby\": describedBy, className,\n}: LinkPickerProps) {\n const v = normLink(value);\n const host = useLinkTargets();\n const sections = useSectionTargets();\n const { MediaPicker } = useKitServices();\n const targets = React.useMemo(() => [...host.targets, ...sections], [host.targets, sections]);\n const picked = findTarget(targets, v);\n const [library, setLibraryState] = React.useState(false);\n const setLibrary = (o: boolean) => {\n libraryOpen = o;\n setLibraryState(o);\n };\n React.useEffect(() => () => void (libraryOpen = false), []);\n const [fileProblem, setFileProblem] = React.useState<string>();\n const [searching, setSearching] = React.useState(!!startSearching || !picked);\n const [text, setText] = React.useState(() => (picked ? \"\" : inputText(v)));\n const [manualTypeState, setManualType] = React.useState<LinkType | null>(null);\n const manualType = lockedType ?? manualTypeState;\n const [open, setOpen] = React.useState(false);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const wrapRef = React.useRef<HTMLDivElement>(null);\n const type = manualType ?? v.type ?? \"page\";\n const meta = typeMeta(manualType ?? (searching && !text ? \"page\" : v.type));\n const showChip = !!picked && !searching;\n\n React.useEffect(() => {\n if (autoFocus)\n requestAnimationFrame(() => {\n inputRef.current?.focus({ preventScroll: true });\n inputRef.current?.select(); // quick edit: typing replaces, paste replaces\n });\n }, [autoFocus]);\n\n /* rows: the host's pages + every collection's entries (+ files when it lists them) */\n const q = text.trim().toLowerCase().replace(/^[/#]/, \"\");\n const searchable = type === \"page\" || type === \"entry\" || type === \"file\" || (type === \"section\" && sections.length > 0);\n const urlish = type !== \"section\" && (/^(https?:|www\\.|mailto:|tel:|#)/i.test(text.trim()) || (text.trim() !== \"\" && detectType(text) !== \"page\" && !manualType));\n const rows: Row[] = React.useMemo(() => {\n if (!searchable || urlish) return [];\n const pool = targets.filter((t) => (type === \"file\" ? t.kind === \"file\" : type === \"entry\" ? t.kind === \"entry\" : type === \"section\" ? t.kind === \"section\" : t.kind === \"page\" || t.kind === \"entry\"));\n const hit = (t: LinkTarget) => !q || t.title.toLowerCase().includes(q) || t.href.toLowerCase().includes(q) || (t.meta ?? \"\").toLowerCase().includes(q);\n const out: Row[] = [];\n const perGroup = new Map<string, number>();\n const cap = q ? 6 : type === \"page\" ? 4 : 6;\n for (const t of pool) {\n if (!hit(t)) continue;\n const n = perGroup.get(t.group) ?? 0;\n if (n >= cap) continue;\n perGroup.set(t.group, n + 1);\n out.push({ key: `${t.kind}:${t.id}`, group: t.group, target: t });\n }\n // keep each group together, groups in first-seen order (Pages first)\n const order = [...new Set(out.map((r) => r.group))];\n return out.sort((a, b) => order.indexOf(a.group) - order.indexOf(b.group)).slice(0, 24);\n }, [targets, type, q, searchable, urlish]);\n /* No silent empty list: when nothing can be listed, the list says why in one line. */\n const note: string | undefined = (() => {\n if (!searchable || urlish || rows.length) return undefined;\n if (type === \"section\") return undefined;\n if (type === \"file\") return MediaPicker ? \"Choose a file from the library with the folder button.\" : undefined;\n if (host.unavailable) return \"Page search isn't available here. Type a path, like /about.\";\n if (host.error) return `${host.error.replace(/\\.?$/, \".\")} Type a path, like /about.`;\n if (host.loading) return \"Loading pages…\";\n return q ? `Nothing matches “${text.trim()}”. Type a path, like /about.` : type === \"entry\" ? \"No CMS items yet.\" : \"No pages yet. Type a path, like /about.\";\n })();\n const choose = (t: LinkTarget) => {\n t.onChoose?.();\n const n = withTarget(v, t);\n setText(\"\");\n setManualType(null);\n setSearching(false);\n setOpen(false);\n setFileProblem(undefined);\n onChange(n);\n onPick?.(n);\n };\n const type_ = (s: string) => {\n setText(s);\n setOpen(true);\n onChange(withText(v, s, manualType ?? undefined));\n };\n const clear = () => {\n setText(\"\");\n setManualType(null);\n setSearching(true);\n onChange({ ...withText(v, \"\"), href: \"\" });\n requestAnimationFrame(() => inputRef.current?.focus());\n };\n const setType = (t: LinkType) => {\n setManualType(t);\n setText(\"\");\n setSearching(true);\n onChange({ ...withText(v, \"\", t), href: \"\" });\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n };\n\n const h = size === \"sm\" ? \"h-8\" : \"h-9\";\n /* the rows as the Autocomplete's options (V2 link.tsx:520-560: icon, title, href or file name, status) */\n const options: SelectOption[] = rows.map((r) => ({\n value: r.key,\n label: r.target.title,\n group: r.group,\n icon: linkIcon({ href: r.target.href, type: r.target.kind }, r.target),\n description: r.target.kind === \"file\" ? fileName(r.target.href) : r.target.href,\n meta: r.target.status ? STATUS_LABEL[r.target.status] : undefined,\n }));\n /* some targets loaded and some did not (a collection's items): the gap is named under the list */\n const listNote = host.error && type !== \"file\" && type !== \"section\" ? host.error.replace(/\\.?$/, \".\") : undefined;\n const allowed = LINK_TYPES.filter((t) => (!types || types.includes(t.type)) && (t.type !== \"file\" || MediaPicker || v.type === \"file\"));\n const typeMenu = (\n <Menu>\n <MenuTrigger\n render={\n <button\n type=\"button\"\n aria-label={`Link type: ${meta.label}`}\n className=\"ml-0.5 flex h-7 shrink-0 items-center gap-0.5 rounded-kit-md px-1.5 text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover [&_svg]:size-3.5\"\n />\n }\n >\n {meta.icon}\n <IconChevronDown className=\"!size-3\" stroke={1.5} />\n </MenuTrigger>\n <MenuContent className=\"min-w-48\">\n {allowed.map((t) => (\n <MenuItem key={t.type} icon={t.icon} onClick={() => setType(t.type)}>\n <span className=\"flex w-full items-center justify-between gap-3\">\n {t.label}\n {t.type === type ? <IconCheck className=\"size-3.5 text-kit-fg-2\" stroke={2} /> : null}\n </span>\n </MenuItem>\n ))}\n </MenuContent>\n </Menu>\n );\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-1\", className)}>\n <div\n ref={wrapRef}\n className=\"min-w-0\"\n onKeyDown={(e) => {\n // Escape with the list closed (the Autocomplete claims the one that closes it): back to the chip, else the host's\n if (e.key !== \"Escape\" || showChip) return;\n if (picked && !text && !startSearching) {\n e.preventDefault();\n e.stopPropagation();\n setSearching(false);\n } else if (onEscape) {\n e.preventDefault();\n e.stopPropagation();\n onEscape();\n }\n }}\n >\n {showChip ? (\n <div\n className={cn(\n \"flex min-w-0 items-center\",\n bare\n ? \"bg-transparent\"\n : \"rounded-kit-md border border-kit-field-border bg-kit-field-bg shadow-kit-field transition-colors hover:border-kit-field-border-hover focus-within:border-kit-field-border-focus\",\n !bare && invalid && \"border-[var(--kit-field-invalid)] hover:border-[var(--kit-field-invalid)]\",\n h,\n )}\n >\n <span className=\"ml-2 flex shrink-0 text-kit-fg-2 [&_svg]:size-4\" aria-hidden>\n {linkIcon(v, picked)}\n </span>\n <button\n id={id}\n type=\"button\"\n onClick={() => {\n setSearching(true);\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n }}\n aria-label={`${ariaLabel}: ${picked!.title}, ${picked!.href}. Change`}\n className=\"flex h-full min-w-0 flex-1 items-center gap-2 px-2 text-left outline-none\"\n >\n <span className=\"min-w-0 shrink truncate text-kit-sm text-kit-fg\">{picked!.title}</span>\n <span className=\"min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3\">{describeLink(v, picked).secondary}</span>\n </button>\n <IconButton label=\"Clear link\" size=\"xs\" className=\"mr-1\" onClick={clear}>\n <IconX stroke={1.5} />\n </IconButton>\n </div>\n ) : (\n /* search: the kit Autocomplete with V2 link.tsx's extras (one combobox implementation in the kit) */\n <Autocomplete\n id={id}\n aria-label={ariaLabel}\n aria-describedby={describedBy}\n invalid={invalid}\n size={size === \"sm\" ? \"md\" : \"lg\"}\n className={cn(\"shadow-none\", bare ? \"border-0 bg-transparent focus-within:shadow-none\" : \"shadow-kit-field focus-within:shadow-none\")}\n value={text}\n onValueChange={type_}\n options={options}\n filter={null}\n onSelect={(o) => {\n const r = rows.find((x) => x.key === o.value);\n if (r) choose(r.target);\n }}\n fillOnSelect={false}\n onEnter={() => onEnter?.(withText(v, text, manualType ?? undefined))}\n open={open && searching}\n onOpenChange={setOpen}\n inlineList={inlineList}\n emptyNote={note}\n listNote={listNote}\n highlightFirst\n highlightMatches={false}\n listLabel={type === \"file\" ? \"Files\" : type === \"section\" ? \"Sections on this page\" : \"Pages and CMS items\"}\n inputRef={inputRef}\n onBlur={(e) => {\n if (wrapRef.current?.contains(e.relatedTarget as Node)) return;\n if (inlineList) setOpen(false);\n // came from a chip: nothing typed → show the chip again\n if (picked && !text) setSearching(false);\n }}\n placeholder={picked && !text ? picked.title : meta.placeholder}\n leading={lockedType !== undefined || inlineList ? meta.icon : undefined}\n leadingSlot={lockedType !== undefined || inlineList ? undefined : typeMenu}\n onClear={clear}\n trailingSlot={\n type === \"file\" && MediaPicker ? (\n <IconButton\n label=\"Choose or upload a file\"\n size=\"xs\"\n className=\"mr-1 text-kit-fg-3\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n setOpen(false);\n setLibrary(true);\n }}\n >\n <IconFolderOpen stroke={1.5} />\n </IconButton>\n ) : null\n }\n listAttrs={{ [LIST_ATTR]: \"\" }}\n menuClassName={inlineList ? \"mt-0 [&_[role=listbox]]:max-h-56\" : \"shadow-kit-lg\"}\n />\n )}\n </div>\n {fileProblem ? (\n <p role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {fileProblem}\n </p>\n ) : null}\n {/* File: the host's media library (search, folders, upload) is one click away; mounted only while open */}\n {library && MediaPicker ? (\n <MediaPicker\n open\n accept={[\"file\"]}\n onOpenChange={(o) => !o && setLibrary(false)}\n onPick={(a) => {\n if (!a[0]) return;\n const t = fileTarget(a[0]);\n if (\"problem\" in t) setFileProblem(t.problem);\n else choose(t);\n }}\n />\n ) : null}\n </div>\n );\n}\n\n/* ── Shared options (subject · open in new tab · rel) ───────────────── */\nexport function LinkOptions({ v, onChange, compact, disabled }: { v: LinkValue; onChange: (v: LinkValue) => void; compact?: boolean; disabled?: boolean }) {\n const tabId = React.useId();\n return (\n <div className={cn(\"flex flex-col\", compact ? \"gap-2\" : \"gap-2.5\")}>\n {v.type === \"email\" ? (\n <label className=\"flex items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Subject</span>\n <Input size=\"sm\" value={v.subject ?? \"\"} onChange={(e) => onChange({ ...v, subject: e.target.value })} placeholder=\"Wholesale inquiry\" className=\"max-w-52\" />\n </label>\n ) : null}\n <label htmlFor={tabId} className=\"flex min-h-7 items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Open in new tab</span>\n <Switch disabled={disabled} id={tabId} size=\"sm\" checked={!!v.newTab} onCheckedChange={(c) => onChange({ ...v, newTab: c, target: undefined })} />\n </label>\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Rel</span>\n <Select disabled={disabled} aria-label=\"Rel\" size=\"sm\" className=\"w-[168px]\" value={v.rel ?? \"follow\"} onValueChange={(r) => onChange({ ...v, rel: r as LinkRel })} options={REL_ITEMS} />\n </div>\n </div>\n );\n}\n\n/* ── The link element ───────────────────────────────────────────────\n * CPO D48 + D57: the ONE way to edit a link, wherever a link is edited: Type (dropdown) → the target for that type\n * (results appear only once you focus or type, in the flow below the input, never over the panel; File adds the media\n * library) → the error in plain words when it can't be saved → Section on the picked page → the options as plain rows\n * (new tab, rel, subject). Hosts wrap it: the link panel (LinkPopoverBody), the button screen. Controlled: the host owns\n * the value; remount (key) to start over.\n */\nexport function LinkForm({\n value,\n onChange,\n onEnter,\n hideOptions,\n types,\n autoFocus,\n readOnly,\n className,\n}: {\n value: LinkValue;\n onChange: (v: LinkValue) => void;\n /** Enter in the target with a value that can be saved */\n onEnter?: (v: LinkValue) => void;\n /** string-only values: no new tab / rel */\n hideOptions?: boolean;\n /** the link types this place allows. Default: all */\n types?: LinkType[];\n /** focus the Type control on open (D48: never the search) */\n autoFocus?: boolean;\n /** the lens can't edit the link: every control is disabled */\n readOnly?: boolean;\n className?: string;\n}) {\n const v = normLink(value);\n const { MediaPicker } = useKitServices();\n const allowed = LINK_TYPES.filter((t) => (!types || types.includes(t.type)) && (t.type !== \"file\" || MediaPicker || v.type === \"file\"));\n const [kind, setKind] = React.useState<LinkType>(() => {\n const k = v.type === \"entry\" && hasLink(v) ? \"page\" : v.type ?? \"page\";\n return allowed.some((t) => t.type === k) ? k : allowed[0]?.type ?? \"page\";\n });\n const [resetKey, setResetKey] = React.useState(0);\n const [touched, setTouched] = React.useState(false);\n const { targets } = useLinkTargets();\n const anchors = findTarget(targets, v)?.anchors;\n const typeId = React.useId();\n const targetId = React.useId();\n const errId = React.useId();\n const problem = touched ? linkProblem(v) : undefined;\n // the type select follows what the target turned out to be (a picked CMS item, a pasted URL) while \"Page\" is searching\n const shownType: LinkType = kind === \"page\" && hasLink(v) ? v.type ?? \"page\" : kind;\n React.useEffect(() => {\n if (autoFocus) requestAnimationFrame(() => document.getElementById(typeId)?.focus({ preventScroll: true }));\n }, [autoFocus, typeId]);\n const changeType = (t: LinkType) => {\n setKind(t);\n setTouched(false);\n onChange({ ...withText(v, \"\", t === \"page\" ? undefined : t), href: \"\", type: t, anchor: undefined });\n setResetKey((k) => k + 1);\n requestAnimationFrame(() => document.getElementById(targetId)?.focus());\n };\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-3\", className)}>\n <div className=\"flex items-center justify-between gap-3\">\n <label htmlFor={typeId} className=\"text-kit-xs text-kit-fg-2\">\n Type\n </label>\n <Select disabled={readOnly} id={typeId} size=\"sm\" className=\"w-[180px]\" value={shownType} onValueChange={(t) => changeType(t as LinkType)} options={allowed.map((t) => ({ value: t.type, label: t.label, icon: t.icon }))} />\n </div>\n <div\n className=\"flex flex-col gap-1.5\"\n onBlur={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node)) setTouched(true);\n }}\n >\n <label htmlFor={targetId} className=\"text-kit-xs text-kit-fg-2\">\n {typeMeta(kind).target}\n </label>\n <LinkPicker\n key={resetKey}\n id={targetId}\n size=\"sm\"\n value={v}\n onChange={onChange}\n onPick={() => setTouched(true)}\n onEnter={(n) => {\n setTouched(true);\n if (!linkProblem(n)) onEnter?.(n);\n }}\n lockedType={kind === \"page\" ? undefined : kind}\n inlineList\n types={types}\n invalid={!!problem}\n aria-describedby={problem ? errId : undefined}\n aria-label={typeMeta(kind).target}\n />\n {problem ? (\n <p id={errId} role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {problem}\n </p>\n ) : null}\n </div>\n {anchors?.length ? (\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Section</span>\n <Select disabled={readOnly} aria-label=\"Section\"\n size=\"sm\"\n className=\"w-[180px]\"\n value={v.anchor ?? \"none\"}\n onValueChange={(a) => onChange({ ...v, anchor: a })}\n options={[{ value: \"none\", label: \"Top of page\" }, ...anchors.map((a) => ({ value: a, label: a }))]}\n />\n </div>\n ) : null}\n {hideOptions ? null : <LinkOptions v={v} onChange={onChange} compact disabled={readOnly} />}\n </div>\n );\n}\n\n/* ── The link panel ─────────────────────────────────────────────────\n * What it links to now → the link element (LinkForm) → Remove link · Cancel · Apply (Apply only when something changed\n * and the link can be saved). Esc closes the results first, then the panel.\n */\nexport function LinkPopoverBody({\n initial,\n onSave,\n onDetach,\n onCancel,\n hideOptions,\n types,\n}: {\n initial: LinkValue;\n onSave: (v: LinkValue) => void;\n onDetach?: () => void;\n onCancel?: () => void;\n /** string-only fields: no new tab / rel */\n hideOptions?: boolean;\n /** the link types this place allows. Default: all */\n types?: LinkType[];\n}) {\n const start = normLink(initial);\n const [v, setV] = React.useState<LinkValue>(start);\n const { targets } = useLinkTargets();\n const startTarget = findTarget(targets, start);\n const fin = (x: LinkValue) => {\n const f = finalizeLink(x);\n return f ? JSON.stringify(storedLink(f)) : \"\";\n };\n const changed = fin(v) !== fin(start);\n const ok = hasLink(v) && !linkProblem(v);\n const apply = (n = v) => {\n const out = finalizeLink(n);\n if (out && hasLink(out) && !linkProblem(out)) onSave(out);\n };\n return (\n <form\n className=\"flex flex-col gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n e.stopPropagation();\n apply();\n }}\n >\n <div className=\"flex min-w-0 flex-col gap-1\">\n <span className=\"text-kit-sm font-medium text-kit-fg\">Link</span>\n {hasLink(start) ? (\n <span className=\"flex min-w-0 text-kit-fg-2\">\n <LinkLine v={start} target={startTarget} />\n </span>\n ) : (\n <span className=\"text-kit-xs text-kit-fg-3\">No link yet</span>\n )}\n </div>\n <LinkForm value={v} onChange={setV} onEnter={(n) => apply(n)} hideOptions={hideOptions} types={types} autoFocus />\n <div className=\"flex items-center gap-2 border-t border-kit-line pt-2.5\">\n {onDetach ? (\n <Button type=\"button\" size=\"xs\" variant=\"danger-ghost\" onClick={onDetach}>\n Remove link\n </Button>\n ) : null}\n <span className=\"flex-1\" />\n {onCancel ? (\n <Button type=\"button\" size=\"xs\" variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n ) : null}\n <Button type=\"submit\" size=\"xs\" variant=\"primary\" disabled={!changed || !ok}>\n Apply\n </Button>\n </div>\n </form>\n );\n}\n\n/* ── Quick edit: the link row turns into the picker in place ───────── */\nexport function LinkQuickEdit({\n value,\n onCommit,\n onDone,\n ariaLabel,\n size,\n bare,\n types,\n}: {\n value: LinkValue;\n /** null = cleared */\n onCommit: (v: LinkValue | null) => void;\n onDone: () => void;\n ariaLabel: string;\n size?: \"sm\" | \"md\";\n bare?: boolean;\n types?: LinkType[];\n}) {\n const [draft, setDraft] = React.useState(value);\n const [problem, setProblem] = React.useState<string>();\n const done = React.useRef(false);\n const ref = React.useRef<HTMLDivElement>(null);\n const errId = React.useId();\n const commit = (n: LinkValue, strict = true) => {\n if (done.current) return;\n if (hasLink(n) && strict && linkProblem(n)) return setProblem(linkProblem(n));\n done.current = true;\n if (!hasLink(n)) onCommit(null);\n else {\n const out = finalizeLink(n);\n // a script link is dropped, never written (finalizeLink refuses it)\n if (out) onCommit(out);\n }\n onDone();\n };\n return (\n <div\n ref={ref}\n className=\"flex min-w-0 flex-col gap-1\"\n onBlur={(e) => {\n const next = e.relatedTarget as HTMLElement | null;\n if (libraryOpen || (next && (ref.current?.contains(next) || next.closest?.(`[${LIST_ATTR}],[role=menu]`)))) return;\n // focus left the editor: keep what was typed (nothing changed → nothing written)\n window.setTimeout(() => {\n if (libraryOpen || done.current || ref.current?.contains(document.activeElement)) return;\n if (hrefOf(draft) === hrefOf(value) && draft.pageId === value.pageId && draft.entryId === value.entryId) {\n done.current = true;\n onDone();\n } else commit(draft, false);\n }, 0);\n }}\n >\n <LinkPicker\n value={draft}\n onChange={(n) => {\n setDraft(n);\n setProblem(undefined);\n }}\n onPick={(n) => commit(n)}\n onEnter={(n) => commit(n)}\n onEscape={() => {\n done.current = true;\n onDone();\n }}\n autoFocus\n startSearching\n aria-label={ariaLabel}\n size={size}\n bare={bare}\n types={types}\n invalid={!!problem}\n aria-describedby={problem ? errId : undefined}\n />\n {problem ? (\n <p id={errId} role=\"alert\" className={cn(\"text-kit-xs text-kit-danger-fg\", bare && \"px-2.5 pb-1.5\")}>\n {problem}\n </p>\n ) : null}\n </div>\n );\n}\n\n/* ── Link field: one bordered row; click edits in place, the sliders icon opens the link panel ── */\nexport interface LinkFieldProps {\n /** a LinkValue or a plain href string */\n value: unknown;\n /** null = cleared (object shape); \"\" = cleared (string shape) */\n onChange: (v: LinkValue | string | null) => void;\n /** \"string\": the value is the href alone. New tab and rel need the object shape, so they hide. */\n valueShape?: \"string\" | \"object\";\n id?: string;\n \"aria-label\": string;\n readOnly?: boolean;\n size?: \"sm\" | \"md\";\n /** the link types this place allows. Default: all */\n types?: LinkType[];\n invalid?: boolean;\n placeholder?: string;\n className?: string;\n}\nexport function LinkField({ value, onChange: write, valueShape, id: idProp, \"aria-label\": label, readOnly, size = \"sm\", types, invalid, placeholder, className }: LinkFieldProps) {\n const v = normLink(value);\n const stringOnly = valueShape === \"string\";\n const onChange = (n: LinkValue | null) => write(stringOnly ? (n ? hrefOf(n) : \"\") : n ? storedLink(n, value) : null);\n const autoId = React.useId();\n const id = idProp ?? autoId;\n const [editing, setEditing] = React.useState(false);\n const [open, setOpen] = React.useState(false);\n const { targets } = useLinkTargets();\n const target = findTarget(targets, v);\n const has = hasLink(v);\n if (editing && !readOnly)\n return (\n <LinkQuickEdit\n value={v}\n ariaLabel={label}\n size={size}\n types={types}\n onCommit={onChange}\n onDone={() => {\n setEditing(false);\n requestAnimationFrame(() => document.getElementById(id)?.focus({ preventScroll: true }));\n }}\n />\n );\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverAnchor\n data-kit-link-field=\"\"\n className={cn(\n \"group/link relative flex min-w-0 items-center rounded-kit-md border border-kit-field-border bg-kit-field-bg shadow-kit-field transition-colors hover:border-kit-field-border-hover\",\n size === \"md\" ? \"h-9\" : \"h-8\",\n readOnly && \"hover:border-kit-field-border\",\n invalid && \"border-[var(--kit-field-invalid)]\",\n className,\n )}\n >\n <button\n id={id}\n type=\"button\"\n disabled={readOnly}\n onClick={() => setEditing(true)}\n // V2 link.tsx:977: the name reads the link's own text (its title, else its address), not the picked target's title\n aria-label={has ? `${label}: ${linkText(v)}. Edit link` : `Add ${label.toLowerCase()}`}\n aria-invalid={invalid || undefined}\n className=\"flex h-full min-w-0 flex-1 items-center px-2.5 text-left outline-none disabled:cursor-default\"\n >\n <LinkLine v={v} target={target} placeholder={placeholder} />\n </button>\n {readOnly ? null : (\n <span className=\"mr-1 flex shrink-0 items-center gap-0.5\">\n <Tooltip content=\"Link options\">\n <PopoverTrigger\n render={\n <IconButton label=\"Link options\" tooltip={false} size=\"xs\" className=\"text-kit-fg-3\">\n <IconAdjustmentsHorizontal stroke={1.5} />\n </IconButton>\n }\n />\n </Tooltip>\n {has ? (\n <IconButton\n label={`Clear ${label.toLowerCase()}`}\n size=\"xs\"\n className=\"hidden text-kit-fg-3 group-hover/link:inline-flex group-focus-within/link:inline-flex [@media(pointer:coarse)]:inline-flex\"\n onClick={() => onChange(null)}\n >\n <IconX stroke={1.5} />\n </IconButton>\n ) : null}\n </span>\n )}\n </PopoverAnchor>\n <PopoverContent className=\"w-[340px] p-3\" align=\"start\">\n <LinkPopoverBody\n initial={v}\n hideOptions={stringOnly}\n types={types}\n onSave={(n) => {\n onChange(n);\n setOpen(false);\n }}\n onDetach={\n has\n ? () => {\n onChange(null);\n setOpen(false);\n }\n : undefined\n }\n onCancel={() => setOpen(false)}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\n/**\n * The shape a link field writes: the shape its value already has (a string stays a string, an object an object), and\n * for an empty field `field.valueShape`, else the string prod stores by default.\n */\nexport function linkShapeOf(value: unknown, valueShape?: \"string\" | \"object\"): \"string\" | \"object\" {\n if (isObj(value)) return \"object\";\n if (typeof value === \"string\" && value !== \"\") return \"string\";\n return valueShape ?? \"string\";\n}\n\n/** The Block Kit `link` field: the LinkField above, sized for the form it sits in. */\nexport function LinkControl({ value, onChange, readOnly, id, field, invalid }: ControlProps) {\n const { variant } = useKitEnv();\n return (\n <LinkField\n id={id}\n value={value}\n onChange={onChange}\n valueShape={linkShapeOf(value, field.valueShape)}\n aria-label={field.title}\n readOnly={readOnly}\n size={variant === \"document\" ? \"md\" : \"sm\"}\n invalid={invalid}\n />\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"link.js","names":[],"sources":["../../src/controls/link.tsx"],"sourcesContent":["/**\n * LINK — the ONE link element of the product (V2 HEAD kit/controls/link.tsx, DESIGN §8.7, CPO D43 · D48 · D57).\n *\n * - <LinkForm> Type (Page · CMS item · URL · Email · Phone · Section · File) → the target for that type (search over\n * the host's pages and CMS items, paste detection, URL / email / phone / #anchor validation; File =\n * the host's media library) → Section on the picked page → options (new tab · rel · email subject).\n * - <LinkPopoverBody> the link panel: what it links to now + LinkForm + Remove link · Cancel · Apply.\n * - <LinkField> a link at rest (one bordered row): click edits in place (quick edit), the sliders icon opens the panel.\n * - <LinkPicker> the target input inside all of the above.\n * - <LinkLine> how a link READS at rest: page icon + title + path · external icon + domain · mail / phone.\n *\n * Where the targets come from. The kit never fetches: the host hands its own link-target query in as a React hook,\n * `KitServices.useLinkTargets` (KitLinkServices below), and the media library as `KitServices.MediaPicker`. With no hook a\n * page link is typed as a path and the list says so in words; with no media picker the File type is not offered.\n * Section anchors come from the host that knows the page (SectionAnchorsProvider); without one a section is typed (#faq).\n *\n * Stored shape (prod `link`, adapters/values.ts linkToProd / linkFromProd). The kit value is what the field already\n * stores: a STRING href stays a string (legacy fields and the sites that read `href={link}`), an object stays an object.\n * An empty field takes `field.valueShape` and, with none, the string (prod LinkField's default). In the string shape the\n * options (new tab, rel) need the object, so they hide — V2's `valueShape=\"string\"`. An object never carries `target`\n * (derived from newTab), `rel: \"follow\"` (follow = no rel) or `newTab: false`, so it reads back exactly as written.\n *\n * Deviations from V2, each because prod has no source for it: no \"From this entry\" {{token}} targets (no binding store\n * behind them), no seeded page anchors, no fabricated CDN address for a file (a file without a public url is refused).\n */\nimport * as React from \"react\";\nimport {\n IconAdjustmentsHorizontal, IconArrowUpRight, IconAt, IconCheck, IconChevronDown, IconExternalLink, IconFile, IconFileDatabase,\n IconFolderOpen, IconHash, IconLink, IconMail, IconPaperclip, IconPhone, IconWorld, IconX,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { isObj } from \"../lib/path\";\nimport { useKitEnv, useKitServices, type KitMediaAsset, type KitServices } from \"../context\";\nimport { Button, IconButton } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport { Switch } from \"../ui/controls\";\nimport { Autocomplete } from \"../ui/autocomplete\";\nimport { Select, type SelectOption } from \"../ui/select\";\nimport { Menu, MenuContent, MenuItem, MenuTrigger, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Tooltip } from \"../ui/overlay\";\nimport type { ControlProps } from \"../types\";\n\nexport type LinkType = \"page\" | \"url\" | \"section\" | \"email\" | \"phone\" | \"file\" | \"entry\";\nexport type LinkRel = \"follow\" | \"nofollow\" | \"ugc\" | \"sponsored\";\nexport type ButtonStyle = \"primary\" | \"secondary\" | \"outline\" | \"link\";\nexport interface LinkValue {\n type?: LinkType;\n href: string;\n /** button label / link text */\n label?: string;\n /** resolved title of the target (page or entry name) */\n title?: string;\n pageId?: string;\n entryId?: string;\n anchor?: string;\n assetId?: string;\n email?: string;\n subject?: string;\n phone?: string;\n /** legacy target: read as newTab, never written */\n target?: \"_self\" | \"_blank\";\n newTab?: boolean;\n rel?: LinkRel;\n /* button-only (controls/button.tsx) */\n style?: ButtonStyle;\n variant?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n arrow?: boolean;\n icon?: string;\n fullWidth?: boolean;\n}\n\n/* ── Host services ───────────────────────────────────────────────────── */\n/** A place a link can point at, as the host lists it. */\nexport interface LinkTarget {\n id: string;\n title: string;\n /** the public path (\"/about\", \"/blog/hello\") or a file's url */\n href: string;\n kind: \"page\" | \"entry\" | \"file\" | \"section\";\n /** collection name for an entry, file kind for a file */\n meta?: string;\n /** list group: \"Pages\", the collection's name, \"Files\", \"On this page\" */\n group: string;\n /** draft · published · scheduled · archived … (shown when it is not live) */\n status?: string;\n /** \"#faq\" anchors on that page, when the host knows them */\n anchors?: string[];\n /** a section without an anchor yet gets it when picked */\n onChoose?: () => void;\n}\n/**\n * The link services a host provides next to KitServices (registerKitServices / KitServicesProvider take them as is).\n * `useLinkTargets` is a React HOOK (called on every render of a link control), so a host passes the same function for\n * the life of the form.\n */\nexport type KitLinkServices = Pick<KitServices, \"useLinkTargets\">;\ntype LinkHost = { targets: LinkTarget[]; loading: boolean; error?: string; unavailable: boolean };\nconst NO_TARGETS: LinkTarget[] = [];\nconst useNoTargets = () => ({ targets: NO_TARGETS, loading: false, error: undefined as string | undefined });\n\n/** The host's pages, CMS items (and files, when it lists them). */\nexport function useLinkTargets(): LinkHost {\n const svc = useKitServices();\n const useHost = svc.useLinkTargets ?? useNoTargets;\n const r = useHost();\n return { targets: r.targets ?? NO_TARGETS, loading: !!r.loading, error: r.error, unavailable: !svc.useLinkTargets };\n}\n\n/** A section on the page being edited that a link can jump to (`id` on the block). */\nexport interface SectionAnchor {\n /** \"#faq\" */\n anchor: string;\n /** what a person reads: the block's name */\n label: string;\n /** the block has no anchor yet: give it this one when a link picks it */\n ensure?: () => void;\n}\nconst SectionAnchorsCtx = React.createContext<SectionAnchor[] | null>(null);\n/** The host that knows the page being edited lists its section anchors, so the Section type is a pick. */\nexport function SectionAnchorsProvider({ anchors, children }: { anchors: SectionAnchor[]; children: React.ReactNode }) {\n return <SectionAnchorsCtx.Provider value={anchors}>{children}</SectionAnchorsCtx.Provider>;\n}\nfunction useSectionTargets(): LinkTarget[] {\n const anchors = React.useContext(SectionAnchorsCtx);\n return React.useMemo(\n () =>\n (anchors ?? []).map((a) => ({\n id: `section:${a.anchor}`,\n title: a.label,\n href: a.anchor.startsWith(\"#\") ? a.anchor : `#${a.anchor}`,\n kind: \"section\" as const,\n group: \"On this page\",\n onChoose: a.ensure,\n })),\n [anchors],\n );\n}\n\n/** A file from the media library as a link target, or the reason it can't be one. */\nexport function fileTarget(a: Pick<KitMediaAsset, \"id\" | \"name\" | \"url\">): LinkTarget | { problem: string } {\n if (!a.url || a.url.startsWith(\"blob:\")) return { problem: \"This file has no public address yet. Wait for the upload to finish, then pick it again.\" };\n const name = a.name || fileName(a.url);\n return { id: a.id, title: name, href: a.url, kind: \"file\", meta: name.split(\".\").pop()?.toUpperCase(), group: \"Files\" };\n}\n\n/* ── Value helpers ───────────────────────────────────────────────────── */\nexport const normLink = (v: unknown): LinkValue => {\n const o: LinkValue = typeof v === \"string\" ? { href: v } : isObj(v) ? ({ ...(v as object), href: typeof v.href === \"string\" ? v.href : \"\" } as LinkValue) : { href: \"\" };\n if (o.newTab === undefined && o.target === \"_blank\") o.newTab = true;\n if (!o.type) o.type = detectType(o.href);\n return o;\n};\n\nexport function detectType(raw: string): LinkType {\n const s = raw.trim();\n if (!s) return \"page\";\n if (s.startsWith(\"#\")) return \"section\";\n if (/^mailto:/i.test(s) || /^[^\\s@/]+@[^\\s@]+\\.[^\\s@]+$/.test(s)) return \"email\";\n if (/^tel:/i.test(s) || /^\\+?[\\d\\s().-]{7,}$/.test(s)) return \"phone\";\n if (/\\.(pdf|zip|docx?|csv)$/i.test(s)) return \"file\";\n if (/^https?:\\/\\//i.test(s) || /^www\\./i.test(s) || /^[a-z0-9-]+(\\.[a-z0-9-]+)+(\\/|$)/i.test(s)) return \"url\";\n return \"page\";\n}\n\nexport const LINK_TYPES: { type: LinkType; label: string; icon: React.ReactNode; placeholder: string; target: string }[] = [\n { type: \"page\", label: \"Page\", icon: <IconFile stroke={1.5} />, placeholder: \"Search pages and CMS items, or paste a link\", target: \"Page\" },\n { type: \"entry\", label: \"CMS item\", icon: <IconFileDatabase stroke={1.5} />, placeholder: \"Search CMS items\", target: \"CMS item\" },\n { type: \"url\", label: \"URL\", icon: <IconWorld stroke={1.5} />, placeholder: \"https://example.com\", target: \"Address\" },\n { type: \"email\", label: \"Email\", icon: <IconAt stroke={1.5} />, placeholder: \"name@company.com\", target: \"Email address\" },\n { type: \"phone\", label: \"Phone\", icon: <IconPhone stroke={1.5} />, placeholder: \"+1 541 555 0182\", target: \"Phone number\" },\n { type: \"section\", label: \"Section\", icon: <IconHash stroke={1.5} />, placeholder: \"#section-on-this-page\", target: \"Section on this page\" },\n { type: \"file\", label: \"File\", icon: <IconPaperclip stroke={1.5} />, placeholder: \"Search files\", target: \"File\" },\n];\nconst typeMeta = (t?: string) => LINK_TYPES.find((x) => x.type === t) ?? LINK_TYPES[0];\n\n/** The target a value points at: by id first, then by an exact path (\"/about\" typed by hand still reads as About). */\nexport function findTarget(targets: LinkTarget[], v: LinkValue): LinkTarget | undefined {\n const byId = targets.find((t) => (v.pageId && t.id === v.pageId) || (v.entryId && t.id === v.entryId) || (v.assetId && t.id === v.assetId));\n if (byId) return byId;\n if (v.type === \"section\") return v.href ? targets.find((t) => t.kind === \"section\" && t.href === (v.href.startsWith(\"#\") ? v.href : `#${v.href}`)) : undefined;\n if (!v.href || (v.type !== \"page\" && v.type !== \"entry\" && v.type !== \"file\")) return undefined;\n if (v.type === \"file\") {\n const f = targets.find((t) => t.kind === \"file\" && t.href === v.href);\n // a file picked from the library reads as the file by the name stored with it\n return f ?? (v.title ? { id: v.assetId ?? v.href, title: v.title, href: v.href, kind: \"file\", group: \"Files\" } : undefined);\n }\n const path = v.href.replace(/[?#].*$/, \"\").replace(/\\/$/, \"\") || \"/\";\n return targets.find((t) => t.kind !== \"file\" && t.kind !== \"section\" && t.href === path);\n}\n\n/** The final href for a link value. */\nexport function hrefOf(v: LinkValue): string {\n switch (v.type) {\n case \"email\": {\n const addr = (v.email ?? v.href).replace(/^mailto:/i, \"\").replace(/\\?.*$/, \"\");\n return addr ? `mailto:${addr}${v.subject ? `?subject=${encodeURIComponent(v.subject)}` : \"\"}` : \"\";\n }\n case \"phone\": {\n const n = (v.phone ?? v.href).replace(/^tel:/i, \"\").replace(/[^\\d+]/g, \"\");\n return n ? `tel:${n}` : \"\";\n }\n case \"section\":\n return v.href.startsWith(\"#\") ? v.href : v.href ? `#${v.href}` : \"\";\n default: {\n // idempotent: a stored href already carries its anchor, so a changed or removed anchor replaces it\n const base = v.anchor !== undefined ? v.href.replace(/#.*$/, \"\") : v.href;\n return `${base}${v.anchor && v.anchor !== \"none\" ? v.anchor : \"\"}`;\n }\n }\n}\n\nconst BAD_URL = \"Enter a full address, like https://example.com.\";\n/** Why a link can't be saved yet, in plain words. Undefined when it is fine (or empty). */\nexport function linkProblem(v: LinkValue): string | undefined {\n if (!hasLink(v)) return undefined;\n const raw = (v.type === \"email\" ? v.email ?? v.href : v.type === \"phone\" ? v.phone ?? v.href : v.href).trim();\n if (/^(javascript|data|vbscript):/i.test(raw.replace(/[\\u0000- ]/g, \"\"))) return \"Script links aren't allowed.\";\n switch (v.type) {\n case \"url\": {\n if (raw.startsWith(\"/\") || raw.startsWith(\"#\")) return undefined;\n try {\n const u = new URL(/^[a-z][a-z0-9+.-]*:/i.test(raw) ? raw : `https://${raw}`);\n if (!/^https?:$/.test(u.protocol)) return BAD_URL;\n return /\\.[a-z]{2,}$/i.test(u.hostname) || u.hostname === \"localhost\" ? undefined : BAD_URL;\n } catch {\n return BAD_URL;\n }\n }\n case \"email\":\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$/.test(raw.replace(/^mailto:/i, \"\").replace(/\\?.*$/, \"\")) ? undefined : \"Enter an email address, like name@company.com.\";\n case \"phone\":\n return raw.replace(/^tel:/i, \"\").replace(/\\D/g, \"\").length >= 7 ? undefined : \"Enter a phone number with at least 7 digits.\";\n case \"section\":\n return /^#?[A-Za-z][\\w-]*$/.test(raw) ? undefined : \"Use letters, numbers and dashes, like #faq.\";\n case \"page\":\n case \"entry\":\n return raw.startsWith(\"/\") || raw.startsWith(\"#\") || v.pageId || v.entryId ? undefined : \"Pick a page, or start a path with /, like /about.\";\n default:\n return undefined;\n }\n}\n\n/** One list for every link editor (dropdown, never a segmented row — D40). */\nexport const REL_ITEMS: { value: LinkRel; label: string; description: string }[] = [\n { value: \"follow\", label: \"Do-follow\", description: \"Normal link. Search engines follow it.\" },\n { value: \"nofollow\", label: \"No-follow\", description: \"Search engines don't follow or credit it.\" },\n { value: \"sponsored\", label: \"Sponsored\", description: \"Paid, affiliate or ad link.\" },\n { value: \"ugc\", label: \"UGC\", description: \"Link added by users, e.g. comments.\" },\n];\n\nexport const hasLink = (v: LinkValue) => !!(v.href || v.email || v.phone);\nexport const TARGET_KEYS = { title: undefined, pageId: undefined, entryId: undefined, assetId: undefined, anchor: undefined } as const;\n\n/** The value a picked target produces (keeps label, style and options). */\nexport function withTarget(v: LinkValue, t: LinkTarget): LinkValue {\n return {\n ...v,\n ...TARGET_KEYS,\n email: undefined,\n phone: undefined,\n subject: undefined,\n type: t.kind === \"file\" ? \"file\" : t.kind === \"entry\" ? \"entry\" : t.kind === \"section\" ? \"section\" : \"page\",\n href: t.href,\n title: t.title,\n pageId: t.kind === \"page\" ? t.id : undefined,\n entryId: t.kind === \"entry\" ? t.id : undefined,\n assetId: t.kind === \"file\" ? t.id : undefined,\n };\n}\n/** The value typed text produces (auto-detects URL / email / phone / #section unless the type was chosen). */\nexport function withText(v: LinkValue, s: string, type?: LinkType): LinkValue {\n const t = type ?? detectType(s);\n const n: LinkValue = { ...v, ...TARGET_KEYS, type: t, email: undefined, phone: undefined };\n if (t === \"email\") Object.assign(n, { email: s.replace(/^mailto:/i, \"\"), href: s });\n else if (t === \"phone\") Object.assign(n, { phone: s.replace(/^tel:/i, \"\"), href: s });\n else n.href = s;\n return n;\n}\n/** Clean a value before it is stored: add https:// to bare domains, refuse script URLs, store the href the site renders. */\nexport function finalizeLink(v: LinkValue): LinkValue | null {\n const out: LinkValue = { ...v };\n if (/^(javascript|data|vbscript):/i.test(out.href.replace(/[\\u0000- ]/g, \"\"))) return null;\n if (out.type === \"url\" && out.href && !/^(https?:|\\/|#)/.test(out.href)) out.href = `https://${out.href.replace(/^\\/+/, \"\")}`;\n // the stored href is the one the site renders (mailto:, tel:, #anchor); every consumer reads `href` as is\n if (hasLink(out)) out.href = hrefOf(out);\n return out;\n}\n/**\n * The object as prod stores it, keyed like the value it replaces (`original`), so an edit changes only what was edited:\n * no undefined keys; no `rel: \"follow\"` (follow is no rel: the backend normalises it away and a button refuses it); no\n * `newTab: false` and no `target` unless the stored value had that key (a stored `target` is kept in sync with newTab,\n * and is then the one that carries it).\n */\nexport function storedLink<T extends LinkValue>(v: T, original?: unknown): T {\n const had = (k: string) => isObj(original) && k in original;\n const out: Record<string, unknown> = {};\n for (const [k, x] of Object.entries(v)) {\n if (x === undefined || k === \"target\") continue;\n if (k === \"rel\" && x === \"follow\") continue;\n if (k === \"newTab\" && !had(\"newTab\") && (x === false || had(\"target\"))) continue;\n out[k] = x;\n }\n if (had(\"target\")) out.target = v.newTab ? \"_blank\" : \"_self\";\n return out as T;\n}\n/** Text the picker's input shows for a value that has no picked target. */\nconst inputText = (v: LinkValue) =>\n v.type === \"email\" ? (v.email ?? v.href.replace(/^mailto:/i, \"\")) : v.type === \"phone\" ? (v.phone ?? v.href.replace(/^tel:/i, \"\")) : v.href;\n\nconst STATUS_LABEL: Record<string, string> = { draft: \"Draft\", changed: \"Edited\", scheduled: \"Scheduled\", review: \"In review\", archived: \"Archived\" };\n\n/* ── How a link reads ───────────────────────────────────────────────── */\nexport function linkIcon(v: LinkValue, target?: LinkTarget): React.ReactNode {\n if (!hasLink(v)) return <IconLink stroke={1.5} />;\n if (target) return target.kind === \"entry\" ? <IconFileDatabase stroke={1.5} /> : target.kind === \"file\" ? <IconPaperclip stroke={1.5} /> : target.kind === \"section\" ? <IconHash stroke={1.5} /> : <IconFile stroke={1.5} />;\n switch (v.type) {\n case \"url\": return <IconExternalLink stroke={1.5} />;\n case \"email\": return <IconMail stroke={1.5} />;\n case \"phone\": return <IconPhone stroke={1.5} />;\n case \"section\": return <IconHash stroke={1.5} />;\n case \"file\": return <IconPaperclip stroke={1.5} />;\n case \"entry\": return <IconFileDatabase stroke={1.5} />;\n default: return <IconFile stroke={1.5} />;\n }\n}\n/** Primary + secondary text: page title + path · domain + rest of the URL · address · number. */\nexport function describeLink(v: LinkValue, target?: LinkTarget): { primary: string; secondary?: string } {\n if (!hasLink(v)) return { primary: \"\" };\n const anchor = v.anchor && v.anchor !== \"none\" ? v.anchor : \"\";\n if (target) return { primary: target.title, secondary: target.kind === \"section\" ? `${target.href} on this page` : target.kind === \"file\" ? fileKind(target) : `${target.href}${anchor}` };\n switch (v.type) {\n case \"url\": {\n try {\n const u = new URL(/^https?:/i.test(v.href) ? v.href : `https://${v.href}`);\n const rest = `${u.pathname === \"/\" ? \"\" : u.pathname}${u.search}${u.hash}`;\n return { primary: u.hostname.replace(/^www\\./, \"\"), secondary: rest || undefined };\n } catch {\n return { primary: v.href };\n }\n }\n case \"email\": return { primary: v.email ?? v.href.replace(/^mailto:/i, \"\").replace(/\\?.*$/, \"\"), secondary: v.subject ? `Subject: ${v.subject}` : undefined };\n case \"phone\": return { primary: v.phone ?? v.href.replace(/^tel:/i, \"\") };\n case \"section\": return { primary: v.href, secondary: \"On this page\" };\n // a stored href already carries its anchor (finalizeLink)\n default: return { primary: v.title || v.href, secondary: v.title ? v.href : undefined };\n }\n}\n/** \"PDF file\": the name is already the title */\nconst fileKind = (t: LinkTarget) => `${t.meta ?? (fileName(t.href).split(\".\").pop() ?? \"\").toUpperCase()} file`.trim();\nfunction fileName(href: string) {\n const last = href.replace(/[?#].*$/, \"\").split(\"/\").pop() ?? href;\n try {\n return decodeURIComponent(last);\n } catch {\n return last;\n }\n}\n/** What a person reads for a link (one string — menus, aria labels, history). */\nexport const linkText = (v: LinkValue) => (hasLink(v) ? v.title || describeLink(v).primary : \"\");\n\n/** A link at rest: icon · title (fg) · path (fg-3) · new-tab mark. Empty → \"Add link\". */\nexport function LinkLine({ v, target, placeholder = \"Add link\", className }: { v: LinkValue; target?: LinkTarget; placeholder?: string; className?: string }) {\n const d = describeLink(v, target);\n const empty = !hasLink(v);\n return (\n <span className={cn(\"flex min-w-0 flex-1 items-center gap-2\", className)}>\n <span className={cn(\"flex shrink-0 [&_svg]:size-4\", empty ? \"text-kit-fg-3\" : \"text-kit-fg-2\")} aria-hidden>{linkIcon(v, target)}</span>\n <span className={cn(\"min-w-0 shrink truncate text-kit-sm\", empty ? \"text-kit-fg-3\" : \"text-kit-fg\")}>{empty ? placeholder : d.primary}</span>\n {d.secondary ? <span className=\"min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3\">{d.secondary}</span> : <span className=\"flex-1\" />}\n {!empty && v.newTab ? (\n <span className=\"inline-flex shrink-0 items-center gap-0.5 text-kit-2xs text-kit-fg-3\">\n <IconArrowUpRight className=\"size-3\" stroke={1.5} aria-hidden />\n New tab\n </span>\n ) : null}\n </span>\n );\n}\n\n/* ── The picker: ONE link input for the whole product ───────────────── */\ntype Row = { key: string; group: string; target: LinkTarget };\n\n/** While the media library is open from a picker, focus sits in its dialog: a quick edit must not close under it. */\nlet libraryOpen = false;\n/** Marks the floating results list, so a quick edit losing focus to it is not \"focus left the editor\". */\nconst LIST_ATTR = \"data-kit-link-list\";\n\nexport interface LinkPickerProps {\n value: LinkValue;\n /** every change: typed text, a picked target, a cleared value */\n onChange: (v: LinkValue) => void;\n /** a target was chosen from the list (quick editors commit here) */\n onPick?: (v: LinkValue) => void;\n /** Enter with no list row active */\n onEnter?: (v: LinkValue) => void;\n /** Escape with the list closed */\n onEscape?: () => void;\n autoFocus?: boolean;\n /** open straight into search (quick edit), even when a target is picked */\n startSearching?: boolean;\n id?: string;\n \"aria-label\"?: string;\n size?: \"sm\" | \"md\";\n /** no border of its own — it sits inside a unit that already draws one (button field) */\n bare?: boolean;\n /** the host shows its own type control (link panel): hide the inline type menu and search only this type */\n lockedType?: LinkType;\n /** results render in the flow under the input instead of a floating list — panels/popovers, never over them */\n inlineList?: boolean;\n /** the link types this place allows. Default: all of them */\n types?: LinkType[];\n /** the value can't be saved as it is (shown as the field's error state) */\n invalid?: boolean;\n \"aria-describedby\"?: string;\n className?: string;\n}\n\nexport function LinkPicker({\n value, onChange, onPick, onEnter, onEscape, autoFocus, startSearching, id, \"aria-label\": ariaLabel = \"Link to\", size = \"md\", bare, lockedType,\n inlineList, types, invalid, \"aria-describedby\": describedBy, className,\n}: LinkPickerProps) {\n const v = normLink(value);\n const host = useLinkTargets();\n const sections = useSectionTargets();\n const { MediaPicker } = useKitServices();\n const targets = React.useMemo(() => [...host.targets, ...sections], [host.targets, sections]);\n const picked = findTarget(targets, v);\n const [library, setLibraryState] = React.useState(false);\n const setLibrary = (o: boolean) => {\n libraryOpen = o;\n setLibraryState(o);\n };\n React.useEffect(() => () => void (libraryOpen = false), []);\n const [fileProblem, setFileProblem] = React.useState<string>();\n const [searching, setSearching] = React.useState(!!startSearching || !picked);\n const [text, setText] = React.useState(() => (picked ? \"\" : inputText(v)));\n const [manualTypeState, setManualType] = React.useState<LinkType | null>(null);\n const manualType = lockedType ?? manualTypeState;\n const [open, setOpen] = React.useState(false);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const wrapRef = React.useRef<HTMLDivElement>(null);\n const type = manualType ?? v.type ?? \"page\";\n const meta = typeMeta(manualType ?? (searching && !text ? \"page\" : v.type));\n const showChip = !!picked && !searching;\n\n React.useEffect(() => {\n if (autoFocus)\n requestAnimationFrame(() => {\n inputRef.current?.focus({ preventScroll: true });\n inputRef.current?.select(); // quick edit: typing replaces, paste replaces\n });\n }, [autoFocus]);\n\n /* rows: the host's pages + every collection's entries (+ files when it lists them) */\n const q = text.trim().toLowerCase().replace(/^[/#]/, \"\");\n const searchable = type === \"page\" || type === \"entry\" || type === \"file\" || (type === \"section\" && sections.length > 0);\n const urlish = type !== \"section\" && (/^(https?:|www\\.|mailto:|tel:|#)/i.test(text.trim()) || (text.trim() !== \"\" && detectType(text) !== \"page\" && !manualType));\n const rows: Row[] = React.useMemo(() => {\n if (!searchable || urlish) return [];\n const pool = targets.filter((t) => (type === \"file\" ? t.kind === \"file\" : type === \"entry\" ? t.kind === \"entry\" : type === \"section\" ? t.kind === \"section\" : t.kind === \"page\" || t.kind === \"entry\"));\n const hit = (t: LinkTarget) => !q || t.title.toLowerCase().includes(q) || t.href.toLowerCase().includes(q) || (t.meta ?? \"\").toLowerCase().includes(q);\n const out: Row[] = [];\n const perGroup = new Map<string, number>();\n const cap = q ? 6 : type === \"page\" ? 4 : 6;\n for (const t of pool) {\n if (!hit(t)) continue;\n const n = perGroup.get(t.group) ?? 0;\n if (n >= cap) continue;\n perGroup.set(t.group, n + 1);\n out.push({ key: `${t.kind}:${t.id}`, group: t.group, target: t });\n }\n // keep each group together, groups in first-seen order (Pages first)\n const order = [...new Set(out.map((r) => r.group))];\n return out.sort((a, b) => order.indexOf(a.group) - order.indexOf(b.group)).slice(0, 24);\n }, [targets, type, q, searchable, urlish]);\n /* No silent empty list: when nothing can be listed, the list says why in one line. */\n const note: string | undefined = (() => {\n if (!searchable || urlish || rows.length) return undefined;\n if (type === \"section\") return undefined;\n if (type === \"file\") return MediaPicker ? \"Choose a file from the library with the folder button.\" : undefined;\n if (host.unavailable) return \"Page search isn't available here. Type a path, like /about.\";\n if (host.error) return `${host.error.replace(/\\.?$/, \".\")} Type a path, like /about.`;\n if (host.loading) return \"Loading pages…\";\n return q ? `Nothing matches “${text.trim()}”. Type a path, like /about.` : type === \"entry\" ? \"No CMS items yet.\" : \"No pages yet. Type a path, like /about.\";\n })();\n const choose = (t: LinkTarget) => {\n t.onChoose?.();\n const n = withTarget(v, t);\n setText(\"\");\n setManualType(null);\n setSearching(false);\n setOpen(false);\n setFileProblem(undefined);\n onChange(n);\n onPick?.(n);\n };\n const type_ = (s: string) => {\n setText(s);\n setOpen(true);\n onChange(withText(v, s, manualType ?? undefined));\n };\n const clear = () => {\n setText(\"\");\n setManualType(null);\n setSearching(true);\n onChange({ ...withText(v, \"\"), href: \"\" });\n requestAnimationFrame(() => inputRef.current?.focus());\n };\n const setType = (t: LinkType) => {\n setManualType(t);\n setText(\"\");\n setSearching(true);\n onChange({ ...withText(v, \"\", t), href: \"\" });\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n };\n\n const h = size === \"sm\" ? \"h-8\" : \"h-9\";\n /* the rows as the Autocomplete's options (V2 link.tsx:520-560: icon, title, href or file name, status) */\n const options: SelectOption[] = rows.map((r) => ({\n value: r.key,\n label: r.target.title,\n group: r.group,\n icon: linkIcon({ href: r.target.href, type: r.target.kind }, r.target),\n description: r.target.kind === \"file\" ? fileName(r.target.href) : r.target.href,\n meta: r.target.status ? STATUS_LABEL[r.target.status] : undefined,\n }));\n /* some targets loaded and some did not (a collection's items): the gap is named under the list */\n const listNote = host.error && type !== \"file\" && type !== \"section\" ? host.error.replace(/\\.?$/, \".\") : undefined;\n const allowed = LINK_TYPES.filter((t) => (!types || types.includes(t.type)) && (t.type !== \"file\" || MediaPicker || v.type === \"file\"));\n const typeMenu = (\n <Menu>\n <MenuTrigger\n render={\n <button\n type=\"button\"\n aria-label={`Link type: ${meta.label}`}\n className=\"ml-0.5 flex h-7 shrink-0 items-center gap-0.5 rounded-kit-md px-1.5 text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover [&_svg]:size-3.5\"\n />\n }\n >\n {meta.icon}\n <IconChevronDown className=\"!size-3\" stroke={1.5} />\n </MenuTrigger>\n <MenuContent className=\"min-w-48\">\n {allowed.map((t) => (\n <MenuItem key={t.type} icon={t.icon} onClick={() => setType(t.type)}>\n <span className=\"flex w-full items-center justify-between gap-3\">\n {t.label}\n {t.type === type ? <IconCheck className=\"size-3.5 text-kit-fg-2\" stroke={2} /> : null}\n </span>\n </MenuItem>\n ))}\n </MenuContent>\n </Menu>\n );\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-1\", className)}>\n <div\n ref={wrapRef}\n className=\"min-w-0\"\n onKeyDown={(e) => {\n // Escape with the list closed (the Autocomplete claims the one that closes it): back to the chip, else the host's\n if (e.key !== \"Escape\" || showChip) return;\n if (picked && !text && !startSearching) {\n e.preventDefault();\n e.stopPropagation();\n setSearching(false);\n } else if (onEscape) {\n e.preventDefault();\n e.stopPropagation();\n onEscape();\n }\n }}\n >\n {showChip ? (\n <div\n className={cn(\n \"flex min-w-0 items-center\",\n bare\n ? \"bg-transparent\"\n : \"rounded-kit-md border border-kit-field-border bg-kit-field-bg shadow-kit-field transition-colors hover:border-kit-field-border-hover focus-within:border-kit-field-border-focus\",\n !bare && invalid && \"border-[var(--kit-field-invalid)] hover:border-[var(--kit-field-invalid)]\",\n h,\n )}\n >\n <span className=\"ml-2 flex shrink-0 text-kit-fg-2 [&_svg]:size-4\" aria-hidden>\n {linkIcon(v, picked)}\n </span>\n <button\n id={id}\n type=\"button\"\n onClick={() => {\n setSearching(true);\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n }}\n aria-label={`${ariaLabel}: ${picked!.title}, ${picked!.href}. Change`}\n className=\"flex h-full min-w-0 flex-1 items-center gap-2 px-2 text-left outline-none\"\n >\n <span className=\"min-w-0 shrink truncate text-kit-sm text-kit-fg\">{picked!.title}</span>\n <span className=\"min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3\">{describeLink(v, picked).secondary}</span>\n </button>\n <IconButton label=\"Clear link\" size=\"xs\" className=\"mr-1\" onClick={clear}>\n <IconX stroke={1.5} />\n </IconButton>\n </div>\n ) : (\n /* search: the kit Autocomplete with V2 link.tsx's extras (one combobox implementation in the kit) */\n <Autocomplete\n id={id}\n aria-label={ariaLabel}\n aria-describedby={describedBy}\n invalid={invalid}\n size={size === \"sm\" ? \"md\" : \"lg\"}\n className={cn(\"shadow-none\", bare ? \"border-0 bg-transparent focus-within:shadow-none\" : \"shadow-kit-field focus-within:shadow-none\")}\n value={text}\n onValueChange={type_}\n options={options}\n filter={null}\n onSelect={(o) => {\n const r = rows.find((x) => x.key === o.value);\n if (r) choose(r.target);\n }}\n fillOnSelect={false}\n onEnter={() => onEnter?.(withText(v, text, manualType ?? undefined))}\n open={open && searching}\n onOpenChange={setOpen}\n inlineList={inlineList}\n emptyNote={note}\n listNote={listNote}\n highlightFirst\n highlightMatches={false}\n listLabel={type === \"file\" ? \"Files\" : type === \"section\" ? \"Sections on this page\" : \"Pages and CMS items\"}\n inputRef={inputRef}\n onBlur={(e) => {\n if (wrapRef.current?.contains(e.relatedTarget as Node)) return;\n if (inlineList) setOpen(false);\n // came from a chip: nothing typed → show the chip again\n if (picked && !text) setSearching(false);\n }}\n placeholder={picked && !text ? picked.title : meta.placeholder}\n leading={lockedType !== undefined || inlineList ? meta.icon : undefined}\n leadingSlot={lockedType !== undefined || inlineList ? undefined : typeMenu}\n onClear={clear}\n trailingSlot={\n type === \"file\" && MediaPicker ? (\n <IconButton\n label=\"Choose or upload a file\"\n size=\"xs\"\n className=\"mr-1 text-kit-fg-3\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n setOpen(false);\n setLibrary(true);\n }}\n >\n <IconFolderOpen stroke={1.5} />\n </IconButton>\n ) : null\n }\n listAttrs={{ [LIST_ATTR]: \"\" }}\n menuClassName={inlineList ? \"mt-0 [&_[role=listbox]]:max-h-56\" : \"shadow-kit-lg\"}\n />\n )}\n </div>\n {fileProblem ? (\n <p role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {fileProblem}\n </p>\n ) : null}\n {/* File: the host's media library (search, folders, upload) is one click away; mounted only while open */}\n {library && MediaPicker ? (\n <MediaPicker\n open\n accept={[\"file\"]}\n onOpenChange={(o) => !o && setLibrary(false)}\n onPick={(a) => {\n if (!a[0]) return;\n const t = fileTarget(a[0]);\n if (\"problem\" in t) setFileProblem(t.problem);\n else choose(t);\n }}\n />\n ) : null}\n </div>\n );\n}\n\n/* ── Shared options (subject · open in new tab · rel) ───────────────── */\nexport function LinkOptions({\n v, onChange, compact, disabled, hideNewTab,\n}: { v: LinkValue; onChange: (v: LinkValue) => void; compact?: boolean; disabled?: boolean; /** the place forbids a new tab (a rich-text field without allowTargetBlank) */ hideNewTab?: boolean }) {\n const tabId = React.useId();\n return (\n <div className={cn(\"flex flex-col\", compact ? \"gap-2\" : \"gap-2.5\")}>\n {v.type === \"email\" ? (\n <label className=\"flex items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Subject</span>\n <Input size=\"sm\" value={v.subject ?? \"\"} onChange={(e) => onChange({ ...v, subject: e.target.value })} placeholder=\"Wholesale inquiry\" className=\"max-w-52\" />\n </label>\n ) : null}\n {hideNewTab ? null : (\n <label htmlFor={tabId} className=\"flex min-h-7 items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Open in new tab</span>\n <Switch disabled={disabled} id={tabId} size=\"sm\" checked={!!v.newTab} onCheckedChange={(c) => onChange({ ...v, newTab: c, target: undefined })} />\n </label>\n )}\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Rel</span>\n <Select disabled={disabled} aria-label=\"Rel\" size=\"sm\" className=\"w-[168px]\" value={v.rel ?? \"follow\"} onValueChange={(r) => onChange({ ...v, rel: r as LinkRel })} options={REL_ITEMS} />\n </div>\n </div>\n );\n}\n\n/* ── The link element ───────────────────────────────────────────────\n * CPO D48 + D57: the ONE way to edit a link, wherever a link is edited: Type (dropdown) → the target for that type\n * (results appear only once you focus or type, in the flow below the input, never over the panel; File adds the media\n * library) → the error in plain words when it can't be saved → Section on the picked page → the options as plain rows\n * (new tab, rel, subject). Hosts wrap it: the link panel (LinkPopoverBody), the button screen. Controlled: the host owns\n * the value; remount (key) to start over.\n */\nexport function LinkForm({\n value,\n onChange,\n onEnter,\n hideOptions,\n hideNewTab,\n types,\n autoFocus,\n readOnly,\n className,\n}: {\n value: LinkValue;\n onChange: (v: LinkValue) => void;\n /** Enter in the target with a value that can be saved */\n onEnter?: (v: LinkValue) => void;\n /** string-only values: no new tab / rel */\n hideOptions?: boolean;\n /** no new tab here (rel stays) */\n hideNewTab?: boolean;\n /** the link types this place allows. Default: all */\n types?: LinkType[];\n /** focus the Type control on open (D48: never the search) */\n autoFocus?: boolean;\n /** the lens can't edit the link: every control is disabled */\n readOnly?: boolean;\n className?: string;\n}) {\n const v = normLink(value);\n const { MediaPicker } = useKitServices();\n const allowed = LINK_TYPES.filter((t) => (!types || types.includes(t.type)) && (t.type !== \"file\" || MediaPicker || v.type === \"file\"));\n const [kind, setKind] = React.useState<LinkType>(() => {\n const k = v.type === \"entry\" && hasLink(v) ? \"page\" : v.type ?? \"page\";\n return allowed.some((t) => t.type === k) ? k : allowed[0]?.type ?? \"page\";\n });\n const [resetKey, setResetKey] = React.useState(0);\n const [touched, setTouched] = React.useState(false);\n const { targets } = useLinkTargets();\n const anchors = findTarget(targets, v)?.anchors;\n const typeId = React.useId();\n const targetId = React.useId();\n const errId = React.useId();\n const problem = touched ? linkProblem(v) : undefined;\n // the type select follows what the target turned out to be (a picked CMS item, a pasted URL) while \"Page\" is searching\n const shownType: LinkType = kind === \"page\" && hasLink(v) ? v.type ?? \"page\" : kind;\n React.useEffect(() => {\n if (autoFocus) requestAnimationFrame(() => document.getElementById(typeId)?.focus({ preventScroll: true }));\n }, [autoFocus, typeId]);\n const changeType = (t: LinkType) => {\n setKind(t);\n setTouched(false);\n onChange({ ...withText(v, \"\", t === \"page\" ? undefined : t), href: \"\", type: t, anchor: undefined });\n setResetKey((k) => k + 1);\n requestAnimationFrame(() => document.getElementById(targetId)?.focus());\n };\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-3\", className)}>\n <div className=\"flex items-center justify-between gap-3\">\n <label htmlFor={typeId} className=\"text-kit-xs text-kit-fg-2\">\n Type\n </label>\n <Select disabled={readOnly} id={typeId} size=\"sm\" className=\"w-[180px]\" value={shownType} onValueChange={(t) => changeType(t as LinkType)} options={allowed.map((t) => ({ value: t.type, label: t.label, icon: t.icon }))} />\n </div>\n <div\n className=\"flex flex-col gap-1.5\"\n onBlur={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node)) setTouched(true);\n }}\n >\n <label htmlFor={targetId} className=\"text-kit-xs text-kit-fg-2\">\n {typeMeta(kind).target}\n </label>\n <LinkPicker\n key={resetKey}\n id={targetId}\n size=\"sm\"\n value={v}\n onChange={onChange}\n onPick={() => setTouched(true)}\n onEnter={(n) => {\n setTouched(true);\n if (!linkProblem(n)) onEnter?.(n);\n }}\n lockedType={kind === \"page\" ? undefined : kind}\n inlineList\n types={types}\n invalid={!!problem}\n aria-describedby={problem ? errId : undefined}\n aria-label={typeMeta(kind).target}\n />\n {problem ? (\n <p id={errId} role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {problem}\n </p>\n ) : null}\n </div>\n {anchors?.length ? (\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Section</span>\n <Select disabled={readOnly} aria-label=\"Section\"\n size=\"sm\"\n className=\"w-[180px]\"\n value={v.anchor ?? \"none\"}\n onValueChange={(a) => onChange({ ...v, anchor: a })}\n options={[{ value: \"none\", label: \"Top of page\" }, ...anchors.map((a) => ({ value: a, label: a }))]}\n />\n </div>\n ) : null}\n {hideOptions ? null : <LinkOptions v={v} onChange={onChange} compact disabled={readOnly} hideNewTab={hideNewTab} />}\n </div>\n );\n}\n\n/* ── The link panel ─────────────────────────────────────────────────\n * What it links to now → the link element (LinkForm) → Remove link · Cancel · Apply (Apply only when something changed\n * and the link can be saved). Esc closes the results first, then the panel.\n */\nexport function LinkPopoverBody({\n initial,\n onSave,\n onDetach,\n onCancel,\n hideOptions,\n hideNewTab,\n types,\n dirty = false,\n}: {\n initial: LinkValue;\n onSave: (v: LinkValue) => void;\n onDetach?: () => void;\n onCancel?: () => void;\n /** string-only fields: no new tab / rel */\n hideOptions?: boolean;\n /** no new tab here (rel stays): a rich-text field without allowTargetBlank */\n hideNewTab?: boolean;\n /** the link types this place allows. Default: all */\n types?: LinkType[];\n /** something the host draws beside the form changed (a button's label), so Apply has something to save */\n dirty?: boolean;\n}) {\n const start = normLink(initial);\n const [v, setV] = React.useState<LinkValue>(start);\n const { targets } = useLinkTargets();\n const startTarget = findTarget(targets, start);\n const fin = (x: LinkValue) => {\n const f = finalizeLink(x);\n return f ? JSON.stringify(storedLink(f)) : \"\";\n };\n const changed = dirty || fin(v) !== fin(start);\n const ok = hasLink(v) && !linkProblem(v);\n const apply = (n = v) => {\n const out = finalizeLink(n);\n if (out && hasLink(out) && !linkProblem(out)) onSave(out);\n };\n return (\n <form\n className=\"flex flex-col gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n e.stopPropagation();\n apply();\n }}\n >\n <div className=\"flex min-w-0 flex-col gap-1\">\n <span className=\"text-kit-sm font-medium text-kit-fg\">Link</span>\n {hasLink(start) ? (\n <span className=\"flex min-w-0 text-kit-fg-2\">\n <LinkLine v={start} target={startTarget} />\n </span>\n ) : (\n <span className=\"text-kit-xs text-kit-fg-3\">No link yet</span>\n )}\n </div>\n <LinkForm value={v} onChange={setV} onEnter={(n) => apply(n)} hideOptions={hideOptions} hideNewTab={hideNewTab} types={types} autoFocus />\n <div className=\"flex items-center gap-2 border-t border-kit-line pt-2.5\">\n {onDetach ? (\n <Button type=\"button\" size=\"xs\" variant=\"danger-ghost\" onClick={onDetach}>\n Remove link\n </Button>\n ) : null}\n <span className=\"flex-1\" />\n {onCancel ? (\n <Button type=\"button\" size=\"xs\" variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n ) : null}\n <Button type=\"submit\" size=\"xs\" variant=\"primary\" disabled={!changed || !ok}>\n Apply\n </Button>\n </div>\n </form>\n );\n}\n\n/* ── Quick edit: the link row turns into the picker in place ───────── */\nexport function LinkQuickEdit({\n value,\n onCommit,\n onDone,\n ariaLabel,\n size,\n bare,\n types,\n}: {\n value: LinkValue;\n /** null = cleared */\n onCommit: (v: LinkValue | null) => void;\n onDone: () => void;\n ariaLabel: string;\n size?: \"sm\" | \"md\";\n bare?: boolean;\n types?: LinkType[];\n}) {\n const [draft, setDraft] = React.useState(value);\n const [problem, setProblem] = React.useState<string>();\n const done = React.useRef(false);\n const ref = React.useRef<HTMLDivElement>(null);\n const errId = React.useId();\n const commit = (n: LinkValue, strict = true) => {\n if (done.current) return;\n if (hasLink(n) && strict && linkProblem(n)) return setProblem(linkProblem(n));\n done.current = true;\n if (!hasLink(n)) onCommit(null);\n else {\n const out = finalizeLink(n);\n // a script link is dropped, never written (finalizeLink refuses it)\n if (out) onCommit(out);\n }\n onDone();\n };\n return (\n <div\n ref={ref}\n className=\"flex min-w-0 flex-col gap-1\"\n onBlur={(e) => {\n const next = e.relatedTarget as HTMLElement | null;\n if (libraryOpen || (next && (ref.current?.contains(next) || next.closest?.(`[${LIST_ATTR}],[role=menu]`)))) return;\n // focus left the editor: keep what was typed (nothing changed → nothing written)\n window.setTimeout(() => {\n if (libraryOpen || done.current || ref.current?.contains(document.activeElement)) return;\n if (hrefOf(draft) === hrefOf(value) && draft.pageId === value.pageId && draft.entryId === value.entryId) {\n done.current = true;\n onDone();\n } else commit(draft, false);\n }, 0);\n }}\n >\n <LinkPicker\n value={draft}\n onChange={(n) => {\n setDraft(n);\n setProblem(undefined);\n }}\n onPick={(n) => commit(n)}\n onEnter={(n) => commit(n)}\n onEscape={() => {\n done.current = true;\n onDone();\n }}\n autoFocus\n startSearching\n aria-label={ariaLabel}\n size={size}\n bare={bare}\n types={types}\n invalid={!!problem}\n aria-describedby={problem ? errId : undefined}\n />\n {problem ? (\n <p id={errId} role=\"alert\" className={cn(\"text-kit-xs text-kit-danger-fg\", bare && \"px-2.5 pb-1.5\")}>\n {problem}\n </p>\n ) : null}\n </div>\n );\n}\n\n/* ── Link field: one bordered row; click edits in place, the sliders icon opens the link panel ── */\nexport interface LinkFieldProps {\n /** a LinkValue or a plain href string */\n value: unknown;\n /** null = cleared (object shape); \"\" = cleared (string shape) */\n onChange: (v: LinkValue | string | null) => void;\n /** \"string\": the value is the href alone. New tab and rel need the object shape, so they hide. */\n valueShape?: \"string\" | \"object\";\n id?: string;\n \"aria-label\": string;\n readOnly?: boolean;\n size?: \"sm\" | \"md\";\n /** the link types this place allows. Default: all */\n types?: LinkType[];\n invalid?: boolean;\n placeholder?: string;\n className?: string;\n}\nexport function LinkField({ value, onChange: write, valueShape, id: idProp, \"aria-label\": label, readOnly, size = \"sm\", types, invalid, placeholder, className }: LinkFieldProps) {\n const v = normLink(value);\n const stringOnly = valueShape === \"string\";\n const onChange = (n: LinkValue | null) => write(stringOnly ? (n ? hrefOf(n) : \"\") : n ? storedLink(n, value) : null);\n const autoId = React.useId();\n const id = idProp ?? autoId;\n const [editing, setEditing] = React.useState(false);\n const [open, setOpen] = React.useState(false);\n const { targets } = useLinkTargets();\n const target = findTarget(targets, v);\n const has = hasLink(v);\n if (editing && !readOnly)\n return (\n <LinkQuickEdit\n value={v}\n ariaLabel={label}\n size={size}\n types={types}\n onCommit={onChange}\n onDone={() => {\n setEditing(false);\n requestAnimationFrame(() => document.getElementById(id)?.focus({ preventScroll: true }));\n }}\n />\n );\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverAnchor\n data-kit-link-field=\"\"\n className={cn(\n \"group/link relative flex min-w-0 items-center rounded-kit-md border border-kit-field-border bg-kit-field-bg shadow-kit-field transition-colors hover:border-kit-field-border-hover\",\n size === \"md\" ? \"h-9\" : \"h-8\",\n readOnly && \"hover:border-kit-field-border\",\n invalid && \"border-[var(--kit-field-invalid)]\",\n className,\n )}\n >\n <button\n id={id}\n type=\"button\"\n disabled={readOnly}\n onClick={() => setEditing(true)}\n // V2 link.tsx:977: the name reads the link's own text (its title, else its address), not the picked target's title\n aria-label={has ? `${label}: ${linkText(v)}. Edit link` : `Add ${label.toLowerCase()}`}\n aria-invalid={invalid || undefined}\n className=\"flex h-full min-w-0 flex-1 items-center px-2.5 text-left outline-none disabled:cursor-default\"\n >\n <LinkLine v={v} target={target} placeholder={placeholder} />\n </button>\n {readOnly ? null : (\n <span className=\"mr-1 flex shrink-0 items-center gap-0.5\">\n <Tooltip content=\"Link options\">\n <PopoverTrigger\n render={\n <IconButton label=\"Link options\" tooltip={false} size=\"xs\" className=\"text-kit-fg-3\">\n <IconAdjustmentsHorizontal stroke={1.5} />\n </IconButton>\n }\n />\n </Tooltip>\n {has ? (\n <IconButton\n label={`Clear ${label.toLowerCase()}`}\n size=\"xs\"\n className=\"hidden text-kit-fg-3 group-hover/link:inline-flex group-focus-within/link:inline-flex [@media(pointer:coarse)]:inline-flex\"\n onClick={() => onChange(null)}\n >\n <IconX stroke={1.5} />\n </IconButton>\n ) : null}\n </span>\n )}\n </PopoverAnchor>\n <PopoverContent className=\"w-[340px] p-3\" align=\"start\">\n <LinkPopoverBody\n initial={v}\n hideOptions={stringOnly}\n types={types}\n onSave={(n) => {\n onChange(n);\n setOpen(false);\n }}\n onDetach={\n has\n ? () => {\n onChange(null);\n setOpen(false);\n }\n : undefined\n }\n onCancel={() => setOpen(false)}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\n/**\n * The shape a link field writes: the shape its value already has (a string stays a string, an object an object), and\n * for an empty field `field.valueShape`, else the string prod stores by default.\n */\nexport function linkShapeOf(value: unknown, valueShape?: \"string\" | \"object\"): \"string\" | \"object\" {\n if (isObj(value)) return \"object\";\n if (typeof value === \"string\" && value !== \"\") return \"string\";\n return valueShape ?? \"string\";\n}\n\n/** The Block Kit `link` field: the LinkField above, sized for the form it sits in. */\nexport function LinkControl({ value, onChange, readOnly, id, field, invalid }: ControlProps) {\n const { variant } = useKitEnv();\n return (\n <LinkField\n id={id}\n value={value}\n onChange={onChange}\n valueShape={linkShapeOf(value, field.valueShape)}\n aria-label={field.title}\n readOnly={readOnly}\n size={variant === \"document\" ? \"md\" : \"sm\"}\n invalid={invalid}\n />\n );\n}\n"],"mappings":"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"}
@@ -469,6 +469,7 @@ function ArticlePopoverBlock({ label, kind, schema, m, set, el, ctx, autoFocus,
469
469
  }), editing ? /* @__PURE__ */ jsxs(PopoverContent, {
470
470
  align: "end",
471
471
  side: "bottom",
472
+ arrowPadding: 0,
472
473
  className: "w-[340px] p-0",
473
474
  initialFocus: false,
474
475
  finalFocus: false,