@emdash-cms/admin 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/{LocaleDirectionProvider-DO7M3Tgi.js → LocaleDirectionProvider-CI7U6BBr.js} +50 -11
  2. package/dist/LocaleDirectionProvider-CI7U6BBr.js.map +1 -0
  3. package/dist/{config-Jgetw4hr.d.ts → config-D8i8U4bV.d.ts} +1 -1
  4. package/dist/{config-Jgetw4hr.d.ts.map → config-D8i8U4bV.d.ts.map} +1 -1
  5. package/dist/index.d.ts +16 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +989 -634
  8. package/dist/index.js.map +1 -1
  9. package/dist/locales/ar/messages.mjs +1 -1
  10. package/dist/locales/de/messages.mjs +1 -1
  11. package/dist/locales/en/messages.mjs +1 -1
  12. package/dist/locales/es-419/messages.mjs +1 -0
  13. package/dist/locales/eu/messages.mjs +1 -1
  14. package/dist/locales/fa/messages.mjs +1 -0
  15. package/dist/locales/fr/messages.mjs +1 -1
  16. package/dist/locales/index.d.ts +1 -1
  17. package/dist/locales/index.js +1 -1
  18. package/dist/locales/ja/messages.mjs +1 -1
  19. package/dist/locales/ko/messages.mjs +1 -0
  20. package/dist/locales/pseudo/messages.mjs +1 -1
  21. package/dist/locales/pt-BR/messages.mjs +1 -1
  22. package/dist/locales/zh-CN/messages.mjs +1 -1
  23. package/dist/locales/zh-TW/messages.mjs +1 -0
  24. package/dist/messages-57qx1FXa.js +6 -0
  25. package/dist/messages-57qx1FXa.js.map +1 -0
  26. package/dist/messages-8uPA5VDB.js +6 -0
  27. package/dist/messages-8uPA5VDB.js.map +1 -0
  28. package/dist/messages-Bc3iE3Xx.js +6 -0
  29. package/dist/messages-Bc3iE3Xx.js.map +1 -0
  30. package/dist/messages-BudiTpRZ.js +6 -0
  31. package/dist/messages-BudiTpRZ.js.map +1 -0
  32. package/dist/messages-CLJeZfc0.js +6 -0
  33. package/dist/messages-CLJeZfc0.js.map +1 -0
  34. package/dist/messages-CXyBDum7.js +6 -0
  35. package/dist/messages-CXyBDum7.js.map +1 -0
  36. package/dist/messages-DFXk1gAB.js +6 -0
  37. package/dist/messages-DFXk1gAB.js.map +1 -0
  38. package/dist/messages-DHg9t0ML.js +6 -0
  39. package/dist/messages-DHg9t0ML.js.map +1 -0
  40. package/dist/messages-DT-_3Gqh.js +6 -0
  41. package/dist/messages-DT-_3Gqh.js.map +1 -0
  42. package/dist/messages-DYWnQ-qc.js +6 -0
  43. package/dist/messages-DYWnQ-qc.js.map +1 -0
  44. package/dist/messages-DrHBJ5Tm.js +6 -0
  45. package/dist/messages-DrHBJ5Tm.js.map +1 -0
  46. package/dist/messages-TukFV9EF.js +6 -0
  47. package/dist/messages-TukFV9EF.js.map +1 -0
  48. package/dist/messages-cadUq4Pc.js +6 -0
  49. package/dist/messages-cadUq4Pc.js.map +1 -0
  50. package/dist/plugins-XhZqfegd.js.map +1 -1
  51. package/dist/styles.css +1 -1
  52. package/package.json +2 -2
  53. package/dist/LocaleDirectionProvider-DO7M3Tgi.js.map +0 -1
  54. package/dist/messages-03AQQSlE.js +0 -6
  55. package/dist/messages-03AQQSlE.js.map +0 -1
  56. package/dist/messages-BMkWfYDe.js +0 -6
  57. package/dist/messages-BMkWfYDe.js.map +0 -1
  58. package/dist/messages-CsGdD1lJ.js +0 -6
  59. package/dist/messages-CsGdD1lJ.js.map +0 -1
  60. package/dist/messages-CwBBghBM.js +0 -6
  61. package/dist/messages-CwBBghBM.js.map +0 -1
  62. package/dist/messages-CxEI1suK.js +0 -6
  63. package/dist/messages-CxEI1suK.js.map +0 -1
  64. package/dist/messages-D70eWqXP.js +0 -6
  65. package/dist/messages-D70eWqXP.js.map +0 -1
  66. package/dist/messages-DKQntaHs.js +0 -6
  67. package/dist/messages-DKQntaHs.js.map +0 -1
  68. package/dist/messages-DgIBjYba.js +0 -6
  69. package/dist/messages-DgIBjYba.js.map +0 -1
  70. package/dist/messages-DhLA1X_1.js +0 -6
  71. package/dist/messages-DhLA1X_1.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { c as fetchManifest, i as fetchPlugins, l as parseApiResponse, n as enablePlugin, o as API_BASE, r as fetchPlugin, s as apiFetch, t as disablePlugin, u as throwResponseError } from "./plugins-XhZqfegd.js";
2
- import { a as SUPPORTED_LOCALES, i as DEFAULT_LOCALE, l as resolveLocale, n as useLocale, o as SUPPORTED_LOCALE_CODES, t as LocaleDirectionProvider } from "./LocaleDirectionProvider-DO7M3Tgi.js";
2
+ import { a as SUPPORTED_LOCALES, i as DEFAULT_LOCALE, l as resolveLocale, n as useLocale, o as SUPPORTED_LOCALE_CODES, t as LocaleDirectionProvider } from "./LocaleDirectionProvider-CI7U6BBr.js";
3
3
  import "./locales/index.js";
4
4
  import { Badge, Button, Checkbox, CommandPalette, Dialog, Input, InputArea, Label, LinkButton, Loader, Popover, Select, Sidebar as KumoSidebar, Switch, Tabs, Toast, Toasty, Tooltip, buttonVariants, useSidebar } from "@cloudflare/kumo";
5
5
  import { i18n } from "@lingui/core";
