@emdash-cms/admin 0.36.0 → 0.37.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 (152) hide show
  1. package/dist/{LocaleDirectionProvider-BjVpQpBl.js → LocaleDirectionProvider-DWBtquoB.js} +29 -29
  2. package/dist/{LocaleDirectionProvider-BjVpQpBl.js.map → LocaleDirectionProvider-DWBtquoB.js.map} +1 -1
  3. package/dist/index.d.ts +63 -33
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +28548 -23726
  6. package/dist/index.js.map +1 -1
  7. package/dist/locales/ar/messages.mjs +1 -1
  8. package/dist/locales/ca/messages.mjs +1 -1
  9. package/dist/locales/cs/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/en-GB/messages.mjs +1 -1
  13. package/dist/locales/es-419/messages.mjs +1 -1
  14. package/dist/locales/es-ES/messages.mjs +1 -1
  15. package/dist/locales/eu/messages.mjs +1 -1
  16. package/dist/locales/fa/messages.mjs +1 -1
  17. package/dist/locales/fr/messages.mjs +1 -1
  18. package/dist/locales/hi/messages.mjs +1 -1
  19. package/dist/locales/hu/messages.mjs +1 -1
  20. package/dist/locales/id/messages.mjs +1 -1
  21. package/dist/locales/index.js +1 -1
  22. package/dist/locales/ja/messages.mjs +1 -1
  23. package/dist/locales/ko/messages.mjs +1 -1
  24. package/dist/locales/nb/messages.mjs +1 -1
  25. package/dist/locales/nl/messages.mjs +1 -1
  26. package/dist/locales/pl/messages.mjs +1 -1
  27. package/dist/locales/pseudo/messages.mjs +1 -1
  28. package/dist/locales/pt-BR/messages.mjs +1 -1
  29. package/dist/locales/sr-Latn/messages.mjs +1 -1
  30. package/dist/locales/sv/messages.mjs +1 -1
  31. package/dist/locales/th/messages.mjs +1 -1
  32. package/dist/locales/tr/messages.mjs +1 -1
  33. package/dist/locales/uk/messages.mjs +1 -1
  34. package/dist/locales/zh-CN/messages.mjs +1 -1
  35. package/dist/locales/zh-TW/messages.mjs +1 -1
  36. package/dist/messages--4H_uJJx.js +6 -0
  37. package/dist/messages--4H_uJJx.js.map +1 -0
  38. package/dist/messages-1HW-Clzo.js +6 -0
  39. package/dist/messages-1HW-Clzo.js.map +1 -0
  40. package/dist/messages-3g7OPPLD.js +6 -0
  41. package/dist/messages-3g7OPPLD.js.map +1 -0
  42. package/dist/messages-3y7urMNZ.js +6 -0
  43. package/dist/messages-3y7urMNZ.js.map +1 -0
  44. package/dist/messages-Bi8Q6hQh.js +6 -0
  45. package/dist/messages-Bi8Q6hQh.js.map +1 -0
  46. package/dist/messages-C5M2v621.js +6 -0
  47. package/dist/messages-C5M2v621.js.map +1 -0
  48. package/dist/messages-CJVEZ_A5.js +6 -0
  49. package/dist/messages-CJVEZ_A5.js.map +1 -0
  50. package/dist/messages-CNbPYtov.js +6 -0
  51. package/dist/messages-CNbPYtov.js.map +1 -0
  52. package/dist/messages-CXOtPqxW.js +6 -0
  53. package/dist/messages-CXOtPqxW.js.map +1 -0
  54. package/dist/messages-CkNuItb-.js +6 -0
  55. package/dist/messages-CkNuItb-.js.map +1 -0
  56. package/dist/messages-ClabBphB.js +6 -0
  57. package/dist/messages-ClabBphB.js.map +1 -0
  58. package/dist/messages-Cqj_YnUc.js +6 -0
  59. package/dist/messages-Cqj_YnUc.js.map +1 -0
  60. package/dist/messages-Cy_HI78n.js +6 -0
  61. package/dist/messages-Cy_HI78n.js.map +1 -0
  62. package/dist/messages-D-WF9xWO.js +6 -0
  63. package/dist/messages-D-WF9xWO.js.map +1 -0
  64. package/dist/messages-D2cvoQzD.js +6 -0
  65. package/dist/messages-D2cvoQzD.js.map +1 -0
  66. package/dist/messages-DC8BlS4V.js +6 -0
  67. package/dist/messages-DC8BlS4V.js.map +1 -0
  68. package/dist/messages-DMQToQxw.js +6 -0
  69. package/dist/messages-DMQToQxw.js.map +1 -0
  70. package/dist/messages-DWBTgm-y.js +6 -0
  71. package/dist/messages-DWBTgm-y.js.map +1 -0
  72. package/dist/messages-DjoDBrf1.js +6 -0
  73. package/dist/messages-DjoDBrf1.js.map +1 -0
  74. package/dist/messages-Dkr-4VFi.js +6 -0
  75. package/dist/messages-Dkr-4VFi.js.map +1 -0
  76. package/dist/messages-DmQsSz7M.js +6 -0
  77. package/dist/messages-DmQsSz7M.js.map +1 -0
  78. package/dist/messages-Dnpi1ztm.js +6 -0
  79. package/dist/messages-Dnpi1ztm.js.map +1 -0
  80. package/dist/messages-OdBFlKpa.js +6 -0
  81. package/dist/messages-OdBFlKpa.js.map +1 -0
  82. package/dist/messages-RBIsUSWq.js +6 -0
  83. package/dist/messages-RBIsUSWq.js.map +1 -0
  84. package/dist/messages-_6oZo840.js +6 -0
  85. package/dist/messages-_6oZo840.js.map +1 -0
  86. package/dist/messages-kpo6a8yB.js +6 -0
  87. package/dist/messages-kpo6a8yB.js.map +1 -0
  88. package/dist/messages-oZUnGK0y.js +6 -0
  89. package/dist/messages-oZUnGK0y.js.map +1 -0
  90. package/dist/messages-u4KSs1DK.js +6 -0
  91. package/dist/messages-u4KSs1DK.js.map +1 -0
  92. package/dist/{plugins-DJsLy2K-.js → plugins-BPVhvih_.js} +16 -1
  93. package/dist/plugins-BPVhvih_.js.map +1 -0
  94. package/dist/styles.css +1 -1
  95. package/package.json +5 -4
  96. package/dist/messages-3FU8zCct.js +0 -6
  97. package/dist/messages-3FU8zCct.js.map +0 -1
  98. package/dist/messages-9k1iDJF6.js +0 -6
  99. package/dist/messages-9k1iDJF6.js.map +0 -1
  100. package/dist/messages-B3Q7NUrK.js +0 -6
  101. package/dist/messages-B3Q7NUrK.js.map +0 -1
  102. package/dist/messages-BKjrWDoV.js +0 -6
  103. package/dist/messages-BKjrWDoV.js.map +0 -1
  104. package/dist/messages-BLxOqfxi.js +0 -6
  105. package/dist/messages-BLxOqfxi.js.map +0 -1
  106. package/dist/messages-BUkvBAQ_.js +0 -6
  107. package/dist/messages-BUkvBAQ_.js.map +0 -1
  108. package/dist/messages-BYPUIPvx.js +0 -6
  109. package/dist/messages-BYPUIPvx.js.map +0 -1
  110. package/dist/messages-BYaDnRZi.js +0 -6
  111. package/dist/messages-BYaDnRZi.js.map +0 -1
  112. package/dist/messages-C-omjoCi.js +0 -6
  113. package/dist/messages-C-omjoCi.js.map +0 -1
  114. package/dist/messages-CA8gfGRN.js +0 -6
  115. package/dist/messages-CA8gfGRN.js.map +0 -1
  116. package/dist/messages-CKCmO_US.js +0 -6
  117. package/dist/messages-CKCmO_US.js.map +0 -1
  118. package/dist/messages-CKtyiPlE.js +0 -6
  119. package/dist/messages-CKtyiPlE.js.map +0 -1
  120. package/dist/messages-CMlXT2mo.js +0 -6
  121. package/dist/messages-CMlXT2mo.js.map +0 -1
  122. package/dist/messages-CSzVxyoV.js +0 -6
  123. package/dist/messages-CSzVxyoV.js.map +0 -1
  124. package/dist/messages-CUVVH-l2.js +0 -6
  125. package/dist/messages-CUVVH-l2.js.map +0 -1
  126. package/dist/messages-CXBqJPo6.js +0 -6
  127. package/dist/messages-CXBqJPo6.js.map +0 -1
  128. package/dist/messages-Cb_WSNlm.js +0 -6
  129. package/dist/messages-Cb_WSNlm.js.map +0 -1
  130. package/dist/messages-CiFlbS-H.js +0 -6
  131. package/dist/messages-CiFlbS-H.js.map +0 -1
  132. package/dist/messages-CkVoAW1_.js +0 -6
  133. package/dist/messages-CkVoAW1_.js.map +0 -1
  134. package/dist/messages-DKYRxT68.js +0 -6
  135. package/dist/messages-DKYRxT68.js.map +0 -1
  136. package/dist/messages-DZiI-npH.js +0 -6
  137. package/dist/messages-DZiI-npH.js.map +0 -1
  138. package/dist/messages-DrqeFeSw.js +0 -6
  139. package/dist/messages-DrqeFeSw.js.map +0 -1
  140. package/dist/messages-UWbNAre2.js +0 -6
  141. package/dist/messages-UWbNAre2.js.map +0 -1
  142. package/dist/messages-_-gK_V4q.js +0 -6
  143. package/dist/messages-_-gK_V4q.js.map +0 -1
  144. package/dist/messages-ha2_ySOs.js +0 -6
  145. package/dist/messages-ha2_ySOs.js.map +0 -1
  146. package/dist/messages-kFHcdfMU.js +0 -6
  147. package/dist/messages-kFHcdfMU.js.map +0 -1
  148. package/dist/messages-sJpTSD2G.js +0 -6
  149. package/dist/messages-sJpTSD2G.js.map +0 -1
  150. package/dist/messages-vx3-MYVH.js +0 -6
  151. package/dist/messages-vx3-MYVH.js.map +0 -1
  152. package/dist/plugins-DJsLy2K-.js.map +0 -1
