@bettercms-ai/kit 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/adapters/lossy.d.ts +12 -4
  2. package/dist/adapters/lossy.js +19 -8
  3. package/dist/adapters/lossy.js.map +1 -1
  4. package/dist/adapters/prod-types.d.ts +46 -14
  5. package/dist/adapters/prod-types.js +37 -35
  6. package/dist/adapters/prod-types.js.map +1 -1
  7. package/dist/adapters/schema.d.ts +39 -0
  8. package/dist/adapters/schema.js +281 -82
  9. package/dist/adapters/schema.js.map +1 -1
  10. package/dist/context.d.ts +39 -0
  11. package/dist/context.js +40 -1
  12. package/dist/context.js.map +1 -1
  13. package/dist/controls/form-picker-register.d.ts +7 -1
  14. package/dist/controls/form-picker-register.js +1 -5
  15. package/dist/controls/form-picker-register.js.map +1 -1
  16. package/dist/controls/icon.d.ts +1 -1
  17. package/dist/controls/icon.js +1 -1
  18. package/dist/controls/icon.js.map +1 -1
  19. package/dist/controls/link.d.ts +11 -4
  20. package/dist/controls/link.js +120 -202
  21. package/dist/controls/link.js.map +1 -1
  22. package/dist/controls/location.js +3 -8
  23. package/dist/controls/location.js.map +1 -1
  24. package/dist/controls/media.d.ts +0 -14
  25. package/dist/controls/media.js +52 -95
  26. package/dist/controls/media.js.map +1 -1
  27. package/dist/controls/reference-services.d.ts +23 -2
  28. package/dist/controls/reference.d.ts +2 -2
  29. package/dist/controls/reference.js +79 -28
  30. package/dist/controls/reference.js.map +1 -1
  31. package/dist/controls/rich-text/article-shell.d.ts +145 -0
  32. package/dist/controls/rich-text/article-shell.js +514 -0
  33. package/dist/controls/rich-text/article-shell.js.map +1 -0
  34. package/dist/controls/rich-text/author.d.ts +25 -0
  35. package/dist/controls/rich-text/author.js +107 -0
  36. package/dist/controls/rich-text/author.js.map +1 -0
  37. package/dist/controls/rich-text/blocks.d.ts +19 -2
  38. package/dist/controls/rich-text/blocks.js +275 -638
  39. package/dist/controls/rich-text/blocks.js.map +1 -1
  40. package/dist/controls/rich-text/button.d.ts +23 -0
  41. package/dist/controls/rich-text/button.js +81 -0
  42. package/dist/controls/rich-text/button.js.map +1 -0
  43. package/dist/controls/rich-text/catalog.d.ts +2 -5
  44. package/dist/controls/rich-text/catalog.js +121 -7
  45. package/dist/controls/rich-text/catalog.js.map +1 -1
  46. package/dist/controls/rich-text/checklist.d.ts +24 -0
  47. package/dist/controls/rich-text/checklist.js +115 -0
  48. package/dist/controls/rich-text/checklist.js.map +1 -0
  49. package/dist/controls/rich-text/codec.d.ts +15 -1
  50. package/dist/controls/rich-text/codec.js +11 -1
  51. package/dist/controls/rich-text/codec.js.map +1 -1
  52. package/dist/controls/rich-text/columns.d.ts +41 -0
  53. package/dist/controls/rich-text/columns.js +181 -0
  54. package/dist/controls/rich-text/columns.js.map +1 -0
  55. package/dist/controls/rich-text/control.js +1 -0
  56. package/dist/controls/rich-text/control.js.map +1 -1
  57. package/dist/controls/rich-text/dom.d.ts +84 -4
  58. package/dist/controls/rich-text/dom.js +171 -10
  59. package/dist/controls/rich-text/dom.js.map +1 -1
  60. package/dist/controls/rich-text/editor.d.ts +4 -2
  61. package/dist/controls/rich-text/editor.js +199 -26
  62. package/dist/controls/rich-text/editor.js.map +1 -1
  63. package/dist/controls/rich-text/embed.d.ts +28 -0
  64. package/dist/controls/rich-text/embed.js +210 -0
  65. package/dist/controls/rich-text/embed.js.map +1 -0
  66. package/dist/controls/rich-text/footnote.d.ts +41 -0
  67. package/dist/controls/rich-text/footnote.js +185 -0
  68. package/dist/controls/rich-text/footnote.js.map +1 -0
  69. package/dist/controls/rich-text/gallery.d.ts +28 -0
  70. package/dist/controls/rich-text/gallery.js +167 -0
  71. package/dist/controls/rich-text/gallery.js.map +1 -0
  72. package/dist/controls/rich-text/link-form.d.ts +13 -1
  73. package/dist/controls/rich-text/link-form.js +41 -7
  74. package/dist/controls/rich-text/link-form.js.map +1 -1
  75. package/dist/controls/rich-text/ops.js +6 -0
  76. package/dist/controls/rich-text/ops.js.map +1 -1
  77. package/dist/controls/rich-text/related.d.ts +49 -0
  78. package/dist/controls/rich-text/related.js +233 -0
  79. package/dist/controls/rich-text/related.js.map +1 -0
  80. package/dist/controls/rich-text/toc.d.ts +47 -0
  81. package/dist/controls/rich-text/toc.js +160 -0
  82. package/dist/controls/rich-text/toc.js.map +1 -0
  83. package/dist/controls/slot-register.d.ts +6 -1
  84. package/dist/controls/slot-register.js +1 -4
  85. package/dist/controls/slot-register.js.map +1 -1
  86. package/dist/core/core.d.ts +11 -3
  87. package/dist/core/core.js +24 -6
  88. package/dist/core/core.js.map +1 -1
  89. package/dist/core/facets.d.ts +16 -0
  90. package/dist/core/facets.js +17 -1
  91. package/dist/core/facets.js.map +1 -1
  92. package/dist/core/index.js +2 -2
  93. package/dist/index.js +16 -5
  94. package/dist/index.js.map +1 -1
  95. package/dist/ledgers/exclusions.v1.js +141 -0
  96. package/dist/ledgers/exclusions.v1.js.map +1 -0
  97. package/dist/library/coverage.d.ts +13 -1
  98. package/dist/library/coverage.js +12 -1
  99. package/dist/library/coverage.js.map +1 -1
  100. package/dist/library/kit-catalog.json +156 -153
  101. package/dist/schema/types.d.ts +17 -0
  102. package/dist/schema/types.js.map +1 -1
  103. package/dist/styles.css +1 -1
  104. package/dist/testing/coverage-extras.d.ts +8 -0
  105. package/dist/testing/coverage-extras.js +44 -0
  106. package/dist/testing/coverage-extras.js.map +1 -0
  107. package/dist/testing/exclusions.d.ts +30 -0
  108. package/dist/testing/exclusions.js +13 -0
  109. package/dist/testing/exclusions.js.map +1 -0
  110. package/dist/ui/autocomplete.d.ts +29 -1
  111. package/dist/ui/autocomplete.js +102 -47
  112. package/dist/ui/autocomplete.js.map +1 -1
  113. package/dist/ui/button.js +3 -5
  114. package/dist/ui/button.js.map +1 -1
  115. package/dist/ui/index.js +2 -2
  116. package/dist/ui/overlay.d.ts +4 -1
  117. package/dist/ui/overlay.js +2 -1
  118. package/dist/ui/overlay.js.map +1 -1
  119. package/dist/ui/toast.js +1 -1
  120. package/package.json +8 -2