@@ -9,6 +9,7 @@ import { Link, Link as Link$1, Outlet, RouterProvider, createRootRouteWithContex
9
9
  import * as React from "react";
10
10
  import { createContext, useCallback, useContext, useEffect, useState } from "react";
11
11
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ import { Dialog as Dialog$1 } from "@cloudflare/kumo/primitives";
12
13
  import { ArrowCounterClockwise, ArrowLeft, ArrowRight, ArrowSquareOut, ArrowUUpLeft, ArrowUUpRight, ArrowsClockwise, ArrowsInSimple, ArrowsLeftRight, ArrowsOutSimple, BracketsCurly, Calendar, CalendarBlank, CaretDown, CaretLeft, CaretRight, CaretUp, ChatCircle, Check, CheckCircle, CircleDashed, CircleNotch, ClockCounterClockwise, Cloud, Code, CodeBlock, Copy, Cube, Database, DeviceMobile, DotsSixVertical, DownloadSimple, Envelope, EnvelopeSimple, Eye, EyeSlash, File, FileArrowDown, FileText, FloppyDisk, FolderOpen, Gear, GithubLogo, Globe, GlobeSimple, GridFour, HardDrive, Hash, Image as Image$1, ImageSquare, Info, Key, Link as Link$2, LinkBreak, LinkSimple, List, ListBullets, ListChecks, ListNumbers, MagnifyingGlass, Minus, Monitor, Moon, Palette, PaperPlaneTilt, Paragraph, Pencil, PencilSimple, PlugsConnected, Plus, Prohibit, PuzzlePiece, Quotes, Rows, Ruler, ShareNetwork, Shield, ShieldCheck, ShieldWarning, SignOut, SlidersHorizontal, Sparkle, SquaresFour, Stack, Storefront, Sun, TextAlignCenter, TextAlignLeft, TextAlignRight, TextB, TextHOne, TextHThree, TextHTwo, TextItalic, TextStrikethrough, TextT, TextUnderline, ToggleLeft, Trash, Upload, User, UserCircle, UserPlus, Users, Warning, WarningCircle, WebhooksLogo, X, YoutubeLogo } from "@phosphor-icons/react";
13
14
  import { clsx } from "clsx";
14
15
  import { twMerge } from "tailwind-merge";
@@ -290,7 +291,7 @@ function CommentDetail({ comment, onClose, onStatusChange, onDelete, isAdmin, is
290
291
  onClick: onClose,
291
292
  "aria-hidden": "true"
292
293
  }), /* @__PURE__ */ jsxs("div", {
293
- className: "fixed inset-y-0 right-0 z-50 w-full max-w-lg overflow-y-auto bg-kumo-base border-l shadow-lg",
294
+ className: "fixed inset-y-0 end-0 z-50 w-full max-w-lg overflow-y-auto bg-kumo-base border-s shadow-lg",
294
295
  children: [
295
296
  /* @__PURE__ */ jsxs("div", {
296
297
  className: "flex items-center justify-between border-b px-6 py-4",
@@ -614,7 +615,7 @@ function CommentInbox({ comments, counts, isLoading, nextCursor, collections, ac
614
615
  className: "flex items-center gap-3 flex-wrap",
615
616
  children: [/* @__PURE__ */ jsxs("div", {
616
617
  className: "relative max-w-xs flex-1 min-w-[200px]",
617
- children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
618
+ children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute start-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
618
619
  type: "search",
619
620
  placeholder: _t({
620
621
  id: "egS4fF",
@@ -626,7 +627,7 @@ function CommentInbox({ comments, counts, isLoading, nextCursor, collections, ac
626
627
  }),
627
628
  value: searchQuery,
628
629
  onChange: (e) => onSearchChange(e.target.value),
629
- className: "pl-9"
630
+ className: "ps-9"
630
631
  })]
631
632
  }), Object.keys(collections).length > 1 && /* @__PURE__ */ jsx("div", {
632
633
  className: "w-48",
@@ -706,7 +707,7 @@ function CommentInbox({ comments, counts, isLoading, nextCursor, collections, ac
706
707
  values: { 0: selected.size }
707
708
  })
708
709
  }), /* @__PURE__ */ jsxs("div", {
709
- className: "flex gap-2 ml-auto",
710
+ className: "flex gap-2 ms-auto",
710
711
  children: [
711
712
  activeStatus !== "approved" && /* @__PURE__ */ jsx(Button, {
712
713
  size: "sm",
@@ -771,7 +772,7 @@ function CommentInbox({ comments, counts, isLoading, nextCursor, collections, ac
771
772
  }),
772
773
  /* @__PURE__ */ jsx("th", {
773
774
  scope: "col",
774
- className: "px-4 py-3 text-left text-sm font-medium",
775
+ className: "px-4 py-3 text-start text-sm font-medium",
775
776
  children: _t({
776
777
  id: "VbeIOx",
777
778
  message: "Author"
@@ -779,7 +780,7 @@ function CommentInbox({ comments, counts, isLoading, nextCursor, collections, ac
779
780
  }),
780
781
  /* @__PURE__ */ jsx("th", {
781
782
  scope: "col",
782
- className: "px-4 py-3 text-left text-sm font-medium",
783
+ className: "px-4 py-3 text-start text-sm font-medium",
783
784
  children: _t({
784
785
  id: "NBdIgR",
785
786
  message: "Comment"
@@ -787,7 +788,7 @@ function CommentInbox({ comments, counts, isLoading, nextCursor, collections, ac
787
788
  }),
788
789
  /* @__PURE__ */ jsx("th", {
789
790
  scope: "col",
790
- className: "px-4 py-3 text-left text-sm font-medium",
791
+ className: "px-4 py-3 text-start text-sm font-medium",
791
792
  children: _t({
792
793
  id: "4b3oEV",
793
794
  message: "Content"
@@ -795,7 +796,7 @@ function CommentInbox({ comments, counts, isLoading, nextCursor, collections, ac
795
796
  }),
796
797
  /* @__PURE__ */ jsx("th", {
797
798
  scope: "col",
798
- className: "px-4 py-3 text-left text-sm font-medium",
799
+ className: "px-4 py-3 text-start text-sm font-medium",
799
800
  children: _t({
800
801
  id: "mYGY3B",
801
802
  message: "Date"
@@ -803,7 +804,7 @@ function CommentInbox({ comments, counts, isLoading, nextCursor, collections, ac
803
804
  }),
804
805
  /* @__PURE__ */ jsx("th", {
805
806
  scope: "col",
806
- className: "px-4 py-3 text-right text-sm font-medium",
807
+ className: "px-4 py-3 text-end text-sm font-medium",
807
808
  children: _t({
808
809
  id: "7L01XJ",
809
810
  message: "Actions"
@@ -961,7 +962,7 @@ function CommentRow({ comment, isSelected, onToggle, onRowClick, onStatusChange,
961
962
  children: /* @__PURE__ */ jsxs("button", {
962
963
  type: "button",
963
964
  onClick: onRowClick,
964
- className: "text-left",
965
+ className: "text-start",
965
966
  children: [/* @__PURE__ */ jsx("div", {
966
967
  className: "font-medium text-sm",
967
968
  children: comment.authorName
@@ -976,7 +977,7 @@ function CommentRow({ comment, isSelected, onToggle, onRowClick, onStatusChange,
976
977
  children: /* @__PURE__ */ jsx("button", {
977
978
  type: "button",
978
979
  onClick: onRowClick,
979
- className: "text-left text-sm text-kumo-subtle hover:text-kumo-default line-clamp-2",
980
+ className: "text-start text-sm text-kumo-subtle hover:text-kumo-default line-clamp-2",
980
981
  children: excerpt
981
982
  })
982
983
  }),
@@ -995,7 +996,7 @@ function CommentRow({ comment, isSelected, onToggle, onRowClick, onStatusChange,
995
996
  children: date.toLocaleDateString()
996
997
  }),
997
998
  /* @__PURE__ */ jsx("td", {
998
- className: "px-4 py-3 text-right",
999
+ className: "px-4 py-3 text-end",
999
1000
  children: /* @__PURE__ */ jsxs("div", {
1000
1001
  className: "flex items-center justify-end gap-1",
1001
1002
  children: [
@@ -2746,10 +2747,10 @@ function BlockKitFieldElement({ element, value, onChange }) {
2746
2747
  */
2747
2748
  function getIndentClass(level) {
2748
2749
  switch (level) {
2749
- case 1: return "pl-0";
2750
- case 2: return "pl-4";
2751
- case 3: return "pl-8";
2752
- default: return "pl-0";
2750
+ case 1: return "ps-0";
2751
+ case 2: return "ps-4";
2752
+ case 3: return "ps-8";
2753
+ default: return "ps-0";
2753
2754
  }
2754
2755
  }
2755
2756
  function getTextClass(level) {
@@ -2859,7 +2860,7 @@ function DocumentOutline({ editor, className }) {
2859
2860
  return /* @__PURE__ */ jsx("button", {
2860
2861
  type: "button",
2861
2862
  onClick: () => handleHeadingClick(heading),
2862
- className: cn("w-full text-left px-2 py-1 text-sm rounded transition-colors", "hover:bg-kumo-tint/50 cursor-pointer", "truncate", getIndentClass(heading.level), getTextClass(heading.level), isCurrent && "bg-kumo-tint text-kumo-default"),
2863
+ className: cn("w-full text-start px-2 py-1 text-sm rounded transition-colors", "hover:bg-kumo-tint/50 cursor-pointer", "truncate", getIndentClass(heading.level), getTextClass(heading.level), isCurrent && "bg-kumo-tint text-kumo-default"),
2863
2864
  title: heading.text,
2864
2865
  children: heading.text
2865
2866
  }, heading.key);
@@ -2938,7 +2939,15 @@ function RepeaterField({ label, id, value, onChange, subFields, minItems = 0, ma
2938
2939
  const [items, setItems] = React.useState(() => ensureKeys(rawItems));
2939
2940
  const [collapsedItems, setCollapsedItems] = React.useState(/* @__PURE__ */ new Set());
2940
2941
  React.useEffect(() => {
2941
- setItems(ensureKeys(Array.isArray(value) ? value : []));
2942
+ const incoming = Array.isArray(value) ? value : [];
2943
+ setItems((prev) => incoming.map((item, i) => {
2944
+ const obj = typeof item === "object" && item !== null ? item : {};
2945
+ const existingKey = obj._key || prev[i]?._key;
2946
+ return {
2947
+ ...obj,
2948
+ _key: existingKey || `item-${i}-${Date.now()}`
2949
+ };
2950
+ }));
2942
2951
  }, [value]);
2943
2952
  const emitChange = (updated) => {
2944
2953
  setItems(updated);
@@ -2986,7 +2995,7 @@ function RepeaterField({ label, id, value, onChange, subFields, minItems = 0, ma
2986
2995
  htmlFor: id,
2987
2996
  className: "text-sm font-medium",
2988
2997
  children: [label, items.length > 0 && /* @__PURE__ */ jsx("span", {
2989
- className: "ml-2 text-kumo-subtle font-normal",
2998
+ className: "ms-2 text-kumo-subtle font-normal",
2990
2999
  children: i18n._({
2991
3000
  id: "JcH6Wc",
2992
3001
  message: "{0, plural, one {(# item)} other {(# items)}}",
@@ -3537,7 +3546,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
3537
3546
  id: "yz7wBu",
3538
3547
  message: "Close"
3539
3548
  }),
3540
- className: "absolute right-4 top-4",
3549
+ className: "absolute end-4 top-4",
3541
3550
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
3542
3551
  className: "sr-only",
3543
3552
  children: _t({
@@ -3559,7 +3568,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
3559
3568
  className: "flex gap-2 mt-1.5",
3560
3569
  children: [/* @__PURE__ */ jsxs("div", {
3561
3570
  className: "flex-1 relative",
3562
- children: [/* @__PURE__ */ jsx(Globe, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
3571
+ children: [/* @__PURE__ */ jsx(Globe, { className: "absolute start-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
3563
3572
  type: "url",
3564
3573
  placeholder: "https://example.com/image.jpg",
3565
3574
  "aria-label": _t({
@@ -3572,7 +3581,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
3572
3581
  setUrlError(null);
3573
3582
  },
3574
3583
  onKeyDown: handleUrlKeyDown,
3575
- className: "pl-9"
3584
+ className: "ps-9"
3576
3585
  })]
3577
3586
  }), /* @__PURE__ */ jsx(Button, {
3578
3587
  onClick: handleUrlSubmit,
@@ -3630,7 +3639,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
3630
3639
  className: "flex items-center justify-between pb-3 gap-4",
3631
3640
  children: [canSearch ? /* @__PURE__ */ jsxs("div", {
3632
3641
  className: "relative flex-1 max-w-xs",
3633
- children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
3642
+ children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute start-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
3634
3643
  type: "search",
3635
3644
  placeholder: _t({
3636
3645
  id: "YIix5Y",
@@ -3642,7 +3651,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
3642
3651
  }),
3643
3652
  value: searchQuery,
3644
3653
  onChange: (e) => setSearchQuery(e.target.value),
3645
- className: "pl-9"
3654
+ className: "ps-9"
3646
3655
  })]
3647
3656
  }) : /* @__PURE__ */ jsx("p", {
3648
3657
  className: "text-sm text-kumo-subtle",
@@ -3782,7 +3791,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
3782
3791
  " ",
3783
3792
  /* @__PURE__ */ jsx("strong", { children: selectedItem.item.filename }),
3784
3793
  selectedItem.providerId !== "local" && /* @__PURE__ */ jsx("span", {
3785
- className: "ml-2 text-xs",
3794
+ className: "ms-2 text-xs",
3786
3795
  children: _t({
3787
3796
  id: "qjriNt",
3788
3797
  message: "(from {0})",
@@ -3869,7 +3878,7 @@ function MediaPickerItem({ item, selected, onClick, onDoubleClick, onDimensionsD
3869
3878
  })
3870
3879
  }),
3871
3880
  /* @__PURE__ */ jsx("div", {
3872
- className: "absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/60 to-transparent p-2",
3881
+ className: "absolute bottom-0 start-0 end-0 bg-gradient-to-t from-black/60 to-transparent p-2",
3873
3882
  "aria-hidden": "true",
3874
3883
  children: /* @__PURE__ */ jsx("p", {
3875
3884
  className: "text-xs text-white truncate",
@@ -3932,7 +3941,7 @@ function ProviderMediaItem({ item, selected, onClick, onDoubleClick, onDimension
3932
3941
  })
3933
3942
  }),
3934
3943
  /* @__PURE__ */ jsx("div", {
3935
- className: "absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/60 to-transparent p-2",
3944
+ className: "absolute bottom-0 start-0 end-0 bg-gradient-to-t from-black/60 to-transparent p-2",
3936
3945
  "aria-hidden": "true",
3937
3946
  children: /* @__PURE__ */ jsx("p", {
3938
3947
  className: "text-xs text-white truncate",
@@ -4069,7 +4078,7 @@ function ImageDetailPanel({ attributes, onUpdate, onReplace, onDelete, onClose,
4069
4078
  })
4070
4079
  })] });
4071
4080
  if (inline) return /* @__PURE__ */ jsxs("div", {
4072
- className: "rounded-lg border bg-kumo-base flex flex-col animate-in fade-in duration-200",
4081
+ className: "rounded-lg border bg-kumo-base flex flex-col",
4073
4082
  children: [
4074
4083
  /* @__PURE__ */ jsxs("div", {
4075
4084
  className: "flex items-center justify-between p-4 border-b",
@@ -4320,7 +4329,7 @@ function ImageDetailPanel({ attributes, onUpdate, onReplace, onDelete, onClose,
4320
4329
  ]
4321
4330
  });
4322
4331
  return /* @__PURE__ */ jsxs("div", {
4323
- className: "fixed inset-y-0 right-0 w-96 bg-kumo-base border-l shadow-xl z-50 flex flex-col animate-in slide-in-from-right duration-200",
4332
+ className: "fixed inset-y-0 end-0 w-96 bg-kumo-base border-s shadow-xl z-50 flex flex-col",
4324
4333
  children: [
4325
4334
  /* @__PURE__ */ jsxs("div", {
4326
4335
  className: "flex items-center justify-between border-b p-4",
@@ -5051,14 +5060,14 @@ function BlockMenu({ editor, anchorElement, isOpen, onClose }) {
5051
5060
  children: [
5052
5061
  /* @__PURE__ */ jsxs("button", {
5053
5062
  type: "button",
5054
- className: "flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-kumo-tint text-left",
5063
+ className: "flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-kumo-tint text-start",
5055
5064
  onClick: () => setShowTransforms(false),
5056
5065
  children: [/* @__PURE__ */ jsx(CaretRight, { className: "h-4 w-4 rotate-180" }), /* @__PURE__ */ jsx("span", { children: "Back" })]
5057
5066
  }),
5058
5067
  /* @__PURE__ */ jsx("div", { className: "h-px bg-kumo-line my-1" }),
5059
5068
  blockTransforms.map((transform) => /* @__PURE__ */ jsxs("button", {
5060
5069
  type: "button",
5061
- className: "flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-kumo-tint text-left",
5070
+ className: "flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-kumo-tint text-start",
5062
5071
  onClick: () => handleTransform(transform),
5063
5072
  children: [/* @__PURE__ */ jsx(transform.icon, { className: "h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx("span", { children: _t(transform.label) })]
5064
5073
  }, transform.id))
@@ -5068,7 +5077,7 @@ function BlockMenu({ editor, anchorElement, isOpen, onClose }) {
5068
5077
  children: [
5069
5078
  /* @__PURE__ */ jsxs("button", {
5070
5079
  type: "button",
5071
- className: "flex items-center justify-between w-full px-3 py-2 text-sm hover:bg-kumo-tint text-left",
5080
+ className: "flex items-center justify-between w-full px-3 py-2 text-sm hover:bg-kumo-tint text-start",
5072
5081
  onClick: () => setShowTransforms(true),
5073
5082
  children: [/* @__PURE__ */ jsxs("span", {
5074
5083
  className: "flex items-center gap-2",
@@ -5077,14 +5086,14 @@ function BlockMenu({ editor, anchorElement, isOpen, onClose }) {
5077
5086
  }),
5078
5087
  /* @__PURE__ */ jsxs("button", {
5079
5088
  type: "button",
5080
- className: "flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-kumo-tint text-left",
5089
+ className: "flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-kumo-tint text-start",
5081
5090
  onClick: handleDuplicate,
5082
5091
  children: [/* @__PURE__ */ jsx(Copy, { className: "h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx("span", { children: "Duplicate" })]
5083
5092
  }),
5084
5093
  /* @__PURE__ */ jsx("div", { className: "h-px bg-kumo-line my-1" }),
5085
5094
  /* @__PURE__ */ jsxs("button", {
5086
5095
  type: "button",
5087
- className: "flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-kumo-tint text-left text-kumo-danger",
5096
+ className: "flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-kumo-tint text-start text-kumo-danger",
5088
5097
  onClick: handleDelete,
5089
5098
  children: [/* @__PURE__ */ jsx(Trash, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", { children: "Delete" })]
5090
5099
  })
@@ -5248,7 +5257,7 @@ function ImageNodeView({ node, updateAttributes, selected, deleteNode, editor })
5248
5257
  draggable: false
5249
5258
  }),
5250
5259
  selected && /* @__PURE__ */ jsxs("div", {
5251
- className: "absolute top-2 right-2 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity",
5260
+ className: "absolute top-2 end-2 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity",
5252
5261
  children: [
5253
5262
  /* @__PURE__ */ jsx(Button, {
5254
5263
  type: "button",
@@ -5286,7 +5295,7 @@ function ImageNodeView({ node, updateAttributes, selected, deleteNode, editor })
5286
5295
  ]
5287
5296
  }),
5288
5297
  isEditingAlt && /* @__PURE__ */ jsxs("div", {
5289
- className: "absolute bottom-0 left-0 right-0 bg-kumo-base/95 backdrop-blur p-3 rounded-b-lg border-t",
5298
+ className: "absolute bottom-0 start-0 end-0 bg-kumo-base/95 backdrop-blur p-3 rounded-b-lg border-t",
5290
5299
  children: [/* @__PURE__ */ jsx("label", {
5291
5300
  className: "text-xs font-medium text-kumo-subtle mb-1 block",
5292
5301
  children: "Alt text"
@@ -5589,7 +5598,7 @@ function PluginBlockNodeView({ node, updateAttributes, selected, deleteNode, edi
5589
5598
  children: /* @__PURE__ */ jsxs("div", {
5590
5599
  className: "relative group",
5591
5600
  children: [/* @__PURE__ */ jsx("div", {
5592
- className: cn("absolute -left-8 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity cursor-grab active:cursor-grabbing", selected && "opacity-100"),
5601
+ className: cn("absolute -start-8 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity cursor-grab active:cursor-grabbing", selected && "opacity-100"),
5593
5602
  "data-drag-handle": true,
5594
5603
  children: /* @__PURE__ */ jsx(DotsSixVertical, { className: "h-5 w-5 text-kumo-subtle/50" })
5595
5604
  }), /* @__PURE__ */ jsxs("div", {
@@ -5816,7 +5825,7 @@ function SectionPickerModal({ open, onOpenChange, onSelect }) {
5816
5825
  id: "yz7wBu",
5817
5826
  message: "Close"
5818
5827
  }),
5819
- className: "absolute right-4 top-4",
5828
+ className: "absolute end-4 top-4",
5820
5829
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
5821
5830
  className: "sr-only",
5822
5831
  children: _t({
@@ -5831,14 +5840,14 @@ function SectionPickerModal({ open, onOpenChange, onSelect }) {
5831
5840
  className: "flex items-center gap-4 py-4 border-b",
5832
5841
  children: /* @__PURE__ */ jsxs("div", {
5833
5842
  className: "relative flex-1",
5834
- children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
5843
+ children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute start-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
5835
5844
  placeholder: _t({
5836
5845
  id: "qPx4oA",
5837
5846
  message: "Search sections..."
5838
5847
  }),
5839
5848
  value: searchQuery,
5840
5849
  onChange: (e) => setSearchQuery(e.target.value),
5841
- className: "pl-10",
5850
+ className: "ps-10",
5842
5851
  autoFocus: true
5843
5852
  })]
5844
5853
  })
@@ -5916,7 +5925,7 @@ function SectionCard$1({ section, onSelect }) {
5916
5925
  return /* @__PURE__ */ jsxs("button", {
5917
5926
  type: "button",
5918
5927
  onClick: onSelect,
5919
- className: cn("text-left rounded-lg border bg-kumo-base overflow-hidden transition-colors", "hover:border-kumo-brand hover:bg-kumo-tint/50", "focus:outline-none focus:ring-2 focus:ring-kumo-ring focus:ring-offset-2"),
5928
+ className: cn("text-start rounded-lg border bg-kumo-base overflow-hidden transition-colors", "hover:border-kumo-brand hover:bg-kumo-tint/50", "focus:outline-none focus:ring-2 focus:ring-kumo-ring focus:ring-offset-2"),
5920
5929
  children: [/* @__PURE__ */ jsx("div", {
5921
5930
  className: "aspect-video bg-kumo-tint flex items-center justify-center",
5922
5931
  children: section.previewUrl ? /* @__PURE__ */ jsx("img", {
@@ -6613,7 +6622,7 @@ function SlashCommandMenu({ state, onCommand, onClose: _onClose, setSelectedInde
6613
6622
  }) : state.items.map((item, index) => /* @__PURE__ */ jsxs("button", {
6614
6623
  type: "button",
6615
6624
  "data-index": index,
6616
- className: cn("flex items-center gap-3 w-full px-3 py-2 text-sm rounded text-left", index === state.selectedIndex ? "bg-kumo-tint text-kumo-default" : "hover:bg-kumo-tint/50"),
6625
+ className: cn("flex items-center gap-3 w-full px-3 py-2 text-sm rounded text-start", index === state.selectedIndex ? "bg-kumo-tint text-kumo-default" : "hover:bg-kumo-tint/50"),
6617
6626
  onClick: () => onCommand(item),
6618
6627
  onMouseEnter: () => setSelectedIndex(index),
6619
6628
  children: [/* @__PURE__ */ jsx(item.icon, { className: "h-4 w-4 text-kumo-subtle flex-shrink-0" }), /* @__PURE__ */ jsxs("div", {
@@ -6683,7 +6692,7 @@ function PluginBlockModal({ block, initialValues, onClose, onInsert }) {
6683
6692
  variant: "ghost",
6684
6693
  shape: "square",
6685
6694
  "aria-label": "Close",
6686
- className: "absolute right-4 top-4",
6695
+ className: "absolute end-4 top-4",
6687
6696
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
6688
6697
  className: "sr-only",
6689
6698
  children: "Close"
@@ -7605,7 +7614,7 @@ function EditorToolbar({ editor, focusMode, onFocusModeChange }) {
7605
7614
  "aria-hidden": "true"
7606
7615
  })
7607
7616
  }), showLinkPopover && /* @__PURE__ */ jsx("div", {
7608
- className: "absolute top-full left-0 mt-1 z-50 rounded-md border bg-kumo-overlay p-3 shadow-lg",
7617
+ className: "absolute top-full start-0 mt-1 z-50 rounded-md border bg-kumo-overlay p-3 shadow-lg",
7609
7618
  children: /* @__PURE__ */ jsxs("div", {
7610
7619
  className: "flex flex-col gap-2",
7611
7620
  children: [
@@ -7870,7 +7879,7 @@ function RevisionHistory({ collection, entryId, onRestored }) {
7870
7879
  children: [/* @__PURE__ */ jsxs("button", {
7871
7880
  type: "button",
7872
7881
  onClick: () => setIsExpanded(!isExpanded),
7873
- className: "flex w-full items-center justify-between p-4 text-left hover:bg-kumo-tint/50 transition-colors",
7882
+ className: "flex w-full items-center justify-between p-4 text-start hover:bg-kumo-tint/50 transition-colors",
7874
7883
  children: [/* @__PURE__ */ jsxs("div", {
7875
7884
  className: "flex items-center gap-2",
7876
7885
  children: [
@@ -7962,7 +7971,7 @@ function RevisionItem({ revision, compareRevision, isLatest, isRestoring, isSele
7962
7971
  children: [/* @__PURE__ */ jsxs("button", {
7963
7972
  type: "button",
7964
7973
  onClick: onSelect,
7965
- className: "flex-1 text-left",
7974
+ className: "flex-1 text-start",
7966
7975
  children: [/* @__PURE__ */ jsxs("div", {
7967
7976
  className: "flex items-center gap-2",
7968
7977
  children: [/* @__PURE__ */ jsx("span", {
@@ -8210,7 +8219,7 @@ function SeoImageField({ seo, onChange }) {
8210
8219
  alt: "",
8211
8220
  className: "max-h-48 rounded-lg border object-cover"
8212
8221
  }), /* @__PURE__ */ jsxs("div", {
8213
- className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity flex gap-1",
8222
+ className: "absolute top-2 end-2 opacity-0 group-hover:opacity-100 transition-opacity flex gap-1",
8214
8223
  children: [/* @__PURE__ */ jsx(Button, {
8215
8224
  type: "button",
8216
8225
  size: "sm",
@@ -8454,6 +8463,65 @@ function SeoPanel({ contentKey, seo, onChange }) {
8454
8463
  });
8455
8464
  }
8456
8465
 
8466
+ //#endregion
8467
+ //#region src/lib/taxonomy-match.ts
8468
+ /**
8469
+ * Taxonomy term matching for the admin picker.
8470
+ *
8471
+ * The picker filters an editor's typed input against existing terms. A naive
8472
+ * `label.toLowerCase().includes(input.toLowerCase())` fails the accent case:
8473
+ * typing `"Mexico"` does not substring-match a term labeled `"México"`
8474
+ * because `"méxico".toLowerCase()` is still `"méxico"` and
8475
+ * `"méxico".includes("mexico")` is `false`. The editor then sees zero
8476
+ * suggestions and creates a duplicate `"Mexico"` term alongside the
8477
+ * canonical `"México"`, splitting the taxonomy.
8478
+ *
8479
+ * This module folds diacritics via NFD decomposition before substring
8480
+ * matching. No regexes are compiled from user input, so there is no ReDoS
8481
+ * surface.
8482
+ */
8483
+ const DIACRITIC_RANGE = /[\u0300-\u036f]/g;
8484
+ /**
8485
+ * Case-fold + diacritic-fold normalization for substring matching.
8486
+ *
8487
+ * `"México"`, `"mexico"`, `"MÉXICO"` all collapse to `"mexico"`.
8488
+ *
8489
+ * NFD decomposes accented characters into a base + combining-diacritic
8490
+ * sequence; the regex drops the combiners. Greek tonos, Vietnamese
8491
+ * stacked diacritics, and other Latin-adjacent scripts are covered.
8492
+ * Combining marks used meaningfully in non-Latin scripts (Arabic harakat
8493
+ * U+064B–U+0652, Japanese dakuten U+3099) fall outside the U+0300–036F
8494
+ * block and are left untouched — stripping them would change meaning.
8495
+ */
8496
+ function foldForMatch(value) {
8497
+ return value.normalize("NFD").replace(DIACRITIC_RANGE, "").toLowerCase();
8498
+ }
8499
+ /**
8500
+ * True if `input` is a substring of the term's label, ignoring case and
8501
+ * diacritics.
8502
+ *
8503
+ * Empty or whitespace-only input returns `false` — the caller decides
8504
+ * whether to show all terms or none in that state. The whitespace guard
8505
+ * matters: without it, a needle of `" "` would `.includes()`-match
8506
+ * every term whose label contains a space.
8507
+ */
8508
+ function termMatches(term, input) {
8509
+ const needle = foldForMatch(input).trim();
8510
+ if (!needle) return false;
8511
+ return foldForMatch(term.label).includes(needle);
8512
+ }
8513
+ /**
8514
+ * True if `input` is an exact (fold-equal) match for the term's label.
8515
+ * Used to decide whether to show the "Create new term" button — if an
8516
+ * editor types `"Mexico"` and a term labeled `"México"` already exists,
8517
+ * Create must not appear or they'll produce a duplicate.
8518
+ */
8519
+ function termExactMatches(term, input) {
8520
+ const needle = foldForMatch(input).trim();
8521
+ if (!needle) return false;
8522
+ return foldForMatch(term.label).trim() === needle;
8523
+ }
8524
+
8457
8525
  //#endregion
8458
8526
  //#region src/components/TaxonomySidebar.tsx
8459
8527
  /**
@@ -8504,7 +8572,7 @@ function CategoryCheckboxTree({ term, level = 0, selectedIds, onToggle }) {
8504
8572
  type: "checkbox",
8505
8573
  checked: isChecked,
8506
8574
  onChange: () => onToggle(term.id),
8507
- className: "mr-2"
8575
+ className: "me-2"
8508
8576
  }), /* @__PURE__ */ jsx("span", {
8509
8577
  className: "text-sm",
8510
8578
  children: term.label
@@ -8519,22 +8587,40 @@ function CategoryCheckboxTree({ term, level = 0, selectedIds, onToggle }) {
8519
8587
  /**
8520
8588
  * Tag input for flat taxonomies
8521
8589
  */
8522
- function TagInput({ terms, selectedIds, onAdd, onRemove, label }) {
8590
+ function TagInput({ terms, selectedIds, onAdd, onRemove, onCreate, isCreating, label }) {
8523
8591
  const { _: _t } = useLingui();
8524
8592
  const [input, setInput] = React.useState("");
8525
8593
  const selectedTerms = terms.filter((term) => selectedIds.has(term.id));
8594
+ const trimmedInput = input.trim();
8526
8595
  const suggestions = React.useMemo(() => {
8527
- if (!input) return [];
8528
- return terms.filter((term) => term.label.toLowerCase().includes(input.toLowerCase()) && !selectedIds.has(term.id)).slice(0, 5);
8596
+ if (!trimmedInput) return [];
8597
+ return terms.filter((term) => !selectedIds.has(term.id) && termMatches(term, trimmedInput)).slice(0, 5);
8529
8598
  }, [
8530
- input,
8599
+ trimmedInput,
8531
8600
  terms,
8532
8601
  selectedIds
8533
8602
  ]);
8603
+ const hasExactMatch = React.useMemo(() => {
8604
+ if (!trimmedInput) return false;
8605
+ return terms.some((term) => termExactMatches(term, trimmedInput));
8606
+ }, [trimmedInput, terms]);
8607
+ const showCreateOption = trimmedInput.length > 0 && !hasExactMatch;
8534
8608
  const handleSelect = (term) => {
8535
8609
  onAdd(term.id);
8536
8610
  setInput("");
8537
8611
  };
8612
+ const handleCreate = () => {
8613
+ if (!trimmedInput || isCreating) return;
8614
+ onCreate(trimmedInput);
8615
+ setInput("");
8616
+ };
8617
+ const handleKeyDown = (e) => {
8618
+ if (e.key === "Enter") {
8619
+ e.preventDefault();
8620
+ if (suggestions.length === 1 && !showCreateOption) handleSelect(suggestions[0]);
8621
+ else if (showCreateOption && suggestions.length === 0) handleCreate();
8622
+ }
8623
+ };
8538
8624
  return /* @__PURE__ */ jsxs("div", {
8539
8625
  className: "space-y-2",
8540
8626
  children: [selectedTerms.length > 0 && /* @__PURE__ */ jsx("div", {
@@ -8558,6 +8644,7 @@ function TagInput({ terms, selectedIds, onAdd, onRemove, label }) {
8558
8644
  children: [/* @__PURE__ */ jsx(Input, {
8559
8645
  value: input,
8560
8646
  onChange: (e) => setInput(e.target.value),
8647
+ onKeyDown: handleKeyDown,
8561
8648
  placeholder: _t({
8562
8649
  id: "SnJVrE",
8563
8650
  message: "Add tags..."
@@ -8568,14 +8655,20 @@ function TagInput({ terms, selectedIds, onAdd, onRemove, label }) {
8568
8655
  values: { label }
8569
8656
  }),
8570
8657
  className: "text-sm"
8571
- }), suggestions.length > 0 && /* @__PURE__ */ jsx("div", {
8572
- className: "absolute top-full left-0 right-0 mt-1 bg-kumo-overlay border rounded-md shadow-lg z-10",
8573
- children: suggestions.map((term) => /* @__PURE__ */ jsx("button", {
8658
+ }), (suggestions.length > 0 || showCreateOption) && /* @__PURE__ */ jsxs("div", {
8659
+ className: "absolute top-full start-0 end-0 mt-1 bg-kumo-overlay border rounded-md shadow-lg z-10",
8660
+ children: [suggestions.map((term) => /* @__PURE__ */ jsx("button", {
8574
8661
  type: "button",
8575
8662
  onClick: () => handleSelect(term),
8576
- className: "w-full text-left px-3 py-2 text-sm hover:bg-kumo-tint",
8663
+ className: "w-full text-start px-3 py-2 text-sm hover:bg-kumo-tint",
8577
8664
  children: term.label
8578
- }, term.id))
8665
+ }, term.id)), showCreateOption && /* @__PURE__ */ jsxs("button", {
8666
+ type: "button",
8667
+ onClick: handleCreate,
8668
+ disabled: isCreating,
8669
+ className: "w-full text-left px-3 py-2 text-sm hover:bg-kumo-tint text-kumo-accent flex items-center gap-1 border-t",
8670
+ children: [/* @__PURE__ */ jsx(Plus, { className: "w-3 h-3" }), isCreating ? "Creating..." : `Create "${trimmedInput}"`]
8671
+ })]
8579
8672
  })]
8580
8673
  })]
8581
8674
  });
@@ -8586,6 +8679,9 @@ function TagInput({ terms, selectedIds, onAdd, onRemove, label }) {
8586
8679
  function TaxonomySection({ taxonomy, collection, entryId, onChange }) {
8587
8680
  const { _: _t2 } = useLingui();
8588
8681
  const queryClient = useQueryClient();
8682
+ const toastManager = Toast.useToastManager();
8683
+ const [newCategoryLabel, setNewCategoryLabel] = React.useState("");
8684
+ const [showCategoryInput, setShowCategoryInput] = React.useState(false);
8589
8685
  const { data: terms = [] } = useQuery({
8590
8686
  queryKey: ["taxonomy-terms", taxonomy.name],
8591
8687
  queryFn: () => fetchTerms$1(taxonomy.name)
@@ -8615,6 +8711,42 @@ function TaxonomySection({ taxonomy, collection, entryId, onChange }) {
8615
8711
  entryId,
8616
8712
  taxonomy.name
8617
8713
  ] });
8714
+ toastManager.add({ title: _t2({
8715
+ id: "KDffey",
8716
+ message: "{0} updated",
8717
+ values: { 0: taxonomy.label }
8718
+ }) });
8719
+ },
8720
+ onError: (error) => {
8721
+ toastManager.add({
8722
+ title: _t2({
8723
+ id: "J1Hhct",
8724
+ message: "Failed to update {0}",
8725
+ values: { 0: taxonomy.label.toLowerCase() }
8726
+ }),
8727
+ description: error instanceof Error ? error.message : _t2({
8728
+ id: "Vw8l6h",
8729
+ message: "An error occurred"
8730
+ }),
8731
+ type: "error"
8732
+ });
8733
+ }
8734
+ });
8735
+ const createTermMutation = useMutation({
8736
+ mutationFn: (label) => createTerm(taxonomy.name, {
8737
+ slug: slugify(label),
8738
+ label
8739
+ }),
8740
+ onSuccess: (newTerm) => {
8741
+ queryClient.invalidateQueries({ queryKey: ["taxonomy-terms", taxonomy.name] });
8742
+ const newSelected = new Set(selectedIds);
8743
+ newSelected.add(newTerm.id);
8744
+ setSelectedIds(newSelected);
8745
+ const termIdsArray = [...newSelected];
8746
+ onChange?.(termIdsArray);
8747
+ if (entryId) saveMutation.mutate(termIdsArray);
8748
+ setNewCategoryLabel("");
8749
+ setShowCategoryInput(false);
8618
8750
  }
8619
8751
  });
8620
8752
  const [selectedIds, setSelectedIds] = React.useState(/* @__PURE__ */ new Set());
@@ -8636,30 +8768,89 @@ function TaxonomySection({ taxonomy, collection, entryId, onChange }) {
8636
8768
  const handleRemove = (termId) => {
8637
8769
  handleToggle(termId);
8638
8770
  };
8771
+ const handleCreateCategory = () => {
8772
+ const label = newCategoryLabel.trim();
8773
+ if (!label || createTermMutation.isPending) return;
8774
+ createTermMutation.mutate(label);
8775
+ };
8639
8776
  return /* @__PURE__ */ jsxs("div", {
8640
8777
  className: "space-y-2",
8641
8778
  children: [/* @__PURE__ */ jsx(Label, {
8642
8779
  className: "text-sm font-medium",
8643
8780
  children: taxonomy.label
8644
- }), terms.length === 0 ? /* @__PURE__ */ jsx("p", {
8645
- className: "text-sm text-kumo-subtle",
8646
- children: _t2({
8647
- id: "eRblWH",
8648
- message: "No {0} available.",
8649
- values: { 0: taxonomy.label.toLowerCase() }
8781
+ }), taxonomy.hierarchical ? /* @__PURE__ */ jsxs(Fragment, { children: [
8782
+ terms.length === 0 ? /* @__PURE__ */ jsx("p", {
8783
+ className: "text-sm text-kumo-subtle",
8784
+ children: _t2({
8785
+ id: "eRblWH",
8786
+ message: "No {0} available.",
8787
+ values: { 0: taxonomy.label.toLowerCase() }
8788
+ })
8789
+ }) : /* @__PURE__ */ jsx("div", {
8790
+ className: "border rounded-md p-2 max-h-64 overflow-y-auto",
8791
+ children: terms.map((term) => /* @__PURE__ */ jsx(CategoryCheckboxTree, {
8792
+ term,
8793
+ selectedIds,
8794
+ onToggle: handleToggle
8795
+ }, term.id))
8796
+ }),
8797
+ showCategoryInput ? /* @__PURE__ */ jsxs("div", {
8798
+ className: "flex gap-1",
8799
+ children: [/* @__PURE__ */ jsx(Input, {
8800
+ value: newCategoryLabel,
8801
+ onChange: (e) => setNewCategoryLabel(e.target.value),
8802
+ onKeyDown: (e) => {
8803
+ if (e.key === "Enter") {
8804
+ e.preventDefault();
8805
+ handleCreateCategory();
8806
+ } else if (e.key === "Escape") {
8807
+ setShowCategoryInput(false);
8808
+ setNewCategoryLabel("");
8809
+ }
8810
+ },
8811
+ placeholder: _t2({
8812
+ id: "6WSYbN",
8813
+ message: "New {0}",
8814
+ values: { 0: (taxonomy.labelSingular || taxonomy.label).toLowerCase() }
8815
+ }),
8816
+ className: "text-sm flex-1",
8817
+ autoFocus: true,
8818
+ disabled: createTermMutation.isPending
8819
+ }), /* @__PURE__ */ jsx(Button, {
8820
+ type: "button",
8821
+ onClick: handleCreateCategory,
8822
+ disabled: !newCategoryLabel.trim(),
8823
+ loading: createTermMutation.isPending,
8824
+ variant: "primary",
8825
+ children: _t2({
8826
+ id: "m16xKo",
8827
+ message: "Add"
8828
+ })
8829
+ })]
8830
+ }) : /* @__PURE__ */ jsxs("button", {
8831
+ type: "button",
8832
+ onClick: () => setShowCategoryInput(true),
8833
+ className: "text-sm text-kumo-accent hover:underline flex items-center gap-1",
8834
+ children: [/* @__PURE__ */ jsx(Plus, { className: "w-3 h-3" }), _t2({
8835
+ id: "eABj3Y",
8836
+ message: "Add new {0}",
8837
+ values: { 0: (taxonomy.labelSingular || taxonomy.label).toLowerCase() }
8838
+ })]
8839
+ }),
8840
+ createTermMutation.error && /* @__PURE__ */ jsx("p", {
8841
+ className: "text-sm text-kumo-danger",
8842
+ children: createTermMutation.error instanceof Error ? createTermMutation.error.message : _t2({
8843
+ id: "CyQAPp",
8844
+ message: "Failed to create term"
8845
+ })
8650
8846
  })
8651
- }) : taxonomy.hierarchical ? /* @__PURE__ */ jsx("div", {
8652
- className: "border rounded-md p-2 max-h-64 overflow-y-auto",
8653
- children: terms.map((term) => /* @__PURE__ */ jsx(CategoryCheckboxTree, {
8654
- term,
8655
- selectedIds,
8656
- onToggle: handleToggle
8657
- }, term.id))
8658
- }) : /* @__PURE__ */ jsx(TagInput, {
8847
+ ] }) : /* @__PURE__ */ jsx(TagInput, {
8659
8848
  terms,
8660
8849
  selectedIds,
8661
8850
  onAdd: handleAdd,
8662
8851
  onRemove: handleRemove,
8852
+ onCreate: (label) => createTermMutation.mutate(label),
8853
+ isCreating: createTermMutation.isPending,
8663
8854
  label: taxonomy.label
8664
8855
  })]
8665
8856
  });
@@ -8726,6 +8917,13 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
8726
8917
  roleLabel: entry.roleLabel
8727
8918
  })) ?? []);
8728
8919
  const [portableTextEditor, setPortableTextEditor] = React.useState(null);
8920
+ const ptEditorClaimedRef = React.useRef(false);
8921
+ React.useCallback((editor) => {
8922
+ if (!ptEditorClaimedRef.current) {
8923
+ ptEditorClaimedRef.current = true;
8924
+ setPortableTextEditor(editor);
8925
+ }
8926
+ }, []);
8729
8927
  const [blockSidebarPanel, setBlockSidebarPanel] = React.useState(null);
8730
8928
  const handleBlockSidebarOpen = React.useCallback((panel) => {
8731
8929
  setBlockSidebarPanel(panel);
@@ -8804,11 +9002,19 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
8804
9002
  setLastSavedData(pendingAutosaveStateRef.current);
8805
9003
  pendingAutosaveStateRef.current = null;
8806
9004
  }, [lastAutosaveAt]);
9005
+ const hasInvalidUrls = React.useCallback((data) => {
9006
+ for (const [name, field] of Object.entries(fields)) if (field.kind === "url") {
9007
+ const val = typeof data[name] === "string" ? data[name].trim() : "";
9008
+ if (val && !isValidUrl(val)) return true;
9009
+ }
9010
+ return false;
9011
+ }, [fields]);
8807
9012
  React.useEffect(() => {
8808
9013
  if (isNew || !onAutosave || !item?.id) return;
8809
9014
  if (!isDirty || isSaving || isAutosaving) return;
8810
9015
  if (autosaveTimeoutRef.current) clearTimeout(autosaveTimeoutRef.current);
8811
9016
  autosaveTimeoutRef.current = setTimeout(() => {
9017
+ if (hasInvalidUrls(formDataRef.current)) return;
8812
9018
  const payload = {
8813
9019
  data: formDataRef.current,
8814
9020
  slug: slugRef.current || void 0,
@@ -8832,10 +9038,12 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
8832
9038
  isDirty,
8833
9039
  isSaving,
8834
9040
  isAutosaving,
8835
- activeBylines
9041
+ activeBylines,
9042
+ hasInvalidUrls
8836
9043
  ]);
8837
9044
  const handleSubmit = (e) => {
8838
9045
  e.preventDefault();
9046
+ if (hasInvalidUrls(formData)) return;
8839
9047
  if (autosaveTimeoutRef.current) {
8840
9048
  clearTimeout(autosaveTimeoutRef.current);
8841
9049
  autosaveTimeoutRef.current = null;
@@ -8904,7 +9112,7 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
8904
9112
  onSubmit: handleSubmit,
8905
9113
  className: cn("space-y-6 transition-all duration-300", isDistractionFree && "fixed inset-0 z-50 bg-kumo-base p-8 overflow-auto"),
8906
9114
  children: [/* @__PURE__ */ jsxs("div", {
8907
- className: cn("flex flex-wrap items-center justify-between gap-y-2", isDistractionFree && "opacity-0 hover:opacity-100 transition-opacity duration-200 fixed top-0 left-0 right-0 bg-kumo-base/95 backdrop-blur p-4 z-10"),
9115
+ className: cn("flex flex-wrap items-center justify-between gap-y-2", isDistractionFree && "opacity-0 hover:opacity-100 transition-opacity duration-200 fixed top-0 start-0 end-0 bg-kumo-base/95 backdrop-blur p-4 z-10"),
8908
9116
  children: [/* @__PURE__ */ jsxs("div", {
8909
9117
  className: "flex items-center space-x-4",
8910
9118
  children: [
@@ -8966,13 +9174,13 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
8966
9174
  "aria-label": "Autosave status",
8967
9175
  "aria-live": "polite",
8968
9176
  children: isAutosaving ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Loader, { size: "sm" }), /* @__PURE__ */ jsx("span", {
8969
- className: "ml-1",
9177
+ className: "ms-1",
8970
9178
  children: _t({
8971
9179
  id: "XvjC4F",
8972
9180
  message: "Saving..."
8973
9181
  })
8974
9182
  })] }) : lastAutosaveAt ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Check, {
8975
- className: "mr-1 h-3 w-3 text-green-600",
9183
+ className: "me-1 h-3 w-3 text-green-600",
8976
9184
  "aria-hidden": "true"
8977
9185
  }), /* @__PURE__ */ jsx("span", { children: _t({
8978
9186
  id: "idD8Ev",
@@ -9097,7 +9305,7 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
9097
9305
  rel: "noopener noreferrer",
9098
9306
  className: buttonVariants({ variant: "outline" }),
9099
9307
  children: [/* @__PURE__ */ jsx(ArrowSquareOut, {
9100
- className: "mr-2 h-4 w-4",
9308
+ className: "me-2 h-4 w-4",
9101
9309
  "aria-hidden": "true"
9102
9310
  }), _t({
9103
9311
  id: "I1UtWg",
@@ -9121,7 +9329,7 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
9121
9329
  field,
9122
9330
  value: formData[name],
9123
9331
  onChange: handleFieldChange,
9124
- onEditorReady: field.kind === "portableText" ? setPortableTextEditor : void 0,
9332
+ onEditorReady: field.kind === "portableText" && name === "content" ? setPortableTextEditor : void 0,
9125
9333
  minimal: isDistractionFree,
9126
9334
  pluginBlocks,
9127
9335
  onBlockSidebarOpen: field.kind === "portableText" ? handleBlockSidebarOpen : void 0,
@@ -9559,7 +9767,7 @@ function FieldRenderer({ name, field, value, onChange, onEditorReady, minimal, p
9559
9767
  case "boolean": return /* @__PURE__ */ jsx(Switch, {
9560
9768
  id,
9561
9769
  label,
9562
- checked: typeof value === "boolean" ? value : false,
9770
+ checked: Boolean(value),
9563
9771
  onCheckedChange: handleChange
9564
9772
  });
9565
9773
  case "portableText": {
@@ -9675,6 +9883,15 @@ function FieldRenderer({ name, field, value, onChange, onEditorReady, minimal, p
9675
9883
  onChange: handleChange,
9676
9884
  required: field.required
9677
9885
  });
9886
+ case "url": return /* @__PURE__ */ jsx(UrlFieldEditor, {
9887
+ label,
9888
+ labelClass,
9889
+ id,
9890
+ value: typeof value === "string" ? value : "",
9891
+ onChange: handleChange,
9892
+ required: field.required,
9893
+ placeholder: "https://"
9894
+ });
9678
9895
  default: return /* @__PURE__ */ jsx(Input, {
9679
9896
  label,
9680
9897
  id,
@@ -9684,11 +9901,61 @@ function FieldRenderer({ name, field, value, onChange, onEditorReady, minimal, p
9684
9901
  });
9685
9902
  }
9686
9903
  }
9904
+ const URL_PROTOCOL_PATTERN = /^https?:\/\//;
9905
+ function isValidUrl(val) {
9906
+ if (!URL_PROTOCOL_PATTERN.test(val)) return false;
9907
+ try {
9908
+ const url = new URL(val);
9909
+ if (url.protocol !== "http:" && url.protocol !== "https:") return false;
9910
+ if (url.hostname.includes("..")) return false;
9911
+ return url.hostname.includes(".") || url.hostname === "localhost";
9912
+ } catch {
9913
+ return false;
9914
+ }
9915
+ }
9916
+ /**
9917
+ * URL field editor with validation on blur
9918
+ */
9919
+ function UrlFieldEditor({ label, labelClass, id, value, onChange, required, placeholder }) {
9920
+ const { _: _t3 } = useLingui();
9921
+ const [error, setError] = React.useState(null);
9922
+ const handleBlur = (e) => {
9923
+ const val = e.target.value.trim();
9924
+ if (!val) {
9925
+ setError(null);
9926
+ return;
9927
+ }
9928
+ if (!isValidUrl(val)) setError(_t3({
9929
+ id: "KPnpQW",
9930
+ message: "Enter a valid URL (e.g. https://example.com)"
9931
+ }));
9932
+ else setError(null);
9933
+ };
9934
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input, {
9935
+ label: /* @__PURE__ */ jsx("span", {
9936
+ className: labelClass,
9937
+ children: label
9938
+ }),
9939
+ id,
9940
+ type: "url",
9941
+ value,
9942
+ onChange: (e) => {
9943
+ if (error) setError(null);
9944
+ onChange(e.target.value);
9945
+ },
9946
+ onBlur: handleBlur,
9947
+ required,
9948
+ placeholder
9949
+ }), error && /* @__PURE__ */ jsx("p", {
9950
+ className: "text-sm text-kumo-danger mt-1",
9951
+ children: error
9952
+ })] });
9953
+ }
9687
9954
  /**
9688
9955
  * JSON field editor with syntax validation
9689
9956
  */
9690
9957
  function JsonFieldEditor({ label, id, value, onChange, required }) {
9691
- const { _: _t3 } = useLingui();
9958
+ const { _: _t4 } = useLingui();
9692
9959
  const [text, setText] = React.useState(value);
9693
9960
  const [error, setError] = React.useState(null);
9694
9961
  React.useEffect(() => {
@@ -9711,7 +9978,7 @@ function JsonFieldEditor({ label, id, value, onChange, required }) {
9711
9978
  setError(null);
9712
9979
  onChange(parsed);
9713
9980
  } catch {
9714
- setError(_t3({
9981
+ setError(_t4({
9715
9982
  id: "Deej3j",
9716
9983
  message: "Invalid JSON"
9717
9984
  }));
@@ -9733,7 +10000,7 @@ function JsonFieldEditor({ label, id, value, onChange, required }) {
9733
10000
  })] });
9734
10001
  }
9735
10002
  function ImageFieldRenderer({ id, label, description, value, onChange, required }) {
9736
- const { _: _t4 } = useLingui();
10003
+ const { _: _t5 } = useLingui();
9737
10004
  const [pickerOpen, setPickerOpen] = React.useState(false);
9738
10005
  const displayUrl = typeof value === "string" ? value : value?.previewUrl || value?.src || (value && (!value.provider || value.provider === "local") ? `/_emdash/api/media/file/${typeof value.meta?.storageKey === "string" ? value.meta.storageKey : value.id}` : void 0);
9739
10006
  const handleSelect = (item) => {
@@ -9765,13 +10032,13 @@ function ImageFieldRenderer({ id, label, description, value, onChange, required
9765
10032
  alt: "",
9766
10033
  className: "max-h-48 rounded-lg border object-cover"
9767
10034
  }), /* @__PURE__ */ jsxs("div", {
9768
- className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity flex gap-1",
10035
+ className: "absolute top-2 end-2 opacity-0 group-hover:opacity-100 transition-opacity flex gap-1",
9769
10036
  children: [/* @__PURE__ */ jsx(Button, {
9770
10037
  type: "button",
9771
10038
  size: "sm",
9772
10039
  variant: "secondary",
9773
10040
  onClick: () => setPickerOpen(true),
9774
- children: _t4({
10041
+ children: _t5({
9775
10042
  id: "o+XJ9D",
9776
10043
  message: "Change"
9777
10044
  })
@@ -9781,7 +10048,7 @@ function ImageFieldRenderer({ id, label, description, value, onChange, required
9781
10048
  variant: "destructive",
9782
10049
  className: "h-8 w-8",
9783
10050
  onClick: handleRemove,
9784
- "aria-label": _t4({
10051
+ "aria-label": _t5({
9785
10052
  id: "5ywtDz",
9786
10053
  message: "Remove image"
9787
10054
  }),
@@ -9795,7 +10062,7 @@ function ImageFieldRenderer({ id, label, description, value, onChange, required
9795
10062
  onClick: () => setPickerOpen(true),
9796
10063
  children: /* @__PURE__ */ jsxs("div", {
9797
10064
  className: "flex flex-col items-center gap-2 text-kumo-subtle",
9798
- children: [/* @__PURE__ */ jsx(Image$1, { className: "h-8 w-8" }), /* @__PURE__ */ jsx("span", { children: _t4({
10065
+ children: [/* @__PURE__ */ jsx(Image$1, { className: "h-8 w-8" }), /* @__PURE__ */ jsx("span", { children: _t5({
9799
10066
  id: "oDodff",
9800
10067
  message: "Select image"
9801
10068
  }) })]
@@ -9806,7 +10073,7 @@ function ImageFieldRenderer({ id, label, description, value, onChange, required
9806
10073
  onOpenChange: setPickerOpen,
9807
10074
  onSelect: handleSelect,
9808
10075
  mimeTypeFilter: "image/",
9809
- title: _t4({
10076
+ title: _t5({
9810
10077
  id: "pov/PW",
9811
10078
  message: "Select {label}",
9812
10079
  values: { label }
@@ -9818,7 +10085,7 @@ function ImageFieldRenderer({ id, label, description, value, onChange, required
9818
10085
  }),
9819
10086
  required && !displayUrl && /* @__PURE__ */ jsx("p", {
9820
10087
  className: "text-sm text-kumo-danger mt-1",
9821
- children: _t4({
10088
+ children: _t5({
9822
10089
  id: "B8AaMI",
9823
10090
  message: "This field is required"
9824
10091
  })
@@ -9827,7 +10094,7 @@ function ImageFieldRenderer({ id, label, description, value, onChange, required
9827
10094
  });
9828
10095
  }
9829
10096
  function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuickEdit }) {
9830
- const { _: _t5 } = useLingui();
10097
+ const { _: _t6 } = useLingui();
9831
10098
  const [selectedBylineId, setSelectedBylineId] = React.useState("");
9832
10099
  const [quickName, setQuickName] = React.useState("");
9833
10100
  const [quickSlug, setQuickSlug] = React.useState("");
@@ -9877,7 +10144,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
9877
10144
  className: "w-full rounded border bg-kumo-base px-3 py-2 text-sm",
9878
10145
  children: [/* @__PURE__ */ jsx("option", {
9879
10146
  value: "",
9880
- children: _t5({
10147
+ children: _t6({
9881
10148
  id: "r5zcIE",
9882
10149
  message: "Select byline..."
9883
10150
  })
@@ -9897,7 +10164,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
9897
10164
  setSelectedBylineId("");
9898
10165
  },
9899
10166
  disabled: !selectedBylineId,
9900
- children: _t5({
10167
+ children: _t6({
9901
10168
  id: "m16xKo",
9902
10169
  message: "Add"
9903
10170
  })
@@ -9926,7 +10193,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
9926
10193
  variant: "ghost",
9927
10194
  size: "sm",
9928
10195
  onClick: () => move(index, -1),
9929
- children: _t5({
10196
+ children: _t6({
9930
10197
  id: "n+PHuv",
9931
10198
  message: "Up"
9932
10199
  })
@@ -9936,7 +10203,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
9936
10203
  variant: "ghost",
9937
10204
  size: "sm",
9938
10205
  onClick: () => move(index, 1),
9939
- children: _t5({
10206
+ children: _t6({
9940
10207
  id: "gUjkl/",
9941
10208
  message: "Down"
9942
10209
  })
@@ -9946,7 +10213,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
9946
10213
  variant: "ghost",
9947
10214
  size: "sm",
9948
10215
  onClick: () => openEditByline(byline),
9949
- children: _t5({
10216
+ children: _t6({
9950
10217
  id: "ePK91l",
9951
10218
  message: "Edit"
9952
10219
  })
@@ -9956,7 +10223,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
9956
10223
  variant: "destructive",
9957
10224
  size: "sm",
9958
10225
  onClick: () => onChange(credits.filter((_, i) => i !== index)),
9959
- children: _t5({
10226
+ children: _t6({
9960
10227
  id: "t/YqKh",
9961
10228
  message: "Remove"
9962
10229
  })
@@ -9964,7 +10231,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
9964
10231
  ]
9965
10232
  })]
9966
10233
  }), /* @__PURE__ */ jsx(Input, {
9967
- label: _t5({
10234
+ label: _t6({
9968
10235
  id: "QeScoL",
9969
10236
  message: "Role label"
9970
10237
  }),
@@ -9984,7 +10251,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
9984
10251
  })
9985
10252
  }) : /* @__PURE__ */ jsx("p", {
9986
10253
  className: "text-sm text-kumo-subtle",
9987
- children: _t5({
10254
+ children: _t6({
9988
10255
  id: "dyZY24",
9989
10256
  message: "No bylines selected."
9990
10257
  })
@@ -9993,7 +10260,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
9993
10260
  ...p,
9994
10261
  type: "button",
9995
10262
  variant: "secondary",
9996
- children: _t5({
10263
+ children: _t6({
9997
10264
  id: "gqa8eq",
9998
10265
  message: "Quick create byline"
9999
10266
  })
@@ -10003,7 +10270,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10003
10270
  children: [
10004
10271
  /* @__PURE__ */ jsx(Dialog.Title, {
10005
10272
  className: "text-lg font-semibold",
10006
- children: _t5({
10273
+ children: _t6({
10007
10274
  id: "d6HWlw",
10008
10275
  message: "Create byline"
10009
10276
  })
@@ -10012,7 +10279,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10012
10279
  className: "mt-4 space-y-3",
10013
10280
  children: [
10014
10281
  /* @__PURE__ */ jsx(Input, {
10015
- label: _t5({
10282
+ label: _t6({
10016
10283
  id: "pfa8F0",
10017
10284
  message: "Display name"
10018
10285
  }),
@@ -10023,7 +10290,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10023
10290
  }
10024
10291
  }),
10025
10292
  /* @__PURE__ */ jsx(Input, {
10026
- label: _t5({
10293
+ label: _t6({
10027
10294
  id: "L85WcV",
10028
10295
  message: "Slug"
10029
10296
  }),
@@ -10045,7 +10312,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10045
10312
  resetQuickCreate();
10046
10313
  p.onClick?.(e);
10047
10314
  },
10048
- children: _t5({
10315
+ children: _t6({
10049
10316
  id: "dEgA5A",
10050
10317
  message: "Cancel"
10051
10318
  })
@@ -10066,7 +10333,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10066
10333
  }]);
10067
10334
  resetQuickCreate();
10068
10335
  } catch (err) {
10069
- setQuickError(err instanceof Error ? err.message : _t5({
10336
+ setQuickError(err instanceof Error ? err.message : _t6({
10070
10337
  id: "Kd9Ewv",
10071
10338
  message: "Failed to create byline"
10072
10339
  }));
@@ -10074,10 +10341,10 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10074
10341
  setIsCreating(false);
10075
10342
  }
10076
10343
  },
10077
- children: isCreating ? _t5({
10344
+ children: isCreating ? _t6({
10078
10345
  id: "HM56Bx",
10079
10346
  message: "Creating..."
10080
- }) : _t5({
10347
+ }) : _t6({
10081
10348
  id: "hYgDIe",
10082
10349
  message: "Create"
10083
10350
  })
@@ -10094,7 +10361,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10094
10361
  children: [
10095
10362
  /* @__PURE__ */ jsx(Dialog.Title, {
10096
10363
  className: "text-lg font-semibold",
10097
- children: _t5({
10364
+ children: _t6({
10098
10365
  id: "d9lVyw",
10099
10366
  message: "Edit byline"
10100
10367
  })
@@ -10103,7 +10370,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10103
10370
  className: "mt-4 space-y-3",
10104
10371
  children: [
10105
10372
  /* @__PURE__ */ jsx(Input, {
10106
- label: _t5({
10373
+ label: _t6({
10107
10374
  id: "pfa8F0",
10108
10375
  message: "Display name"
10109
10376
  }),
@@ -10114,7 +10381,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10114
10381
  }
10115
10382
  }),
10116
10383
  /* @__PURE__ */ jsx(Input, {
10117
- label: _t5({
10384
+ label: _t6({
10118
10385
  id: "L85WcV",
10119
10386
  message: "Slug"
10120
10387
  }),
@@ -10133,7 +10400,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10133
10400
  type: "button",
10134
10401
  variant: "secondary",
10135
10402
  onClick: resetQuickEdit,
10136
- children: _t5({
10403
+ children: _t6({
10137
10404
  id: "dEgA5A",
10138
10405
  message: "Cancel"
10139
10406
  })
@@ -10150,7 +10417,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10150
10417
  });
10151
10418
  resetQuickEdit();
10152
10419
  } catch (err) {
10153
- setEditError(err instanceof Error ? err.message : _t5({
10420
+ setEditError(err instanceof Error ? err.message : _t6({
10154
10421
  id: "fd6o+d",
10155
10422
  message: "Failed to update byline"
10156
10423
  }));
@@ -10158,10 +10425,10 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10158
10425
  setIsEditing(false);
10159
10426
  }
10160
10427
  },
10161
- children: isEditing ? _t5({
10428
+ children: isEditing ? _t6({
10162
10429
  id: "XvjC4F",
10163
10430
  message: "Saving..."
10164
- }) : _t5({
10431
+ }) : _t6({
10165
10432
  id: "tfDRzk",
10166
10433
  message: "Save"
10167
10434
  })
@@ -10174,9 +10441,9 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
10174
10441
  });
10175
10442
  }
10176
10443
  function AuthorSelector({ authorId, users, onChange }) {
10177
- const { _: _t6 } = useLingui();
10444
+ const { _: _t7 } = useLingui();
10178
10445
  const currentAuthor = users.find((u) => u.id === authorId);
10179
- const authorItems = { unassigned: _t6({
10446
+ const authorItems = { unassigned: _t7({
10180
10447
  id: "EbMPZJ",
10181
10448
  message: "Unassigned"
10182
10449
  }) };
@@ -10191,7 +10458,7 @@ function AuthorSelector({ authorId, users, onChange }) {
10191
10458
  value: "unassigned",
10192
10459
  children: /* @__PURE__ */ jsx("span", {
10193
10460
  className: "text-kumo-subtle",
10194
- children: _t6({
10461
+ children: _t7({
10195
10462
  id: "EbMPZJ",
10196
10463
  message: "Unassigned"
10197
10464
  })
@@ -10318,7 +10585,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
10318
10585
  search: { locale: activeLocale },
10319
10586
  className: buttonVariants(),
10320
10587
  children: [/* @__PURE__ */ jsx(Plus, {
10321
- className: "mr-2 h-4 w-4",
10588
+ className: "me-2 h-4 w-4",
10322
10589
  "aria-hidden": "true"
10323
10590
  }), _t({
10324
10591
  id: "ApsD9J",
@@ -10328,7 +10595,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
10328
10595
  }),
10329
10596
  items.length > 0 && /* @__PURE__ */ jsxs("div", {
10330
10597
  className: "relative max-w-sm",
10331
- children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
10598
+ children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute start-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
10332
10599
  type: "search",
10333
10600
  placeholder: _t({
10334
10601
  id: "FpEIAP",
@@ -10342,7 +10609,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
10342
10609
  }),
10343
10610
  value: searchQuery,
10344
10611
  onChange: handleSearchChange,
10345
- className: "pl-9"
10612
+ className: "ps-9"
10346
10613
  })]
10347
10614
  }),
10348
10615
  /* @__PURE__ */ jsx(Tabs, {
@@ -10388,7 +10655,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
10388
10655
  children: [
10389
10656
  /* @__PURE__ */ jsx("th", {
10390
10657
  scope: "col",
10391
- className: "px-4 py-3 text-left text-sm font-medium",
10658
+ className: "px-4 py-3 text-start text-sm font-medium",
10392
10659
  children: _t({
10393
10660
  id: "MHrjPM",
10394
10661
  message: "Title"
@@ -10396,7 +10663,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
10396
10663
  }),
10397
10664
  /* @__PURE__ */ jsx("th", {
10398
10665
  scope: "col",
10399
- className: "px-4 py-3 text-left text-sm font-medium",
10666
+ className: "px-4 py-3 text-start text-sm font-medium",
10400
10667
  children: _t({
10401
10668
  id: "uAQUqI",
10402
10669
  message: "Status"
@@ -10404,7 +10671,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
10404
10671
  }),
10405
10672
  i18n$1 && /* @__PURE__ */ jsx("th", {
10406
10673
  scope: "col",
10407
- className: "px-4 py-3 text-left text-sm font-medium",
10674
+ className: "px-4 py-3 text-start text-sm font-medium",
10408
10675
  children: _t({
10409
10676
  id: "8NbHF7",
10410
10677
  message: "Locale"
@@ -10412,7 +10679,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
10412
10679
  }),
10413
10680
  /* @__PURE__ */ jsx("th", {
10414
10681
  scope: "col",
10415
- className: "px-4 py-3 text-left text-sm font-medium",
10682
+ className: "px-4 py-3 text-start text-sm font-medium",
10416
10683
  children: _t({
10417
10684
  id: "mYGY3B",
10418
10685
  message: "Date"
@@ -10420,7 +10687,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
10420
10687
  }),
10421
10688
  /* @__PURE__ */ jsx("th", {
10422
10689
  scope: "col",
10423
- className: "px-4 py-3 text-right text-sm font-medium",
10690
+ className: "px-4 py-3 text-end text-sm font-medium",
10424
10691
  children: _t({
10425
10692
  id: "7L01XJ",
10426
10693
  message: "Actions"
@@ -10552,7 +10819,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
10552
10819
  children: [
10553
10820
  /* @__PURE__ */ jsx("th", {
10554
10821
  scope: "col",
10555
- className: "px-4 py-3 text-left text-sm font-medium",
10822
+ className: "px-4 py-3 text-start text-sm font-medium",
10556
10823
  children: _t({
10557
10824
  id: "MHrjPM",
10558
10825
  message: "Title"
@@ -10560,7 +10827,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
10560
10827
  }),
10561
10828
  /* @__PURE__ */ jsx("th", {
10562
10829
  scope: "col",
10563
- className: "px-4 py-3 text-left text-sm font-medium",
10830
+ className: "px-4 py-3 text-start text-sm font-medium",
10564
10831
  children: _t({
10565
10832
  id: "vGjmyl",
10566
10833
  message: "Deleted"
@@ -10568,7 +10835,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
10568
10835
  }),
10569
10836
  /* @__PURE__ */ jsx("th", {
10570
10837
  scope: "col",
10571
- className: "px-4 py-3 text-right text-sm font-medium",
10838
+ className: "px-4 py-3 text-end text-sm font-medium",
10572
10839
  children: _t({
10573
10840
  id: "7L01XJ",
10574
10841
  message: "Actions"
@@ -10644,7 +10911,7 @@ function ContentListItem({ item, collection, onDelete, onDuplicate, showLocale,
10644
10911
  children: date.toLocaleDateString()
10645
10912
  }),
10646
10913
  /* @__PURE__ */ jsx("td", {
10647
- className: "px-4 py-3 text-right",
10914
+ className: "px-4 py-3 text-end",
10648
10915
  children: /* @__PURE__ */ jsxs("div", {
10649
10916
  className: "flex items-center justify-end space-x-1",
10650
10917
  children: [
@@ -10781,7 +11048,7 @@ function TrashedListItem({ item, onRestore, onPermanentDelete }) {
10781
11048
  children: deletedDate.toLocaleDateString()
10782
11049
  }),
10783
11050
  /* @__PURE__ */ jsx("td", {
10784
- className: "px-4 py-3 text-right",
11051
+ className: "px-4 py-3 text-end",
10785
11052
  children: /* @__PURE__ */ jsxs("div", {
10786
11053
  className: "flex items-center justify-end space-x-1",
10787
11054
  children: [/* @__PURE__ */ jsx(Button, {
@@ -11114,6 +11381,18 @@ function FieldEditor({ open, onOpenChange, field, onSave, isSaving }) {
11114
11381
  }),
11115
11382
  icon: Link$2
11116
11383
  },
11384
+ {
11385
+ type: "url",
11386
+ label: _t({
11387
+ id: "IagCbF",
11388
+ message: "URL"
11389
+ }),
11390
+ description: _t({
11391
+ id: "55l21g",
11392
+ message: "Web address"
11393
+ }),
11394
+ icon: GlobeSimple
11395
+ },
11117
11396
  {
11118
11397
  type: "repeater",
11119
11398
  label: _t({
@@ -11170,7 +11449,7 @@ function FieldEditor({ open, onOpenChange, field, onSave, isSaving }) {
11170
11449
  type: selectedType,
11171
11450
  required,
11172
11451
  unique,
11173
- searchable: selectedType === "string" || selectedType === "text" || selectedType === "portableText" || selectedType === "slug" ? searchable : void 0,
11452
+ searchable: selectedType === "string" || selectedType === "text" || selectedType === "portableText" || selectedType === "slug" || selectedType === "url" ? searchable : void 0,
11174
11453
  validation: Object.keys(validation).length > 0 ? validation : void 0
11175
11454
  });
11176
11455
  };
@@ -11209,7 +11488,7 @@ function FieldEditor({ open, onOpenChange, field, onSave, isSaving }) {
11209
11488
  id: "yz7wBu",
11210
11489
  message: "Close"
11211
11490
  }),
11212
- className: "absolute right-4 top-4",
11491
+ className: "absolute end-4 top-4",
11213
11492
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
11214
11493
  className: "sr-only",
11215
11494
  children: _t({
@@ -11227,7 +11506,7 @@ function FieldEditor({ open, onOpenChange, field, onSave, isSaving }) {
11227
11506
  return /* @__PURE__ */ jsxs("button", {
11228
11507
  type: "button",
11229
11508
  onClick: () => handleTypeSelect(ft.type),
11230
- className: cn("flex items-start space-x-3 p-4 rounded-lg border text-left transition-colors hover:border-kumo-brand hover:bg-kumo-tint/50"),
11509
+ className: cn("flex items-start space-x-3 p-4 rounded-lg border text-start transition-colors hover:border-kumo-brand hover:bg-kumo-tint/50"),
11231
11510
  children: [/* @__PURE__ */ jsx("div", {
11232
11511
  className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-kumo-tint",
11233
11512
  children: /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5" })
@@ -11257,7 +11536,7 @@ function FieldEditor({ open, onOpenChange, field, onSave, isSaving }) {
11257
11536
  !field && /* @__PURE__ */ jsx(Button, {
11258
11537
  variant: "ghost",
11259
11538
  size: "sm",
11260
- className: "ml-auto",
11539
+ className: "ms-auto",
11261
11540
  onClick: () => setField("step", "type"),
11262
11541
  children: _t({
11263
11542
  id: "o+XJ9D",
@@ -11329,7 +11608,7 @@ function FieldEditor({ open, onOpenChange, field, onSave, isSaving }) {
11329
11608
  })
11330
11609
  })]
11331
11610
  }),
11332
- (selectedType === "string" || selectedType === "text" || selectedType === "portableText" || selectedType === "slug") && /* @__PURE__ */ jsxs("label", {
11611
+ (selectedType === "string" || selectedType === "text" || selectedType === "portableText" || selectedType === "slug" || selectedType === "url") && /* @__PURE__ */ jsxs("label", {
11333
11612
  className: "flex items-center space-x-2",
11334
11613
  children: [/* @__PURE__ */ jsx("input", {
11335
11614
  type: "checkbox",
@@ -11576,6 +11855,13 @@ function FieldEditor({ open, onOpenChange, field, onSave, isSaving }) {
11576
11855
  id: "rG3WVm",
11577
11856
  message: "Select"
11578
11857
  })
11858
+ }),
11859
+ /* @__PURE__ */ jsx("option", {
11860
+ value: "url",
11861
+ children: _t({
11862
+ id: "IagCbF",
11863
+ message: "URL"
11864
+ })
11579
11865
  })
11580
11866
  ]
11581
11867
  })] })]
@@ -11808,7 +12094,7 @@ function ContentTypeEditor({ collection, isNew, isSaving, onSave, onAddField, on
11808
12094
  const [labelSingular, setLabelSingular] = React.useState(collection?.labelSingular ?? "");
11809
12095
  const [description, setDescription] = React.useState(collection?.description ?? "");
11810
12096
  const [urlPattern, setUrlPattern] = React.useState(collection?.urlPattern ?? "");
11811
- const [supports, setSupports] = React.useState(collection?.supports ?? ["drafts"]);
12097
+ const [supports, setSupports] = React.useState((collection?.supports ?? ["drafts"]).filter((s) => s !== "seo"));
11812
12098
  const [hasSeo, setHasSeo] = React.useState(collection?.hasSeo ?? false);
11813
12099
  const [commentsEnabled, setCommentsEnabled] = React.useState(collection?.commentsEnabled ?? false);
11814
12100
  const [commentsModeration, setCommentsModeration] = React.useState(collection?.commentsModeration ?? "first_time");
@@ -11822,7 +12108,7 @@ function ContentTypeEditor({ collection, isNew, isSaving, onSave, onAddField, on
11822
12108
  const hasChanges = React.useMemo(() => {
11823
12109
  if (isNew) return slug && label;
11824
12110
  if (!collection) return false;
11825
- return label !== collection.label || labelSingular !== (collection.labelSingular ?? "") || description !== (collection.description ?? "") || urlPattern !== (collection.urlPattern ?? "") || JSON.stringify([...supports].toSorted()) !== JSON.stringify([...collection.supports].toSorted()) || hasSeo !== collection.hasSeo || commentsEnabled !== collection.commentsEnabled || commentsModeration !== collection.commentsModeration || commentsClosedAfterDays !== collection.commentsClosedAfterDays || commentsAutoApproveUsers !== collection.commentsAutoApproveUsers;
12111
+ return label !== collection.label || labelSingular !== (collection.labelSingular ?? "") || description !== (collection.description ?? "") || urlPattern !== (collection.urlPattern ?? "") || JSON.stringify([...supports].toSorted()) !== JSON.stringify(collection.supports.filter((s) => s !== "seo").toSorted()) || hasSeo !== collection.hasSeo || commentsEnabled !== collection.commentsEnabled || commentsModeration !== collection.commentsModeration || commentsClosedAfterDays !== collection.commentsClosedAfterDays || commentsAutoApproveUsers !== collection.commentsAutoApproveUsers;
11826
12112
  }, [
11827
12113
  isNew,
11828
12114
  collection,
@@ -11928,7 +12214,7 @@ function ContentTypeEditor({ collection, isNew, isSaving, onSave, onAddField, on
11928
12214
  className: "bg-kumo-tint px-1.5 py-0.5 rounded",
11929
12215
  children: collection?.slug
11930
12216
  }), isFromCode && /* @__PURE__ */ jsx("span", {
11931
- className: "ml-2 text-purple-600 dark:text-purple-400",
12217
+ className: "ms-2 text-purple-600 dark:text-purple-400",
11932
12218
  children: "Defined in code"
11933
12219
  })]
11934
12220
  })]
@@ -12250,7 +12536,7 @@ function FieldRow({ field, isFromCode, onEdit, onDelete }) {
12250
12536
  !isFromCode && /* @__PURE__ */ jsx("button", {
12251
12537
  ...attributes,
12252
12538
  ...listeners,
12253
- className: "cursor-grab active:cursor-grabbing mr-3",
12539
+ className: "cursor-grab active:cursor-grabbing me-3",
12254
12540
  "aria-label": `Drag to reorder ${field.label}`,
12255
12541
  children: /* @__PURE__ */ jsx(DotsSixVertical, { className: "h-5 w-5 text-kumo-subtle" })
12256
12542
  }),
@@ -12370,7 +12656,7 @@ function ContentTypeList({ collections, orphanedTables, isLoading, onDelete, onR
12370
12656
  to: "/content-types/new",
12371
12657
  className: buttonVariants(),
12372
12658
  children: [/* @__PURE__ */ jsx(Plus, {
12373
- className: "mr-2 h-4 w-4",
12659
+ className: "me-2 h-4 w-4",
12374
12660
  "aria-hidden": "true"
12375
12661
  }), _t({
12376
12662
  id: "NFFxa9",
@@ -12407,7 +12693,7 @@ function ContentTypeList({ collections, orphanedTables, isLoading, onDelete, onR
12407
12693
  className: "text-sm font-medium",
12408
12694
  children: orphan.slug
12409
12695
  }), /* @__PURE__ */ jsx("span", {
12410
- className: "text-xs text-kumo-subtle ml-2",
12696
+ className: "text-xs text-kumo-subtle ms-2",
12411
12697
  children: i18n._({
12412
12698
  id: "JcH6Wc",
12413
12699
  message: "{0, plural, one {(# item)} other {(# items)}}",
@@ -12438,7 +12724,7 @@ function ContentTypeList({ collections, orphanedTables, isLoading, onDelete, onR
12438
12724
  children: [
12439
12725
  /* @__PURE__ */ jsx("th", {
12440
12726
  scope: "col",
12441
- className: "px-4 py-3 text-left text-sm font-medium",
12727
+ className: "px-4 py-3 text-start text-sm font-medium",
12442
12728
  children: _t({
12443
12729
  id: "6YtxFj",
12444
12730
  message: "Name"
@@ -12446,7 +12732,7 @@ function ContentTypeList({ collections, orphanedTables, isLoading, onDelete, onR
12446
12732
  }),
12447
12733
  /* @__PURE__ */ jsx("th", {
12448
12734
  scope: "col",
12449
- className: "px-4 py-3 text-left text-sm font-medium",
12735
+ className: "px-4 py-3 text-start text-sm font-medium",
12450
12736
  children: _t({
12451
12737
  id: "L85WcV",
12452
12738
  message: "Slug"
@@ -12454,7 +12740,7 @@ function ContentTypeList({ collections, orphanedTables, isLoading, onDelete, onR
12454
12740
  }),
12455
12741
  /* @__PURE__ */ jsx("th", {
12456
12742
  scope: "col",
12457
- className: "px-4 py-3 text-left text-sm font-medium",
12743
+ className: "px-4 py-3 text-start text-sm font-medium",
12458
12744
  children: _t({
12459
12745
  id: "wdxz7K",
12460
12746
  message: "Source"
@@ -12462,7 +12748,7 @@ function ContentTypeList({ collections, orphanedTables, isLoading, onDelete, onR
12462
12748
  }),
12463
12749
  /* @__PURE__ */ jsx("th", {
12464
12750
  scope: "col",
12465
- className: "px-4 py-3 text-left text-sm font-medium",
12751
+ className: "px-4 py-3 text-start text-sm font-medium",
12466
12752
  children: _t({
12467
12753
  id: "PpZkda",
12468
12754
  message: "Features"
@@ -12470,7 +12756,7 @@ function ContentTypeList({ collections, orphanedTables, isLoading, onDelete, onR
12470
12756
  }),
12471
12757
  /* @__PURE__ */ jsx("th", {
12472
12758
  scope: "col",
12473
- className: "px-4 py-3 text-right text-sm font-medium",
12759
+ className: "px-4 py-3 text-end text-sm font-medium",
12474
12760
  children: _t({
12475
12761
  id: "7L01XJ",
12476
12762
  message: "Actions"
@@ -12586,7 +12872,7 @@ function ContentTypeRow({ collection, onRequestDelete }) {
12586
12872
  })
12587
12873
  }),
12588
12874
  /* @__PURE__ */ jsx("td", {
12589
- className: "px-4 py-3 text-right",
12875
+ className: "px-4 py-3 text-end",
12590
12876
  children: /* @__PURE__ */ jsxs("div", {
12591
12877
  className: "flex items-center justify-end space-x-1",
12592
12878
  children: [/* @__PURE__ */ jsx(Link$1, {
@@ -13900,6 +14186,24 @@ function LogoLockup({ className, ...props }) {
13900
14186
  ]
13901
14187
  });
13902
14188
  }
14189
+ function BrandLogo({ logoUrl, siteName, className }) {
14190
+ if (logoUrl) return /* @__PURE__ */ jsx("img", {
14191
+ src: logoUrl,
14192
+ alt: siteName || "",
14193
+ className,
14194
+ style: { objectFit: "contain" }
14195
+ });
14196
+ return /* @__PURE__ */ jsx(LogoLockup, { className });
14197
+ }
14198
+ function BrandIcon({ logoUrl, siteName, className }) {
14199
+ if (logoUrl) return /* @__PURE__ */ jsx("img", {
14200
+ src: logoUrl,
14201
+ alt: siteName || "",
14202
+ className,
14203
+ style: { objectFit: "contain" }
14204
+ });
14205
+ return /* @__PURE__ */ jsx(LogoIcon, { className });
14206
+ }
13903
14207
 
13904
14208
  //#endregion
13905
14209
  //#region src/components/InviteAcceptPage.tsx
@@ -14661,8 +14965,12 @@ function LoginPage({ redirectUrl = "/_emdash/admin" }) {
14661
14965
  if (manifestLoading || manifest?.authMode && manifest.authMode !== "passkey") return /* @__PURE__ */ jsx("div", {
14662
14966
  className: "min-h-screen flex items-center justify-center bg-kumo-base p-4",
14663
14967
  children: /* @__PURE__ */ jsxs("div", {
14664
- className: "text-center",
14665
- children: [/* @__PURE__ */ jsx(LogoLockup, { className: "h-10 mx-auto mb-4" }), /* @__PURE__ */ jsx(Loader, {})]
14968
+ className: "flex flex-col items-center",
14969
+ children: [/* @__PURE__ */ jsx(BrandLogo, {
14970
+ logoUrl: manifest?.admin?.logo,
14971
+ siteName: manifest?.admin?.siteName,
14972
+ className: "h-10 mb-4"
14973
+ }), /* @__PURE__ */ jsx(Loader, {})]
14666
14974
  })
14667
14975
  });
14668
14976
  return /* @__PURE__ */ jsx("div", {
@@ -14672,7 +14980,11 @@ function LoginPage({ redirectUrl = "/_emdash/admin" }) {
14672
14980
  children: [
14673
14981
  /* @__PURE__ */ jsxs("div", {
14674
14982
  className: "text-center mb-8",
14675
- children: [/* @__PURE__ */ jsx(LogoLockup, { className: "h-10 mx-auto mb-2" }), /* @__PURE__ */ jsxs("h1", {
14983
+ children: [/* @__PURE__ */ jsx(BrandLogo, {
14984
+ logoUrl: manifest?.admin?.logo,
14985
+ siteName: manifest?.admin?.siteName,
14986
+ className: "h-10 mx-auto mb-2"
14987
+ }), /* @__PURE__ */ jsxs("h1", {
14676
14988
  className: "text-2xl font-semibold text-kumo-default",
14677
14989
  children: [method === "passkey" && _t2({
14678
14990
  id: "lE0wHD",
@@ -14725,7 +15037,7 @@ function LoginPage({ redirectUrl = "/_emdash/admin" }) {
14725
15037
  onClick: () => handleOAuthClick(provider.id),
14726
15038
  className: "w-full justify-center",
14727
15039
  children: [provider.icon, /* @__PURE__ */ jsx("span", {
14728
- className: "ml-2",
15040
+ className: "ms-2",
14729
15041
  children: provider.name
14730
15042
  })]
14731
15043
  }, provider.id))
@@ -14765,12 +15077,17 @@ function LoginPage({ redirectUrl = "/_emdash/admin" }) {
14765
15077
  })
14766
15078
  }),
14767
15079
  SUPPORTED_LOCALES.length > 1 && /* @__PURE__ */ jsx("div", {
14768
- className: "mt-6 flex justify-center gap-2 text-xs text-kumo-subtle",
14769
- children: SUPPORTED_LOCALES.map((l, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [i > 0 && /* @__PURE__ */ jsx("span", { children: "·" }), /* @__PURE__ */ jsx("button", {
14770
- onClick: () => setLocale(l.code),
14771
- className: l.code === locale ? "font-medium text-kumo-default" : "hover:text-kumo-default transition-colors",
14772
- children: l.label
14773
- })] }, l.code))
15080
+ className: "mt-6 flex justify-center",
15081
+ children: /* @__PURE__ */ jsx(Select, {
15082
+ "aria-label": _t2({
15083
+ id: "vXIe7J",
15084
+ message: "Language"
15085
+ }),
15086
+ className: "w-48",
15087
+ value: locale,
15088
+ onValueChange: (v) => v && setLocale(v),
15089
+ items: Object.fromEntries(SUPPORTED_LOCALES.map((l) => [l.code, l.label]))
15090
+ })
14774
15091
  })
14775
15092
  ]
14776
15093
  })
@@ -14851,7 +15168,7 @@ function MarketplaceBrowse({ installedPluginIds = /* @__PURE__ */ new Set() }) {
14851
15168
  children: [
14852
15169
  /* @__PURE__ */ jsxs("div", {
14853
15170
  className: "relative flex-1",
14854
- children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-kumo-subtle" }), /* @__PURE__ */ jsx("input", {
15171
+ children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute start-3 top-1/2 h-4 w-4 -translate-y-1/2 text-kumo-subtle" }), /* @__PURE__ */ jsx("input", {
14855
15172
  type: "search",
14856
15173
  placeholder: _t({
14857
15174
  id: "slq1pb",
@@ -14859,7 +15176,7 @@ function MarketplaceBrowse({ installedPluginIds = /* @__PURE__ */ new Set() }) {
14859
15176
  }),
14860
15177
  value: searchQuery,
14861
15178
  onChange: (e) => setSearchQuery(e.target.value),
14862
- className: "w-full rounded-md border bg-kumo-base px-3 py-2 pl-9 text-sm placeholder:text-kumo-subtle focus:outline-none focus:ring-2 focus:ring-kumo-ring"
15179
+ className: "w-full rounded-md border bg-kumo-base px-3 py-2 ps-9 text-sm placeholder:text-kumo-subtle focus:outline-none focus:ring-2 focus:ring-kumo-ring"
14863
15180
  })]
14864
15181
  }),
14865
15182
  /* @__PURE__ */ jsxs("select", {
@@ -14921,7 +15238,7 @@ function MarketplaceBrowse({ installedPluginIds = /* @__PURE__ */ new Set() }) {
14921
15238
  variant: "ghost",
14922
15239
  className: "mt-4",
14923
15240
  onClick: () => void refetch(),
14924
- children: [/* @__PURE__ */ jsx(ArrowsClockwise, { className: "mr-2 h-4 w-4" }), _t({
15241
+ children: [/* @__PURE__ */ jsx(ArrowsClockwise, { className: "me-2 h-4 w-4" }), _t({
14925
15242
  id: "6gRgw8",
14926
15243
  message: "Retry"
14927
15244
  })]
@@ -15179,7 +15496,7 @@ function CapabilityConsentDialog({ mode, pluginName, capabilities, allowedHosts,
15179
15496
  className: cn(isNew && "font-medium"),
15180
15497
  children: describeCapability(cap, allowedHosts)
15181
15498
  }), isNew && /* @__PURE__ */ jsx("span", {
15182
- className: "ml-2 text-xs text-warning font-medium",
15499
+ className: "ms-2 text-xs text-warning font-medium",
15183
15500
  children: _t({
15184
15501
  id: "p6NueD",
15185
15502
  message: "NEW"
@@ -15375,7 +15692,7 @@ function PluginManager({ manifest }) {
15375
15692
  variant: "ghost",
15376
15693
  onClick: () => void refetchUpdates(),
15377
15694
  disabled: isCheckingUpdates,
15378
- children: [/* @__PURE__ */ jsx(ArrowsClockwise, { className: cn("mr-2 h-4 w-4", isCheckingUpdates && "animate-spin") }), _t({
15695
+ children: [/* @__PURE__ */ jsx(ArrowsClockwise, { className: cn("me-2 h-4 w-4", isCheckingUpdates && "animate-spin") }), _t({
15379
15696
  id: "WMCwmR",
15380
15697
  message: "Check for updates"
15381
15698
  })]
@@ -15384,7 +15701,7 @@ function PluginManager({ manifest }) {
15384
15701
  to: "/plugins/marketplace",
15385
15702
  children: /* @__PURE__ */ jsxs(Button, {
15386
15703
  variant: "ghost",
15387
- children: [/* @__PURE__ */ jsx(Storefront, { className: "mr-2 h-4 w-4" }), _t({
15704
+ children: [/* @__PURE__ */ jsx(Storefront, { className: "me-2 h-4 w-4" }), _t({
15388
15705
  id: "Zt5PUS",
15389
15706
  message: "Marketplace"
15390
15707
  })]
@@ -15637,7 +15954,7 @@ function PluginCard({ plugin, updateInfo, onEnable, onDisable, isToggling, hasMa
15637
15954
  children: /* @__PURE__ */ jsxs(Button, {
15638
15955
  variant: "ghost",
15639
15956
  size: "sm",
15640
- children: [/* @__PURE__ */ jsx(Storefront, { className: "mr-1.5 h-3.5 w-3.5" }), _t2({
15957
+ children: [/* @__PURE__ */ jsx(Storefront, { className: "me-1.5 h-3.5 w-3.5" }), _t2({
15641
15958
  id: "w1kDNj",
15642
15959
  message: "View in Marketplace"
15643
15960
  })]
@@ -15796,7 +16113,7 @@ function PluginCard({ plugin, updateInfo, onEnable, onDisable, isToggling, hasMa
15796
16113
  className: "text-kumo-danger hover:text-kumo-danger",
15797
16114
  onClick: () => setShowUninstallConfirm(true),
15798
16115
  disabled: uninstallMutation.isPending,
15799
- children: [/* @__PURE__ */ jsx(Trash, { className: "mr-2 h-4 w-4" }), _t2({
16116
+ children: [/* @__PURE__ */ jsx(Trash, { className: "me-2 h-4 w-4" }), _t2({
15800
16117
  id: "fo0VXg",
15801
16118
  message: "Uninstall"
15802
16119
  })]
@@ -16081,7 +16398,7 @@ function MarketplacePluginDetail({ pluginId, installedPluginIds = /* @__PURE__ *
16081
16398
  })]
16082
16399
  }) : /* @__PURE__ */ jsxs(Button, {
16083
16400
  onClick: () => setShowConsent(true),
16084
- children: [/* @__PURE__ */ jsx(DownloadSimple, { className: "mr-2 h-4 w-4" }), _t({
16401
+ children: [/* @__PURE__ */ jsx(DownloadSimple, { className: "me-2 h-4 w-4" }), _t({
16085
16402
  id: "TKQ7K+",
16086
16403
  message: "Install"
16087
16404
  })]
@@ -16325,7 +16642,7 @@ function ScreenshotLightbox({ screenshots, index, isBlurred = false, onClose, on
16325
16642
  children: [
16326
16643
  /* @__PURE__ */ jsx("button", {
16327
16644
  onClick: onClose,
16328
- className: "absolute right-4 top-4 rounded-full bg-black/50 p-2 text-white hover:bg-black/70",
16645
+ className: "absolute end-4 top-4 rounded-full bg-black/50 p-2 text-white hover:bg-black/70",
16329
16646
  "aria-label": _t3({
16330
16647
  id: "yz7wBu",
16331
16648
  message: "Close"
@@ -16334,7 +16651,7 @@ function ScreenshotLightbox({ screenshots, index, isBlurred = false, onClose, on
16334
16651
  }),
16335
16652
  index > 0 && /* @__PURE__ */ jsx("button", {
16336
16653
  onClick: () => onNavigate(index - 1),
16337
- className: "absolute left-4 rounded-full bg-black/50 p-2 text-white hover:bg-black/70",
16654
+ className: "absolute start-4 rounded-full bg-black/50 p-2 text-white hover:bg-black/70",
16338
16655
  "aria-label": _t3({
16339
16656
  id: "k7xxm/",
16340
16657
  message: "Previous screenshot"
@@ -16355,7 +16672,7 @@ function ScreenshotLightbox({ screenshots, index, isBlurred = false, onClose, on
16355
16672
  }),
16356
16673
  index < screenshots.length - 1 && /* @__PURE__ */ jsx("button", {
16357
16674
  onClick: () => onNavigate(index + 1),
16358
- className: "absolute right-4 rounded-full bg-black/50 p-2 text-white hover:bg-black/70",
16675
+ className: "absolute end-4 rounded-full bg-black/50 p-2 text-white hover:bg-black/70",
16359
16676
  "aria-label": _t3({
16360
16677
  id: "tgnDjk",
16361
16678
  message: "Next screenshot"
@@ -16363,7 +16680,7 @@ function ScreenshotLightbox({ screenshots, index, isBlurred = false, onClose, on
16363
16680
  children: /* @__PURE__ */ jsx(CaretRight, { className: "h-5 w-5" })
16364
16681
  }),
16365
16682
  /* @__PURE__ */ jsxs("div", {
16366
- className: "absolute bottom-4 left-1/2 -translate-x-1/2 rounded-full bg-black/50 px-3 py-1 text-sm text-white",
16683
+ className: "absolute bottom-4 start-1/2 -translate-x-1/2 rounded-full bg-black/50 px-3 py-1 text-sm text-white",
16367
16684
  children: [
16368
16685
  index + 1,
16369
16686
  " / ",
@@ -16528,12 +16845,12 @@ function MediaDetailPanel({ item, onClose, onDeleted }) {
16528
16845
  const isVideo = item.mimeType.startsWith("video/");
16529
16846
  const isAudio = item.mimeType.startsWith("audio/");
16530
16847
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
16531
- className: cn("fixed inset-y-0 right-0 w-96 bg-kumo-base border-l shadow-xl z-50", "flex flex-col", "animate-in slide-in-from-right duration-200"),
16848
+ className: cn("fixed inset-y-0 end-0 w-96 bg-kumo-base border-s shadow-xl z-50", "flex flex-col"),
16532
16849
  children: [
16533
16850
  /* @__PURE__ */ jsxs("div", {
16534
16851
  className: "flex items-center justify-between p-4 border-b",
16535
16852
  children: [/* @__PURE__ */ jsx("h2", {
16536
- className: "font-semibold truncate pr-2",
16853
+ className: "font-semibold truncate pe-2",
16537
16854
  children: _t({
16538
16855
  id: "T9un00",
16539
16856
  message: "Media Details"
@@ -17084,7 +17401,7 @@ function MediaLibrary({ items = [], isLoading, onUpload, onDelete, onItemUpdated
17084
17401
  }),
17085
17402
  canSearch && /* @__PURE__ */ jsxs("div", {
17086
17403
  className: "relative max-w-sm",
17087
- children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
17404
+ children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute start-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
17088
17405
  type: "search",
17089
17406
  placeholder: _t({
17090
17407
  id: "YIix5Y",
@@ -17092,7 +17409,7 @@ function MediaLibrary({ items = [], isLoading, onUpload, onDelete, onItemUpdated
17092
17409
  }),
17093
17410
  value: searchQuery,
17094
17411
  onChange: (e) => setSearchQuery(e.target.value),
17095
- className: "pl-9"
17412
+ className: "ps-9"
17096
17413
  })]
17097
17414
  }),
17098
17415
  currentLoading ? /* @__PURE__ */ jsx("div", {
@@ -17193,35 +17510,35 @@ function MediaLibrary({ items = [], isLoading, onUpload, onDelete, onItemUpdated
17193
17510
  className: "border-b bg-kumo-tint/50",
17194
17511
  children: [
17195
17512
  /* @__PURE__ */ jsx("th", {
17196
- className: "px-4 py-3 text-left text-sm font-medium",
17513
+ className: "px-4 py-3 text-start text-sm font-medium",
17197
17514
  children: _t({
17198
17515
  id: "rdUucN",
17199
17516
  message: "Preview"
17200
17517
  })
17201
17518
  }),
17202
17519
  /* @__PURE__ */ jsx("th", {
17203
- className: "px-4 py-3 text-left text-sm font-medium",
17520
+ className: "px-4 py-3 text-start text-sm font-medium",
17204
17521
  children: _t({
17205
17522
  id: "GN6L5F",
17206
17523
  message: "Filename"
17207
17524
  })
17208
17525
  }),
17209
17526
  /* @__PURE__ */ jsx("th", {
17210
- className: "px-4 py-3 text-left text-sm font-medium",
17527
+ className: "px-4 py-3 text-start text-sm font-medium",
17211
17528
  children: _t({
17212
17529
  id: "+zy2Nq",
17213
17530
  message: "Type"
17214
17531
  })
17215
17532
  }),
17216
17533
  /* @__PURE__ */ jsx("th", {
17217
- className: "px-4 py-3 text-left text-sm font-medium",
17534
+ className: "px-4 py-3 text-start text-sm font-medium",
17218
17535
  children: _t({
17219
17536
  id: "Cj2Gtd",
17220
17537
  message: "Size"
17221
17538
  })
17222
17539
  }),
17223
17540
  /* @__PURE__ */ jsx("th", {
17224
- className: "px-4 py-3 text-right text-sm font-medium",
17541
+ className: "px-4 py-3 text-end text-sm font-medium",
17225
17542
  children: _t({
17226
17543
  id: "7L01XJ",
17227
17544
  message: "Actions"
@@ -17274,7 +17591,7 @@ function MediaGridItem({ item, selected, onClick }) {
17274
17591
  return /* @__PURE__ */ jsxs("button", {
17275
17592
  type: "button",
17276
17593
  onClick,
17277
- className: cn("group relative overflow-hidden rounded-lg border bg-kumo-base text-left transition-all max-w-[200px]", selected ? "ring-2 ring-kumo-brand border-kumo-brand" : "hover:border-kumo-brand/50"),
17594
+ className: cn("group relative overflow-hidden rounded-lg border bg-kumo-base text-start transition-all max-w-[200px]", selected ? "ring-2 ring-kumo-brand border-kumo-brand" : "hover:border-kumo-brand/50"),
17278
17595
  children: [/* @__PURE__ */ jsx("div", {
17279
17596
  className: "aspect-square",
17280
17597
  children: isImage ? /* @__PURE__ */ jsx("img", {
@@ -17309,7 +17626,7 @@ function ProviderGridItem({ item, selected, onClick, onDimensionsLoaded }) {
17309
17626
  return /* @__PURE__ */ jsxs("button", {
17310
17627
  type: "button",
17311
17628
  onClick,
17312
- className: cn("group relative overflow-hidden rounded-lg border bg-kumo-base text-left transition-all max-w-[200px]", selected ? "ring-2 ring-kumo-brand border-kumo-brand" : "hover:border-kumo-brand/50"),
17629
+ className: cn("group relative overflow-hidden rounded-lg border bg-kumo-base text-start transition-all max-w-[200px]", selected ? "ring-2 ring-kumo-brand border-kumo-brand" : "hover:border-kumo-brand/50"),
17313
17630
  children: [/* @__PURE__ */ jsx("div", {
17314
17631
  className: "aspect-square",
17315
17632
  children: isImage && item.previewUrl ? /* @__PURE__ */ jsx("img", {
@@ -17370,7 +17687,7 @@ function MediaListItem({ item, selected, onClick }) {
17370
17687
  children: formatFileSize(item.size)
17371
17688
  }),
17372
17689
  /* @__PURE__ */ jsx("td", {
17373
- className: "px-4 py-3 text-right",
17690
+ className: "px-4 py-3 text-end",
17374
17691
  children: /* @__PURE__ */ jsx("span", {
17375
17692
  className: "text-sm text-kumo-subtle",
17376
17693
  children: item.alt ? _t2({
@@ -17424,7 +17741,7 @@ function ProviderListItem({ item, selected, onClick, onDimensionsLoaded }) {
17424
17741
  children: item.size ? formatFileSize(item.size) : "—"
17425
17742
  }),
17426
17743
  /* @__PURE__ */ jsx("td", {
17427
- className: "px-4 py-3 text-right",
17744
+ className: "px-4 py-3 text-end",
17428
17745
  children: /* @__PURE__ */ jsx("span", {
17429
17746
  className: "text-sm text-kumo-subtle",
17430
17747
  children: item.alt ? _t3({
@@ -17547,7 +17864,7 @@ function ContentPickerModal({ open, onOpenChange, onSelect }) {
17547
17864
  id: "yz7wBu",
17548
17865
  message: "Close"
17549
17866
  }),
17550
- className: "absolute right-4 top-4",
17867
+ className: "absolute end-4 top-4",
17551
17868
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
17552
17869
  className: "sr-only",
17553
17870
  children: _t({
@@ -17562,14 +17879,14 @@ function ContentPickerModal({ open, onOpenChange, onSelect }) {
17562
17879
  className: "flex items-center gap-4 py-4 border-b",
17563
17880
  children: [/* @__PURE__ */ jsxs("div", {
17564
17881
  className: "relative flex-1",
17565
- children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
17882
+ children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute start-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
17566
17883
  placeholder: _t({
17567
17884
  id: "uqgkuX",
17568
17885
  message: "Search content..."
17569
17886
  }),
17570
17887
  value: searchQuery,
17571
17888
  onChange: (e) => setSearchQuery(e.target.value),
17572
- className: "pl-10",
17889
+ className: "ps-10",
17573
17890
  autoFocus: true
17574
17891
  })]
17575
17892
  }), /* @__PURE__ */ jsx("select", {
@@ -17629,7 +17946,7 @@ function ContentPickerModal({ open, onOpenChange, onSelect }) {
17629
17946
  return /* @__PURE__ */ jsxs("button", {
17630
17947
  type: "button",
17631
17948
  onClick: () => handleSelect(item),
17632
- className: cn("w-full text-left rounded-md px-3 py-2 transition-colors", "hover:bg-kumo-tint/50", "focus:outline-none focus:ring-2 focus:ring-kumo-ring focus:ring-offset-2"),
17949
+ className: cn("w-full text-start rounded-md px-3 py-2 transition-colors", "hover:bg-kumo-tint/50", "focus:outline-none focus:ring-2 focus:ring-kumo-ring focus:ring-offset-2"),
17633
17950
  children: [/* @__PURE__ */ jsx("div", {
17634
17951
  className: "font-medium",
17635
17952
  children: getItemTitle(item)
@@ -17960,7 +18277,7 @@ function MenuEditor() {
17960
18277
  id: "yz7wBu",
17961
18278
  message: "Close"
17962
18279
  }),
17963
- className: "absolute right-4 top-4",
18280
+ className: "absolute end-4 top-4",
17964
18281
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
17965
18282
  className: "sr-only",
17966
18283
  children: _t({
@@ -18206,7 +18523,7 @@ function MenuEditor() {
18206
18523
  id: "yz7wBu",
18207
18524
  message: "Close"
18208
18525
  }),
18209
- className: "absolute right-4 top-4",
18526
+ className: "absolute end-4 top-4",
18210
18527
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
18211
18528
  className: "sr-only",
18212
18529
  children: _t({
@@ -18444,7 +18761,7 @@ function MenuList() {
18444
18761
  id: "yz7wBu",
18445
18762
  message: "Close"
18446
18763
  }),
18447
- className: "absolute right-4 top-4",
18764
+ className: "absolute end-4 top-4",
18448
18765
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
18449
18766
  className: "sr-only",
18450
18767
  children: _t({
@@ -18580,7 +18897,7 @@ function MenuList() {
18580
18897
  variant: "outline",
18581
18898
  size: "sm"
18582
18899
  }),
18583
- children: [/* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4 mr-2" }), _t({
18900
+ children: [/* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4 me-2" }), _t({
18584
18901
  id: "ePK91l",
18585
18902
  message: "Edit"
18586
18903
  })]
@@ -18705,7 +19022,7 @@ function RedirectFormDialog({ open, onClose, redirect, defaultSource }) {
18705
19022
  id: "yz7wBu",
18706
19023
  message: "Close"
18707
19024
  }),
18708
- className: "absolute right-4 top-4",
19025
+ className: "absolute end-4 top-4",
18709
19026
  children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
18710
19027
  })
18711
19028
  })]
@@ -18856,7 +19173,7 @@ function NotFoundPanel({ items, onCreateRedirect }) {
18856
19173
  })
18857
19174
  }),
18858
19175
  /* @__PURE__ */ jsx("div", {
18859
- className: "w-16 text-right",
19176
+ className: "w-16 text-end",
18860
19177
  children: _t2({
18861
19178
  id: "m8rC/C",
18862
19179
  message: "Hits"
@@ -18879,7 +19196,7 @@ function NotFoundPanel({ items, onCreateRedirect }) {
18879
19196
  children: item.path
18880
19197
  }),
18881
19198
  /* @__PURE__ */ jsx("div", {
18882
- className: "w-16 text-right tabular-nums",
19199
+ className: "w-16 text-end tabular-nums",
18883
19200
  children: item.count
18884
19201
  }),
18885
19202
  /* @__PURE__ */ jsx("div", {
@@ -19006,7 +19323,7 @@ function Redirects() {
19006
19323
  message: "Redirects"
19007
19324
  }), redirectsQuery.data && /* @__PURE__ */ jsxs(Badge, {
19008
19325
  variant: "secondary",
19009
- className: "ml-2",
19326
+ className: "ms-2",
19010
19327
  children: [redirectsQuery.data.items.length, redirectsQuery.data.nextCursor ? "+" : ""]
19011
19328
  })]
19012
19329
  }), /* @__PURE__ */ jsx("button", {
@@ -19025,14 +19342,14 @@ function Redirects() {
19025
19342
  /* @__PURE__ */ jsxs("div", {
19026
19343
  className: "relative flex-1 max-w-md",
19027
19344
  children: [/* @__PURE__ */ jsx(MagnifyingGlass, {
19028
- className: "absolute left-3 top-1/2 -translate-y-1/2 text-kumo-subtle",
19345
+ className: "absolute start-3 top-1/2 -translate-y-1/2 text-kumo-subtle",
19029
19346
  size: 16
19030
19347
  }), /* @__PURE__ */ jsx(Input, {
19031
19348
  placeholder: _t3({
19032
19349
  id: "coyvwq",
19033
19350
  message: "Search source or destination..."
19034
19351
  }),
19035
- className: "pl-10",
19352
+ className: "ps-10",
19036
19353
  value: search,
19037
19354
  onChange: (e) => setSearch(e.target.value)
19038
19355
  })]
@@ -19181,7 +19498,7 @@ function Redirects() {
19181
19498
  })
19182
19499
  }),
19183
19500
  /* @__PURE__ */ jsx("div", {
19184
- className: "w-16 text-right",
19501
+ className: "w-16 text-end",
19185
19502
  children: _t3({
19186
19503
  id: "m8rC/C",
19187
19504
  message: "Hits"
@@ -19221,7 +19538,7 @@ function Redirects() {
19221
19538
  })
19222
19539
  }),
19223
19540
  /* @__PURE__ */ jsx("div", {
19224
- className: "w-16 text-right tabular-nums text-kumo-subtle",
19541
+ className: "w-16 text-end tabular-nums text-kumo-subtle",
19225
19542
  children: r.hits
19226
19543
  }),
19227
19544
  /* @__PURE__ */ jsx("div", {
@@ -19249,7 +19566,7 @@ function Redirects() {
19249
19566
  id: "Ny5fJL",
19250
19567
  message: "Part of a redirect loop"
19251
19568
  }),
19252
- className: "mr-1 inline-flex",
19569
+ className: "me-1 inline-flex",
19253
19570
  children: /* @__PURE__ */ jsx(WarningCircle, {
19254
19571
  size: 14,
19255
19572
  weight: "fill",
@@ -19263,7 +19580,7 @@ function Redirects() {
19263
19580
  }),
19264
19581
  r.auto && /* @__PURE__ */ jsx(Badge, {
19265
19582
  variant: "outline",
19266
- className: "mr-1 text-xs",
19583
+ className: "me-1 text-xs",
19267
19584
  children: _t3({
19268
19585
  id: "VS9ghV",
19269
19586
  message: "auto"
@@ -19417,7 +19734,7 @@ function SandboxedPluginPage({ pluginId, page }) {
19417
19734
  return /* @__PURE__ */ jsxs("div", {
19418
19735
  className: "relative",
19419
19736
  children: [toast && /* @__PURE__ */ jsx("div", {
19420
- className: `fixed right-4 top-4 z-50 rounded-lg border px-4 py-3 text-sm shadow-lg ${toast.type === "success" ? "border-green-200 bg-green-50 text-green-800" : toast.type === "error" ? "border-red-200 bg-red-50 text-red-800" : "border-blue-200 bg-blue-50 text-blue-800"}`,
19737
+ className: `fixed end-4 top-4 z-50 rounded-lg border px-4 py-3 text-sm shadow-lg ${toast.type === "success" ? "border-green-200 bg-green-50 text-green-800" : toast.type === "error" ? "border-red-200 bg-red-50 text-red-800" : "border-blue-200 bg-blue-50 text-blue-800"}`,
19421
19738
  children: toast.message
19422
19739
  }), /* @__PURE__ */ jsx(BlockRenderer, {
19423
19740
  blocks,
@@ -19878,7 +20195,7 @@ function Sections() {
19878
20195
  id: "yz7wBu",
19879
20196
  message: "Close"
19880
20197
  }),
19881
- className: "absolute right-4 top-4",
20198
+ className: "absolute end-4 top-4",
19882
20199
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
19883
20200
  className: "sr-only",
19884
20201
  children: _t({
@@ -19972,14 +20289,14 @@ function Sections() {
19972
20289
  className: "flex items-center gap-4",
19973
20290
  children: [/* @__PURE__ */ jsxs("div", {
19974
20291
  className: "relative flex-1 max-w-md",
19975
- children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
20292
+ children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute start-3 top-1/2 -translate-y-1/2 h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsx(Input, {
19976
20293
  placeholder: _t({
19977
20294
  id: "qPx4oA",
19978
20295
  message: "Search sections..."
19979
20296
  }),
19980
20297
  value: searchQuery,
19981
20298
  onChange: (e) => setSearchQuery(e.target.value),
19982
- className: "pl-10"
20299
+ className: "ps-10"
19983
20300
  })]
19984
20301
  }), /* @__PURE__ */ jsxs("select", {
19985
20302
  value: selectedSource || "",
@@ -20943,7 +21260,7 @@ function AllowedDomainsSettings() {
20943
21260
  id: "yz7wBu",
20944
21261
  message: "Close"
20945
21262
  }),
20946
- className: "absolute right-4 top-4",
21263
+ className: "absolute end-4 top-4",
20947
21264
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
20948
21265
  className: "sr-only",
20949
21266
  children: _t({
@@ -23553,7 +23870,7 @@ function StepIndicator$1({ currentStep, useAccessAuth }) {
23553
23870
  })
23554
23871
  }) : index + 1
23555
23872
  }), /* @__PURE__ */ jsx("span", {
23556
- className: `ml-2 text-sm ${index <= currentIndex ? "text-kumo-default" : "text-kumo-subtle"}`,
23873
+ className: `ms-2 text-sm ${index <= currentIndex ? "text-kumo-default" : "text-kumo-subtle"}`,
23557
23874
  children: step.label
23558
23875
  })]
23559
23876
  }), index < steps.length - 1 && /* @__PURE__ */ jsx("div", { className: `w-12 h-0.5 mx-2 ${index < currentIndex ? "bg-kumo-brand" : "bg-kumo-tint"}` })] }, step.key))
@@ -23569,6 +23886,10 @@ function SetupWizard() {
23569
23886
  queryFn: fetchSetupStatus,
23570
23887
  retry: false
23571
23888
  });
23889
+ const { data: manifest } = useQuery({
23890
+ queryKey: ["manifest"],
23891
+ queryFn: fetchManifest
23892
+ });
23572
23893
  const useAccessAuth = status?.authMode === "cloudflare-access";
23573
23894
  const siteMutation = useMutation({
23574
23895
  mutationFn: executeSiteSetup,
@@ -23647,7 +23968,11 @@ function SetupWizard() {
23647
23968
  /* @__PURE__ */ jsxs("div", {
23648
23969
  className: "text-center mb-6",
23649
23970
  children: [
23650
- /* @__PURE__ */ jsx(LogoLockup, { className: "h-10 mx-auto mb-2" }),
23971
+ /* @__PURE__ */ jsx(BrandLogo, {
23972
+ logoUrl: manifest?.admin?.logo,
23973
+ siteName: manifest?.admin?.siteName,
23974
+ className: "h-10 mx-auto mb-2"
23975
+ }),
23651
23976
  /* @__PURE__ */ jsxs("h1", {
23652
23977
  className: "text-2xl font-semibold text-kumo-default",
23653
23978
  children: [
@@ -24103,7 +24428,7 @@ function NavMenuLink({ item, isActive }) {
24103
24428
  className: cn("emdash-nav-icon size-[18px] shrink-0 transition-colors duration-200", isActive ? "text-white" : "text-white/60 group-hover/menu-button:text-white/90"),
24104
24429
  "aria-hidden": "true"
24105
24430
  }), /* @__PURE__ */ jsxs("span", {
24106
- className: "emdash-nav-label flex flex-1 items-center min-w-0 text-left overflow-hidden",
24431
+ className: "emdash-nav-label flex flex-1 items-center min-w-0 text-start overflow-hidden",
24107
24432
  children: [item.label, item.badge != null && item.badge > 0 && /* @__PURE__ */ jsx(KumoSidebar.MenuBadge, { children: item.badge })]
24108
24433
  })]
24109
24434
  });
@@ -24431,12 +24756,14 @@ function SidebarNav({ manifest }) {
24431
24756
  /* @__PURE__ */ jsx(KumoSidebar.Header, { children: /* @__PURE__ */ jsxs(Link$1, {
24432
24757
  to: "/",
24433
24758
  className: "emdash-brand-link flex w-full min-w-0 items-center gap-2 px-3 py-1",
24434
- children: [/* @__PURE__ */ jsx(LogoIcon, {
24759
+ children: [/* @__PURE__ */ jsx(BrandIcon, {
24760
+ logoUrl: manifest.admin?.logo,
24761
+ siteName: manifest.admin?.siteName,
24435
24762
  className: "size-5 shrink-0",
24436
24763
  "aria-hidden": "true"
24437
24764
  }), /* @__PURE__ */ jsx("span", {
24438
24765
  className: "emdash-brand-text font-semibold truncate",
24439
- children: "EmDash"
24766
+ children: manifest.admin?.siteName || "EmDash"
24440
24767
  })]
24441
24768
  }) }),
24442
24769
  /* @__PURE__ */ jsxs(KumoSidebar.Content, { children: [
@@ -24455,42 +24782,55 @@ function SidebarNav({ manifest }) {
24455
24782
  visibleContent.length > 1 && /* @__PURE__ */ jsxs(KumoSidebar.Group, {
24456
24783
  collapsible: true,
24457
24784
  defaultOpen: true,
24458
- children: [/* @__PURE__ */ jsx(KumoSidebar.GroupLabel, { children: _t({
24459
- id: "4b3oEV",
24460
- message: "Content"
24461
- }) }), /* @__PURE__ */ jsx(KumoSidebar.GroupContent, { children: /* @__PURE__ */ jsx(KumoSidebar.Menu, { children: renderNavItems(visibleContent.filter((i) => i.to !== "/")) }) })]
24785
+ children: [/* @__PURE__ */ jsx(KumoSidebar.GroupLabel, {
24786
+ className: "[&>span]:text-start",
24787
+ children: _t({
24788
+ id: "4b3oEV",
24789
+ message: "Content"
24790
+ })
24791
+ }), /* @__PURE__ */ jsx(KumoSidebar.GroupContent, { children: /* @__PURE__ */ jsx(KumoSidebar.Menu, { children: renderNavItems(visibleContent.filter((i) => i.to !== "/")) }) })]
24462
24792
  }),
24463
24793
  /* @__PURE__ */ jsx(KumoSidebar.Separator, {}),
24464
24794
  visibleManage.length > 0 && /* @__PURE__ */ jsxs(KumoSidebar.Group, {
24465
24795
  collapsible: true,
24466
24796
  defaultOpen: true,
24467
- children: [/* @__PURE__ */ jsx(KumoSidebar.GroupLabel, { children: _t({
24468
- id: "wckWOP",
24469
- message: "Manage"
24470
- }) }), /* @__PURE__ */ jsx(KumoSidebar.GroupContent, { children: /* @__PURE__ */ jsx(KumoSidebar.Menu, { children: renderNavItems(visibleManage) }) })]
24797
+ children: [/* @__PURE__ */ jsx(KumoSidebar.GroupLabel, {
24798
+ className: "[&>span]:text-start",
24799
+ children: _t({
24800
+ id: "wckWOP",
24801
+ message: "Manage"
24802
+ })
24803
+ }), /* @__PURE__ */ jsx(KumoSidebar.GroupContent, { children: /* @__PURE__ */ jsx(KumoSidebar.Menu, { children: renderNavItems(visibleManage) }) })]
24471
24804
  }),
24472
24805
  /* @__PURE__ */ jsx(KumoSidebar.Separator, {}),
24473
24806
  visibleAdmin.length > 0 && /* @__PURE__ */ jsxs(KumoSidebar.Group, {
24474
24807
  collapsible: true,
24475
24808
  defaultOpen: true,
24476
- children: [/* @__PURE__ */ jsx(KumoSidebar.GroupLabel, { children: _t({
24477
- id: "U3pytU",
24478
- message: "Admin"
24479
- }) }), /* @__PURE__ */ jsx(KumoSidebar.GroupContent, { children: /* @__PURE__ */ jsx(KumoSidebar.Menu, { children: renderNavItems(visibleAdmin) }) })]
24809
+ children: [/* @__PURE__ */ jsx(KumoSidebar.GroupLabel, {
24810
+ className: "[&>span]:text-start",
24811
+ children: _t({
24812
+ id: "U3pytU",
24813
+ message: "Admin"
24814
+ })
24815
+ }), /* @__PURE__ */ jsx(KumoSidebar.GroupContent, { children: /* @__PURE__ */ jsx(KumoSidebar.Menu, { children: renderNavItems(visibleAdmin) }) })]
24480
24816
  }),
24481
24817
  visiblePlugins.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(KumoSidebar.Separator, {}), /* @__PURE__ */ jsxs(KumoSidebar.Group, {
24482
24818
  collapsible: true,
24483
24819
  defaultOpen: true,
24484
- children: [/* @__PURE__ */ jsx(KumoSidebar.GroupLabel, { children: _t({
24485
- id: "ohUJJM",
24486
- message: "Plugins"
24487
- }) }), /* @__PURE__ */ jsx(KumoSidebar.GroupContent, { children: /* @__PURE__ */ jsx(KumoSidebar.Menu, { children: renderNavItems(visiblePlugins) }) })]
24820
+ children: [/* @__PURE__ */ jsx(KumoSidebar.GroupLabel, {
24821
+ className: "[&>span]:text-start",
24822
+ children: _t({
24823
+ id: "ohUJJM",
24824
+ message: "Plugins"
24825
+ })
24826
+ }), /* @__PURE__ */ jsx(KumoSidebar.GroupContent, { children: /* @__PURE__ */ jsx(KumoSidebar.Menu, { children: renderNavItems(visiblePlugins) }) })]
24488
24827
  })] })
24489
24828
  ] }),
24490
24829
  /* @__PURE__ */ jsx(KumoSidebar.Footer, { children: /* @__PURE__ */ jsxs("p", {
24491
24830
  className: "emdash-nav-label px-3 py-2 text-[11px] text-white/30",
24492
24831
  children: [
24493
- "EmDash CMS v",
24832
+ manifest.admin?.siteName || "EmDash CMS",
24833
+ " v",
24494
24834
  manifest.version || "0.0.0",
24495
24835
  manifest.commit && ` (${manifest.commit})`
24496
24836
  ]
@@ -24583,7 +24923,7 @@ function Header() {
24583
24923
  const initials = ((user?.name || user?.email || "U")[0] ?? "U").toUpperCase();
24584
24924
  return /* @__PURE__ */ jsxs("header", {
24585
24925
  className: "sticky top-0 z-10 flex h-16 items-center justify-between border-b bg-kumo-base px-4",
24586
- children: [/* @__PURE__ */ jsx(KumoSidebar.Trigger, { className: "cursor-pointer" }), /* @__PURE__ */ jsxs("div", {
24926
+ children: [/* @__PURE__ */ jsx(KumoSidebar.Trigger, { className: "cursor-pointer rtl:rotate-180" }), /* @__PURE__ */ jsxs("div", {
24587
24927
  className: "flex items-center gap-2",
24588
24928
  children: [
24589
24929
  /* @__PURE__ */ jsxs(LinkButton, {
@@ -24591,7 +24931,7 @@ function Header() {
24591
24931
  size: "sm",
24592
24932
  href: "/",
24593
24933
  external: true,
24594
- children: [/* @__PURE__ */ jsx(ArrowSquareOut, { className: "h-4 w-4 mr-1" }), _t({
24934
+ children: [/* @__PURE__ */ jsx(ArrowSquareOut, { className: "h-4 w-4 me-1" }), _t({
24595
24935
  id: "4/SFQS",
24596
24936
  message: "View Site"
24597
24937
  })]
@@ -24657,7 +24997,7 @@ function Header() {
24657
24997
  /* @__PURE__ */ jsx("hr", { className: "my-1" }),
24658
24998
  /* @__PURE__ */ jsxs("button", {
24659
24999
  onClick: handleLogout,
24660
- className: "flex items-center gap-2 rounded-md px-3 py-2 text-sm text-kumo-danger hover:bg-kumo-danger/10 w-full text-left",
25000
+ className: "flex items-center gap-2 rounded-md px-3 py-2 text-sm text-kumo-danger hover:bg-kumo-danger/10 w-full text-start",
24661
25001
  children: [/* @__PURE__ */ jsx(SignOut, { className: "h-4 w-4" }), _t({
24662
25002
  id: "FgAxTj",
24663
25003
  message: "Log out"
@@ -24800,7 +25140,7 @@ function WelcomeModal({ open, onClose, userName, userRole }) {
24800
25140
  variant: "ghost",
24801
25141
  shape: "square",
24802
25142
  "aria-label": _t(MSG_CLOSE),
24803
- className: "absolute right-4 top-4",
25143
+ className: "absolute end-4 top-4",
24804
25144
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
24805
25145
  className: "sr-only",
24806
25146
  children: _t(MSG_CLOSE)
@@ -25454,7 +25794,7 @@ function TermRow({ term, level = 0, onEdit, onDelete }) {
25454
25794
  className: "font-medium",
25455
25795
  children: term.label
25456
25796
  }), /* @__PURE__ */ jsxs("span", {
25457
- className: "text-sm text-kumo-subtle ml-2",
25797
+ className: "text-sm text-kumo-subtle ms-2",
25458
25798
  children: [
25459
25799
  "(",
25460
25800
  term.slug,
@@ -25621,7 +25961,7 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
25621
25961
  id: "yz7wBu",
25622
25962
  message: "Close"
25623
25963
  }),
25624
- className: "absolute right-4 top-4",
25964
+ className: "absolute end-4 top-4",
25625
25965
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
25626
25966
  className: "sr-only",
25627
25967
  children: _t2({
@@ -25847,7 +26187,7 @@ function CreateTaxonomyDialog({ open, onClose, onCreated }) {
25847
26187
  id: "yz7wBu",
25848
26188
  message: "Close"
25849
26189
  }),
25850
- className: "absolute right-4 top-4",
26190
+ className: "absolute end-4 top-4",
25851
26191
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
25852
26192
  className: "sr-only",
25853
26193
  children: _t3({
@@ -26232,7 +26572,7 @@ function ThemeMarketplaceBrowse() {
26232
26572
  className: "flex flex-col gap-3 sm:flex-row sm:items-center",
26233
26573
  children: [/* @__PURE__ */ jsxs("div", {
26234
26574
  className: "relative flex-1",
26235
- children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-kumo-subtle" }), /* @__PURE__ */ jsx("input", {
26575
+ children: [/* @__PURE__ */ jsx(MagnifyingGlass, { className: "absolute start-3 top-1/2 h-4 w-4 -translate-y-1/2 text-kumo-subtle" }), /* @__PURE__ */ jsx("input", {
26236
26576
  type: "search",
26237
26577
  placeholder: _t({
26238
26578
  id: "uD5EVk",
@@ -26240,7 +26580,7 @@ function ThemeMarketplaceBrowse() {
26240
26580
  }),
26241
26581
  value: searchQuery,
26242
26582
  onChange: (e) => setSearchQuery(e.target.value),
26243
- className: "w-full rounded-md border bg-kumo-base px-3 py-2 pl-9 text-sm placeholder:text-kumo-subtle focus:outline-none focus:ring-2 focus:ring-kumo-ring"
26583
+ className: "w-full rounded-md border bg-kumo-base px-3 py-2 ps-9 text-sm placeholder:text-kumo-subtle focus:outline-none focus:ring-2 focus:ring-kumo-ring"
26244
26584
  })]
26245
26585
  }), /* @__PURE__ */ jsx("select", {
26246
26586
  value: sort,
@@ -26281,7 +26621,7 @@ function ThemeMarketplaceBrowse() {
26281
26621
  variant: "ghost",
26282
26622
  className: "mt-4",
26283
26623
  onClick: () => void refetch(),
26284
- children: [/* @__PURE__ */ jsx(ArrowsClockwise, { className: "mr-2 h-4 w-4" }), _t({
26624
+ children: [/* @__PURE__ */ jsx(ArrowsClockwise, { className: "me-2 h-4 w-4" }), _t({
26285
26625
  id: "6gRgw8",
26286
26626
  message: "Retry"
26287
26627
  })]
@@ -26404,7 +26744,7 @@ function ThemeCard({ theme }) {
26404
26744
  previewMutation.mutate();
26405
26745
  },
26406
26746
  disabled: previewMutation.isPending,
26407
- children: [/* @__PURE__ */ jsx(Eye, { className: "mr-1.5 h-3.5 w-3.5" }), previewMutation.isPending ? _t2({
26747
+ children: [/* @__PURE__ */ jsx(Eye, { className: "me-1.5 h-3.5 w-3.5" }), previewMutation.isPending ? _t2({
26408
26748
  id: "Z3FXyt",
26409
26749
  message: "Loading..."
26410
26750
  }) : _t2({
@@ -26415,7 +26755,7 @@ function ThemeCard({ theme }) {
26415
26755
  variant: "ghost",
26416
26756
  size: "sm",
26417
26757
  onClick: () => window.open(theme.demoUrl, "_blank", "noopener"),
26418
- children: [/* @__PURE__ */ jsx(ArrowSquareOut, { className: "mr-1.5 h-3.5 w-3.5" }), _t2({
26758
+ children: [/* @__PURE__ */ jsx(ArrowSquareOut, { className: "me-1.5 h-3.5 w-3.5" }), _t2({
26419
26759
  id: "kc+zZA",
26420
26760
  message: "Demo"
26421
26761
  })]
@@ -26550,7 +26890,7 @@ function ThemeMarketplaceDetail({ themeId }) {
26550
26890
  variant: "primary",
26551
26891
  onClick: () => previewMutation.mutate(),
26552
26892
  disabled: previewMutation.isPending,
26553
- children: [/* @__PURE__ */ jsx(Eye, { className: "mr-2 h-4 w-4" }), previewMutation.isPending ? _t({
26893
+ children: [/* @__PURE__ */ jsx(Eye, { className: "me-2 h-4 w-4" }), previewMutation.isPending ? _t({
26554
26894
  id: "Z3FXyt",
26555
26895
  message: "Loading..."
26556
26896
  }) : _t({
@@ -26560,7 +26900,7 @@ function ThemeMarketplaceDetail({ themeId }) {
26560
26900
  }), theme.demoUrl && isSafeUrl(theme.demoUrl) && /* @__PURE__ */ jsxs(Button, {
26561
26901
  variant: "outline",
26562
26902
  onClick: () => window.open(theme.demoUrl, "_blank", "noopener"),
26563
- children: [/* @__PURE__ */ jsx(ArrowSquareOut, { className: "mr-2 h-4 w-4" }), _t({
26903
+ children: [/* @__PURE__ */ jsx(ArrowSquareOut, { className: "me-2 h-4 w-4" }), _t({
26564
26904
  id: "kc+zZA",
26565
26905
  message: "Demo"
26566
26906
  })]
@@ -26698,7 +27038,7 @@ function Lightbox({ urls, index, onClose, onPrev, onNext }) {
26698
27038
  }),
26699
27039
  /* @__PURE__ */ jsx("button", {
26700
27040
  onClick: onClose,
26701
- className: "absolute -top-3 -right-3 rounded-full bg-kumo-base p-1.5 shadow-lg hover:bg-kumo-tint",
27041
+ className: "absolute -top-3 -end-3 rounded-full bg-kumo-base p-1.5 shadow-lg hover:bg-kumo-tint",
26702
27042
  "aria-label": _t2({
26703
27043
  id: "yz7wBu",
26704
27044
  message: "Close"
@@ -26707,7 +27047,7 @@ function Lightbox({ urls, index, onClose, onPrev, onNext }) {
26707
27047
  }),
26708
27048
  urls.length > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("button", {
26709
27049
  onClick: onPrev,
26710
- className: "absolute left-2 top-1/2 -translate-y-1/2 rounded-full bg-kumo-base/80 p-2 shadow hover:bg-kumo-base",
27050
+ className: "absolute start-2 top-1/2 -translate-y-1/2 rounded-full bg-kumo-base/80 p-2 shadow hover:bg-kumo-base",
26711
27051
  "aria-label": _t2({
26712
27052
  id: "DHhJ7s",
26713
27053
  message: "Previous"
@@ -26715,7 +27055,7 @@ function Lightbox({ urls, index, onClose, onPrev, onNext }) {
26715
27055
  children: /* @__PURE__ */ jsx(CaretLeft, { className: "h-5 w-5" })
26716
27056
  }), /* @__PURE__ */ jsx("button", {
26717
27057
  onClick: onNext,
26718
- className: "absolute right-2 top-1/2 -translate-y-1/2 rounded-full bg-kumo-base/80 p-2 shadow hover:bg-kumo-base",
27058
+ className: "absolute end-2 top-1/2 -translate-y-1/2 rounded-full bg-kumo-base/80 p-2 shadow hover:bg-kumo-base",
26719
27059
  "aria-label": _t2({
26720
27060
  id: "hXzOVo",
26721
27061
  message: "Next"
@@ -26723,7 +27063,7 @@ function Lightbox({ urls, index, onClose, onPrev, onNext }) {
26723
27063
  children: /* @__PURE__ */ jsx(CaretRight, { className: "h-5 w-5" })
26724
27064
  })] }),
26725
27065
  /* @__PURE__ */ jsxs("div", {
26726
- className: "absolute bottom-2 left-1/2 -translate-x-1/2 rounded-full bg-kumo-base/80 px-3 py-1 text-xs",
27066
+ className: "absolute bottom-2 start-1/2 -translate-x-1/2 rounded-full bg-kumo-base/80 px-3 py-1 text-xs",
26727
27067
  children: [
26728
27068
  index + 1,
26729
27069
  " / ",
@@ -26735,6 +27075,18 @@ function Lightbox({ urls, index, onClose, onPrev, onNext }) {
26735
27075
  });
26736
27076
  }
26737
27077
 
27078
+ //#endregion
27079
+ //#region src/lib/pluginBlocks.ts
27080
+ /** Extract plugin block definitions from the manifest for the Portable Text editor. */
27081
+ function getPluginBlocks(manifest) {
27082
+ const blocks = [];
27083
+ for (const [pluginId, plugin] of Object.entries(manifest.plugins)) if (plugin.portableTextBlocks) for (const block of plugin.portableTextBlocks) blocks.push({
27084
+ ...block,
27085
+ pluginId
27086
+ });
27087
+ return blocks;
27088
+ }
27089
+
26738
27090
  //#endregion
26739
27091
  //#region src/components/Widgets.tsx
26740
27092
  /**
@@ -26789,6 +27141,11 @@ function Widgets() {
26789
27141
  queryKey: ["widget-components"],
26790
27142
  queryFn: fetchWidgetComponents
26791
27143
  });
27144
+ const { data: manifest } = useQuery({
27145
+ queryKey: ["manifest"],
27146
+ queryFn: fetchManifest
27147
+ });
27148
+ const pluginBlocks = React.useMemo(() => manifest ? getPluginBlocks(manifest) : [], [manifest]);
26792
27149
  const createAreaMutation = useMutation({
26793
27150
  mutationFn: createWidgetArea,
26794
27151
  onSuccess: () => {
@@ -26948,7 +27305,7 @@ function Widgets() {
26948
27305
  variant: "ghost",
26949
27306
  shape: "square",
26950
27307
  "aria-label": "Close",
26951
- className: "absolute right-4 top-4",
27308
+ className: "absolute end-4 top-4",
26952
27309
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
26953
27310
  className: "sr-only",
26954
27311
  children: "Close"
@@ -27046,7 +27403,8 @@ function Widgets() {
27046
27403
  expandedWidgets,
27047
27404
  onToggleWidget: toggleWidget,
27048
27405
  isDraggingPalette: activeDragData !== null && isPaletteItem(activeDragData),
27049
- components
27406
+ components,
27407
+ pluginBlocks
27050
27408
  }, area.id))
27051
27409
  })]
27052
27410
  })]
@@ -27106,7 +27464,7 @@ function DraggablePaletteItem({ id, label, description, widgetInput }) {
27106
27464
  })]
27107
27465
  });
27108
27466
  }
27109
- function WidgetAreaPanel({ area, expandedWidgets, onToggleWidget, isDraggingPalette, components }) {
27467
+ function WidgetAreaPanel({ area, expandedWidgets, onToggleWidget, isDraggingPalette, components, pluginBlocks }) {
27110
27468
  const queryClient = useQueryClient();
27111
27469
  const toastManager = Toast.useToastManager();
27112
27470
  const [deleteAreaName, setDeleteAreaName] = React.useState(null);
@@ -27151,7 +27509,8 @@ function WidgetAreaPanel({ area, expandedWidgets, onToggleWidget, isDraggingPale
27151
27509
  areaName: area.name,
27152
27510
  isExpanded: expandedWidgets.has(widget.id),
27153
27511
  onToggle: () => onToggleWidget(widget.id),
27154
- components
27512
+ components,
27513
+ pluginBlocks
27155
27514
  }, widget.id))
27156
27515
  }) : null,
27157
27516
  isDraggingPalette && /* @__PURE__ */ jsx("div", {
@@ -27181,7 +27540,7 @@ function WidgetAreaPanel({ area, expandedWidgets, onToggleWidget, isDraggingPale
27181
27540
  ]
27182
27541
  });
27183
27542
  }
27184
- function WidgetItem({ widget, areaName, isExpanded, onToggle, components }) {
27543
+ function WidgetItem({ widget, areaName, isExpanded, onToggle, components, pluginBlocks }) {
27185
27544
  const queryClient = useQueryClient();
27186
27545
  const toastManager = Toast.useToastManager();
27187
27546
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
@@ -27239,7 +27598,7 @@ function WidgetItem({ widget, areaName, isExpanded, onToggle, components }) {
27239
27598
  }),
27240
27599
  /* @__PURE__ */ jsx("button", {
27241
27600
  onClick: onToggle,
27242
- className: "flex-1 text-left",
27601
+ className: "flex-1 text-start",
27243
27602
  "aria-expanded": isExpanded,
27244
27603
  children: /* @__PURE__ */ jsxs("div", {
27245
27604
  className: "flex items-center gap-2",
@@ -27271,13 +27630,14 @@ function WidgetItem({ widget, areaName, isExpanded, onToggle, components }) {
27271
27630
  }), isExpanded && /* @__PURE__ */ jsx(WidgetEditor, {
27272
27631
  widget,
27273
27632
  components,
27633
+ pluginBlocks,
27274
27634
  onSave: (input) => updateMutation.mutate(input),
27275
27635
  isSaving: updateMutation.isPending
27276
27636
  })]
27277
27637
  });
27278
27638
  }
27279
27639
  /** Inline editor form for a widget, rendered when the widget is expanded */
27280
- function WidgetEditor({ widget, components, onSave, isSaving }) {
27640
+ function WidgetEditor({ widget, components, pluginBlocks, onSave, isSaving }) {
27281
27641
  const [title, setTitle] = React.useState(widget.title ?? "");
27282
27642
  const [content, setContent] = React.useState(Array.isArray(widget.content) ? widget.content : []);
27283
27643
  const [menuName, setMenuName] = React.useState(widget.menuName ?? "");
@@ -27315,7 +27675,8 @@ function WidgetEditor({ widget, components, onSave, isSaving }) {
27315
27675
  value: content,
27316
27676
  onChange: (value) => setContent(value),
27317
27677
  minimal: true,
27318
- placeholder: "Write widget content..."
27678
+ placeholder: "Write widget content...",
27679
+ pluginBlocks
27319
27680
  })] }),
27320
27681
  widget.type === "menu" && /* @__PURE__ */ jsxs(Select, {
27321
27682
  label: "Menu",
@@ -27389,7 +27750,7 @@ function ComponentPropField({ def, value, onChange }) {
27389
27750
  });
27390
27751
  case "boolean": return /* @__PURE__ */ jsx(Switch, {
27391
27752
  label: def.label,
27392
- checked: typeof value === "boolean" ? value : false,
27753
+ checked: Boolean(value),
27393
27754
  onCheckedChange: onChange
27394
27755
  });
27395
27756
  case "select": {
@@ -28219,7 +28580,7 @@ function FeatureComparison() {
28219
28580
  className: "border-b bg-kumo-tint/20",
28220
28581
  children: [
28221
28582
  /* @__PURE__ */ jsx("th", {
28222
- className: "text-left p-3 font-medium",
28583
+ className: "text-start p-3 font-medium",
28223
28584
  children: _t3({
28224
28585
  id: "en3oy5",
28225
28586
  message: "Feature"
@@ -28320,7 +28681,7 @@ function ProbeResultStep({ result, onUploadFile, onPluginConnect, onPluginManual
28320
28681
  if (!result.isWordPress) return /* @__PURE__ */ jsxs("div", {
28321
28682
  className: "space-y-6",
28322
28683
  children: [/* @__PURE__ */ jsx("div", {
28323
- className: "rounded-lg border-l-4 border-l-orange-500 border border-kumo-line bg-kumo-base p-6",
28684
+ className: "rounded-lg border-s-4 border-s-orange-500 border border-kumo-line bg-kumo-base p-6",
28324
28685
  children: /* @__PURE__ */ jsxs("div", {
28325
28686
  className: "flex items-start gap-4",
28326
28687
  children: [/* @__PURE__ */ jsx(Warning, { className: "h-6 w-6 text-orange-500 flex-shrink-0" }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
@@ -28404,7 +28765,7 @@ function ProbeResultStep({ result, onUploadFile, onPluginConnect, onPluginManual
28404
28765
  className: "space-y-6",
28405
28766
  children: [
28406
28767
  /* @__PURE__ */ jsx("div", {
28407
- className: "rounded-lg border-l-4 border-l-green-500 border border-kumo-line bg-kumo-base p-6",
28768
+ className: "rounded-lg border-s-4 border-s-green-500 border border-kumo-line bg-kumo-base p-6",
28408
28769
  children: /* @__PURE__ */ jsxs("div", {
28409
28770
  className: "flex items-start gap-4",
28410
28771
  children: [/* @__PURE__ */ jsx(Check, { className: "h-6 w-6 text-green-500 flex-shrink-0" }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
@@ -28472,7 +28833,7 @@ function ProbeResultStep({ result, onUploadFile, onPluginConnect, onPluginManual
28472
28833
  }),
28473
28834
  !hasPlugin && /* @__PURE__ */ jsx(FeatureComparison, {}),
28474
28835
  hasPlugin && /* @__PURE__ */ jsx("div", {
28475
- className: "rounded-lg border-l-4 border-l-green-500 border border-kumo-line bg-kumo-base p-6",
28836
+ className: "rounded-lg border-s-4 border-s-green-500 border border-kumo-line bg-kumo-base p-6",
28476
28837
  children: /* @__PURE__ */ jsxs("div", {
28477
28838
  className: "flex items-start gap-4",
28478
28839
  children: [/* @__PURE__ */ jsx("div", {
@@ -28714,7 +29075,7 @@ function PluginAuthStep({ siteTitle, siteUrl, username, password, onUsernameChan
28714
29075
  })
28715
29076
  ]
28716
29077
  }), /* @__PURE__ */ jsx("div", {
28717
- className: "rounded-lg border-l-4 border-l-blue-500 border border-kumo-line bg-kumo-base p-4",
29078
+ className: "rounded-lg border-s-4 border-s-blue-500 border border-kumo-line bg-kumo-base p-4",
28718
29079
  children: /* @__PURE__ */ jsxs("div", {
28719
29080
  className: "flex gap-3",
28720
29081
  children: [/* @__PURE__ */ jsx(ArrowSquareOut, { className: "h-5 w-5 text-blue-500 flex-shrink-0" }), /* @__PURE__ */ jsxs("div", {
@@ -29153,7 +29514,7 @@ function ReviewStep({ analysis, selections, expandedTypes, prepareError, importE
29153
29514
  })
29154
29515
  }),
29155
29516
  selectedCount > 0 && /* @__PURE__ */ jsx("div", {
29156
- className: "rounded-lg border-l-4 border-l-blue-500 border border-kumo-line bg-kumo-base p-4",
29517
+ className: "rounded-lg border-s-4 border-s-blue-500 border border-kumo-line bg-kumo-base p-4",
29157
29518
  children: /* @__PURE__ */ jsxs("div", {
29158
29519
  className: "flex gap-3",
29159
29520
  children: [/* @__PURE__ */ jsx(Database, { className: "h-5 w-5 text-blue-500 flex-shrink-0" }), /* @__PURE__ */ jsxs("div", {
@@ -29253,7 +29614,7 @@ function PostTypeRow({ postType, selection, expanded, onToggleExpand, onToggleEn
29253
29614
  })
29254
29615
  }), /* @__PURE__ */ jsxs("button", {
29255
29616
  onClick: onToggleExpand,
29256
- className: "flex items-center gap-1 text-left",
29617
+ className: "flex items-center gap-1 text-start",
29257
29618
  "aria-expanded": expanded,
29258
29619
  children: [expanded ? /* @__PURE__ */ jsx(CaretDown, { className: "h-4 w-4 text-kumo-subtle" }) : /* @__PURE__ */ jsx(CaretRight, { className: "h-4 w-4 text-kumo-subtle" }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
29259
29620
  className: "font-medium",
@@ -29296,11 +29657,11 @@ function PostTypeRow({ postType, selection, expanded, onToggleExpand, onToggleEn
29296
29657
  }) })
29297
29658
  })]
29298
29659
  }), expanded && /* @__PURE__ */ jsxs("div", {
29299
- className: "mt-4 ml-8 p-3 rounded-lg bg-kumo-tint/50 text-sm",
29660
+ className: "mt-4 ms-8 p-3 rounded-lg bg-kumo-tint/50 text-sm",
29300
29661
  children: [
29301
29662
  !canImport && schemaStatus.reason && /* @__PURE__ */ jsxs("div", {
29302
29663
  className: "mb-3 p-2 rounded bg-red-100 dark:bg-red-900/30 text-red-800 dark:text-red-300",
29303
- children: [/* @__PURE__ */ jsx(WarningCircle, { className: "inline h-4 w-4 mr-1" }), schemaStatus.reason]
29664
+ children: [/* @__PURE__ */ jsx(WarningCircle, { className: "inline h-4 w-4 me-1" }), schemaStatus.reason]
29304
29665
  }),
29305
29666
  /* @__PURE__ */ jsx("p", {
29306
29667
  className: "font-medium mb-2",
@@ -29428,7 +29789,7 @@ function MediaStep({ attachments, error, onImport, onSkip }) {
29428
29789
  })
29429
29790
  }),
29430
29791
  /* @__PURE__ */ jsx("div", {
29431
- className: "mt-4 p-4 rounded-lg border-l-4 border-l-blue-500 border border-kumo-line bg-kumo-base",
29792
+ className: "mt-4 p-4 rounded-lg border-s-4 border-s-blue-500 border border-kumo-line bg-kumo-base",
29432
29793
  children: /* @__PURE__ */ jsxs("div", {
29433
29794
  className: "flex gap-3",
29434
29795
  children: [/* @__PURE__ */ jsx(DownloadSimple, { className: "h-5 w-5 text-blue-500 flex-shrink-0" }), /* @__PURE__ */ jsxs("div", {
@@ -29848,7 +30209,7 @@ function AuthorMappingStep({ authorMappings, emdashUsers, onMappingChange, onCon
29848
30209
  }),
29849
30210
  matchedCount > 0 && /* @__PURE__ */ jsxs("p", {
29850
30211
  className: "text-sm text-green-600 dark:text-green-400 mt-2",
29851
- children: [/* @__PURE__ */ jsx(Check, { className: "inline h-4 w-4 mr-1" }), _t10({
30212
+ children: [/* @__PURE__ */ jsx(Check, { className: "inline h-4 w-4 me-1" }), _t10({
29852
30213
  id: "gIZkFQ",
29853
30214
  message: "{matchedCount} of {totalCount} authors matched by email",
29854
30215
  values: {
@@ -29896,7 +30257,7 @@ function AuthorMappingStep({ authorMappings, emdashUsers, onMappingChange, onCon
29896
30257
  }), /* @__PURE__ */ jsxs("p", {
29897
30258
  className: "text-sm text-kumo-subtle",
29898
30259
  children: [mapping.wpEmail || mapping.wpLogin, mapping.postCount > 0 && /* @__PURE__ */ jsxs("span", {
29899
- className: "ml-2",
30260
+ className: "ms-2",
29900
30261
  children: ["• ", i18n._({
29901
30262
  id: "S6XZwv",
29902
30263
  message: "{0, plural, one {# post} other {# posts}}",
@@ -29929,7 +30290,7 @@ function AuthorMappingStep({ authorMappings, emdashUsers, onMappingChange, onCon
29929
30290
  })]
29930
30291
  }),
29931
30292
  emdashUsers.length === 0 && /* @__PURE__ */ jsx("div", {
29932
- className: "rounded-lg border-l-4 border-l-yellow-500 border border-kumo-line bg-kumo-base p-4",
30293
+ className: "rounded-lg border-s-4 border-s-yellow-500 border border-kumo-line bg-kumo-base p-4",
29933
30294
  children: /* @__PURE__ */ jsxs("div", {
29934
30295
  className: "flex gap-3",
29935
30296
  children: [/* @__PURE__ */ jsx(Warning, { className: "h-5 w-5 text-yellow-500 flex-shrink-0" }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
@@ -30145,7 +30506,7 @@ function BylinesPage() {
30145
30506
  return /* @__PURE__ */ jsxs("button", {
30146
30507
  type: "button",
30147
30508
  onClick: () => setSelectedId(item.id),
30148
- className: `w-full rounded border p-3 text-left ${item.id === selectedId ? "border-kumo-brand bg-kumo-brand/10" : "border-kumo-line"}`,
30509
+ className: `w-full rounded border p-3 text-start ${item.id === selectedId ? "border-kumo-brand bg-kumo-brand/10" : "border-kumo-line"}`,
30149
30510
  children: [/* @__PURE__ */ jsx("p", {
30150
30511
  className: "font-medium",
30151
30512
  children: item.displayName
@@ -30297,7 +30658,7 @@ function RoleBadge({ role, size = "sm", showDescription = false, className }) {
30297
30658
  }[config.color], className),
30298
30659
  title: showDescription ? void 0 : _t(config.description),
30299
30660
  children: [_t(config.label), showDescription && /* @__PURE__ */ jsxs("span", {
30300
- className: "ml-1 opacity-75",
30661
+ className: "ms-1 opacity-75",
30301
30662
  children: ["- ", _t(config.description)]
30302
30663
  })]
30303
30664
  });
@@ -30344,12 +30705,12 @@ function UserList({ users, isLoading, hasMore, searchQuery, roleFilter, onSearch
30344
30705
  children: [/* @__PURE__ */ jsxs("div", {
30345
30706
  className: "relative flex-1 max-w-sm",
30346
30707
  children: [/* @__PURE__ */ jsx(MagnifyingGlass, {
30347
- className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-kumo-subtle",
30708
+ className: "absolute start-3 top-1/2 h-4 w-4 -translate-y-1/2 text-kumo-subtle",
30348
30709
  "aria-hidden": "true"
30349
30710
  }), /* @__PURE__ */ jsx(Input, {
30350
30711
  type: "search",
30351
30712
  placeholder: "Search by name or email...",
30352
- className: "pl-10",
30713
+ className: "ps-10",
30353
30714
  value: searchQuery,
30354
30715
  onChange: (e) => onSearchChange(e.target.value),
30355
30716
  "aria-label": "Search users"
@@ -30374,27 +30735,27 @@ function UserList({ users, isLoading, hasMore, searchQuery, roleFilter, onSearch
30374
30735
  children: [
30375
30736
  /* @__PURE__ */ jsx("th", {
30376
30737
  scope: "col",
30377
- className: "px-4 py-3 text-left text-sm font-medium",
30738
+ className: "px-4 py-3 text-start text-sm font-medium",
30378
30739
  children: "User"
30379
30740
  }),
30380
30741
  /* @__PURE__ */ jsx("th", {
30381
30742
  scope: "col",
30382
- className: "px-4 py-3 text-left text-sm font-medium",
30743
+ className: "px-4 py-3 text-start text-sm font-medium",
30383
30744
  children: "Role"
30384
30745
  }),
30385
30746
  /* @__PURE__ */ jsx("th", {
30386
30747
  scope: "col",
30387
- className: "px-4 py-3 text-left text-sm font-medium",
30748
+ className: "px-4 py-3 text-start text-sm font-medium",
30388
30749
  children: "Status"
30389
30750
  }),
30390
30751
  /* @__PURE__ */ jsx("th", {
30391
30752
  scope: "col",
30392
- className: "px-4 py-3 text-left text-sm font-medium",
30753
+ className: "px-4 py-3 text-start text-sm font-medium",
30393
30754
  children: "Last Login"
30394
30755
  }),
30395
30756
  /* @__PURE__ */ jsx("th", {
30396
30757
  scope: "col",
30397
- className: "px-4 py-3 text-left text-sm font-medium",
30758
+ className: "px-4 py-3 text-start text-sm font-medium",
30398
30759
  children: "Passkeys"
30399
30760
  })
30400
30761
  ]
@@ -30554,14 +30915,6 @@ function UserDetail({ user, isLoading, isOpen, isSaving, isSendingRecovery, reco
30554
30915
  }
30555
30916
  }
30556
30917
  const stableOnClose = useStableCallback(onClose);
30557
- React.useEffect(() => {
30558
- const handleKeyDown = (e) => {
30559
- if (e.key === "Escape") stableOnClose();
30560
- };
30561
- document.addEventListener("keydown", handleKeyDown);
30562
- return () => document.removeEventListener("keydown", handleKeyDown);
30563
- }, [stableOnClose]);
30564
- if (!isOpen) return null;
30565
30918
  const isSelf = user && currentUserId && user.id === currentUserId;
30566
30919
  const isDirty = user && (name !== (user.name ?? "") || email !== user.email || role !== user.role);
30567
30920
  const handleSubmit = (e) => {
@@ -30573,366 +30926,362 @@ function UserDetail({ user, isLoading, isOpen, isSaving, isSendingRecovery, reco
30573
30926
  if (role !== user.role && !isSelf) data.role = role;
30574
30927
  onSave(data);
30575
30928
  };
30576
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
30577
- className: "fixed inset-0 z-40 bg-black/50",
30578
- onClick: onClose,
30579
- "aria-hidden": "true"
30580
- }), /* @__PURE__ */ jsxs("div", {
30581
- className: cn("fixed right-0 top-0 z-50 flex h-full w-full max-w-md flex-col bg-kumo-base shadow-xl", "transform transition-transform duration-200", isOpen ? "translate-x-0" : "translate-x-full"),
30582
- role: "dialog",
30583
- "aria-modal": "true",
30584
- "aria-labelledby": "user-detail-title",
30585
- children: [
30586
- /* @__PURE__ */ jsxs("div", {
30587
- className: "flex items-center justify-between border-b px-6 py-4",
30588
- children: [/* @__PURE__ */ jsx("h2", {
30589
- id: "user-detail-title",
30590
- className: "text-lg font-semibold",
30591
- children: _t({
30592
- id: "anfIXl",
30593
- message: "User Details"
30594
- })
30595
- }), /* @__PURE__ */ jsx(Button, {
30596
- variant: "ghost",
30597
- shape: "square",
30598
- onClick: onClose,
30599
- "aria-label": _t({
30600
- id: "mO95sp",
30601
- message: "Close panel"
30602
- }),
30603
- children: /* @__PURE__ */ jsx(X, {
30604
- className: "h-5 w-5",
30605
- "aria-hidden": "true"
30606
- })
30607
- })]
30608
- }),
30609
- /* @__PURE__ */ jsx("div", {
30610
- className: "flex-1 overflow-y-auto p-6",
30611
- children: isLoading ? /* @__PURE__ */ jsx(UserDetailSkeleton, {}) : user ? /* @__PURE__ */ jsxs("form", {
30612
- id: "user-edit-form",
30613
- onSubmit: handleSubmit,
30614
- className: "space-y-6",
30615
- children: [
30616
- /* @__PURE__ */ jsxs("div", {
30617
- className: "flex items-start gap-4",
30618
- children: [user.avatarUrl ? /* @__PURE__ */ jsx("img", {
30619
- src: user.avatarUrl,
30620
- alt: "",
30621
- className: "h-16 w-16 shrink-0 rounded-full object-cover"
30622
- }) : /* @__PURE__ */ jsx("div", {
30623
- className: "h-16 w-16 shrink-0 rounded-full bg-kumo-tint flex items-center justify-center text-2xl font-medium",
30624
- children: (name || email)?.[0]?.toUpperCase() ?? "?"
30625
- }), /* @__PURE__ */ jsxs("div", {
30626
- className: "flex-1 min-w-0 space-y-3",
30627
- children: [/* @__PURE__ */ jsx(Input, {
30628
- label: _t({
30629
- id: "6YtxFj",
30630
- message: "Name"
30631
- }),
30632
- value: name,
30633
- onChange: (e) => setName(e.target.value),
30634
- placeholder: _t({
30635
- id: "RI7NuK",
30636
- message: "Enter name"
30637
- })
30638
- }), /* @__PURE__ */ jsx(Input, {
30639
- label: _t({
30640
- id: "O3oNi5",
30641
- message: "Email"
30642
- }),
30643
- type: "email",
30644
- value: email,
30645
- onChange: (e) => setEmail(e.target.value),
30646
- placeholder: _t({
30647
- id: "6KnyG0",
30648
- message: "Enter email"
30649
- }),
30650
- required: true
30651
- })]
30652
- })]
30929
+ return /* @__PURE__ */ jsx(Dialog$1.Root, {
30930
+ open: isOpen,
30931
+ onOpenChange: (open) => !open && stableOnClose(),
30932
+ children: /* @__PURE__ */ jsxs(Dialog$1.Portal, { children: [/* @__PURE__ */ jsx(Dialog$1.Backdrop, { className: cn("fixed inset-0 bg-black/50 transition-opacity duration-200", "data-starting-style:opacity-0 data-ending-style:opacity-0") }), /* @__PURE__ */ jsxs(Dialog$1.Popup, {
30933
+ className: cn("fixed top-0 end-0 flex h-full w-full max-w-md flex-col bg-kumo-base shadow-xl outline-none", "transform transition-transform duration-200 ease-out", "data-starting-style:ltr:translate-x-full data-starting-style:rtl:-translate-x-full", "data-ending-style:ltr:translate-x-full data-ending-style:rtl:-translate-x-full"),
30934
+ children: [
30935
+ /* @__PURE__ */ jsxs("div", {
30936
+ className: "flex items-center justify-between border-b px-6 py-4",
30937
+ children: [/* @__PURE__ */ jsx(Dialog$1.Title, {
30938
+ className: "text-lg font-semibold",
30939
+ children: _t({
30940
+ id: "anfIXl",
30941
+ message: "User Details"
30942
+ })
30943
+ }), /* @__PURE__ */ jsx(Button, {
30944
+ variant: "ghost",
30945
+ shape: "square",
30946
+ onClick: stableOnClose,
30947
+ "aria-label": _t({
30948
+ id: "mO95sp",
30949
+ message: "Close panel"
30653
30950
  }),
30654
- /* @__PURE__ */ jsxs("div", {
30655
- className: "flex items-end gap-3",
30656
- children: [isSelf ? /* @__PURE__ */ jsxs("div", {
30657
- className: "flex-1",
30658
- children: [/* @__PURE__ */ jsx(Input, {
30659
- label: _t({
30660
- id: "GDvlUT",
30661
- message: "Role"
30662
- }),
30663
- value: getRoleLabel(role),
30664
- disabled: true,
30665
- className: "cursor-not-allowed"
30666
- }), /* @__PURE__ */ jsx("p", {
30667
- className: "text-xs text-kumo-subtle mt-1",
30668
- children: _t({
30669
- id: "e+3JRc",
30670
- message: "You cannot change your own role"
30671
- })
30672
- })]
30673
- }) : /* @__PURE__ */ jsx("div", {
30674
- className: "flex-1",
30675
- children: /* @__PURE__ */ jsx(Select, {
30676
- label: _t({
30677
- id: "GDvlUT",
30678
- message: "Role"
30679
- }),
30680
- value: role.toString(),
30681
- onValueChange: (v) => v !== null && setRole(parseInt(v, 10)),
30682
- items: roleLabels,
30683
- children: roles.map((r) => /* @__PURE__ */ jsx(Select.Option, {
30684
- value: r.value.toString(),
30685
- children: /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", { children: r.label }), /* @__PURE__ */ jsx("div", {
30686
- className: "text-xs text-kumo-subtle",
30687
- children: r.description
30688
- })] })
30689
- }, r.value))
30690
- })
30691
- }), /* @__PURE__ */ jsx("div", {
30692
- className: "pb-1",
30693
- children: user.disabled ? /* @__PURE__ */ jsxs("span", {
30694
- className: "inline-flex items-center gap-1 text-sm text-kumo-danger",
30695
- children: [/* @__PURE__ */ jsx(Prohibit, {
30696
- className: "h-3.5 w-3.5",
30697
- "aria-hidden": "true"
30698
- }), _t({
30699
- id: "E/QGRL",
30700
- message: "Disabled"
30701
- })]
30702
- }) : /* @__PURE__ */ jsxs("span", {
30703
- className: "inline-flex items-center gap-1 text-sm text-green-600 dark:text-green-400",
30704
- children: [/* @__PURE__ */ jsx(CheckCircle, {
30705
- className: "h-3.5 w-3.5",
30706
- "aria-hidden": "true"
30707
- }), _t({
30708
- id: "F6pfE9",
30709
- message: "Active"
30951
+ children: /* @__PURE__ */ jsx(X, {
30952
+ className: "h-5 w-5",
30953
+ "aria-hidden": "true"
30954
+ })
30955
+ })]
30956
+ }),
30957
+ /* @__PURE__ */ jsx("div", {
30958
+ className: "flex-1 overflow-y-auto p-6",
30959
+ children: isLoading ? /* @__PURE__ */ jsx(UserDetailSkeleton, {}) : user ? /* @__PURE__ */ jsxs("form", {
30960
+ id: "user-edit-form",
30961
+ onSubmit: handleSubmit,
30962
+ className: "space-y-6",
30963
+ children: [
30964
+ /* @__PURE__ */ jsxs("div", {
30965
+ className: "flex items-start gap-4",
30966
+ children: [user.avatarUrl ? /* @__PURE__ */ jsx("img", {
30967
+ src: user.avatarUrl,
30968
+ alt: "",
30969
+ className: "h-16 w-16 shrink-0 rounded-full object-cover"
30970
+ }) : /* @__PURE__ */ jsx("div", {
30971
+ className: "h-16 w-16 shrink-0 rounded-full bg-kumo-tint flex items-center justify-center text-2xl font-medium",
30972
+ children: (name || email)?.[0]?.toUpperCase() ?? "?"
30973
+ }), /* @__PURE__ */ jsxs("div", {
30974
+ className: "flex-1 min-w-0 space-y-3",
30975
+ children: [/* @__PURE__ */ jsx(Input, {
30976
+ label: _t({
30977
+ id: "6YtxFj",
30978
+ message: "Name"
30979
+ }),
30980
+ value: name,
30981
+ onChange: (e) => setName(e.target.value),
30982
+ placeholder: _t({
30983
+ id: "RI7NuK",
30984
+ message: "Enter name"
30985
+ })
30986
+ }), /* @__PURE__ */ jsx(Input, {
30987
+ label: _t({
30988
+ id: "O3oNi5",
30989
+ message: "Email"
30990
+ }),
30991
+ type: "email",
30992
+ value: email,
30993
+ onChange: (e) => setEmail(e.target.value),
30994
+ placeholder: _t({
30995
+ id: "6KnyG0",
30996
+ message: "Enter email"
30997
+ }),
30998
+ required: true
30710
30999
  })]
30711
- })
30712
- })]
30713
- }),
30714
- /* @__PURE__ */ jsxs("div", {
30715
- className: "grid gap-4",
30716
- children: [
30717
- /* @__PURE__ */ jsxs("div", {
30718
- className: "rounded-lg border p-4",
30719
- children: [/* @__PURE__ */ jsx("h4", {
30720
- className: "text-sm font-medium text-kumo-subtle mb-3",
31000
+ })]
31001
+ }),
31002
+ /* @__PURE__ */ jsxs("div", {
31003
+ className: "flex items-end gap-3",
31004
+ children: [isSelf ? /* @__PURE__ */ jsxs("div", {
31005
+ className: "flex-1",
31006
+ children: [/* @__PURE__ */ jsx(Input, {
31007
+ label: _t({
31008
+ id: "GDvlUT",
31009
+ message: "Role"
31010
+ }),
31011
+ value: getRoleLabel(role),
31012
+ disabled: true,
31013
+ className: "cursor-not-allowed"
31014
+ }), /* @__PURE__ */ jsx("p", {
31015
+ className: "text-xs text-kumo-subtle mt-1",
30721
31016
  children: _t({
30722
- id: "NPGiDn",
30723
- message: "Account Info"
31017
+ id: "e+3JRc",
31018
+ message: "You cannot change your own role"
30724
31019
  })
30725
- }), /* @__PURE__ */ jsxs("div", {
30726
- className: "space-y-2 text-sm",
30727
- children: [
30728
- /* @__PURE__ */ jsxs("div", {
30729
- className: "flex justify-between",
30730
- children: [/* @__PURE__ */ jsx("span", {
30731
- className: "text-kumo-subtle",
30732
- children: _t({
30733
- id: "d+F6q9",
30734
- message: "Created"
30735
- })
30736
- }), /* @__PURE__ */ jsx("span", { children: new Date(user.createdAt).toLocaleDateString() })]
30737
- }),
30738
- /* @__PURE__ */ jsxs("div", {
30739
- className: "flex justify-between",
30740
- children: [/* @__PURE__ */ jsx("span", {
30741
- className: "text-kumo-subtle",
30742
- children: _t({
30743
- id: "C3yOz3",
30744
- message: "Last updated"
30745
- })
30746
- }), /* @__PURE__ */ jsx("span", { children: new Date(user.updatedAt).toLocaleDateString() })]
30747
- }),
30748
- /* @__PURE__ */ jsxs("div", {
30749
- className: "flex justify-between",
30750
- children: [/* @__PURE__ */ jsx("span", {
30751
- className: "text-kumo-subtle",
30752
- children: _t({
30753
- id: "I3yitW",
30754
- message: "Last login"
30755
- })
30756
- }), /* @__PURE__ */ jsx("span", { children: user.lastLogin ? new Date(user.lastLogin).toLocaleDateString() : _t({
30757
- id: "qqeAJM",
30758
- message: "Never"
30759
- }) })]
30760
- }),
30761
- /* @__PURE__ */ jsxs("div", {
30762
- className: "flex justify-between",
30763
- children: [/* @__PURE__ */ jsx("span", {
30764
- className: "text-kumo-subtle",
30765
- children: _t({
30766
- id: "PLEl94",
30767
- message: "Email verified"
30768
- })
30769
- }), /* @__PURE__ */ jsx("span", { children: user.emailVerified ? _t({
30770
- id: "l75CjT",
30771
- message: "Yes"
30772
- }) : _t({
30773
- id: "1UzENP",
30774
- message: "No"
30775
- }) })]
30776
- })
30777
- ]
30778
31020
  })]
30779
- }),
30780
- /* @__PURE__ */ jsxs("div", {
30781
- className: "rounded-lg border p-4",
30782
- children: [/* @__PURE__ */ jsxs("h4", {
30783
- className: "text-sm font-medium text-kumo-subtle mb-3 flex items-center gap-2",
30784
- children: [/* @__PURE__ */ jsx(Key, {
30785
- className: "h-4 w-4",
31021
+ }) : /* @__PURE__ */ jsx("div", {
31022
+ className: "flex-1",
31023
+ children: /* @__PURE__ */ jsx(Select, {
31024
+ label: _t({
31025
+ id: "GDvlUT",
31026
+ message: "Role"
31027
+ }),
31028
+ value: role.toString(),
31029
+ onValueChange: (v) => v !== null && setRole(parseInt(v, 10)),
31030
+ items: roleLabels,
31031
+ children: roles.map((r) => /* @__PURE__ */ jsx(Select.Option, {
31032
+ value: r.value.toString(),
31033
+ children: /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", { children: r.label }), /* @__PURE__ */ jsx("div", {
31034
+ className: "text-xs text-kumo-subtle",
31035
+ children: r.description
31036
+ })] })
31037
+ }, r.value))
31038
+ })
31039
+ }), /* @__PURE__ */ jsx("div", {
31040
+ className: "pb-1",
31041
+ children: user.disabled ? /* @__PURE__ */ jsxs("span", {
31042
+ className: "inline-flex items-center gap-1 text-sm text-kumo-danger",
31043
+ children: [/* @__PURE__ */ jsx(Prohibit, {
31044
+ className: "h-3.5 w-3.5",
31045
+ "aria-hidden": "true"
31046
+ }), _t({
31047
+ id: "E/QGRL",
31048
+ message: "Disabled"
31049
+ })]
31050
+ }) : /* @__PURE__ */ jsxs("span", {
31051
+ className: "inline-flex items-center gap-1 text-sm text-green-600 dark:text-green-400",
31052
+ children: [/* @__PURE__ */ jsx(CheckCircle, {
31053
+ className: "h-3.5 w-3.5",
30786
31054
  "aria-hidden": "true"
30787
31055
  }), _t({
30788
- id: "ChKSdm",
30789
- message: "Passkeys ({0})",
30790
- values: { 0: user.credentials.length }
31056
+ id: "F6pfE9",
31057
+ message: "Active"
30791
31058
  })]
30792
- }), user.credentials.length === 0 ? /* @__PURE__ */ jsx("p", {
30793
- className: "text-sm text-kumo-subtle",
30794
- children: _t({
30795
- id: "foMWA+",
30796
- message: "No passkeys registered"
30797
- })
30798
- }) : /* @__PURE__ */ jsx("div", {
30799
- className: "space-y-2",
30800
- children: user.credentials.map((cred) => /* @__PURE__ */ jsxs("div", {
30801
- className: "flex justify-between text-sm",
30802
- children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", { children: cred.name || _t({
30803
- id: "xowKks",
30804
- message: "Unnamed passkey"
30805
- }) }), /* @__PURE__ */ jsx("div", {
30806
- className: "text-xs text-kumo-subtle",
30807
- children: cred.deviceType === "multiDevice" ? _t({
30808
- id: "N2FcBE",
30809
- message: "Synced"
30810
- }) : _t({
30811
- id: "tuIPad",
30812
- message: "Device-bound"
31059
+ })
31060
+ })]
31061
+ }),
31062
+ /* @__PURE__ */ jsxs("div", {
31063
+ className: "grid gap-4",
31064
+ children: [
31065
+ /* @__PURE__ */ jsxs("div", {
31066
+ className: "rounded-lg border p-4",
31067
+ children: [/* @__PURE__ */ jsx("h4", {
31068
+ className: "text-sm font-medium text-kumo-subtle mb-3",
31069
+ children: _t({
31070
+ id: "NPGiDn",
31071
+ message: "Account Info"
31072
+ })
31073
+ }), /* @__PURE__ */ jsxs("div", {
31074
+ className: "space-y-2 text-sm",
31075
+ children: [
31076
+ /* @__PURE__ */ jsxs("div", {
31077
+ className: "flex justify-between",
31078
+ children: [/* @__PURE__ */ jsx("span", {
31079
+ className: "text-kumo-subtle",
31080
+ children: _t({
31081
+ id: "d+F6q9",
31082
+ message: "Created"
31083
+ })
31084
+ }), /* @__PURE__ */ jsx("span", { children: new Date(user.createdAt).toLocaleDateString() })]
31085
+ }),
31086
+ /* @__PURE__ */ jsxs("div", {
31087
+ className: "flex justify-between",
31088
+ children: [/* @__PURE__ */ jsx("span", {
31089
+ className: "text-kumo-subtle",
31090
+ children: _t({
31091
+ id: "C3yOz3",
31092
+ message: "Last updated"
31093
+ })
31094
+ }), /* @__PURE__ */ jsx("span", { children: new Date(user.updatedAt).toLocaleDateString() })]
31095
+ }),
31096
+ /* @__PURE__ */ jsxs("div", {
31097
+ className: "flex justify-between",
31098
+ children: [/* @__PURE__ */ jsx("span", {
31099
+ className: "text-kumo-subtle",
31100
+ children: _t({
31101
+ id: "I3yitW",
31102
+ message: "Last login"
31103
+ })
31104
+ }), /* @__PURE__ */ jsx("span", { children: user.lastLogin ? new Date(user.lastLogin).toLocaleDateString() : _t({
31105
+ id: "qqeAJM",
31106
+ message: "Never"
31107
+ }) })]
31108
+ }),
31109
+ /* @__PURE__ */ jsxs("div", {
31110
+ className: "flex justify-between",
31111
+ children: [/* @__PURE__ */ jsx("span", {
31112
+ className: "text-kumo-subtle",
31113
+ children: _t({
31114
+ id: "PLEl94",
31115
+ message: "Email verified"
31116
+ })
31117
+ }), /* @__PURE__ */ jsx("span", { children: user.emailVerified ? _t({
31118
+ id: "l75CjT",
31119
+ message: "Yes"
31120
+ }) : _t({
31121
+ id: "1UzENP",
31122
+ message: "No"
31123
+ }) })]
30813
31124
  })
30814
- })] }), /* @__PURE__ */ jsxs("div", {
30815
- className: "text-right text-kumo-subtle",
30816
- children: [/* @__PURE__ */ jsx("div", { children: _t({
30817
- id: "MXSt4t",
30818
- message: "Created {0}",
30819
- values: { 0: new Date(cred.createdAt).toLocaleDateString() }
31125
+ ]
31126
+ })]
31127
+ }),
31128
+ /* @__PURE__ */ jsxs("div", {
31129
+ className: "rounded-lg border p-4",
31130
+ children: [/* @__PURE__ */ jsxs("h4", {
31131
+ className: "text-sm font-medium text-kumo-subtle mb-3 flex items-center gap-2",
31132
+ children: [/* @__PURE__ */ jsx(Key, {
31133
+ className: "h-4 w-4",
31134
+ "aria-hidden": "true"
31135
+ }), _t({
31136
+ id: "ChKSdm",
31137
+ message: "Passkeys ({0})",
31138
+ values: { 0: user.credentials.length }
31139
+ })]
31140
+ }), user.credentials.length === 0 ? /* @__PURE__ */ jsx("p", {
31141
+ className: "text-sm text-kumo-subtle",
31142
+ children: _t({
31143
+ id: "foMWA+",
31144
+ message: "No passkeys registered"
31145
+ })
31146
+ }) : /* @__PURE__ */ jsx("div", {
31147
+ className: "space-y-2",
31148
+ children: user.credentials.map((cred) => /* @__PURE__ */ jsxs("div", {
31149
+ className: "flex justify-between text-sm",
31150
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", { children: cred.name || _t({
31151
+ id: "xowKks",
31152
+ message: "Unnamed passkey"
30820
31153
  }) }), /* @__PURE__ */ jsx("div", {
30821
- className: "text-xs",
30822
- children: _t({
30823
- id: "ylo1I0",
30824
- message: "Last used {0}",
30825
- values: { 0: new Date(cred.lastUsedAt).toLocaleDateString() }
31154
+ className: "text-xs text-kumo-subtle",
31155
+ children: cred.deviceType === "multiDevice" ? _t({
31156
+ id: "N2FcBE",
31157
+ message: "Synced"
31158
+ }) : _t({
31159
+ id: "tuIPad",
31160
+ message: "Device-bound"
30826
31161
  })
31162
+ })] }), /* @__PURE__ */ jsxs("div", {
31163
+ className: "text-end text-kumo-subtle",
31164
+ children: [/* @__PURE__ */ jsx("div", { children: _t({
31165
+ id: "MXSt4t",
31166
+ message: "Created {0}",
31167
+ values: { 0: new Date(cred.createdAt).toLocaleDateString() }
31168
+ }) }), /* @__PURE__ */ jsx("div", {
31169
+ className: "text-xs",
31170
+ children: _t({
31171
+ id: "ylo1I0",
31172
+ message: "Last used {0}",
31173
+ values: { 0: new Date(cred.lastUsedAt).toLocaleDateString() }
31174
+ })
31175
+ })]
30827
31176
  })]
30828
- })]
30829
- }, cred.id))
30830
- })]
30831
- }),
30832
- user.oauthAccounts.length > 0 && /* @__PURE__ */ jsxs("div", {
30833
- className: "rounded-lg border p-4",
30834
- children: [/* @__PURE__ */ jsxs("h4", {
30835
- className: "text-sm font-medium text-kumo-subtle mb-3 flex items-center gap-2",
30836
- children: [/* @__PURE__ */ jsx(ArrowSquareOut, {
30837
- className: "h-4 w-4",
30838
- "aria-hidden": "true"
30839
- }), _t({
30840
- id: "V89WqR",
30841
- message: "Linked Accounts ({0})",
30842
- values: { 0: user.oauthAccounts.length }
31177
+ }, cred.id))
30843
31178
  })]
30844
- }), /* @__PURE__ */ jsx("div", {
30845
- className: "space-y-2",
30846
- children: user.oauthAccounts.map((account, i) => /* @__PURE__ */ jsxs("div", {
30847
- className: "flex justify-between text-sm",
30848
- children: [/* @__PURE__ */ jsx("span", {
30849
- className: "capitalize",
30850
- children: account.provider
30851
- }), /* @__PURE__ */ jsx("span", {
30852
- className: "text-kumo-subtle",
30853
- children: _t({
30854
- id: "sk/Z5E",
30855
- message: "Connected {0}",
30856
- values: { 0: new Date(account.createdAt).toLocaleDateString() }
30857
- })
31179
+ }),
31180
+ user.oauthAccounts.length > 0 && /* @__PURE__ */ jsxs("div", {
31181
+ className: "rounded-lg border p-4",
31182
+ children: [/* @__PURE__ */ jsxs("h4", {
31183
+ className: "text-sm font-medium text-kumo-subtle mb-3 flex items-center gap-2",
31184
+ children: [/* @__PURE__ */ jsx(ArrowSquareOut, {
31185
+ className: "h-4 w-4",
31186
+ "aria-hidden": "true"
31187
+ }), _t({
31188
+ id: "V89WqR",
31189
+ message: "Linked Accounts ({0})",
31190
+ values: { 0: user.oauthAccounts.length }
30858
31191
  })]
30859
- }, `${account.provider}-${i}`))
30860
- })]
30861
- })
30862
- ]
31192
+ }), /* @__PURE__ */ jsx("div", {
31193
+ className: "space-y-2",
31194
+ children: user.oauthAccounts.map((account, i) => /* @__PURE__ */ jsxs("div", {
31195
+ className: "flex justify-between text-sm",
31196
+ children: [/* @__PURE__ */ jsx("span", {
31197
+ className: "capitalize",
31198
+ children: account.provider
31199
+ }), /* @__PURE__ */ jsx("span", {
31200
+ className: "text-kumo-subtle",
31201
+ children: _t({
31202
+ id: "sk/Z5E",
31203
+ message: "Connected {0}",
31204
+ values: { 0: new Date(account.createdAt).toLocaleDateString() }
31205
+ })
31206
+ })]
31207
+ }, `${account.provider}-${i}`))
31208
+ })]
31209
+ })
31210
+ ]
31211
+ })
31212
+ ]
31213
+ }) : /* @__PURE__ */ jsx("div", {
31214
+ className: "text-center text-kumo-subtle py-8",
31215
+ children: _t({
31216
+ id: "eW9fDd",
31217
+ message: "User not found"
30863
31218
  })
30864
- ]
30865
- }) : /* @__PURE__ */ jsx("div", {
30866
- className: "text-center text-kumo-subtle py-8",
30867
- children: _t({
30868
- id: "eW9fDd",
30869
- message: "User not found"
30870
31219
  })
30871
- })
30872
- }),
30873
- user && /* @__PURE__ */ jsxs("div", {
30874
- className: "border-t px-6 py-4 space-y-2",
30875
- children: [/* @__PURE__ */ jsxs("div", {
30876
- className: "flex gap-2",
30877
- children: [/* @__PURE__ */ jsx(Button, {
30878
- type: "submit",
30879
- form: "user-edit-form",
30880
- className: "flex-1",
30881
- disabled: !isDirty || isSaving,
30882
- icon: /* @__PURE__ */ jsx(FloppyDisk, {}),
30883
- children: isSaving ? _t({
30884
- id: "XvjC4F",
30885
- message: "Saving..."
30886
- }) : _t({
30887
- id: "IUwGEM",
30888
- message: "Save Changes"
30889
- })
30890
- }), !isSelf && /* @__PURE__ */ jsx(Button, {
30891
- variant: user.disabled ? "outline" : "destructive",
30892
- onClick: user.disabled ? onEnable : onDisable,
30893
- icon: user.disabled ? /* @__PURE__ */ jsx(CheckCircle, {}) : /* @__PURE__ */ jsx(Prohibit, {}),
30894
- children: user.disabled ? _t({
30895
- id: "PaQ3df",
30896
- message: "Enable"
30897
- }) : _t({
30898
- id: "cO9+2L",
30899
- message: "Disable"
30900
- })
30901
- })]
30902
- }), !isSelf && onSendRecovery && /* @__PURE__ */ jsxs("div", {
30903
- className: "space-y-1",
30904
- children: [
30905
- /* @__PURE__ */ jsx(Button, {
30906
- variant: "outline",
30907
- className: "w-full",
30908
- onClick: onSendRecovery,
30909
- disabled: isSendingRecovery,
30910
- icon: /* @__PURE__ */ jsx(Envelope, {}),
30911
- children: isSendingRecovery ? _t({
30912
- id: "IoAuJG",
30913
- message: "Sending..."
31220
+ }),
31221
+ user && /* @__PURE__ */ jsxs("div", {
31222
+ className: "border-t px-6 py-4 space-y-2",
31223
+ children: [/* @__PURE__ */ jsxs("div", {
31224
+ className: "flex gap-2",
31225
+ children: [/* @__PURE__ */ jsx(Button, {
31226
+ type: "submit",
31227
+ form: "user-edit-form",
31228
+ className: "flex-1",
31229
+ disabled: !isDirty || isSaving,
31230
+ icon: /* @__PURE__ */ jsx(FloppyDisk, {}),
31231
+ children: isSaving ? _t({
31232
+ id: "XvjC4F",
31233
+ message: "Saving..."
30914
31234
  }) : _t({
30915
- id: "HHspu6",
30916
- message: "Send Recovery Link"
31235
+ id: "IUwGEM",
31236
+ message: "Save Changes"
30917
31237
  })
30918
- }),
30919
- recoverySent && /* @__PURE__ */ jsx("p", {
30920
- className: "text-xs text-green-600 dark:text-green-400 text-center",
30921
- children: _t({
30922
- id: "SLJUHb",
30923
- message: "Recovery link sent to {0}",
30924
- values: { 0: user.email }
31238
+ }), !isSelf && /* @__PURE__ */ jsx(Button, {
31239
+ variant: user.disabled ? "outline" : "destructive",
31240
+ onClick: user.disabled ? onEnable : onDisable,
31241
+ icon: user.disabled ? /* @__PURE__ */ jsx(CheckCircle, {}) : /* @__PURE__ */ jsx(Prohibit, {}),
31242
+ children: user.disabled ? _t({
31243
+ id: "PaQ3df",
31244
+ message: "Enable"
31245
+ }) : _t({
31246
+ id: "cO9+2L",
31247
+ message: "Disable"
30925
31248
  })
30926
- }),
30927
- recoveryError && /* @__PURE__ */ jsx("p", {
30928
- className: "text-xs text-kumo-danger text-center",
30929
- children: recoveryError
30930
- })
30931
- ]
30932
- })]
30933
- })
30934
- ]
30935
- })] });
31249
+ })]
31250
+ }), !isSelf && onSendRecovery && /* @__PURE__ */ jsxs("div", {
31251
+ className: "space-y-1",
31252
+ children: [
31253
+ /* @__PURE__ */ jsx(Button, {
31254
+ variant: "outline",
31255
+ className: "w-full",
31256
+ onClick: onSendRecovery,
31257
+ disabled: isSendingRecovery,
31258
+ icon: /* @__PURE__ */ jsx(Envelope, {}),
31259
+ children: isSendingRecovery ? _t({
31260
+ id: "IoAuJG",
31261
+ message: "Sending..."
31262
+ }) : _t({
31263
+ id: "HHspu6",
31264
+ message: "Send Recovery Link"
31265
+ })
31266
+ }),
31267
+ recoverySent && /* @__PURE__ */ jsx("p", {
31268
+ className: "text-xs text-green-600 dark:text-green-400 text-center",
31269
+ children: _t({
31270
+ id: "SLJUHb",
31271
+ message: "Recovery link sent to {0}",
31272
+ values: { 0: user.email }
31273
+ })
31274
+ }),
31275
+ recoveryError && /* @__PURE__ */ jsx("p", {
31276
+ className: "text-xs text-kumo-danger text-center",
31277
+ children: recoveryError
31278
+ })
31279
+ ]
31280
+ })]
31281
+ })
31282
+ ]
31283
+ })] })
31284
+ });
30936
31285
  }
30937
31286
  /** Loading skeleton for user detail */
30938
31287
  function UserDetailSkeleton() {
@@ -31045,7 +31394,7 @@ function InviteUserModal({ open, isSending, error, inviteUrl, onOpenChange, onIn
31045
31394
  id: "yz7wBu",
31046
31395
  message: "Close"
31047
31396
  }),
31048
- className: "absolute right-4 top-4",
31397
+ className: "absolute end-4 top-4",
31049
31398
  children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
31050
31399
  className: "sr-only",
31051
31400
  children: _t({
@@ -31668,15 +32017,6 @@ function ContentListPage() {
31668
32017
  urlPattern: collectionConfig.urlPattern
31669
32018
  });
31670
32019
  }
31671
- /** Extract plugin block definitions from the manifest for Portable Text editor */
31672
- function getPluginBlocks(manifest) {
31673
- const blocks = [];
31674
- for (const [pluginId, plugin] of Object.entries(manifest.plugins)) if (plugin.portableTextBlocks) for (const block of plugin.portableTextBlocks) blocks.push({
31675
- ...block,
31676
- pluginId
31677
- });
31678
- return blocks;
31679
- }
31680
32020
  const contentNewRoute = createRoute({
31681
32021
  getParentRoute: () => adminLayoutRoute,
31682
32022
  path: "/content/$collection/new",
@@ -32568,6 +32908,8 @@ const contentTypesEditRoute = createRoute({
32568
32908
  function ContentTypesEditPage() {
32569
32909
  const { slug } = useParams({ from: "/_admin/content-types/$slug" });
32570
32910
  const queryClient = useQueryClient();
32911
+ const toastManager = Toast.useToastManager();
32912
+ const { _: _t } = useLingui();
32571
32913
  const { data: collection, isLoading, error } = useQuery({
32572
32914
  queryKey: [
32573
32915
  "schema",
@@ -32598,6 +32940,19 @@ function ContentTypesEditPage() {
32598
32940
  ] });
32599
32941
  queryClient.invalidateQueries({ queryKey: ["schema", "collections"] });
32600
32942
  queryClient.invalidateQueries({ queryKey: ["manifest"] });
32943
+ },
32944
+ onError: (mutationError) => {
32945
+ toastManager.add({
32946
+ title: _t({
32947
+ id: "+Ya+b9",
32948
+ message: "Failed to save"
32949
+ }),
32950
+ description: mutationError instanceof Error ? mutationError.message : _t({
32951
+ id: "Vw8l6h",
32952
+ message: "An error occurred"
32953
+ }),
32954
+ type: "error"
32955
+ });
32601
32956
  }
32602
32957
  });
32603
32958
  const addFieldMutation = useMutation({