@@ -253,34 +253,34 @@ function resolveLocale(request) {
253
253
  //#endregion
254
254
  //#region src/locales/loadMessages.ts
255
255
  const LOCALE_LOADERS = /* @__PURE__ */ Object.assign({
256
- "./ar/messages.mjs": () => import("./messages-C-omjoCi.js"),
257
- "./ca/messages.mjs": () => import("./messages-B3Q7NUrK.js"),
258
- "./cs/messages.mjs": () => import("./messages-DKYRxT68.js"),
259
- "./de/messages.mjs": () => import("./messages-sJpTSD2G.js"),
260
- "./en/messages.mjs": () => import("./messages-BLxOqfxi.js"),
261
- "./en-GB/messages.mjs": () => import("./messages-CA8gfGRN.js"),
262
- "./es-419/messages.mjs": () => import("./messages-CiFlbS-H.js"),
263
- "./es-ES/messages.mjs": () => import("./messages-CSzVxyoV.js"),
264
- "./eu/messages.mjs": () => import("./messages-Cb_WSNlm.js"),
265
- "./fa/messages.mjs": () => import("./messages-CUVVH-l2.js"),
266
- "./fr/messages.mjs": () => import("./messages-BKjrWDoV.js"),
267
- "./hi/messages.mjs": () => import("./messages-CkVoAW1_.js"),
268
- "./hu/messages.mjs": () => import("./messages-DrqeFeSw.js"),
269
- "./id/messages.mjs": () => import("./messages-CXBqJPo6.js"),
270
- "./ja/messages.mjs": () => import("./messages-BUkvBAQ_.js"),
271
- "./ko/messages.mjs": () => import("./messages-3FU8zCct.js"),
272
- "./nb/messages.mjs": () => import("./messages-UWbNAre2.js"),
273
- "./nl/messages.mjs": () => import("./messages-CKCmO_US.js"),
274
- "./pl/messages.mjs": () => import("./messages-BYPUIPvx.js"),
275
- "./pseudo/messages.mjs": () => import("./messages-kFHcdfMU.js"),
276
- "./pt-BR/messages.mjs": () => import("./messages-BYaDnRZi.js"),
277
- "./sr-Latn/messages.mjs": () => import("./messages-_-gK_V4q.js"),
278
- "./sv/messages.mjs": () => import("./messages-CKtyiPlE.js"),
279
- "./th/messages.mjs": () => import("./messages-DZiI-npH.js"),
280
- "./tr/messages.mjs": () => import("./messages-vx3-MYVH.js"),
281
- "./uk/messages.mjs": () => import("./messages-ha2_ySOs.js"),
282
- "./zh-CN/messages.mjs": () => import("./messages-CMlXT2mo.js"),
283
- "./zh-TW/messages.mjs": () => import("./messages-9k1iDJF6.js")
256
+ "./ar/messages.mjs": () => import("./messages-DWBTgm-y.js"),
257
+ "./ca/messages.mjs": () => import("./messages-CJVEZ_A5.js"),
258
+ "./cs/messages.mjs": () => import("./messages-D-WF9xWO.js"),
259
+ "./de/messages.mjs": () => import("./messages-RBIsUSWq.js"),
260
+ "./en/messages.mjs": () => import("./messages-DMQToQxw.js"),
261
+ "./en-GB/messages.mjs": () => import("./messages-Bi8Q6hQh.js"),
262
+ "./es-419/messages.mjs": () => import("./messages-DjoDBrf1.js"),
263
+ "./es-ES/messages.mjs": () => import("./messages-CkNuItb-.js"),
264
+ "./eu/messages.mjs": () => import("./messages-Dnpi1ztm.js"),
265
+ "./fa/messages.mjs": () => import("./messages-Dkr-4VFi.js"),
266
+ "./fr/messages.mjs": () => import("./messages-CNbPYtov.js"),
267
+ "./hi/messages.mjs": () => import("./messages-D2cvoQzD.js"),
268
+ "./hu/messages.mjs": () => import("./messages-DmQsSz7M.js"),
269
+ "./id/messages.mjs": () => import("./messages-OdBFlKpa.js"),
270
+ "./ja/messages.mjs": () => import("./messages-CXOtPqxW.js"),
271
+ "./ko/messages.mjs": () => import("./messages-DC8BlS4V.js"),
272
+ "./nb/messages.mjs": () => import("./messages-3y7urMNZ.js"),
273
+ "./nl/messages.mjs": () => import("./messages-C5M2v621.js"),
274
+ "./pl/messages.mjs": () => import("./messages-3g7OPPLD.js"),
275
+ "./pseudo/messages.mjs": () => import("./messages-ClabBphB.js"),
276
+ "./pt-BR/messages.mjs": () => import("./messages-_6oZo840.js"),
277
+ "./sr-Latn/messages.mjs": () => import("./messages-1HW-Clzo.js"),
278
+ "./sv/messages.mjs": () => import("./messages-oZUnGK0y.js"),
279
+ "./th/messages.mjs": () => import("./messages-u4KSs1DK.js"),
280
+ "./tr/messages.mjs": () => import("./messages--4H_uJJx.js"),
281
+ "./uk/messages.mjs": () => import("./messages-Cy_HI78n.js"),
282
+ "./zh-CN/messages.mjs": () => import("./messages-kpo6a8yB.js"),
283
+ "./zh-TW/messages.mjs": () => import("./messages-Cqj_YnUc.js")
284
284
  });
285
285
  async function loadMessages(locale) {
286
286
  const key = `./${locale}/messages.mjs`;
@@ -347,4 +347,4 @@ function LocaleDirectionProvider({ children }) {
347
347
 
348
348
  //#endregion
349
349
  export { SUPPORTED_LOCALES as a, getLocaleLabel as c, DEFAULT_LOCALE as i, resolveLocale as l, useLocale as n, SUPPORTED_LOCALE_CODES as o, loadMessages as r, getLocaleDir as s, LocaleDirectionProvider as t };
350
- //# sourceMappingURL=LocaleDirectionProvider-BjVpQpBl.js.map
350
+ //# sourceMappingURL=LocaleDirectionProvider-DWBtquoB.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LocaleDirectionProvider-BjVpQpBl.js","names":["React"],"sources":["../src/locales/locales.ts","../src/locales/config.ts","../src/locales/loadMessages.ts","../src/locales/useLocale.ts","../src/locales/LocaleDirectionProvider.tsx"],"sourcesContent":["/**\n * Canonical locale definitions -- the single source of truth.\n *\n * This file is intentionally free of Vite/Astro APIs (`import.meta.env` etc.)\n * so it can be imported from CLI tools (Lingui, Lunaria) running in plain Node.\n *\n * To add a new locale:\n * 1. Add an entry here (with `enabled: false`).\n * 2. Run `pnpm locale:extract` to generate the PO file.\n * 3. Translate the strings in the PO file.\n * 4. Set `enabled: true` once coverage is sufficient.\n *\n * Lingui and Lunaria use all locales (for extraction and tracking).\n * The admin runtime only exposes locales with `enabled: true`.\n */\n\nexport interface LocaleDefinition {\n\t/** BCP 47 locale code (e.g. \"en\", \"pt-BR\"). */\n\tcode: string;\n\t/** Human-readable label in the locale's own language. */\n\tlabel: string;\n\t/** Whether this locale is selectable in the admin UI. */\n\tenabled: boolean;\n\t/** Text direction for this locale. Defaults to \"ltr\" if not specified. */\n\tdir?: \"rtl\" | \"ltr\";\n}\n\n/**\n * All locales that have (or should have) a PO catalog.\n * First entry is the source/default locale.\n */\nexport const LOCALES: LocaleDefinition[] = [\n\t// Source locale first, then alphabetical by English name.\n\t{ code: \"en\", label: \"English\", enabled: true },\n\t{ code: \"ar\", label: \"العربية\", enabled: true, dir: \"rtl\" }, // Arabic\n\t{ code: \"eu\", label: \"Euskara\", enabled: true }, // Basque\n\t{ code: \"ca\", label: \"Català\", enabled: true }, // Catalan\n\t{ code: \"zh-CN\", label: \"简体中文\", enabled: true }, // Chinese (Simplified)\n\t{ code: \"zh-TW\", label: \"繁體中文\", enabled: true }, // Chinese (Traditional)\n\t{ code: \"cs\", label: \"Čeština\", enabled: true }, // Czech\n\t{ code: \"nl\", label: \"Nederlands\", enabled: true }, // Dutch\n\t{ code: \"en-GB\", label: \"English (UK)\", enabled: true }, // English (United Kingdom)\n\t{ code: \"fa\", label: \"فارسی\", enabled: true, dir: \"rtl\" }, // Farsi (also known as Persian)\n\t{ code: \"fr\", label: \"Français\", enabled: true }, // French\n\t{ code: \"de\", label: \"Deutsch\", enabled: true }, // German\n\t{ code: \"hi\", label: \"हिन्दी\", enabled: true }, // Hindi\n\t{ code: \"hu\", label: \"Magyar\", enabled: true }, // Hungarian\n\t{ code: \"id\", label: \"Bahasa Indonesia\", enabled: true }, // Indonesian\n\t{ code: \"ja\", label: \"日本語\", enabled: true }, // Japanese\n\t{ code: \"ko\", label: \"한국어\", enabled: false }, // Korean\n\t{ code: \"nb\", label: \"Norsk bokmål\", enabled: true }, // Norwegian Bokmål\n\t{ code: \"pl\", label: \"Polski\", enabled: true }, // Polish\n\t{ code: \"pt-BR\", label: \"Português (Brasil)\", enabled: true }, // Portuguese (Brazil)\n\t{ code: \"sr-Latn\", label: \"Srpski\", enabled: true }, // Serbian (Latin script)\n\t{ code: \"es-419\", label: \"Español (Latinoamérica)\", enabled: true }, // Spanish (Latin America)\n\t{ code: \"es-ES\", label: \"Español (España)\", enabled: true }, // Spanish (Spain) - BCP 47\n\t{ code: \"sv\", label: \"Svenska\", enabled: true }, // Swedish\n\t{ code: \"th\", label: \"ไทย\", enabled: true }, // Thai\n\t{ code: \"tr\", label: \"Türkçe\", enabled: true }, // Turkish\n\t{ code: \"uk\", label: \"Українська\", enabled: true }, // Ukrainian\n\t// Pseudo-locale for i18n testing - never enabled in the admin UI by default.\n\t// Set EMDASH_PSEUDO_LOCALE=1 in .env to expose it in the locale switcher (dev only).\n\t{ code: \"pseudo\", label: \"Pseudo\", enabled: false },\n];\n\n/** The source locale (first entry). */\nexport const SOURCE_LOCALE = LOCALES[0]!;\n\n/** All locale codes (for Lingui extraction / Lunaria tracking). */\nexport const LOCALE_CODES = LOCALES.map((l) => l.code);\n\n/** Target locales -- everything except the source (for Lunaria). */\nexport const TARGET_LOCALES = LOCALES.slice(1);\n\n/** Locales enabled in the admin UI. */\nexport const ENABLED_LOCALES = LOCALES.filter((l) => l.enabled);\n","/**\n * Locale configuration for the admin UI runtime.\n *\n * Locale definitions are in `./locales.ts` -- the single source of truth\n * shared by this file, lingui.config.ts and lunaria.config.ts.\n */\n\nimport { ENABLED_LOCALES, LOCALES, SOURCE_LOCALE } from \"./locales.js\";\n\nexport type { LocaleDefinition as SupportedLocale } from \"./locales.js\";\n\nfunction isValidLocale(code: string): boolean {\n\ttry {\n\t\tconst locale = new Intl.Locale(code);\n\t\treturn locale.baseName !== \"\";\n\t} catch {\n\t\tif (import.meta.env.DEV) {\n\t\t\tthrow new Error(`Invalid locale code: \"${code}\"`);\n\t\t}\n\t\treturn false;\n\t}\n}\n\n// Injected by the EmDash Vite integration from process.env.EMDASH_PSEUDO_LOCALE.\n// Only true in dev when EMDASH_PSEUDO_LOCALE=1 is set.\ndeclare const __EMDASH_PSEUDO_LOCALE__: boolean;\n\n/**\n * The pseudo locale, injected into the supported list only when\n * EMDASH_PSEUDO_LOCALE=1 is set. Never available in production.\n */\nconst PSEUDO_LOCALE =\n\ttypeof __EMDASH_PSEUDO_LOCALE__ !== \"undefined\" && __EMDASH_PSEUDO_LOCALE__\n\t\t? LOCALES.find((l) => l.code === \"pseudo\")\n\t\t: undefined;\n\n/** Available locales at runtime, validated against BCP 47. */\nexport const SUPPORTED_LOCALES = [\n\t...ENABLED_LOCALES.filter((l) => isValidLocale(l.code)),\n\t...(PSEUDO_LOCALE ? [PSEUDO_LOCALE] : []),\n];\n\nexport const SUPPORTED_LOCALE_CODES = new Set(SUPPORTED_LOCALES.map((l) => l.code));\n\nexport const DEFAULT_LOCALE = SOURCE_LOCALE.code;\n\n/** Maps base language codes to supported locales (e.g. \"pt\" -> \"pt-BR\"). */\nconst BASE_LANGUAGE_MAP = new Map<string, string>();\n/** Maps script codes to supported locales (e.g. \"zh-Hant\" -> \"zh-TW\", \"zh-Hans\" -> \"zh-CN\"). */\nconst SCRIPT_LANGUAGE_MAP = new Map<string, string>();\n\nfor (const l of SUPPORTED_LOCALES) {\n\tconst base = l.code.split(\"-\")[0]!.toLowerCase();\n\t// First match wins -- if we have both \"pt\" and \"pt-BR\", exact wins via direct lookup.\n\tif (!BASE_LANGUAGE_MAP.has(base)) {\n\t\tBASE_LANGUAGE_MAP.set(base, l.code);\n\t}\n\n\tconst maximized = new Intl.Locale(l.code).maximize();\n\tif (maximized.script) {\n\t\tconst scriptKey = `${maximized.language}-${maximized.script}`.toLowerCase();\n\t\tif (!SCRIPT_LANGUAGE_MAP.has(scriptKey)) {\n\t\t\tSCRIPT_LANGUAGE_MAP.set(scriptKey, l.code);\n\t\t}\n\t}\n}\n\n/**\n * Find the best matching supported locale for a BCP 47 tag.\n * Canonicalizes via Intl.Locale so case differences (e.g. \"pt-br\" vs \"pt-BR\")\n * don't prevent matching. Supports script codes (zh-Hant -> zh-TW, zh-Hans -> zh-CN)\n * and falls back to base language (pt-PT -> pt-BR).\n */\nfunction matchLocale(tag: string): string | undefined {\n\tconst trimmed = tag.trim();\n\tif (!trimmed) return undefined;\n\tlet canonical: string;\n\ttry {\n\t\tcanonical = new Intl.Locale(trimmed).baseName;\n\t} catch {\n\t\treturn undefined;\n\t}\n\n\t// Exact match (case-insensitive via Intl.Locale)\n\tif (SUPPORTED_LOCALE_CODES.has(canonical)) return canonical;\n\n\t// Try script-based matching (zh-Hant -> zh-TW, zh-Hans -> zh-CN)\n\tconst locale = new Intl.Locale(trimmed);\n\tif (locale.script) {\n\t\tconst scriptKey = `${locale.language}-${locale.script}`.toLowerCase();\n\t\tconst scriptMatch = SCRIPT_LANGUAGE_MAP.get(scriptKey);\n\t\tif (scriptMatch) return scriptMatch;\n\t}\n\n\t// Fallback to base language (pt-PT -> pt-BR)\n\tconst base = canonical.split(\"-\")[0]!.toLowerCase();\n\treturn BASE_LANGUAGE_MAP.get(base);\n}\n\nconst LOCALE_LABELS = new Map(SUPPORTED_LOCALES.map((l) => [l.code, l.label]));\n\n/** Get a display label for a locale code, falling back to uppercase code. */\nexport function getLocaleLabel(code: string): string {\n\treturn LOCALE_LABELS.get(code) ?? code.toUpperCase();\n}\n\nconst LOCALE_DIRS = new Map(SUPPORTED_LOCALES.map((l) => [l.code, l.dir]));\n\n/** Get the text direction for a locale code. Defaults to \"ltr\" if not specified. */\nexport function getLocaleDir(code: string): \"ltr\" | \"rtl\" {\n\treturn LOCALE_DIRS.get(code) ?? \"ltr\";\n}\n\nconst LOCALE_COOKIE_RE = /(?:^|;\\s*)emdash-locale=([^;]+)/;\n\n/**\n * Resolve the admin locale from a Request.\n * Priority: emdash-locale cookie -> Accept-Language -> DEFAULT_LOCALE.\n */\nexport function resolveLocale(request: Request): string {\n\tconst cookieHeader = request.headers.get(\"cookie\") ?? \"\";\n\tconst cookieMatch = cookieHeader.match(LOCALE_COOKIE_RE);\n\tconst cookieLocale = cookieMatch?.[1]?.trim() ?? \"\";\n\n\tif (SUPPORTED_LOCALE_CODES.has(cookieLocale)) return cookieLocale;\n\n\tconst acceptLang = request.headers.get(\"accept-language\") ?? \"\";\n\tfor (const entry of acceptLang.split(\",\")) {\n\t\tconst tag = entry.split(\";\")[0]!.trim();\n\t\tconst matched = matchLocale(tag);\n\t\tif (matched) return matched;\n\t}\n\n\treturn DEFAULT_LOCALE;\n}\n","import type { Messages } from \"@lingui/core\";\n\nimport { DEFAULT_LOCALE } from \"./config.js\";\n\nconst LOCALE_LOADERS = import.meta.glob<{ messages: Messages }>(\"./**/messages.mjs\");\n\nexport async function loadMessages(locale: string): Promise<Messages> {\n\tconst key = `./${locale}/messages.mjs`;\n\tconst fallbackKey = `./${DEFAULT_LOCALE}/messages.mjs`;\n\tconst loader = LOCALE_LOADERS[key] ?? LOCALE_LOADERS[fallbackKey];\n\tif (!loader) {\n\t\tthrow new Error(\n\t\t\t`No locale catalog found for \"${locale}\" or \"${DEFAULT_LOCALE}\". Run \\`pnpm locale:compile\\` to generate catalogs.`,\n\t\t);\n\t}\n\tconst { messages } = await loader();\n\treturn messages;\n}\n","import { useLingui } from \"@lingui/react\";\nimport * as React from \"react\";\n\nimport { SUPPORTED_LOCALE_CODES } from \"./config.js\";\nimport { loadMessages } from \"./loadMessages.js\";\n\nfunction setCookie(code: string) {\n\tconst secure = window.location.protocol === \"https:\" ? \"; Secure\" : \"\";\n\tdocument.cookie = `emdash-locale=${code}; Path=/_emdash; SameSite=Lax; Max-Age=31536000${secure}`;\n}\n\n/**\n * Get the current locale and a function to switch locales.\n * Loads the new catalog dynamically and sets a cookie for server-side persistence.\n */\nexport function useLocale() {\n\tconst { i18n } = useLingui();\n\tconst [locale, setLocaleState] = React.useState(i18n.locale);\n\n\tconst setLocale = React.useCallback(\n\t\t(code: string) => {\n\t\t\tif (code === i18n.locale || !SUPPORTED_LOCALE_CODES.has(code)) return;\n\t\t\tsetCookie(code);\n\t\t\tvoid loadMessages(code)\n\t\t\t\t.then((messages) => i18n.loadAndActivate({ locale: code, messages }))\n\t\t\t\t.catch(() => {\n\t\t\t\t\tsetCookie(i18n.locale);\n\t\t\t\t});\n\t\t},\n\t\t[i18n],\n\t);\n\n\t// Subscribe to i18n change events to trigger re-renders\n\tReact.useEffect(() => {\n\t\tconst unsubscribe = i18n.on(\"change\", () => {\n\t\t\tsetLocaleState(i18n.locale);\n\t\t});\n\t\treturn unsubscribe;\n\t}, [i18n]);\n\n\treturn { locale, setLocale };\n}\n","import { DirectionProvider } from \"@cloudflare/kumo/primitives\";\nimport * as React from \"react\";\n\nimport { getLocaleDir } from \"./config.js\";\nimport { useLocale } from \"./useLocale.js\";\n\ninterface LocaleDirectionProviderProps {\n\tchildren: React.ReactNode;\n}\n\n/**\n * Wraps the app with DirectionProvider and keeps it in sync with the current locale.\n * Automatically updates direction when locale changes via useLocale.\n */\nexport function LocaleDirectionProvider({ children }: LocaleDirectionProviderProps) {\n\tconst { locale } = useLocale();\n\tconst dir = React.useMemo(() => getLocaleDir(locale), [locale]);\n\n\t/** Sync the direction and lang attributes with the current locale. */\n\tReact.useEffect(() => {\n\t\tdocument.documentElement.setAttribute(\"lang\", locale);\n\t\tdocument.documentElement.setAttribute(\"dir\", dir);\n\t}, [dir, locale]);\n\n\treturn <DirectionProvider direction={dir}>{children}</DirectionProvider>;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"LocaleDirectionProvider-DWBtquoB.js","names":["React"],"sources":["../src/locales/locales.ts","../src/locales/config.ts","../src/locales/loadMessages.ts","../src/locales/useLocale.ts","../src/locales/LocaleDirectionProvider.tsx"],"sourcesContent":["/**\n * Canonical locale definitions -- the single source of truth.\n *\n * This file is intentionally free of Vite/Astro APIs (`import.meta.env` etc.)\n * so it can be imported from CLI tools (Lingui, Lunaria) running in plain Node.\n *\n * To add a new locale:\n * 1. Add an entry here (with `enabled: false`).\n * 2. Run `pnpm locale:extract` to generate the PO file.\n * 3. Translate the strings in the PO file.\n * 4. Set `enabled: true` once coverage is sufficient.\n *\n * Lingui and Lunaria use all locales (for extraction and tracking).\n * The admin runtime only exposes locales with `enabled: true`.\n */\n\nexport interface LocaleDefinition {\n\t/** BCP 47 locale code (e.g. \"en\", \"pt-BR\"). */\n\tcode: string;\n\t/** Human-readable label in the locale's own language. */\n\tlabel: string;\n\t/** Whether this locale is selectable in the admin UI. */\n\tenabled: boolean;\n\t/** Text direction for this locale. Defaults to \"ltr\" if not specified. */\n\tdir?: \"rtl\" | \"ltr\";\n}\n\n/**\n * All locales that have (or should have) a PO catalog.\n * First entry is the source/default locale.\n */\nexport const LOCALES: LocaleDefinition[] = [\n\t// Source locale first, then alphabetical by English name.\n\t{ code: \"en\", label: \"English\", enabled: true },\n\t{ code: \"ar\", label: \"العربية\", enabled: true, dir: \"rtl\" }, // Arabic\n\t{ code: \"eu\", label: \"Euskara\", enabled: true }, // Basque\n\t{ code: \"ca\", label: \"Català\", enabled: true }, // Catalan\n\t{ code: \"zh-CN\", label: \"简体中文\", enabled: true }, // Chinese (Simplified)\n\t{ code: \"zh-TW\", label: \"繁體中文\", enabled: true }, // Chinese (Traditional)\n\t{ code: \"cs\", label: \"Čeština\", enabled: true }, // Czech\n\t{ code: \"nl\", label: \"Nederlands\", enabled: true }, // Dutch\n\t{ code: \"en-GB\", label: \"English (UK)\", enabled: true }, // English (United Kingdom)\n\t{ code: \"fa\", label: \"فارسی\", enabled: true, dir: \"rtl\" }, // Farsi (also known as Persian)\n\t{ code: \"fr\", label: \"Français\", enabled: true }, // French\n\t{ code: \"de\", label: \"Deutsch\", enabled: true }, // German\n\t{ code: \"hi\", label: \"हिन्दी\", enabled: true }, // Hindi\n\t{ code: \"hu\", label: \"Magyar\", enabled: true }, // Hungarian\n\t{ code: \"id\", label: \"Bahasa Indonesia\", enabled: true }, // Indonesian\n\t{ code: \"ja\", label: \"日本語\", enabled: true }, // Japanese\n\t{ code: \"ko\", label: \"한국어\", enabled: false }, // Korean\n\t{ code: \"nb\", label: \"Norsk bokmål\", enabled: true }, // Norwegian Bokmål\n\t{ code: \"pl\", label: \"Polski\", enabled: true }, // Polish\n\t{ code: \"pt-BR\", label: \"Português (Brasil)\", enabled: true }, // Portuguese (Brazil)\n\t{ code: \"sr-Latn\", label: \"Srpski\", enabled: true }, // Serbian (Latin script)\n\t{ code: \"es-419\", label: \"Español (Latinoamérica)\", enabled: true }, // Spanish (Latin America)\n\t{ code: \"es-ES\", label: \"Español (España)\", enabled: true }, // Spanish (Spain) - BCP 47\n\t{ code: \"sv\", label: \"Svenska\", enabled: true }, // Swedish\n\t{ code: \"th\", label: \"ไทย\", enabled: true }, // Thai\n\t{ code: \"tr\", label: \"Türkçe\", enabled: true }, // Turkish\n\t{ code: \"uk\", label: \"Українська\", enabled: true }, // Ukrainian\n\t// Pseudo-locale for i18n testing - never enabled in the admin UI by default.\n\t// Set EMDASH_PSEUDO_LOCALE=1 in .env to expose it in the locale switcher (dev only).\n\t{ code: \"pseudo\", label: \"Pseudo\", enabled: false },\n];\n\n/** The source locale (first entry). */\nexport const SOURCE_LOCALE = LOCALES[0]!;\n\n/** All locale codes (for Lingui extraction / Lunaria tracking). */\nexport const LOCALE_CODES = LOCALES.map((l) => l.code);\n\n/** Target locales -- everything except the source (for Lunaria). */\nexport const TARGET_LOCALES = LOCALES.slice(1);\n\n/** Locales enabled in the admin UI. */\nexport const ENABLED_LOCALES = LOCALES.filter((l) => l.enabled);\n","/**\n * Locale configuration for the admin UI runtime.\n *\n * Locale definitions are in `./locales.ts` -- the single source of truth\n * shared by this file, lingui.config.ts and lunaria.config.ts.\n */\n\nimport { ENABLED_LOCALES, LOCALES, SOURCE_LOCALE } from \"./locales.js\";\n\nexport type { LocaleDefinition as SupportedLocale } from \"./locales.js\";\n\nfunction isValidLocale(code: string): boolean {\n\ttry {\n\t\tconst locale = new Intl.Locale(code);\n\t\treturn locale.baseName !== \"\";\n\t} catch {\n\t\tif (import.meta.env.DEV) {\n\t\t\tthrow new Error(`Invalid locale code: \"${code}\"`);\n\t\t}\n\t\treturn false;\n\t}\n}\n\n// Injected by the EmDash Vite integration from process.env.EMDASH_PSEUDO_LOCALE.\n// Only true in dev when EMDASH_PSEUDO_LOCALE=1 is set.\ndeclare const __EMDASH_PSEUDO_LOCALE__: boolean;\n\n/**\n * The pseudo locale, injected into the supported list only when\n * EMDASH_PSEUDO_LOCALE=1 is set. Never available in production.\n */\nconst PSEUDO_LOCALE =\n\ttypeof __EMDASH_PSEUDO_LOCALE__ !== \"undefined\" && __EMDASH_PSEUDO_LOCALE__\n\t\t? LOCALES.find((l) => l.code === \"pseudo\")\n\t\t: undefined;\n\n/** Available locales at runtime, validated against BCP 47. */\nexport const SUPPORTED_LOCALES = [\n\t...ENABLED_LOCALES.filter((l) => isValidLocale(l.code)),\n\t...(PSEUDO_LOCALE ? [PSEUDO_LOCALE] : []),\n];\n\nexport const SUPPORTED_LOCALE_CODES = new Set(SUPPORTED_LOCALES.map((l) => l.code));\n\nexport const DEFAULT_LOCALE = SOURCE_LOCALE.code;\n\n/** Maps base language codes to supported locales (e.g. \"pt\" -> \"pt-BR\"). */\nconst BASE_LANGUAGE_MAP = new Map<string, string>();\n/** Maps script codes to supported locales (e.g. \"zh-Hant\" -> \"zh-TW\", \"zh-Hans\" -> \"zh-CN\"). */\nconst SCRIPT_LANGUAGE_MAP = new Map<string, string>();\n\nfor (const l of SUPPORTED_LOCALES) {\n\tconst base = l.code.split(\"-\")[0]!.toLowerCase();\n\t// First match wins -- if we have both \"pt\" and \"pt-BR\", exact wins via direct lookup.\n\tif (!BASE_LANGUAGE_MAP.has(base)) {\n\t\tBASE_LANGUAGE_MAP.set(base, l.code);\n\t}\n\n\tconst maximized = new Intl.Locale(l.code).maximize();\n\tif (maximized.script) {\n\t\tconst scriptKey = `${maximized.language}-${maximized.script}`.toLowerCase();\n\t\tif (!SCRIPT_LANGUAGE_MAP.has(scriptKey)) {\n\t\t\tSCRIPT_LANGUAGE_MAP.set(scriptKey, l.code);\n\t\t}\n\t}\n}\n\n/**\n * Find the best matching supported locale for a BCP 47 tag.\n * Canonicalizes via Intl.Locale so case differences (e.g. \"pt-br\" vs \"pt-BR\")\n * don't prevent matching. Supports script codes (zh-Hant -> zh-TW, zh-Hans -> zh-CN)\n * and falls back to base language (pt-PT -> pt-BR).\n */\nfunction matchLocale(tag: string): string | undefined {\n\tconst trimmed = tag.trim();\n\tif (!trimmed) return undefined;\n\tlet canonical: string;\n\ttry {\n\t\tcanonical = new Intl.Locale(trimmed).baseName;\n\t} catch {\n\t\treturn undefined;\n\t}\n\n\t// Exact match (case-insensitive via Intl.Locale)\n\tif (SUPPORTED_LOCALE_CODES.has(canonical)) return canonical;\n\n\t// Try script-based matching (zh-Hant -> zh-TW, zh-Hans -> zh-CN)\n\tconst locale = new Intl.Locale(trimmed);\n\tif (locale.script) {\n\t\tconst scriptKey = `${locale.language}-${locale.script}`.toLowerCase();\n\t\tconst scriptMatch = SCRIPT_LANGUAGE_MAP.get(scriptKey);\n\t\tif (scriptMatch) return scriptMatch;\n\t}\n\n\t// Fallback to base language (pt-PT -> pt-BR)\n\tconst base = canonical.split(\"-\")[0]!.toLowerCase();\n\treturn BASE_LANGUAGE_MAP.get(base);\n}\n\nconst LOCALE_LABELS = new Map(SUPPORTED_LOCALES.map((l) => [l.code, l.label]));\n\n/** Get a display label for a locale code, falling back to uppercase code. */\nexport function getLocaleLabel(code: string): string {\n\treturn LOCALE_LABELS.get(code) ?? code.toUpperCase();\n}\n\nconst LOCALE_DIRS = new Map(SUPPORTED_LOCALES.map((l) => [l.code, l.dir]));\n\n/** Get the text direction for a locale code. Defaults to \"ltr\" if not specified. */\nexport function getLocaleDir(code: string): \"ltr\" | \"rtl\" {\n\treturn LOCALE_DIRS.get(code) ?? \"ltr\";\n}\n\nconst LOCALE_COOKIE_RE = /(?:^|;\\s*)emdash-locale=([^;]+)/;\n\n/**\n * Resolve the admin locale from a Request.\n * Priority: emdash-locale cookie -> Accept-Language -> DEFAULT_LOCALE.\n */\nexport function resolveLocale(request: Request): string {\n\tconst cookieHeader = request.headers.get(\"cookie\") ?? \"\";\n\tconst cookieMatch = cookieHeader.match(LOCALE_COOKIE_RE);\n\tconst cookieLocale = cookieMatch?.[1]?.trim() ?? \"\";\n\n\tif (SUPPORTED_LOCALE_CODES.has(cookieLocale)) return cookieLocale;\n\n\tconst acceptLang = request.headers.get(\"accept-language\") ?? \"\";\n\tfor (const entry of acceptLang.split(\",\")) {\n\t\tconst tag = entry.split(\";\")[0]!.trim();\n\t\tconst matched = matchLocale(tag);\n\t\tif (matched) return matched;\n\t}\n\n\treturn DEFAULT_LOCALE;\n}\n","import type { Messages } from \"@lingui/core\";\n\nimport { DEFAULT_LOCALE } from \"./config.js\";\n\nconst LOCALE_LOADERS = import.meta.glob<{ messages: Messages }>(\"./**/messages.mjs\");\n\nexport async function loadMessages(locale: string): Promise<Messages> {\n\tconst key = `./${locale}/messages.mjs`;\n\tconst fallbackKey = `./${DEFAULT_LOCALE}/messages.mjs`;\n\tconst loader = LOCALE_LOADERS[key] ?? LOCALE_LOADERS[fallbackKey];\n\tif (!loader) {\n\t\tthrow new Error(\n\t\t\t`No locale catalog found for \"${locale}\" or \"${DEFAULT_LOCALE}\". Run \\`pnpm locale:compile\\` to generate catalogs.`,\n\t\t);\n\t}\n\tconst { messages } = await loader();\n\treturn messages;\n}\n","import { useLingui } from \"@lingui/react\";\nimport * as React from \"react\";\n\nimport { SUPPORTED_LOCALE_CODES } from \"./config.js\";\nimport { loadMessages } from \"./loadMessages.js\";\n\nfunction setCookie(code: string) {\n\tconst secure = window.location.protocol === \"https:\" ? \"; Secure\" : \"\";\n\tdocument.cookie = `emdash-locale=${code}; Path=/_emdash; SameSite=Lax; Max-Age=31536000${secure}`;\n}\n\n/**\n * Get the current locale and a function to switch locales.\n * Loads the new catalog dynamically and sets a cookie for server-side persistence.\n */\nexport function useLocale() {\n\tconst { i18n } = useLingui();\n\tconst [locale, setLocaleState] = React.useState(i18n.locale);\n\n\tconst setLocale = React.useCallback(\n\t\t(code: string) => {\n\t\t\tif (code === i18n.locale || !SUPPORTED_LOCALE_CODES.has(code)) return;\n\t\t\tsetCookie(code);\n\t\t\tvoid loadMessages(code)\n\t\t\t\t.then((messages) => i18n.loadAndActivate({ locale: code, messages }))\n\t\t\t\t.catch(() => {\n\t\t\t\t\tsetCookie(i18n.locale);\n\t\t\t\t});\n\t\t},\n\t\t[i18n],\n\t);\n\n\t// Subscribe to i18n change events to trigger re-renders\n\tReact.useEffect(() => {\n\t\tconst unsubscribe = i18n.on(\"change\", () => {\n\t\t\tsetLocaleState(i18n.locale);\n\t\t});\n\t\treturn unsubscribe;\n\t}, [i18n]);\n\n\treturn { locale, setLocale };\n}\n","import { DirectionProvider } from \"@cloudflare/kumo/primitives\";\nimport * as React from \"react\";\n\nimport { getLocaleDir } from \"./config.js\";\nimport { useLocale } from \"./useLocale.js\";\n\ninterface LocaleDirectionProviderProps {\n\tchildren: React.ReactNode;\n}\n\n/**\n * Wraps the app with DirectionProvider and keeps it in sync with the current locale.\n * Automatically updates direction when locale changes via useLocale.\n */\nexport function LocaleDirectionProvider({ children }: LocaleDirectionProviderProps) {\n\tconst { locale } = useLocale();\n\tconst dir = React.useMemo(() => getLocaleDir(locale), [locale]);\n\n\t/** Sync the direction and lang attributes with the current locale. */\n\tReact.useEffect(() => {\n\t\tdocument.documentElement.setAttribute(\"lang\", locale);\n\t\tdocument.documentElement.setAttribute(\"dir\", dir);\n\t}, [dir, locale]);\n\n\treturn <DirectionProvider direction={dir}>{children}</DirectionProvider>;\n}\n"],"mappings":";;;;;;;;;;AA+BA,MAAa,UAA8B;CAE1C;EAAE,MAAM;EAAM,OAAO;EAAW,SAAS;EAAM;CAC/C;EAAE,MAAM;EAAM,OAAO;EAAW,SAAS;EAAM,KAAK;EAAO;CAC3D;EAAE,MAAM;EAAM,OAAO;EAAW,SAAS;EAAM;CAC/C;EAAE,MAAM;EAAM,OAAO;EAAU,SAAS;EAAM;CAC9C;EAAE,MAAM;EAAS,OAAO;EAAQ,SAAS;EAAM;CAC/C;EAAE,MAAM;EAAS,OAAO;EAAQ,SAAS;EAAM;CAC/C;EAAE,MAAM;EAAM,OAAO;EAAW,SAAS;EAAM;CAC/C;EAAE,MAAM;EAAM,OAAO;EAAc,SAAS;EAAM;CAClD;EAAE,MAAM;EAAS,OAAO;EAAgB,SAAS;EAAM;CACvD;EAAE,MAAM;EAAM,OAAO;EAAS,SAAS;EAAM,KAAK;EAAO;CACzD;EAAE,MAAM;EAAM,OAAO;EAAY,SAAS;EAAM;CAChD;EAAE,MAAM;EAAM,OAAO;EAAW,SAAS;EAAM;CAC/C;EAAE,MAAM;EAAM,OAAO;EAAU,SAAS;EAAM;CAC9C;EAAE,MAAM;EAAM,OAAO;EAAU,SAAS;EAAM;CAC9C;EAAE,MAAM;EAAM,OAAO;EAAoB,SAAS;EAAM;CACxD;EAAE,MAAM;EAAM,OAAO;EAAO,SAAS;EAAM;CAC3C;EAAE,MAAM;EAAM,OAAO;EAAO,SAAS;EAAO;CAC5C;EAAE,MAAM;EAAM,OAAO;EAAgB,SAAS;EAAM;CACpD;EAAE,MAAM;EAAM,OAAO;EAAU,SAAS;EAAM;CAC9C;EAAE,MAAM;EAAS,OAAO;EAAsB,SAAS;EAAM;CAC7D;EAAE,MAAM;EAAW,OAAO;EAAU,SAAS;EAAM;CACnD;EAAE,MAAM;EAAU,OAAO;EAA2B,SAAS;EAAM;CACnE;EAAE,MAAM;EAAS,OAAO;EAAoB,SAAS;EAAM;CAC3D;EAAE,MAAM;EAAM,OAAO;EAAW,SAAS;EAAM;CAC/C;EAAE,MAAM;EAAM,OAAO;EAAO,SAAS;EAAM;CAC3C;EAAE,MAAM;EAAM,OAAO;EAAU,SAAS;EAAM;CAC9C;EAAE,MAAM;EAAM,OAAO;EAAc,SAAS;EAAM;CAGlD;EAAE,MAAM;EAAU,OAAO;EAAU,SAAS;EAAO;CACnD;;AAGD,MAAa,gBAAgB,QAAQ;;AAGrC,MAAa,eAAe,QAAQ,KAAK,MAAM,EAAE,KAAK;;AAGtD,MAAa,iBAAiB,QAAQ,MAAM,EAAE;;AAG9C,MAAa,kBAAkB,QAAQ,QAAQ,MAAM,EAAE,QAAQ;;;;;;;;;;AChE/D,SAAS,cAAc,MAAuB;AAC7C,KAAI;AAEH,SADe,IAAI,KAAK,OAAO,KAAK,CACtB,aAAa;SACpB;AACP,MAAI,OAAO,KAAK,IAAI,IACnB,OAAM,IAAI,MAAM,yBAAyB,KAAK,GAAG;AAElD,SAAO;;;;;;;AAYT,MAAM,gBACL,OAAO,6BAA6B,eAAe,2BAChD,QAAQ,MAAM,MAAM,EAAE,SAAS,SAAS,GACxC;;AAGJ,MAAa,oBAAoB,CAChC,GAAG,gBAAgB,QAAQ,MAAM,cAAc,EAAE,KAAK,CAAC,EACvD,GAAI,gBAAgB,CAAC,cAAc,GAAG,EAAE,CACxC;AAED,MAAa,yBAAyB,IAAI,IAAI,kBAAkB,KAAK,MAAM,EAAE,KAAK,CAAC;AAEnF,MAAa,iBAAiB,cAAc;;AAG5C,MAAM,oCAAoB,IAAI,KAAqB;;AAEnD,MAAM,sCAAsB,IAAI,KAAqB;AAErD,KAAK,MAAM,KAAK,mBAAmB;CAClC,MAAM,OAAO,EAAE,KAAK,MAAM,IAAI,CAAC,GAAI,aAAa;AAEhD,KAAI,CAAC,kBAAkB,IAAI,KAAK,CAC/B,mBAAkB,IAAI,MAAM,EAAE,KAAK;CAGpC,MAAM,YAAY,IAAI,KAAK,OAAO,EAAE,KAAK,CAAC,UAAU;AACpD,KAAI,UAAU,QAAQ;EACrB,MAAM,YAAY,GAAG,UAAU,SAAS,GAAG,UAAU,SAAS,aAAa;AAC3E,MAAI,CAAC,oBAAoB,IAAI,UAAU,CACtC,qBAAoB,IAAI,WAAW,EAAE,KAAK;;;;;;;;;AAW7C,SAAS,YAAY,KAAiC;CACrD,MAAM,UAAU,IAAI,MAAM;AAC1B,KAAI,CAAC,QAAS,QAAO;CACrB,IAAI;AACJ,KAAI;AACH,cAAY,IAAI,KAAK,OAAO,QAAQ,CAAC;SAC9B;AACP;;AAID,KAAI,uBAAuB,IAAI,UAAU,CAAE,QAAO;CAGlD,MAAM,SAAS,IAAI,KAAK,OAAO,QAAQ;AACvC,KAAI,OAAO,QAAQ;EAClB,MAAM,YAAY,GAAG,OAAO,SAAS,GAAG,OAAO,SAAS,aAAa;EACrE,MAAM,cAAc,oBAAoB,IAAI,UAAU;AACtD,MAAI,YAAa,QAAO;;CAIzB,MAAM,OAAO,UAAU,MAAM,IAAI,CAAC,GAAI,aAAa;AACnD,QAAO,kBAAkB,IAAI,KAAK;;AAGnC,MAAM,gBAAgB,IAAI,IAAI,kBAAkB,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;;AAG9E,SAAgB,eAAe,MAAsB;AACpD,QAAO,cAAc,IAAI,KAAK,IAAI,KAAK,aAAa;;AAGrD,MAAM,cAAc,IAAI,IAAI,kBAAkB,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;;AAG1E,SAAgB,aAAa,MAA6B;AACzD,QAAO,YAAY,IAAI,KAAK,IAAI;;AAGjC,MAAM,mBAAmB;;;;;AAMzB,SAAgB,cAAc,SAA0B;CAGvD,MAAM,gBAFe,QAAQ,QAAQ,IAAI,SAAS,IAAI,IACrB,MAAM,iBAAiB,GACrB,IAAI,MAAM,IAAI;AAEjD,KAAI,uBAAuB,IAAI,aAAa,CAAE,QAAO;CAErD,MAAM,aAAa,QAAQ,QAAQ,IAAI,kBAAkB,IAAI;AAC7D,MAAK,MAAM,SAAS,WAAW,MAAM,IAAI,EAAE;EAE1C,MAAM,UAAU,YADJ,MAAM,MAAM,IAAI,CAAC,GAAI,MAAM,CACP;AAChC,MAAI,QAAS,QAAO;;AAGrB,QAAO;;;;;ACnIR,MAAM,iBAA4B,uBAAU,OAAA;;CAE5C,2BAAuB,OAAY;;CAEnC,2BAAsB,OAAa;CAClC,2BAAyB,OAAS;CAClC,8BAAyB,OAAA;CACzB,+BAA8B,OAAQ;CACtC,8BAAa,OAAA;CACZ,2BAAe,OAAA;CACf,2BAA0B,OAAO;CACjC,2BAAC,OAAA;CACF,2BAAA,OAAA;CACA,2BAA2B,OAAQ;CACnC,2BAAe,OAAA;CAChB,2BAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;ACbA,SAAS,UAAA,MAAuB;;AAEhC,UAAS,SAAU,iBAAc,KAAA,iDAAA;;;;;;AAOjC,SAAgB,YAAS;CACvB,MAAA,EACF,SACM,WAAW;CAChB,MAAO,CAAA,QAAQ,kBAAkB,QAAM,SAAS,KAAK,OAAO;;AAE5D,MAAM,SAAU,KAAE,UAAM,CAAA,uBAAW,IAAA,KAAA,CAAA;AACjC,YAAM,KAAU;AAChB,EAAI,aAAc,KAAM,CAAC,MAAI,aAAA,KAAA,gBAAkC;GAC/D,QAAU;GACV;GACE,CAAA,CAAA,CAAA,YAAe;AACf,aAAW,KAAC,OAAA;IACZ;IACA,CAAC,KAAA,CAAA;AAGJ,SAAA,gBAAA;AAIA;AAFE,kBAAiB,KAAC,OAAO;IACvB;IAEH,CAAA,KAAA,CAAA;AACD,QAAE;EACF;EACE;;;;;;;;;;ACxBJ,SAAgB,wBAAwB,EAAE,YAA0C;CACnF,MAAM,EAAE,WAAW,WAAW;CAC9B,MAAM,MAAMA,QAAM,cAAc,aAAa,OAAO,EAAE,CAAC,OAAO,CAAC;;AAG/D,SAAM,gBAAgB;AACrB,WAAS,gBAAgB,aAAa,QAAQ,OAAO;AACrD,WAAS,gBAAgB,aAAa,OAAO,IAAI;IAC/C,CAAC,KAAK,OAAO,CAAC;AAEjB,QAAO,oBAAC;EAAkB,WAAW;EAAM;GAA6B"}
package/dist/index.d.ts CHANGED
@@ -197,6 +197,7 @@ interface AdminManifest {
197
197
  i18n?: {
198
198
  defaultLocale: string;
199
199
  locales: string[];
200
+ prefixDefaultLocale?: boolean;
200
201
  };
201
202
  /** Stored-content locale policy, independent from the admin UI language. */
202
203
  contentLocale?: {
@@ -409,6 +410,12 @@ interface ContentItem {
409
410
  liveRevisionId: string | null;
410
411
  draftRevisionId: string | null;
411
412
  seo?: ContentSeo;
413
+ /**
414
+ * Opaque optimistic-concurrency token returned by the content API on
415
+ * reads. Echo it back on writes so the server can reject a save that is
416
+ * based on a stale read (#2121). Undefined if the server didn't send one.
417
+ */
418
+ _rev?: string;
412
419
  }
413
420
  interface CreateContentInput {
414
421
  type: string;
@@ -452,6 +459,13 @@ interface UpdateContentInput {
452
459
  /** Skip revision creation (used by autosave) */
453
460
  skipRevision?: boolean;
454
461
  seo?: ContentSeoInput;
462
+ /**
463
+ * Optimistic-concurrency token from the last read. When present, the
464
+ * server rejects the write with 409 if the entry changed since that read,
465
+ * preventing a stale editor from silently overwriting a newer draft
466
+ * (#2121). Omit for a blind write (backwards-compatible).
467
+ */
468
+ _rev?: string;
455
469
  }
456
470
  /**
457
471
  * Trashed content item with deletion timestamp
@@ -536,6 +550,7 @@ declare function deleteContent(collection: string, id: string, options?: {
536
550
  declare function fetchTrashedContent(collection: string, options?: {
537
551
  cursor?: string;
538
552
  limit?: number;
553
+ locale?: string;
539
554
  }): Promise<FindManyResult<TrashedContentItem>>;
540
555
  /**
541
556
  * Restore content from trash
@@ -578,6 +593,7 @@ declare function getPreviewUrl(collection: string, id: string, options?: {
578
593
  */
579
594
  declare function publishContent(collection: string, id: string, options?: {
580
595
  locale?: string;
596
+ _rev?: string;
581
597
  }): Promise<ContentItem>;
582
598
  /**
583
599
  * Unpublish content - removes from public, preserves draft
@@ -633,6 +649,9 @@ interface MediaUploadOptions {
633
649
  }
634
650
  interface UploadMediaOptions extends MediaUploadOptions {
635
651
  fieldId?: string;
652
+ deduplicate?: boolean;
653
+ ensureUniqueFilename?: boolean;
654
+ folderId?: string | null;
636
655
  }
637
656
  type MediaUsageCoverageStatus = "complete" | "never" | "running" | "partial" | "failed" | "stale" | "unknown";
638
657
  interface MediaUsageCoverage {
@@ -675,6 +694,7 @@ interface MediaItem {
675
694
  url: string;
676
695
  /** Storage key for local media (e.g., "01ABC.jpg"). Not present for external URLs. */
677
696
  storageKey?: string;
697
+ contentHash?: string | null;
678
698
  size: number;
679
699
  width?: number;
680
700
  height?: number;
@@ -687,6 +707,7 @@ interface MediaItem {
687
707
  alt?: string;
688
708
  caption?: string;
689
709
  createdAt: string;
710
+ status?: "pending" | "ready" | "failed";
690
711
  /** Provider ID for external media (e.g., "cloudflare-images") */
691
712
  provider?: string;
692
713
  /** Provider-specific metadata */
@@ -744,7 +765,11 @@ declare function deleteMediaFolder(id: string): Promise<void>;
744
765
  * Tries signed URL upload first (for S3/R2 storage), falls back to direct upload
745
766
  * (for local storage) if signed URLs are not supported.
746
767
  */
747
- declare function uploadMedia(file: File, opts?: UploadMediaOptions): Promise<MediaItem>;
768
+ declare function uploadMedia(file: File, opts?: UploadMediaOptions): Promise<LocalMediaItem>;
769
+ declare function replaceMediaImage(id: string, file: File, dimensions: {
770
+ width: number;
771
+ height: number;
772
+ }, options?: MediaUploadOptions): Promise<LocalMediaItem>;
748
773
  /**
749
774
  * Delete media
750
775
  */
@@ -2983,6 +3008,7 @@ interface ContentListProps {
2983
3008
  i18n?: {
2984
3009
  defaultLocale: string;
2985
3010
  locales: string[];
3011
+ prefixDefaultLocale?: boolean;
2986
3012
  };
2987
3013
  /** Currently active locale filter */
2988
3014
  activeLocale?: string;
@@ -3146,6 +3172,7 @@ interface PortableTextImageBlock {
3146
3172
  asset: {
3147
3173
  _ref: string;
3148
3174
  url?: string;
3175
+ provider?: string;
3149
3176
  meta?: Record<string, unknown>;
3150
3177
  };
3151
3178
  alt?: string;
@@ -3287,20 +3314,44 @@ interface ContentEditorProps {
3287
3314
  isAutosaveFeedbackActive?: boolean;
3288
3315
  /** Entry-scoped token advanced after a successful autosave. */
3289
3316
  autosaveCompletionToken?: number;
3290
- /** Entry-scoped token advanced after the server rejected an autosave payload. */
3317
+ /**
3318
+ * Entry-scoped token advanced after the server rejected an autosave payload in
3319
+ * a way that resending cannot fix. A conflict does not count: it recovers
3320
+ * through `hasSaveConflict`.
3321
+ */
3291
3322
  autosaveRejectionToken?: number;
3292
- onPublish?: () => void;
3323
+ /** Whether the server refused the last save because it was based on a stale read. */
3324
+ hasSaveConflict?: boolean;
3325
+ onPublish?: (payload: {
3326
+ data: Record<string, unknown>;
3327
+ slug?: string;
3328
+ bylines?: BylineCreditInput[];
3329
+ }) => void | Promise<void>;
3293
3330
  onUnpublish?: () => void;
3294
3331
  /** Callback to discard draft changes (revert to published version) */
3295
3332
  onDiscardDraft?: () => void;
3296
3333
  /** Callback to schedule for future publishing */
3297
- onSchedule?: (scheduledAt: string) => void;
3334
+ onSchedule?: (scheduledAt: string, payload?: {
3335
+ data: Record<string, unknown>;
3336
+ slug?: string;
3337
+ bylines?: BylineCreditInput[];
3338
+ }) => void | Promise<void>;
3298
3339
  /** Callback to cancel scheduling (revert to draft) */
3299
- onUnschedule?: () => void;
3340
+ onUnschedule?: (payload?: {
3341
+ data: Record<string, unknown>;
3342
+ slug?: string;
3343
+ bylines?: BylineCreditInput[];
3344
+ }) => void | Promise<void>;
3300
3345
  /** Whether scheduling is in progress */
3301
3346
  isScheduling?: boolean;
3347
+ /** Whether schedule removal is in progress */
3348
+ isUnscheduling?: boolean;
3302
3349
  /** Callback to change the timestamp of published content */
3303
- onPublishedAtChange?: (publishedAt: string) => void;
3350
+ onPublishedAtChange?: (publishedAt: string, payload?: {
3351
+ data: Record<string, unknown>;
3352
+ slug?: string;
3353
+ bylines?: BylineCreditInput[];
3354
+ }) => void | Promise<void>;
3304
3355
  /** Whether the publish timestamp is being updated */
3305
3356
  isUpdatingPublishedAt?: boolean;
3306
3357
  /** Whether this collection supports drafts */
@@ -3341,6 +3392,7 @@ interface ContentEditorProps {
3341
3392
  i18n?: {
3342
3393
  defaultLocale: string;
3343
3394
  locales: string[];
3395
+ prefixDefaultLocale?: boolean;
3344
3396
  };
3345
3397
  /** Existing translations for this content item */
3346
3398
  translations?: TranslationSummary[];
@@ -3373,12 +3425,14 @@ declare function ContentEditor({
3373
3425
  isAutosaveFeedbackActive,
3374
3426
  autosaveCompletionToken,
3375
3427
  autosaveRejectionToken,
3428
+ hasSaveConflict,
3376
3429
  onPublish,
3377
3430
  onUnpublish,
3378
3431
  onDiscardDraft,
3379
3432
  onSchedule,
3380
3433
  onUnschedule,
3381
3434
  isScheduling,
3435
+ isUnscheduling,
3382
3436
  onPublishedAtChange,
3383
3437
  isUpdatingPublishedAt,
3384
3438
  supportsDrafts,
@@ -3488,40 +3542,15 @@ interface MediaPickerModalProps {
3488
3542
  open: boolean;
3489
3543
  onOpenChange: (open: boolean) => void;
3490
3544
  onSelect: (item: MediaItem) => void;
3491
- /** Allow selecting several items at once; confirms through `onSelectMany`. */
3492
3545
  multiple?: boolean;
3493
- /** Called instead of `onSelect` when `multiple` is set. */
3494
3546
  onSelectMany?: (items: MediaItem[]) => void;
3495
- /** Filter by mime type prefix, e.g. "image/" */
3496
3547
  mimeTypeFilter?: string;
3497
3548
  title?: string;
3498
- /**
3499
- * Hide the "Insert from URL" input. Defaults to false.
3500
- * The URL input probes image dimensions and is only meaningful for image pickers,
3501
- * so non-image pickers (e.g. generic file pickers) should hide it.
3502
- */
3549
+ confirmLabel?: string;
3503
3550
  hideUrlInput?: boolean;
3504
- /**
3505
- * What kind of media this picker is for. Drives user-facing copy
3506
- * (default title, empty-state message, upload button label, empty-state icon).
3507
- * Defaults to "image" — set to "file" for generic file pickers.
3508
- */
3509
3551
  mediaKind?: "image" | "file";
3510
- /** MIME allowlist — array of exact MIMEs or `type/` prefixes. */
3511
3552
  mimeTypeFilters?: string[];
3512
- /** `_emdash_fields` row id for server-side MIME widening. */
3513
3553
  fieldId?: string;
3514
- /**
3515
- * Restrict the picker to the local Library only — hides the "Insert from URL"
3516
- * input and suppresses external provider tabs.
3517
- *
3518
- * Use this for fields whose storage model only persists a local `mediaId`.
3519
- * Selecting an external URL or provider item would return an item the
3520
- * server cannot later resolve back to a URL (the `id` is either empty
3521
- * for "Insert from URL" or a provider-namespaced string that won't match
3522
- * a row in the `media` table). Site settings (logo, favicon,
3523
- * `seo.defaultOgImage`) are the canonical callers.
3524
- */
3525
3554
  localOnly?: boolean;
3526
3555
  }
3527
3556
  declare function MediaPickerModal({
@@ -3534,6 +3563,7 @@ declare function MediaPickerModal({
3534
3563
  mimeTypeFilters,
3535
3564
  fieldId,
3536
3565
  title: providedTitle,
3566
+ confirmLabel,
3537
3567
  hideUrlInput,
3538
3568
  mediaKind,
3539
3569
  localOnly
@@ -3718,5 +3748,5 @@ declare function SetupWizard(): react_jsx_runtime0.JSX.Element | null;
3718
3748
  */
3719
3749
  declare function cn(...inputs: ClassValue[]): string;
3720
3750
  //#endregion
3721
- export { API_BASE, API_TOKEN_SCOPES, AdminApp, AdminApp as App, type AdminBranding, type AdminComment, type AdminManifest, type AllowedDomain, ApiResponseError, type ApiTokenCreateResult, type ApiTokenInfo, type ApiTokenScopeValue, type AttachmentInfo, type AuthProviderModule, AuthProviderProvider, type AuthProviders, type AuthorMapping, type BulkAction, type BylineCreditInput, type BylineCustomFieldValue, type BylineFieldDefinition, type BylineFieldType, type BylineFieldUsage, type BylineFieldValidation, type BylineInput, type BylineSummary, type BylineTranslationInput, CAPABILITY_LABELS, type CollectionSchemaStatus, type CollectionStats, type CommentCounts, type CommentStatus, type ContentAuthor, type ContentDateField, ContentEditor, type ContentEditorPanelContext, type ContentEditorPanelExtension, type ContentEditorProps, type ContentItem, ContentList, type ContentListColumn, type ContentListColumnCellContext, type ContentListColumnExtension, type ContentListColumnHeaderContext, type ContentListProps, type ContentSeo, type ContentSeoInput, type CreateAllowedDomainInput, type CreateApiTokenInput, type CreateBylineFieldInput, type CreateCollectionInput, type CreateContentInput, type CreateFieldInput, type CreateMenuInput, type CreateMenuItemInput, type CreateRedirectInput, type CreateSectionInput, type CreateTaxonomyInput, type CreateTermInput, type CreateWidgetAreaInput, type CreateWidgetInput, type CurrentUser, type CustomTaxonomy, DEFAULT_LOCALE, Dashboard, type DashboardProps, type DashboardStats, EditorHeader, type EditorHeaderProps, type EmailProvider, type EmailSettings, type FieldCompatibility, type FieldDescriptor, type FieldType, type FindManyResult, type GetSectionsOptions, Header, type ImportConfig, type ImportFieldDef, type ImportResult, type InstallPluginOpts, type InviteVerifyResult, Link, type LocalMediaItem, LoginPage, MEDIA_SEARCH_MAX_LENGTH, type MarketplaceAuditSummary, type MarketplaceAuthor, type MarketplaceImageAuditSummary, type MarketplacePluginDetail, type MarketplacePluginSummary, type MarketplaceSearchOpts, type MarketplaceSearchResult, type MarketplaceVersion, type MediaFolder, type MediaFolderListResult, type MediaImportProgress, type MediaImportResult, type MediaItem, MediaLibrary, type MediaLibraryProps, MediaPickerModal, type MediaPickerModalProps, type MediaProviderCapabilities, type MediaProviderInfo, type MediaProviderItem, type MediaUpdateInput, type MediaUploadOptions, MediaUsageAccessDeniedError, type MediaUsageCoverage, type MediaUsageCoverageStatus, type MediaUsageDetailsResponse, type MediaUsageEntryDetail, type MediaUsageOccurrenceDetail, type MediaUsageSourceDetail, type Menu, type MenuItem, type LocaleOptions as MenuLocaleOptions, type MenuTranslation, type MenuTranslationsResponse, type MenuWithItems, type NavMenu, type NotFoundSummary, type OrphanedTable, type PasskeyInfo, PasskeyLogin, type PasskeyLoginProps, PasskeyRegistration, type PasskeyRegistrationProps, type PluginAdminModule, PluginAdminProvider, type PluginAdmins, type PluginInfo, type PluginUpdateInfo, PortableTextEditor, type PortableTextEditorProps, type PostTypeAnalysis, type PrepareRequest, type PrepareResult, type PreviewUrlResponse, type ProbeResult, type RecentItem, type Redirect, type RedirectListOptions, type RedirectListResult, type ReorderMenuItemsInput, type Revision, type RevisionListResponse, type RewriteUrlsResult, SUPPORTED_LOCALES, SUPPORTED_LOCALE_CODES, SaveButton, type SaveButtonProps, type SchemaCollection, type SchemaCollectionWithFields, type SchemaField, type SearchEnableResult, type Section, type SectionSource, type SectionsResult, type SettingField, Settings, SetupWizard, Shell, type ShellProps, KumoSidebar as Sidebar, SidebarNav, type SidebarNavProps, type SignupVerifyResult, type SiteSettings, type SourceAuth, type SourceCapabilities, type SourceProbeResult, type SuggestedAction, type LocaleDefinition as SupportedLocale, type TaxonomyDef, type TaxonomyTerm, type TermTranslation, type TermTranslationsResponse, type ThemeAuthor, type ThemeAuthorDetail, type ThemeDetail, type ThemeSearchOpts, type ThemeSearchResult, type ThemeSummary, type TranslationSummary, type TranslationsResponse, type TrashedContentItem, type UninstallPluginOpts, type UpdateAllowedDomainInput, type UpdateBylineFieldInput, type UpdateCollectionInput, type UpdateContentInput, type UpdateFieldInput, type UpdateMenuInput, type UpdateMenuItemInput, type UpdatePluginOpts, type UpdateRedirectInput, type UpdateSectionInput, type UpdateTermInput, type UpdateUserInput, type UpdateWidgetInput, type UploadMediaOptions, type UserDetail, type UserListItem, type Widget, type WidgetArea, type WidgetComponent, type WpAuthorInfo, type WpImportProgress, type WpPluginAnalysis, type WxrAnalysis, analyzeWpPluginSite, analyzeWxr, apiFetch, bulkCommentAction, checkPluginUpdates, cn, compareRevisions, completeSignup, createAdminRouter, createAllowedDomain, createApiToken, createByline, createBylineField, createBylineTranslation, createCollection, createContent, createField, createMediaFolder, createMenu, createMenuItem, createMenuTranslation, createRedirect, createSection, createTaxonomy, createTerm, createTermTranslation, createWidget, createWidgetArea, deleteAllowedDomain, deleteByline, deleteBylineField, deleteCollection, deleteComment, deleteContent, deleteField, deleteFromProvider, deleteMedia, deleteMediaFolder, deleteMenu, deleteMenuItem, deletePasskey, deleteRedirect, deleteSection, deleteTerm, deleteWidget, deleteWidgetArea, describeCapability, disablePlugin, disableUser, discardDraft, duplicateContent, enablePlugin, enableUser, executeWpPluginImport, executeWxrImport, fetch404Summary, fetchAllowedDomains, fetchApiTokens, fetchAuthMode, fetchByline, fetchBylineTranslations, fetchBylines, fetchCollection, fetchCollections, fetchComment, fetchCommentCounts, fetchComments, fetchContent, fetchContentAuthors, fetchContentList, fetchDashboardStats, fetchEmailSettings, fetchFields, fetchManifest, fetchMarketplacePlugin, fetchMediaFolder, fetchMediaFolders, fetchMediaItem, fetchMediaList, fetchMediaProviders, fetchMediaUsageDetails, fetchMenu, fetchMenuTranslations, fetchMenus, fetchOrphanedTables, fetchPasskeys, fetchPlugin, fetchPluginSettings, fetchPlugins, fetchProviderMedia, fetchRedirects, fetchRevision, fetchRevisions, fetchSection, fetchSections, fetchSettings, fetchTaxonomyDef, fetchTaxonomyDefs, fetchTermTranslations, fetchTerms, fetchTheme, fetchTranslations, fetchTrashedContent, fetchUser, fetchUsers, fetchWidgetArea, fetchWidgetAreas, fetchWidgetComponents, generatePreviewUrl, getBylineFieldUsage, getDraftStatus, getPreviewUrl, hasAllowedDomains, importWxrMedia, importWxrMediaBatched, installMarketplacePlugin, inviteUser, isTerminalRequestError, listBylineFields, parseApiResponse, permanentDeleteContent, prepareWxrImport, probeImportUrl, publishContent, registerOrphanedTable, renameMediaFolder, renamePasskey, reorderBylineFields, reorderCollections, reorderFields, reorderMenuItems, reorderWidgets, requestSignup, resolveLocale, restoreContent, restoreRevision, revokeApiToken, rewriteContentUrls, scheduleContent, searchMarketplace, searchThemes, sendRecoveryLink, sendTestEmail, setPluginMcpEnabled, setSearchEnabled, throwResponseError, uninstallMarketplacePlugin, unpublishContent, unscheduleContent, updateAllowedDomain, updateByline, updateBylineField, updateCollection, updateCommentStatus, updateContent, updateField, updateMarketplacePlugin, updateMedia, updateMenu, updateMenuItem, updatePluginSettings, updateRedirect, updateSection, updateSettings, updateTerm, updateUser, updateWidget, uploadMedia, uploadToProvider, useAuthProviderList, useAuthProviders, useCurrentUser, useLocale, useNavigate, useParams, usePluginAdmins, usePluginField, usePluginHasPages, usePluginHasWidgets, usePluginPage, usePluginWidget, validateInviteToken, verifySignupToken };
3751
+ export { API_BASE, API_TOKEN_SCOPES, AdminApp, AdminApp as App, type AdminBranding, type AdminComment, type AdminManifest, type AllowedDomain, ApiResponseError, type ApiTokenCreateResult, type ApiTokenInfo, type ApiTokenScopeValue, type AttachmentInfo, type AuthProviderModule, AuthProviderProvider, type AuthProviders, type AuthorMapping, type BulkAction, type BylineCreditInput, type BylineCustomFieldValue, type BylineFieldDefinition, type BylineFieldType, type BylineFieldUsage, type BylineFieldValidation, type BylineInput, type BylineSummary, type BylineTranslationInput, CAPABILITY_LABELS, type CollectionSchemaStatus, type CollectionStats, type CommentCounts, type CommentStatus, type ContentAuthor, type ContentDateField, ContentEditor, type ContentEditorPanelContext, type ContentEditorPanelExtension, type ContentEditorProps, type ContentItem, ContentList, type ContentListColumn, type ContentListColumnCellContext, type ContentListColumnExtension, type ContentListColumnHeaderContext, type ContentListProps, type ContentSeo, type ContentSeoInput, type CreateAllowedDomainInput, type CreateApiTokenInput, type CreateBylineFieldInput, type CreateCollectionInput, type CreateContentInput, type CreateFieldInput, type CreateMenuInput, type CreateMenuItemInput, type CreateRedirectInput, type CreateSectionInput, type CreateTaxonomyInput, type CreateTermInput, type CreateWidgetAreaInput, type CreateWidgetInput, type CurrentUser, type CustomTaxonomy, DEFAULT_LOCALE, Dashboard, type DashboardProps, type DashboardStats, EditorHeader, type EditorHeaderProps, type EmailProvider, type EmailSettings, type FieldCompatibility, type FieldDescriptor, type FieldType, type FindManyResult, type GetSectionsOptions, Header, type ImportConfig, type ImportFieldDef, type ImportResult, type InstallPluginOpts, type InviteVerifyResult, Link, type LocalMediaItem, LoginPage, MEDIA_SEARCH_MAX_LENGTH, type MarketplaceAuditSummary, type MarketplaceAuthor, type MarketplaceImageAuditSummary, type MarketplacePluginDetail, type MarketplacePluginSummary, type MarketplaceSearchOpts, type MarketplaceSearchResult, type MarketplaceVersion, type MediaFolder, type MediaFolderListResult, type MediaImportProgress, type MediaImportResult, type MediaItem, MediaLibrary, type MediaLibraryProps, MediaPickerModal, type MediaPickerModalProps, type MediaProviderCapabilities, type MediaProviderInfo, type MediaProviderItem, type MediaUpdateInput, type MediaUploadOptions, MediaUsageAccessDeniedError, type MediaUsageCoverage, type MediaUsageCoverageStatus, type MediaUsageDetailsResponse, type MediaUsageEntryDetail, type MediaUsageOccurrenceDetail, type MediaUsageSourceDetail, type Menu, type MenuItem, type LocaleOptions as MenuLocaleOptions, type MenuTranslation, type MenuTranslationsResponse, type MenuWithItems, type NavMenu, type NotFoundSummary, type OrphanedTable, type PasskeyInfo, PasskeyLogin, type PasskeyLoginProps, PasskeyRegistration, type PasskeyRegistrationProps, type PluginAdminModule, PluginAdminProvider, type PluginAdmins, type PluginInfo, type PluginUpdateInfo, PortableTextEditor, type PortableTextEditorProps, type PostTypeAnalysis, type PrepareRequest, type PrepareResult, type PreviewUrlResponse, type ProbeResult, type RecentItem, type Redirect, type RedirectListOptions, type RedirectListResult, type ReorderMenuItemsInput, type Revision, type RevisionListResponse, type RewriteUrlsResult, SUPPORTED_LOCALES, SUPPORTED_LOCALE_CODES, SaveButton, type SaveButtonProps, type SchemaCollection, type SchemaCollectionWithFields, type SchemaField, type SearchEnableResult, type Section, type SectionSource, type SectionsResult, type SettingField, Settings, SetupWizard, Shell, type ShellProps, KumoSidebar as Sidebar, SidebarNav, type SidebarNavProps, type SignupVerifyResult, type SiteSettings, type SourceAuth, type SourceCapabilities, type SourceProbeResult, type SuggestedAction, type LocaleDefinition as SupportedLocale, type TaxonomyDef, type TaxonomyTerm, type TermTranslation, type TermTranslationsResponse, type ThemeAuthor, type ThemeAuthorDetail, type ThemeDetail, type ThemeSearchOpts, type ThemeSearchResult, type ThemeSummary, type TranslationSummary, type TranslationsResponse, type TrashedContentItem, type UninstallPluginOpts, type UpdateAllowedDomainInput, type UpdateBylineFieldInput, type UpdateCollectionInput, type UpdateContentInput, type UpdateFieldInput, type UpdateMenuInput, type UpdateMenuItemInput, type UpdatePluginOpts, type UpdateRedirectInput, type UpdateSectionInput, type UpdateTermInput, type UpdateUserInput, type UpdateWidgetInput, type UploadMediaOptions, type UserDetail, type UserListItem, type Widget, type WidgetArea, type WidgetComponent, type WpAuthorInfo, type WpImportProgress, type WpPluginAnalysis, type WxrAnalysis, analyzeWpPluginSite, analyzeWxr, apiFetch, bulkCommentAction, checkPluginUpdates, cn, compareRevisions, completeSignup, createAdminRouter, createAllowedDomain, createApiToken, createByline, createBylineField, createBylineTranslation, createCollection, createContent, createField, createMediaFolder, createMenu, createMenuItem, createMenuTranslation, createRedirect, createSection, createTaxonomy, createTerm, createTermTranslation, createWidget, createWidgetArea, deleteAllowedDomain, deleteByline, deleteBylineField, deleteCollection, deleteComment, deleteContent, deleteField, deleteFromProvider, deleteMedia, deleteMediaFolder, deleteMenu, deleteMenuItem, deletePasskey, deleteRedirect, deleteSection, deleteTerm, deleteWidget, deleteWidgetArea, describeCapability, disablePlugin, disableUser, discardDraft, duplicateContent, enablePlugin, enableUser, executeWpPluginImport, executeWxrImport, fetch404Summary, fetchAllowedDomains, fetchApiTokens, fetchAuthMode, fetchByline, fetchBylineTranslations, fetchBylines, fetchCollection, fetchCollections, fetchComment, fetchCommentCounts, fetchComments, fetchContent, fetchContentAuthors, fetchContentList, fetchDashboardStats, fetchEmailSettings, fetchFields, fetchManifest, fetchMarketplacePlugin, fetchMediaFolder, fetchMediaFolders, fetchMediaItem, fetchMediaList, fetchMediaProviders, fetchMediaUsageDetails, fetchMenu, fetchMenuTranslations, fetchMenus, fetchOrphanedTables, fetchPasskeys, fetchPlugin, fetchPluginSettings, fetchPlugins, fetchProviderMedia, fetchRedirects, fetchRevision, fetchRevisions, fetchSection, fetchSections, fetchSettings, fetchTaxonomyDef, fetchTaxonomyDefs, fetchTermTranslations, fetchTerms, fetchTheme, fetchTranslations, fetchTrashedContent, fetchUser, fetchUsers, fetchWidgetArea, fetchWidgetAreas, fetchWidgetComponents, generatePreviewUrl, getBylineFieldUsage, getDraftStatus, getPreviewUrl, hasAllowedDomains, importWxrMedia, importWxrMediaBatched, installMarketplacePlugin, inviteUser, isTerminalRequestError, listBylineFields, parseApiResponse, permanentDeleteContent, prepareWxrImport, probeImportUrl, publishContent, registerOrphanedTable, renameMediaFolder, renamePasskey, reorderBylineFields, reorderCollections, reorderFields, reorderMenuItems, reorderWidgets, replaceMediaImage, requestSignup, resolveLocale, restoreContent, restoreRevision, revokeApiToken, rewriteContentUrls, scheduleContent, searchMarketplace, searchThemes, sendRecoveryLink, sendTestEmail, setPluginMcpEnabled, setSearchEnabled, throwResponseError, uninstallMarketplacePlugin, unpublishContent, unscheduleContent, updateAllowedDomain, updateByline, updateBylineField, updateCollection, updateCommentStatus, updateContent, updateField, updateMarketplacePlugin, updateMedia, updateMenu, updateMenuItem, updatePluginSettings, updateRedirect, updateSection, updateSettings, updateTerm, updateUser, updateWidget, uploadMedia, uploadToProvider, useAuthProviderList, useAuthProviders, useCurrentUser, useLocale, useNavigate, useParams, usePluginAdmins, usePluginField, usePluginHasPages, usePluginHasWidgets, usePluginPage, usePluginWidget, validateInviteToken, verifySignupToken };
3722
3752
  //# sourceMappingURL=index.d.ts.map