@@ -6,8 +6,9 @@ import { Switch } from "../ui/controls.js";
6
6
  import { Menu, MenuContent, MenuItem, MenuTrigger, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Tooltip } from "../ui/overlay.js";
7
7
  import { Input } from "../ui/input.js";
8
8
  import { Select } from "../ui/select.js";
9
+ import { Autocomplete } from "../ui/autocomplete.js";
9
10
  import * as React from "react";
10
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
11
12
  import { IconAdjustmentsHorizontal, IconArrowUpRight, IconAt, IconCheck, IconChevronDown, IconExternalLink, IconFile, IconFileDatabase, IconFolderOpen, IconHash, IconLink, IconMail, IconPaperclip, IconPhone, IconWorld, IconX } from "@tabler/icons-react";
12
13
  //#region src/controls/link.tsx
13
14
  /**
@@ -426,10 +427,8 @@ function LinkPicker({ value, onChange, onPick, onEnter, onEscape, autoFocus, sta
426
427
  const [manualTypeState, setManualType] = React.useState(null);
427
428
  const manualType = lockedType ?? manualTypeState;
428
429
  const [open, setOpen] = React.useState(false);
429
- const [active, setActive] = React.useState(-1);
430
430
  const inputRef = React.useRef(null);
431
431
  const wrapRef = React.useRef(null);
432
- const listId = React.useId();
433
432
  const type = manualType ?? v.type ?? "page";
434
433
  const meta = typeMeta(manualType ?? (searching && !text ? "page" : v.type));
435
434
  const showChip = !!picked && !searching;
@@ -478,18 +477,6 @@ function LinkPicker({ value, onChange, onPick, onEnter, onEscape, autoFocus, sta
478
477
  if (host.loading) return "Loading pages…";
479
478
  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.";
480
479
  })();
481
- const listOpen = open && searching && (rows.length > 0 || !!note);
482
- React.useEffect(() => {
483
- if (!listOpen) return;
484
- const onKey = (e) => {
485
- if (e.key !== "Escape" || !wrapRef.current?.contains(document.activeElement)) return;
486
- e.preventDefault();
487
- e.stopPropagation();
488
- setOpen(false);
489
- };
490
- window.addEventListener("keydown", onKey, true);
491
- return () => window.removeEventListener("keydown", onKey, true);
492
- }, [listOpen]);
493
480
  const choose = (t) => {
494
481
  t.onChoose?.();
495
482
  const n = withTarget(v, t);
@@ -504,7 +491,6 @@ function LinkPicker({ value, onChange, onPick, onEnter, onEscape, autoFocus, sta
504
491
  const type_ = (s) => {
505
492
  setText(s);
506
493
  setOpen(true);
507
- setActive(s.trim() ? 0 : -1);
508
494
  onChange(withText(v, s, manualType ?? void 0));
509
495
  };
510
496
  const clear = () => {
@@ -529,54 +515,18 @@ function LinkPicker({ value, onChange, onPick, onEnter, onEscape, autoFocus, sta
529
515
  requestAnimationFrame(() => inputRef.current?.focus());
530
516
  };
531
517
  const h = size === "sm" ? "h-8" : "h-9";
532
- const list = /* @__PURE__ */ jsxs("div", {
533
- id: listId,
534
- role: "listbox",
535
- "aria-label": type === "file" ? "Files" : type === "section" ? "Sections on this page" : "Pages and CMS items",
536
- className: "max-h-72 overflow-y-auto overscroll-contain",
537
- children: [rows.map((r, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [i === 0 || rows[i - 1].group !== r.group ? /* @__PURE__ */ jsx("div", {
538
- role: "presentation",
539
- className: "px-2 pb-1 pt-2 text-kit-xs font-medium text-kit-fg-3 first:pt-1",
540
- children: r.group
541
- }) : null, /* @__PURE__ */ jsxs("div", {
542
- id: `${listId}-${i}`,
543
- role: "option",
544
- "aria-selected": i === active,
545
- onMouseEnter: () => setActive(i),
546
- onClick: () => choose(r.target),
547
- className: cn("flex h-8 cursor-pointer items-center gap-2 rounded-kit-md px-2 text-kit-sm", i === active && "bg-kit-hover"),
548
- children: [
549
- /* @__PURE__ */ jsx("span", {
550
- className: "flex shrink-0 text-kit-fg-3 [&_svg]:size-4",
551
- "aria-hidden": true,
552
- children: linkIcon({
553
- href: r.target.href,
554
- type: r.target.kind
555
- }, r.target)
556
- }),
557
- /* @__PURE__ */ jsx("span", {
558
- className: "min-w-0 shrink truncate text-kit-fg",
559
- children: r.target.title
560
- }),
561
- /* @__PURE__ */ jsx("span", {
562
- className: "min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3",
563
- children: r.target.kind === "file" ? fileName(r.target.href) : r.target.href
564
- }),
565
- r.target.status && STATUS_LABEL[r.target.status] ? /* @__PURE__ */ jsx("span", {
566
- className: "shrink-0 text-kit-2xs text-kit-fg-3",
567
- children: STATUS_LABEL[r.target.status]
568
- }) : null
569
- ]
570
- })] }, r.key)), !rows.length && note ? /* @__PURE__ */ jsx("p", {
571
- role: "status",
572
- className: "px-2 py-1.5 text-kit-xs text-kit-fg-3",
573
- children: note
574
- }) : rows.length && host.error && type !== "file" && type !== "section" ? /* @__PURE__ */ jsx("p", {
575
- role: "status",
576
- className: "px-2 py-1.5 text-kit-xs text-kit-fg-3",
577
- children: host.error.replace(/\.?$/, ".")
578
- }) : null]
579
- });
518
+ const options = rows.map((r) => ({
519
+ value: r.key,
520
+ label: r.target.title,
521
+ group: r.group,
522
+ icon: linkIcon({
523
+ href: r.target.href,
524
+ type: r.target.kind
525
+ }, r.target),
526
+ description: r.target.kind === "file" ? fileName(r.target.href) : r.target.href,
527
+ meta: r.target.status ? STATUS_LABEL[r.target.status] : void 0
528
+ }));
529
+ const listNote = host.error && type !== "file" && type !== "section" ? host.error.replace(/\.?$/, ".") : void 0;
580
530
  const allowed = LINK_TYPES.filter((t) => (!types || types.includes(t.type)) && (t.type !== "file" || MediaPicker || v.type === "file"));
581
531
  const typeMenu = /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsxs(MenuTrigger, {
582
532
  render: /* @__PURE__ */ jsx("button", {
@@ -605,139 +555,105 @@ function LinkPicker({ value, onChange, onPick, onEnter, onEscape, autoFocus, sta
605
555
  return /* @__PURE__ */ jsxs("div", {
606
556
  className: cn("flex min-w-0 flex-col gap-1", className),
607
557
  children: [
608
- /* @__PURE__ */ jsxs(Popover, {
609
- open: listOpen && !inlineList,
610
- onOpenChange: (o) => !o && setOpen(false),
611
- children: [/* @__PURE__ */ jsx("div", {
612
- ref: wrapRef,
613
- className: "min-w-0",
614
- children: /* @__PURE__ */ jsx(PopoverAnchor, {
615
- className: cn("flex min-w-0 items-center", bare ? "bg-transparent" : "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", !bare && invalid && "border-[var(--kit-field-invalid)] hover:border-[var(--kit-field-invalid)]", h),
616
- children: showChip ? /* @__PURE__ */ jsxs(Fragment, { children: [
617
- /* @__PURE__ */ jsx("span", {
618
- className: "ml-2 flex shrink-0 text-kit-fg-2 [&_svg]:size-4",
619
- "aria-hidden": true,
620
- children: linkIcon(v, picked)
621
- }),
622
- /* @__PURE__ */ jsxs("button", {
623
- id,
624
- type: "button",
625
- onClick: () => {
626
- setSearching(true);
627
- setOpen(true);
628
- requestAnimationFrame(() => inputRef.current?.focus());
629
- },
630
- "aria-label": `${ariaLabel}: ${picked.title}, ${picked.href}. Change`,
631
- className: "flex h-full min-w-0 flex-1 items-center gap-2 px-2 text-left outline-none",
632
- children: [/* @__PURE__ */ jsx("span", {
633
- className: "min-w-0 shrink truncate text-kit-sm text-kit-fg",
634
- children: picked.title
635
- }), /* @__PURE__ */ jsx("span", {
636
- className: "min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3",
637
- children: describeLink(v, picked).secondary
638
- })]
639
- }),
640
- /* @__PURE__ */ jsx(IconButton, {
641
- label: "Clear link",
642
- size: "xs",
643
- className: "mr-1",
644
- onClick: clear,
645
- children: /* @__PURE__ */ jsx(IconX, { stroke: 1.5 })
646
- })
647
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
648
- lockedType !== void 0 || inlineList ? /* @__PURE__ */ jsx("span", {
649
- className: "ml-2.5 flex shrink-0 text-kit-fg-3 [&_svg]:size-4",
650
- "aria-hidden": true,
651
- children: meta.icon
652
- }) : typeMenu,
653
- /* @__PURE__ */ jsx("input", {
654
- ref: inputRef,
655
- id,
656
- role: "combobox",
657
- "aria-label": ariaLabel,
658
- "aria-invalid": invalid || void 0,
659
- "aria-describedby": describedBy,
660
- "aria-expanded": listOpen,
661
- "aria-controls": listOpen ? listId : void 0,
662
- "aria-autocomplete": "list",
663
- "aria-activedescendant": listOpen && active >= 0 && rows[active] ? `${listId}-${active}` : void 0,
664
- value: text,
665
- onChange: (e) => type_(e.target.value),
666
- onFocus: () => setOpen(true),
667
- onBlur: (e) => {
668
- if (wrapRef.current?.contains(e.relatedTarget)) return;
669
- if (inlineList) setOpen(false);
670
- if (picked && !text) setSearching(false);
671
- },
672
- onKeyDown: (e) => {
673
- if (e.key === "ArrowDown" && rows.length) {
674
- e.preventDefault();
675
- setOpen(true);
676
- setActive((a) => (a + 1) % rows.length);
677
- } else if (e.key === "ArrowUp" && rows.length) {
678
- e.preventDefault();
679
- setActive((a) => a <= 0 ? rows.length - 1 : a - 1);
680
- } else if (e.key === "Enter") {
681
- e.preventDefault();
682
- if (listOpen && active >= 0 && rows[active]) choose(rows[active].target);
683
- else onEnter?.(withText(v, text, manualType ?? void 0));
684
- } else if (e.key === "Escape") {
685
- if (listOpen) {
686
- e.preventDefault();
687
- e.stopPropagation();
688
- setOpen(false);
689
- } else if (picked && !text && !startSearching) {
690
- e.preventDefault();
691
- e.stopPropagation();
692
- setSearching(false);
693
- } else if (onEscape) {
694
- e.preventDefault();
695
- e.stopPropagation();
696
- onEscape();
697
- }
698
- }
699
- },
700
- placeholder: picked && !text ? picked.title : meta.placeholder,
701
- autoComplete: "off",
702
- spellCheck: false,
703
- className: "h-full min-w-0 flex-1 bg-transparent px-2 text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-3"
704
- }),
705
- text ? /* @__PURE__ */ jsx(IconButton, {
706
- label: "Clear",
707
- size: "xs",
708
- className: "mr-1",
709
- onMouseDown: (e) => e.preventDefault(),
710
- onClick: clear,
711
- children: /* @__PURE__ */ jsx(IconX, { stroke: 1.5 })
712
- }) : null,
713
- type === "file" && MediaPicker ? /* @__PURE__ */ jsx(IconButton, {
714
- label: "Choose or upload a file",
715
- size: "xs",
716
- className: "mr-1 text-kit-fg-3",
717
- onMouseDown: (e) => e.preventDefault(),
718
- onClick: () => {
719
- setOpen(false);
720
- setLibrary(true);
721
- },
722
- children: /* @__PURE__ */ jsx(IconFolderOpen, { stroke: 1.5 })
723
- }) : null
724
- ] })
725
- })
726
- }), /* @__PURE__ */ jsx(PopoverContent, {
727
- keepFocus: true,
728
- align: "start",
729
- side: "bottom",
730
- sideOffset: 4,
731
- "data-kit-link-list": "",
732
- className: "w-[max(var(--anchor-width),280px)] max-w-[min(420px,calc(100vw-24px))] !bg-kit-surface p-1 shadow-kit-lg",
733
- children: list
734
- })]
558
+ /* @__PURE__ */ jsx("div", {
559
+ ref: wrapRef,
560
+ className: "min-w-0",
561
+ onKeyDown: (e) => {
562
+ if (e.key !== "Escape" || showChip) return;
563
+ if (picked && !text && !startSearching) {
564
+ e.preventDefault();
565
+ e.stopPropagation();
566
+ setSearching(false);
567
+ } else if (onEscape) {
568
+ e.preventDefault();
569
+ e.stopPropagation();
570
+ onEscape();
571
+ }
572
+ },
573
+ children: showChip ? /* @__PURE__ */ jsxs("div", {
574
+ className: cn("flex min-w-0 items-center", bare ? "bg-transparent" : "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", !bare && invalid && "border-[var(--kit-field-invalid)] hover:border-[var(--kit-field-invalid)]", h),
575
+ children: [
576
+ /* @__PURE__ */ jsx("span", {
577
+ className: "ml-2 flex shrink-0 text-kit-fg-2 [&_svg]:size-4",
578
+ "aria-hidden": true,
579
+ children: linkIcon(v, picked)
580
+ }),
581
+ /* @__PURE__ */ jsxs("button", {
582
+ id,
583
+ type: "button",
584
+ onClick: () => {
585
+ setSearching(true);
586
+ setOpen(true);
587
+ requestAnimationFrame(() => inputRef.current?.focus());
588
+ },
589
+ "aria-label": `${ariaLabel}: ${picked.title}, ${picked.href}. Change`,
590
+ className: "flex h-full min-w-0 flex-1 items-center gap-2 px-2 text-left outline-none",
591
+ children: [/* @__PURE__ */ jsx("span", {
592
+ className: "min-w-0 shrink truncate text-kit-sm text-kit-fg",
593
+ children: picked.title
594
+ }), /* @__PURE__ */ jsx("span", {
595
+ className: "min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3",
596
+ children: describeLink(v, picked).secondary
597
+ })]
598
+ }),
599
+ /* @__PURE__ */ jsx(IconButton, {
600
+ label: "Clear link",
601
+ size: "xs",
602
+ className: "mr-1",
603
+ onClick: clear,
604
+ children: /* @__PURE__ */ jsx(IconX, { stroke: 1.5 })
605
+ })
606
+ ]
607
+ }) : /* @__PURE__ */ jsx(Autocomplete, {
608
+ id,
609
+ "aria-label": ariaLabel,
610
+ "aria-describedby": describedBy,
611
+ invalid,
612
+ size: size === "sm" ? "md" : "lg",
613
+ className: cn("shadow-none", bare ? "border-0 bg-transparent focus-within:shadow-none" : "shadow-kit-field focus-within:shadow-none"),
614
+ value: text,
615
+ onValueChange: type_,
616
+ options,
617
+ filter: null,
618
+ onSelect: (o) => {
619
+ const r = rows.find((x) => x.key === o.value);
620
+ if (r) choose(r.target);
621
+ },
622
+ fillOnSelect: false,
623
+ onEnter: () => onEnter?.(withText(v, text, manualType ?? void 0)),
624
+ open: open && searching,
625
+ onOpenChange: setOpen,
626
+ inlineList,
627
+ emptyNote: note,
628
+ listNote,
629
+ highlightFirst: true,
630
+ highlightMatches: false,
631
+ listLabel: type === "file" ? "Files" : type === "section" ? "Sections on this page" : "Pages and CMS items",
632
+ inputRef,
633
+ onBlur: (e) => {
634
+ if (wrapRef.current?.contains(e.relatedTarget)) return;
635
+ if (inlineList) setOpen(false);
636
+ if (picked && !text) setSearching(false);
637
+ },
638
+ placeholder: picked && !text ? picked.title : meta.placeholder,
639
+ leading: lockedType !== void 0 || inlineList ? meta.icon : void 0,
640
+ leadingSlot: lockedType !== void 0 || inlineList ? void 0 : typeMenu,
641
+ onClear: clear,
642
+ trailingSlot: type === "file" && MediaPicker ? /* @__PURE__ */ jsx(IconButton, {
643
+ label: "Choose or upload a file",
644
+ size: "xs",
645
+ className: "mr-1 text-kit-fg-3",
646
+ onMouseDown: (e) => e.preventDefault(),
647
+ onClick: () => {
648
+ setOpen(false);
649
+ setLibrary(true);
650
+ },
651
+ children: /* @__PURE__ */ jsx(IconFolderOpen, { stroke: 1.5 })
652
+ }) : null,
653
+ listAttrs: { [LIST_ATTR]: "" },
654
+ menuClassName: inlineList ? "mt-0 [&_[role=listbox]]:max-h-56" : "shadow-kit-lg"
655
+ })
735
656
  }),
736
- inlineList && listOpen ? /* @__PURE__ */ jsx("div", {
737
- className: "rounded-kit-md border border-kit-line bg-kit-surface p-1 [&_[role=listbox]]:max-h-56",
738
- onMouseDown: (e) => e.preventDefault(),
739
- children: list
740
- }) : null,
741
657
  fileProblem ? /* @__PURE__ */ jsx("p", {
742
658
  role: "alert",
743
659
  className: "text-kit-xs text-kit-danger-fg",
@@ -757,7 +673,7 @@ function LinkPicker({ value, onChange, onPick, onEnter, onEscape, autoFocus, sta
757
673
  ]
758
674
  });
759
675
  }
760
- function LinkOptions({ v, onChange, compact, disabled }) {
676
+ function LinkOptions({ v, onChange, compact, disabled, hideNewTab }) {
761
677
  const tabId = React.useId();
762
678
  return /* @__PURE__ */ jsxs("div", {
763
679
  className: cn("flex flex-col", compact ? "gap-2" : "gap-2.5"),
@@ -778,7 +694,7 @@ function LinkOptions({ v, onChange, compact, disabled }) {
778
694
  className: "max-w-52"
779
695
  })]
780
696
  }) : null,
781
- /* @__PURE__ */ jsxs("label", {
697
+ hideNewTab ? null : /* @__PURE__ */ jsxs("label", {
782
698
  htmlFor: tabId,
783
699
  className: "flex min-h-7 items-center justify-between gap-3",
784
700
  children: [/* @__PURE__ */ jsx("span", {
@@ -817,7 +733,7 @@ function LinkOptions({ v, onChange, compact, disabled }) {
817
733
  ]
818
734
  });
819
735
  }
820
- function LinkForm({ value, onChange, onEnter, hideOptions, types, autoFocus, readOnly, className }) {
736
+ function LinkForm({ value, onChange, onEnter, hideOptions, hideNewTab, types, autoFocus, readOnly, className }) {
821
737
  const v = normLink(value);
822
738
  const { MediaPicker } = useKitServices();
823
739
  const allowed = LINK_TYPES.filter((t) => (!types || types.includes(t.type)) && (t.type !== "file" || MediaPicker || v.type === "file"));
@@ -936,12 +852,13 @@ function LinkForm({ value, onChange, onEnter, hideOptions, types, autoFocus, rea
936
852
  v,
937
853
  onChange,
938
854
  compact: true,
939
- disabled: readOnly
855
+ disabled: readOnly,
856
+ hideNewTab
940
857
  })
941
858
  ]
942
859
  });
943
860
  }
944
- function LinkPopoverBody({ initial, onSave, onDetach, onCancel, hideOptions, types }) {
861
+ function LinkPopoverBody({ initial, onSave, onDetach, onCancel, hideOptions, hideNewTab, types, dirty = false }) {
945
862
  const start = normLink(initial);
946
863
  const [v, setV] = React.useState(start);
947
864
  const { targets } = useLinkTargets();
@@ -950,7 +867,7 @@ function LinkPopoverBody({ initial, onSave, onDetach, onCancel, hideOptions, typ
950
867
  const f = finalizeLink(x);
951
868
  return f ? JSON.stringify(storedLink(f)) : "";
952
869
  };
953
- const changed = fin(v) !== fin(start);
870
+ const changed = dirty || fin(v) !== fin(start);
954
871
  const ok = hasLink(v) && !linkProblem(v);
955
872
  const apply = (n = v) => {
956
873
  const out = finalizeLink(n);
@@ -985,6 +902,7 @@ function LinkPopoverBody({ initial, onSave, onDetach, onCancel, hideOptions, typ
985
902
  onChange: setV,
986
903
  onEnter: (n) => apply(n),
987
904
  hideOptions,
905
+ hideNewTab,
988
906
  types,
989
907
  autoFocus: true
990
908
  }),