@openrails/contentkit-ui 0.86.0 → 0.87.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 (127) hide show
  1. package/README.md +39 -14
  2. package/dist/client/beacons.js +5 -1
  3. package/dist/client/beacons.js.map +1 -1
  4. package/dist/client/content/types.d.ts +4 -2
  5. package/dist/client/content/types.js.map +1 -1
  6. package/dist/client/contents.d.ts +8 -6
  7. package/dist/client/contents.js +10 -7
  8. package/dist/client/contents.js.map +1 -1
  9. package/dist/client/discovery.js +3 -0
  10. package/dist/client/discovery.js.map +1 -1
  11. package/dist/client/errors.d.ts +21 -3
  12. package/dist/client/errors.js +44 -14
  13. package/dist/client/errors.js.map +1 -1
  14. package/dist/client/gallery.d.ts +3 -5
  15. package/dist/client/gallery.js +16 -20
  16. package/dist/client/gallery.js.map +1 -1
  17. package/dist/client/generated/error-codes.d.ts +1 -1
  18. package/dist/client/generated/error-codes.js +8 -0
  19. package/dist/client/generated/error-codes.js.map +1 -1
  20. package/dist/client/generated/routes.d.ts +16 -3
  21. package/dist/client/generated/routes.js +28 -3
  22. package/dist/client/generated/routes.js.map +1 -1
  23. package/dist/client/generated/wire.d.ts +43 -14
  24. package/dist/client/generated/wire.js.map +1 -1
  25. package/dist/client/http.js +27 -27
  26. package/dist/client/http.js.map +1 -1
  27. package/dist/client/index.d.ts +2 -2
  28. package/dist/client/media/client.d.ts +10 -4
  29. package/dist/client/media/client.js +33 -7
  30. package/dist/client/media/client.js.map +1 -1
  31. package/dist/client/media/rules.d.ts +1 -1
  32. package/dist/client/media/rules.js +6 -6
  33. package/dist/client/media/rules.js.map +1 -1
  34. package/dist/client/media/transport.d.ts +1 -1
  35. package/dist/client/media/transport.js +16 -16
  36. package/dist/client/media/transport.js.map +1 -1
  37. package/dist/client/media/windows.js +1 -1
  38. package/dist/client/media/windows.js.map +1 -1
  39. package/dist/client/public.d.ts +2 -2
  40. package/dist/client/public.js +2 -2
  41. package/dist/client/public.js.map +1 -1
  42. package/dist/client/versions.d.ts +6 -4
  43. package/dist/client/versions.js +24 -26
  44. package/dist/client/versions.js.map +1 -1
  45. package/dist/client.js +25 -25
  46. package/dist/components/admin/content-manager.js +233 -232
  47. package/dist/components/admin/content-manager.js.map +1 -1
  48. package/dist/components/content/card.d.ts +5 -3
  49. package/dist/components/content/card.js +131 -109
  50. package/dist/components/content/card.js.map +1 -1
  51. package/dist/components/content/download-button.d.ts +26 -0
  52. package/dist/components/content/download-button.js +51 -0
  53. package/dist/components/content/download-button.js.map +1 -0
  54. package/dist/components/content/editors.d.ts +8 -0
  55. package/dist/components/content/editors.js +299 -229
  56. package/dist/components/content/editors.js.map +1 -1
  57. package/dist/components/content/grid.d.ts +8 -1
  58. package/dist/components/content/grid.js +125 -76
  59. package/dist/components/content/grid.js.map +1 -1
  60. package/dist/components/content/index.d.ts +3 -2
  61. package/dist/components/content/listing.d.ts +3 -1
  62. package/dist/components/content/listing.js.map +1 -1
  63. package/dist/components/content/paywall.js +61 -61
  64. package/dist/components/content/paywall.js.map +1 -1
  65. package/dist/components/media-gallery.d.ts +1 -4
  66. package/dist/components/media-gallery.js +19 -34
  67. package/dist/components/media-gallery.js.map +1 -1
  68. package/dist/components/social/comments.js +1 -1
  69. package/dist/components/social/comments.js.map +1 -1
  70. package/dist/components/social/engagement.d.ts +2 -1
  71. package/dist/components/social/engagement.js +5 -3
  72. package/dist/components/social/engagement.js.map +1 -1
  73. package/dist/i18n/messages.js +49 -46
  74. package/dist/i18n/messages.js.map +1 -1
  75. package/dist/index.js +12 -11
  76. package/dist/locales/de.js +15 -3
  77. package/dist/locales/de.js.map +1 -1
  78. package/dist/locales/discovery/de.js +3 -0
  79. package/dist/locales/discovery/de.js.map +1 -1
  80. package/dist/locales/discovery/en.d.ts +3 -0
  81. package/dist/locales/discovery/en.js +3 -0
  82. package/dist/locales/discovery/en.js.map +1 -1
  83. package/dist/locales/discovery/es.js +3 -0
  84. package/dist/locales/discovery/es.js.map +1 -1
  85. package/dist/locales/discovery/ja.js +3 -0
  86. package/dist/locales/discovery/ja.js.map +1 -1
  87. package/dist/locales/discovery/ko.js +3 -0
  88. package/dist/locales/discovery/ko.js.map +1 -1
  89. package/dist/locales/discovery/zh.js +3 -0
  90. package/dist/locales/discovery/zh.js.map +1 -1
  91. package/dist/locales/en.d.ts +17 -2
  92. package/dist/locales/en.js +15 -3
  93. package/dist/locales/en.js.map +1 -1
  94. package/dist/locales/es.js +15 -3
  95. package/dist/locales/es.js.map +1 -1
  96. package/dist/locales/ja.js +15 -3
  97. package/dist/locales/ja.js.map +1 -1
  98. package/dist/locales/ko.js +15 -3
  99. package/dist/locales/ko.js.map +1 -1
  100. package/dist/locales/zh.js +15 -3
  101. package/dist/locales/zh.js.map +1 -1
  102. package/dist/react/comments.d.ts +1 -1
  103. package/dist/react/comments.js +3 -2
  104. package/dist/react/comments.js.map +1 -1
  105. package/dist/react/contents.d.ts +13 -5
  106. package/dist/react/contents.js +163 -149
  107. package/dist/react/contents.js.map +1 -1
  108. package/dist/react/context.d.ts +1 -1
  109. package/dist/react/context.js.map +1 -1
  110. package/dist/react/detail.d.ts +7 -1
  111. package/dist/react/detail.js +9 -6
  112. package/dist/react/detail.js.map +1 -1
  113. package/dist/react/discovery.d.ts +11 -0
  114. package/dist/react/discovery.js +49 -30
  115. package/dist/react/discovery.js.map +1 -1
  116. package/dist/react/engagement.d.ts +6 -2
  117. package/dist/react/engagement.js +2 -6
  118. package/dist/react/engagement.js.map +1 -1
  119. package/dist/react/index.d.ts +3 -3
  120. package/dist/react/public.js +17 -16
  121. package/dist/react/public.js.map +1 -1
  122. package/dist/react/versions.d.ts +25 -5
  123. package/dist/react/versions.js +58 -37
  124. package/dist/react/versions.js.map +1 -1
  125. package/dist/react.js +9 -9
  126. package/dist/styles.css +1 -1
  127. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"engagement.js","names":[],"sources":["../../../src/components/social/engagement.tsx"],"sourcesContent":["import { FavouriteIcon, ThumbsDownIcon, ThumbsUpIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useContext, useState } from \"react\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { ContentKitError } from \"../../client/errors.js\";\nimport { toContentKitError } from \"../../client/errors.js\";\nimport type { Target } from \"../../client/content/types.js\";\nimport type { ReactionCounts } from \"../../client/generated/wire.js\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext, useErrorReporter, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useContentConfig } from \"../../react/config.js\";\nimport { useFavorite, useReaction } from \"../../react/engagement.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { contentError } from \"./parts.js\";\n\n\nconst compact = (n: number, language?: string) => new Intl.NumberFormat(language, { notation: \"compact\", maximumFractionDigits: 1 }).format(n);\n\nexport interface ReactionButtonsProps {\n item: Target;\n /** Counts the host already has, used instead of reading them. */\n counts?: ReactionCounts;\n /** Offer dislike too. Default true. */\n dislike?: boolean;\n /** Asks a signed-out visitor to sign in where the server takes no anonymous reactions (default the provider's). */\n onSignIn?: () => void;\n size?: \"sm\" | \"default\";\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/**\n * Like and dislike toggles with counts: they change at once and roll back if\n * the server refuses. Signed out, they react anonymously where the server\n * allows it (`Config.anonymous.reactions`) and ask to sign in elsewhere.\n */\nexport function ReactionButtons({ item, counts: initial, dislike = true, onSignIn, size = \"default\", client, onError, className, appearance }: ReactionButtonsProps) {\n const m = useMessages();\n const { t } = m;\n const r = useReaction(item, { initial, client });\n const ctx = useContext(ContentKitContext);\n const { config } = useContentConfig({ client });\n const signIn = onSignIn ?? ctx?.onSignIn;\n // Signed out where the server takes no anonymous reactions.\n const mustSignIn = ctx?.viewer === null && config?.anonymous.reactions === false;\n const report = useErrorReporter(onError);\n const [error, setError] = useState<ContentKitError | null>(null);\n const toggle = (v: 1 | -1) => {\n if (mustSignIn) return signIn?.();\n setError(null);\n r.toggle(v).catch((e) => {\n const err = toContentKitError(e);\n if (err.code === \"unauthorized\" && signIn) return signIn();\n setError(err);\n report(err, \"reaction.save\");\n });\n };\n const btn = size === \"sm\" ? \"sm\" : \"default\";\n const hint = mustSignIn ? t(\"reactions.signIn\") : undefined;\n const disabled = mustSignIn && !signIn;\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"inline-flex flex-wrap items-center gap-1 text-sm\", className)} data-ckui=\"reaction-buttons\">\n <div className=\"inline-flex items-center gap-1\">\n <Button variant={r.counts.mine === 1 ? \"secondary\" : \"ghost\"} size={btn} aria-pressed={r.counts.mine === 1} aria-label={t(\"reactions.like\")} title={hint} disabled={disabled} onClick={() => toggle(1)}>\n <HugeiconsIcon icon={ThumbsUpIcon} strokeWidth={2} />\n <span>{compact(r.counts.likes, m.language)}</span>\n </Button>\n {dislike && (\n <Button variant={r.counts.mine === -1 ? \"secondary\" : \"ghost\"} size={btn} aria-pressed={r.counts.mine === -1} aria-label={t(\"reactions.dislike\")} title={hint} disabled={disabled} onClick={() => toggle(-1)}>\n <HugeiconsIcon icon={ThumbsDownIcon} strokeWidth={2} />\n <span>{compact(r.counts.dislikes, m.language)}</span>\n </Button>\n )}\n </div>\n {error && (\n <span role=\"alert\" className=\"text-xs text-destructive\">\n {error.code === \"rate_limited\" || error.code === \"forbidden\" ? contentError(m, error) : t(\"reactions.failed\")}\n </span>\n )}\n </ContentKitUiRoot>\n );\n}\n\nexport interface FavoriteButtonProps {\n item: Target;\n /** Whether it is favorited and the item's count, as the host already has them: both given, nothing is read. */\n favorited?: boolean;\n count?: number;\n /** Show the item's favorite count. Default true. */\n showCount?: boolean;\n /** Show the label beside the icon. Default true. */\n label?: boolean;\n /** Asks a signed-out visitor to sign in (default the provider's). */\n onSignIn?: () => void;\n /** After each saved change. */\n onChange?: (favorited: boolean) => void;\n size?: \"sm\" | \"default\";\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** Adds the item to the signed-in visitor's favorites, or removes it, with the server's count; changes at once and rolls back if refused. */\nexport function FavoriteButton({ item, favorited, count, showCount = true, label = true, onSignIn, onChange, size = \"default\", client, onError, className, appearance }: FavoriteButtonProps) {\n const m = useMessages();\n const { t } = m;\n const ctx = useContext(ContentKitContext);\n const f = useFavorite(item, { initial: favorited !== undefined && count !== undefined ? { favorited, count } : undefined, client });\n const signIn = onSignIn ?? ctx?.onSignIn;\n const report = useErrorReporter(onError);\n const [error, setError] = useState<ContentKitError | null>(null);\n const [status, setStatus] = useState(\"\");\n const shown = showCount ? f.count : undefined;\n const click = () => {\n if (ctx?.viewer === null) return signIn?.();\n setError(null);\n const next = !f.favorited;\n f.set(next).then(\n () => {\n setStatus(t(next ? \"favorites.added\" : \"favorites.removed\"));\n onChange?.(next);\n },\n (e) => {\n const err = toContentKitError(e);\n if (err.code === \"unauthorized\" && signIn) return signIn();\n setError(err);\n report(err, \"favorite.save\");\n },\n );\n };\n const text = t(ctx?.viewer === null && signIn ? \"favorites.signIn\" : f.favorited ? \"favorites.remove\" : \"favorites.add\");\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"inline-flex flex-wrap items-center gap-2 text-sm\", className)} data-ckui=\"favorite-button\">\n <Button\n variant={f.favorited ? \"secondary\" : \"outline\"}\n size={label ? (size === \"sm\" ? \"sm\" : \"default\") : size === \"sm\" ? \"icon-sm\" : \"icon\"}\n aria-pressed={f.favorited}\n aria-label={label ? undefined : text}\n disabled={f.pending}\n onClick={click}\n >\n <HugeiconsIcon icon={FavouriteIcon} strokeWidth={2} className={cn(f.favorited && \"fill-current text-destructive\")} />\n {label && <span>{text}</span>}\n {shown !== undefined && <span className=\"tabular-nums text-muted-foreground\">{compact(Math.max(0, shown), m.language)}</span>}\n </Button>\n <span className=\"sr-only\" role=\"status\">\n {status}\n </span>\n {error && (\n <span role=\"alert\" className=\"text-xs text-destructive\">\n {contentError(m, error)}\n </span>\n )}\n </ContentKitUiRoot>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"engagement.js","names":[],"sources":["../../../src/components/social/engagement.tsx"],"sourcesContent":["import { FavouriteIcon, ThumbsDownIcon, ThumbsUpIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useContext, useState } from \"react\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { ContentKitError } from \"../../client/errors.js\";\nimport { toContentKitError } from \"../../client/errors.js\";\nimport type { Target } from \"../../client/content/types.js\";\nimport type { ReactionCounts } from \"../../client/generated/wire.js\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext, useErrorReporter, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useContentConfig } from \"../../react/config.js\";\nimport { useFavorite, useReaction } from \"../../react/engagement.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { contentError } from \"./parts.js\";\n\n\nconst compact = (n: number, language?: string) => new Intl.NumberFormat(language, { notation: \"compact\", maximumFractionDigits: 1 }).format(n);\n\nexport interface ReactionButtonsProps {\n item: Target;\n /** Counts the host already has, used instead of reading them. */\n counts?: ReactionCounts;\n /** Offer dislike too. Default true. */\n dislike?: boolean;\n /** Asks a signed-out visitor to sign in where the server takes no anonymous reactions (default the provider's). */\n onSignIn?: () => void;\n size?: \"sm\" | \"default\";\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/**\n * Like and dislike toggles with counts: they change at once and roll back if\n * the server refuses. Signed out, they react anonymously where the server\n * allows it (`Config.anonymous.reactions`) and ask to sign in elsewhere.\n * Nothing renders where the item's kind's locked view hides reactions.\n */\nexport function ReactionButtons({ item, counts: initial, dislike = true, onSignIn, size = \"default\", client, onError, className, appearance }: ReactionButtonsProps) {\n const m = useMessages();\n const { t } = m;\n const r = useReaction(item, { initial, client });\n const ctx = useContext(ContentKitContext);\n const { config } = useContentConfig({ client });\n const signIn = onSignIn ?? ctx?.onSignIn;\n // Signed out where the server takes no anonymous reactions.\n const mustSignIn = ctx?.viewer === null && config?.anonymous.reactions === false;\n const report = useErrorReporter(onError);\n const [error, setError] = useState<ContentKitError | null>(null);\n const toggle = (v: 1 | -1) => {\n if (mustSignIn) return signIn?.();\n setError(null);\n r.toggle(v).catch((e) => {\n const err = toContentKitError(e);\n if (err.code === \"unauthorized\" && signIn) return signIn();\n setError(err);\n report(err, \"reaction.save\");\n });\n };\n if (r.counts.likes === undefined && !r.loading) return null;\n const btn = size === \"sm\" ? \"sm\" : \"default\";\n const hint = mustSignIn ? t(\"reactions.signIn\") : undefined;\n const disabled = mustSignIn && !signIn;\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"inline-flex flex-wrap items-center gap-1 text-sm\", className)} data-ckui=\"reaction-buttons\">\n <div className=\"inline-flex items-center gap-1\">\n <Button variant={r.counts.mine === 1 ? \"secondary\" : \"ghost\"} size={btn} aria-pressed={r.counts.mine === 1} aria-label={t(\"reactions.like\")} title={hint} disabled={disabled} onClick={() => toggle(1)}>\n <HugeiconsIcon icon={ThumbsUpIcon} strokeWidth={2} />\n {r.counts.likes !== undefined && <span>{compact(r.counts.likes, m.language)}</span>}\n </Button>\n {dislike && (\n <Button variant={r.counts.mine === -1 ? \"secondary\" : \"ghost\"} size={btn} aria-pressed={r.counts.mine === -1} aria-label={t(\"reactions.dislike\")} title={hint} disabled={disabled} onClick={() => toggle(-1)}>\n <HugeiconsIcon icon={ThumbsDownIcon} strokeWidth={2} />\n {r.counts.dislikes !== undefined && <span>{compact(r.counts.dislikes, m.language)}</span>}\n </Button>\n )}\n </div>\n {error && (\n <span role=\"alert\" className=\"text-xs text-destructive\">\n {error.code === \"rate_limited\" || error.code === \"forbidden\" ? contentError(m, error) : t(\"reactions.failed\")}\n </span>\n )}\n </ContentKitUiRoot>\n );\n}\n\nexport interface FavoriteButtonProps {\n item: Target;\n /** Whether it is favorited and the item's count, as the host already has them: both given, nothing is read. */\n favorited?: boolean;\n count?: number;\n /** Show the item's favorite count. Default true. */\n showCount?: boolean;\n /** Show the label beside the icon. Default true. */\n label?: boolean;\n /** Asks a signed-out visitor to sign in (default the provider's). */\n onSignIn?: () => void;\n /** After each saved change. */\n onChange?: (favorited: boolean) => void;\n size?: \"sm\" | \"default\";\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** Adds the item to the signed-in visitor's favorites, or removes it, with the server's count; changes at once and rolls back if refused. */\nexport function FavoriteButton({ item, favorited, count, showCount = true, label = true, onSignIn, onChange, size = \"default\", client, onError, className, appearance }: FavoriteButtonProps) {\n const m = useMessages();\n const { t } = m;\n const ctx = useContext(ContentKitContext);\n const f = useFavorite(item, { initial: favorited !== undefined && count !== undefined ? { favorited, count } : undefined, client });\n const signIn = onSignIn ?? ctx?.onSignIn;\n const report = useErrorReporter(onError);\n const [error, setError] = useState<ContentKitError | null>(null);\n const [status, setStatus] = useState(\"\");\n const shown = showCount ? f.count : undefined;\n const click = () => {\n if (ctx?.viewer === null) return signIn?.();\n setError(null);\n const next = !f.favorited;\n f.set(next).then(\n () => {\n setStatus(t(next ? \"favorites.added\" : \"favorites.removed\"));\n onChange?.(next);\n },\n (e) => {\n const err = toContentKitError(e);\n if (err.code === \"unauthorized\" && signIn) return signIn();\n setError(err);\n report(err, \"favorite.save\");\n },\n );\n };\n const text = t(ctx?.viewer === null && signIn ? \"favorites.signIn\" : f.favorited ? \"favorites.remove\" : \"favorites.add\");\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"inline-flex flex-wrap items-center gap-2 text-sm\", className)} data-ckui=\"favorite-button\">\n <Button\n variant={f.favorited ? \"secondary\" : \"outline\"}\n size={label ? (size === \"sm\" ? \"sm\" : \"default\") : size === \"sm\" ? \"icon-sm\" : \"icon\"}\n aria-pressed={f.favorited}\n aria-label={label ? undefined : text}\n disabled={f.pending}\n onClick={click}\n >\n <HugeiconsIcon icon={FavouriteIcon} strokeWidth={2} className={cn(f.favorited && \"fill-current text-destructive\")} />\n {label && <span>{text}</span>}\n {shown !== undefined && <span className=\"tabular-nums text-muted-foreground\">{compact(Math.max(0, shown), m.language)}</span>}\n </Button>\n <span className=\"sr-only\" role=\"status\">\n {status}\n </span>\n {error && (\n <span role=\"alert\" className=\"text-xs text-destructive\">\n {contentError(m, error)}\n </span>\n )}\n </ContentKitUiRoot>\n );\n}\n"],"mappings":"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"}
@@ -1,28 +1,29 @@
1
1
  import { en as e } from "../locales/en.js";
2
- import { ratioLabel as t } from "../client/media/rules.js";
2
+ import { transportFailure as t } from "../client/errors.js";
3
+ import { ratioLabel as n } from "../client/media/rules.js";
3
4
  //#region src/i18n/messages.ts
4
- var n = e;
5
- function r(e) {
5
+ var r = e;
6
+ function i(e) {
6
7
  return e;
7
8
  }
8
- function i(e, t) {
9
+ function a(e, t) {
9
10
  let n = { ...e };
10
11
  for (let [e, r] of Object.entries(t)) {
11
12
  if (r == null) continue;
12
13
  let t = n[e];
13
- typeof r == "string" ? r !== "" && (n[e] = r) : n[e] = i(typeof t == "object" ? t : {}, r);
14
+ typeof r == "string" ? r !== "" && (n[e] = r) : n[e] = a(typeof t == "object" ? t : {}, r);
14
15
  }
15
16
  return n;
16
17
  }
17
- function a(t) {
18
+ function o(t) {
18
19
  let n = t ? Array.isArray(t) ? t : [t] : [], r = e;
19
- for (let e of n) r = i(r, e);
20
+ for (let e of n) r = a(r, e);
20
21
  return r;
21
22
  }
22
- function o(e, t) {
23
+ function s(e, t) {
23
24
  return t ? e.replace(/\{(\w+)\}/g, (e, n) => n in t ? String(t[n]) : e) : e;
24
25
  }
25
- function s(e, t) {
26
+ function c(e, t) {
26
27
  let n = e;
27
28
  for (let e of t.split(".")) {
28
29
  if (!n || typeof n != "object") return;
@@ -30,65 +31,67 @@ function s(e, t) {
30
31
  }
31
32
  return typeof n == "string" ? n : void 0;
32
33
  }
33
- function c(e, n, r) {
34
- let i = (t, r) => {
35
- let i = n?.(t, r);
34
+ function l(e, r, i) {
35
+ let a = (t, n) => {
36
+ let i = r?.(t, n);
36
37
  if (i && i !== t) return i;
37
- let a = s(e, t);
38
- return a === void 0 ? void 0 : o(a, r);
39
- }, a;
38
+ let a = c(e, t);
39
+ return a === void 0 ? void 0 : s(a, n);
40
+ }, o;
40
41
  return {
41
42
  messages: e,
42
- language: r,
43
- t: (e, t) => i(e, t) ?? e,
43
+ language: i,
44
+ t: (e, t) => a(e, t) ?? e,
44
45
  plural(e, t, n) {
45
- a ??= new Intl.PluralRules(r);
46
- let o = {
46
+ o ??= new Intl.PluralRules(i);
47
+ let r = {
47
48
  ...n,
48
49
  count: t
49
50
  };
50
- return i(`${e}_${a.select(t)}`, o) ?? i(`${e}_other`, o) ?? e;
51
+ return a(`${e}_${o.select(t)}`, r) ?? a(`${e}_other`, r) ?? e;
51
52
  },
52
- error(n) {
53
- if (typeof n == "string") return i(`errors.${n}`, { seconds: 60 }) ?? e.errors.generic;
54
- let r = n ?? {}, a = typeof r.code == "string" ? r.code : void 0, o = typeof r.message == "string" && r.message ? d(r.message) : void 0, s = r.details ?? {}, c = {
55
- seconds: r.retryAfter ?? 60,
56
- width: s.width ?? "",
57
- height: s.height ?? "",
58
- min: s.min_width ?? "",
59
- megapixels: s.max_pixels ? Math.round(s.max_pixels / 1e6) : "",
60
- format: l(s.type),
61
- allowed: (s.allowed ?? []).map(l).join(", "),
62
- size: s.size ? u(s.size) : "",
63
- max: s.max_bytes ? u(s.max_bytes) : "",
64
- frames: s.frames ?? "",
65
- maxFrames: s.max_frames ?? "",
66
- maxSeconds: s.max_seconds ?? "",
67
- duration: s.seconds ?? "",
68
- shape: s.width && s.height ? t(s.width / s.height) : "",
69
- minAspect: s.min_aspect ? t(s.min_aspect) : "",
70
- maxAspect: s.max_aspect ? t(s.max_aspect) : "",
71
- maxFiles: s.max ?? "",
72
- maxChars: s.max ?? ""
53
+ error(r) {
54
+ if (typeof r == "string") return a(`errors.${r}`, { seconds: 60 }) ?? e.errors.generic;
55
+ let i = r ?? {}, o = t(r) ?? (typeof i.code == "string" ? i.code : void 0), s = typeof i.message == "string" && i.message ? f(i.message) : void 0;
56
+ if (i.unknownCode && s) return s;
57
+ let c = i.details ?? {}, l = {
58
+ seconds: i.retryAfter ?? 60,
59
+ width: c.width ?? "",
60
+ height: c.height ?? "",
61
+ min: c.min_width ?? "",
62
+ megapixels: c.max_pixels ? Math.round(c.max_pixels / 1e6) : "",
63
+ format: u(c.type),
64
+ allowed: (c.allowed ?? []).map(u).join(", "),
65
+ size: c.size ? d(c.size) : "",
66
+ max: c.max_bytes ? d(c.max_bytes) : "",
67
+ frames: c.frames ?? "",
68
+ maxFrames: c.max_frames ?? "",
69
+ maxSeconds: c.max_seconds ?? "",
70
+ duration: c.seconds ?? "",
71
+ shape: c.width && c.height ? n(c.width / c.height) : "",
72
+ minAspect: c.min_aspect ? n(c.min_aspect) : "",
73
+ maxAspect: c.max_aspect ? n(c.max_aspect) : "",
74
+ maxFiles: c.max ?? "",
75
+ maxChars: c.max ?? ""
73
76
  };
74
- return a === "invalid_request" && o ? o : a === "type_not_allowed" && s.allowed?.length ? `${i("errors.type_not_allowed", c)} ${i("errors.allowedTypes", c)}` : a === "comment_too_long" && s.max ? i("errors.commentTooLongBy", c) ?? e.errors.comment_too_long : a === "too_large" && s.max_bytes ? i("errors.tooLargeBy", c) ?? e.errors.too_large : a === "image_too_large" && (s.frames ?? 0) > 1 ? i("errors.animationTooLarge", c) ?? e.errors.image_too_large : a === "animation_too_long" && (s.max_frames || s.max_seconds) ? i(s.max_frames ? "errors.animationFrames" : "errors.animationSeconds", c) ?? e.errors.generic : a === "video_too_long" && s.max_seconds ? i("errors.videoTooLongBy", c) ?? e.errors.video_too_long : a === "video_too_large" && s.max_pixels ? i("errors.videoTooLargeBy", c) ?? e.errors.video_too_large : a === "video_aspect_unsupported" && s.width && s.height && s.min_aspect && s.max_aspect ? i("errors.videoAspectBy", c) ?? e.errors.video_aspect_unsupported : a === "too_many_files" && s.max ? i("errors.tooManyFilesBy", c) ?? e.errors.too_many_files : a && i(`errors.${a}`, c) || (o && (r.refusal ?? (r.status !== void 0 && r.status >= 400 && r.status < 500)) ? o : e.errors.generic);
77
+ return o === "invalid_request" && s ? s : o === "type_not_allowed" && c.allowed?.length ? `${a("errors.type_not_allowed", l)} ${a("errors.allowedTypes", l)}` : o === "comment_too_long" && c.max ? a("errors.commentTooLongBy", l) ?? e.errors.comment_too_long : o === "too_large" && c.max_bytes ? a("errors.tooLargeBy", l) ?? e.errors.too_large : o === "image_too_large" && (c.frames ?? 0) > 1 ? a("errors.animationTooLarge", l) ?? e.errors.image_too_large : o === "animation_too_long" && (c.max_frames || c.max_seconds) ? a(c.max_frames ? "errors.animationFrames" : "errors.animationSeconds", l) ?? e.errors.generic : o === "video_too_long" && c.max_seconds ? a("errors.videoTooLongBy", l) ?? e.errors.video_too_long : o === "video_too_large" && c.max_pixels ? a("errors.videoTooLargeBy", l) ?? e.errors.video_too_large : o === "video_aspect_unsupported" && c.width && c.height && c.min_aspect && c.max_aspect ? a("errors.videoAspectBy", l) ?? e.errors.video_aspect_unsupported : o === "too_many_files" && c.max ? a("errors.tooManyFilesBy", l) ?? e.errors.too_many_files : o && a(`errors.${o}`, l) || (s && (i.refusal ?? (i.status !== void 0 && i.status >= 400 && i.status < 500)) ? s : e.errors.generic);
75
78
  }
76
79
  };
77
80
  }
78
- function l(e) {
81
+ function u(e) {
79
82
  if (!e) return "";
80
83
  let t = e.split("/")[1] ?? e;
81
84
  return (t.split("+")[0] ?? t).replace(/^x-/, "").toUpperCase().replace(/^JPG$/, "JPEG").replace(/^WEBP$/, "WebP");
82
85
  }
83
- function u(e) {
86
+ function d(e) {
84
87
  let t = e / 1048576;
85
88
  return t >= 1024 ? `${+(t / 1024).toFixed(1)} GB` : `${+t.toFixed(+(t < 10))} MB`;
86
89
  }
87
- function d(e) {
90
+ function f(e) {
88
91
  let t = e.replace(/^media(\/\w+)?: /, "");
89
92
  return t.charAt(0).toUpperCase() + t.slice(1) + (/[.!?]$/.test(t) ? "" : ".");
90
93
  }
91
94
  //#endregion
92
- export { c as createTranslator, n as defaultMessages, r as defineMessages, l as formatName, o as interpolate, u as megabytes, a as resolveMessages };
95
+ export { l as createTranslator, r as defaultMessages, i as defineMessages, u as formatName, s as interpolate, d as megabytes, o as resolveMessages };
93
96
 
94
97
  //# sourceMappingURL=messages.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.js","names":[],"sources":["../../src/i18n/messages.ts"],"sourcesContent":["import { en } from \"../locales/en.js\";\nimport type { ErrorDetails } from \"../client/generated/wire.js\";\nimport { ratioLabel } from \"../client/media/rules.js\";\n\n\ntype Widen<T> = { [K in keyof T]: T[K] extends string ? string : Widen<T[K]> };\ntype DeepPartial<T> = { [K in keyof T]?: T[K] extends string ? string : DeepPartial<T[K]> };\ntype Paths<T, P extends string = \"\"> = {\n [K in keyof T & string]: T[K] extends string ? `${P}${K}` : Paths<T[K], `${P}${K}.`>;\n}[keyof T & string];\n\n/** The complete message tree; English is the reference shape. */\nexport type ContentKitUiMessages = Widen<typeof en>;\n/** A locale bundle or host override: any subset of the tree. */\nexport type ContentKitUiMessageBundle = DeepPartial<ContentKitUiMessages>;\n/** Dotted key of any message, e.g. `crop.title`. */\nexport type MessageKey = Paths<ContentKitUiMessages>;\nexport type MessageVars = Record<string, string | number>;\n/** Host translation hook; return nothing (or the key) to use ours. */\nexport type ContentKitUiTranslate = (key: string, vars?: MessageVars) => string | null | undefined;\n\nexport const defaultMessages: ContentKitUiMessages = en;\n\nexport function defineMessages(bundle: ContentKitUiMessageBundle): ContentKitUiMessageBundle {\n return bundle;\n}\n\ntype Tree = { [key: string]: string | Tree };\n\nfunction mergeInto(target: Tree, source: Tree): Tree {\n const out: Tree = { ...target };\n for (const [key, value] of Object.entries(source)) {\n if (value === undefined || value === null) continue;\n const current = out[key];\n if (typeof value === \"string\") {\n if (value !== \"\") out[key] = value;\n } else out[key] = mergeInto(typeof current === \"object\" ? current : {}, value);\n }\n return out;\n}\n\n/** Layers bundles over English; later bundles win, missing keys fall back. */\nexport function resolveMessages(bundles?: ContentKitUiMessageBundle | readonly ContentKitUiMessageBundle[]): ContentKitUiMessages {\n const list = bundles ? (Array.isArray(bundles) ? bundles : [bundles]) : [];\n let tree = en as unknown as Tree;\n for (const b of list) tree = mergeInto(tree, b as Tree);\n return tree as unknown as ContentKitUiMessages;\n}\n\nexport function interpolate(template: string, vars?: MessageVars): string {\n if (!vars) return template;\n return template.replace(/\\{(\\w+)\\}/g, (m, name: string) => (name in vars ? String(vars[name]) : m));\n}\n\nfunction lookup(messages: ContentKitUiMessages, key: string): string | undefined {\n let node: unknown = messages;\n for (const part of key.split(\".\")) {\n if (!node || typeof node !== \"object\") return undefined;\n node = (node as Tree)[part];\n }\n return typeof node === \"string\" ? node : undefined;\n}\n\nexport interface Translator {\n messages: ContentKitUiMessages;\n /** The UI's BCP 47 language (dates, plurals); undefined: the browser's. */\n language?: string;\n t(key: MessageKey, vars?: MessageVars): string;\n /** key_one or key_other by count (as the language's plural rules pick), with {count}. */\n plural(key: string, count: number, vars?: MessageVars): string;\n /** Message for a ContentKitError (or its code). */\n error(error: unknown): string;\n}\n\nexport function createTranslator(messages: ContentKitUiMessages, hostT?: ContentKitUiTranslate, language?: string): Translator {\n const translate = (key: string, vars?: MessageVars) => {\n const hosted = hostT?.(key, vars);\n if (hosted && hosted !== key) return hosted;\n const own = lookup(messages, key);\n return own === undefined ? undefined : interpolate(own, vars);\n };\n let rules: Intl.PluralRules | undefined;\n return {\n messages,\n language,\n t: (key, vars) => translate(key, vars) ?? key,\n plural(key, count, vars) {\n rules ??= new Intl.PluralRules(language);\n const all = { ...vars, count };\n return translate(`${key}_${rules.select(count)}`, all) ?? translate(`${key}_other`, all) ?? key;\n },\n error(error) {\n if (typeof error === \"string\") return translate(`errors.${error}`, { seconds: 60 }) ?? messages.errors.generic;\n const e = (error ?? {}) as { code?: unknown; message?: unknown; status?: number; retryAfter?: number; details?: ErrorDetails; refusal?: boolean };\n const code = typeof e.code === \"string\" ? e.code : undefined;\n const server = typeof e.message === \"string\" && e.message ? sentence(e.message) : undefined;\n const d = e.details ?? {};\n const vars: MessageVars = {\n seconds: e.retryAfter ?? 60,\n width: d.width ?? \"\",\n height: d.height ?? \"\",\n min: d.min_width ?? \"\",\n megapixels: d.max_pixels ? Math.round(d.max_pixels / 1e6) : \"\",\n format: formatName(d.type),\n allowed: (d.allowed ?? []).map(formatName).join(\", \"),\n size: d.size ? megabytes(d.size) : \"\",\n max: d.max_bytes ? megabytes(d.max_bytes) : \"\",\n frames: d.frames ?? \"\",\n maxFrames: d.max_frames ?? \"\",\n maxSeconds: d.max_seconds ?? \"\",\n duration: d.seconds ?? \"\",\n shape: d.width && d.height ? ratioLabel(d.width / d.height) : \"\",\n minAspect: d.min_aspect ? ratioLabel(d.min_aspect) : \"\",\n maxAspect: d.max_aspect ? ratioLabel(d.max_aspect) : \"\",\n maxFiles: d.max ?? \"\",\n maxChars: d.max ?? \"\",\n };\n // A refusal the server words itself states its rule; show it rather than a vaguer line.\n if (code === \"invalid_request\" && server) return server;\n if (code === \"type_not_allowed\" && d.allowed?.length) return `${translate(\"errors.type_not_allowed\", vars)} ${translate(\"errors.allowedTypes\", vars)}`;\n if (code === \"comment_too_long\" && d.max) return translate(\"errors.commentTooLongBy\", vars) ?? messages.errors.comment_too_long;\n if (code === \"too_large\" && d.max_bytes) return translate(\"errors.tooLargeBy\", vars) ?? messages.errors.too_large;\n if (code === \"image_too_large\" && (d.frames ?? 0) > 1) return translate(\"errors.animationTooLarge\", vars) ?? messages.errors.image_too_large;\n if (code === \"animation_too_long\" && (d.max_frames || d.max_seconds)) return translate(d.max_frames ? \"errors.animationFrames\" : \"errors.animationSeconds\", vars) ?? messages.errors.generic;\n if (code === \"video_too_long\" && d.max_seconds) return translate(\"errors.videoTooLongBy\", vars) ?? messages.errors.video_too_long;\n if (code === \"video_too_large\" && d.max_pixels) return translate(\"errors.videoTooLargeBy\", vars) ?? messages.errors.video_too_large;\n if (code === \"video_aspect_unsupported\" && d.width && d.height && d.min_aspect && d.max_aspect) return translate(\"errors.videoAspectBy\", vars) ?? messages.errors.video_aspect_unsupported;\n if (code === \"too_many_files\" && d.max) return translate(\"errors.tooManyFilesBy\", vars) ?? messages.errors.too_many_files;\n const own = code && translate(`errors.${code}`, vars);\n if (own) return own;\n // An unknown refusal (4xx) says what is wrong; faults get the generic line.\n if (server && (e.refusal ?? (e.status !== undefined && e.status >= 400 && e.status < 500))) return server;\n return messages.errors.generic;\n },\n };\n}\n\n/** \"image/avif\" → \"AVIF\". */\nexport function formatName(type?: string): string {\n if (!type) return \"\";\n const sub = type.split(\"/\")[1] ?? type;\n return (sub.split(\"+\")[0] ?? sub).replace(/^x-/, \"\").toUpperCase().replace(/^JPG$/, \"JPEG\").replace(/^WEBP$/, \"WebP\");\n}\n\n/** A byte size as the messages state it: \"2.5 MB\", \"25 MB\", \"20 GB\". */\nexport function megabytes(n: number): string {\n const mb = n / (1024 * 1024);\n return mb >= 1024 ? `${+(mb / 1024).toFixed(1)} GB` : `${+mb.toFixed(mb < 10 ? 1 : 0)} MB`;\n}\n\nfunction sentence(s: string): string {\n const t = s.replace(/^media(\\/\\w+)?: /, \"\");\n return t.charAt(0).toUpperCase() + t.slice(1) + (/[.!?]$/.test(t) ? \"\" : \".\");\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"messages.js","names":[],"sources":["../../src/i18n/messages.ts"],"sourcesContent":["import { en } from \"../locales/en.js\";\nimport type { ErrorDetails } from \"../client/generated/wire.js\";\nimport { ratioLabel } from \"../client/media/rules.js\";\nimport { transportFailure } from \"../client/errors.js\";\n\n\ntype Widen<T> = { [K in keyof T]: T[K] extends string ? string : Widen<T[K]> };\ntype DeepPartial<T> = { [K in keyof T]?: T[K] extends string ? string : DeepPartial<T[K]> };\ntype Paths<T, P extends string = \"\"> = {\n [K in keyof T & string]: T[K] extends string ? `${P}${K}` : Paths<T[K], `${P}${K}.`>;\n}[keyof T & string];\n\n/** The complete message tree; English is the reference shape. */\nexport type ContentKitUiMessages = Widen<typeof en>;\n/** A locale bundle or host override: any subset of the tree. */\nexport type ContentKitUiMessageBundle = DeepPartial<ContentKitUiMessages>;\n/** Dotted key of any message, e.g. `crop.title`. */\nexport type MessageKey = Paths<ContentKitUiMessages>;\nexport type MessageVars = Record<string, string | number>;\n/** Host translation hook; return nothing (or the key) to use ours. */\nexport type ContentKitUiTranslate = (key: string, vars?: MessageVars) => string | null | undefined;\n\nexport const defaultMessages: ContentKitUiMessages = en;\n\nexport function defineMessages(bundle: ContentKitUiMessageBundle): ContentKitUiMessageBundle {\n return bundle;\n}\n\ntype Tree = { [key: string]: string | Tree };\n\nfunction mergeInto(target: Tree, source: Tree): Tree {\n const out: Tree = { ...target };\n for (const [key, value] of Object.entries(source)) {\n if (value === undefined || value === null) continue;\n const current = out[key];\n if (typeof value === \"string\") {\n if (value !== \"\") out[key] = value;\n } else out[key] = mergeInto(typeof current === \"object\" ? current : {}, value);\n }\n return out;\n}\n\n/** Layers bundles over English; later bundles win, missing keys fall back. */\nexport function resolveMessages(bundles?: ContentKitUiMessageBundle | readonly ContentKitUiMessageBundle[]): ContentKitUiMessages {\n const list = bundles ? (Array.isArray(bundles) ? bundles : [bundles]) : [];\n let tree = en as unknown as Tree;\n for (const b of list) tree = mergeInto(tree, b as Tree);\n return tree as unknown as ContentKitUiMessages;\n}\n\nexport function interpolate(template: string, vars?: MessageVars): string {\n if (!vars) return template;\n return template.replace(/\\{(\\w+)\\}/g, (m, name: string) => (name in vars ? String(vars[name]) : m));\n}\n\nfunction lookup(messages: ContentKitUiMessages, key: string): string | undefined {\n let node: unknown = messages;\n for (const part of key.split(\".\")) {\n if (!node || typeof node !== \"object\") return undefined;\n node = (node as Tree)[part];\n }\n return typeof node === \"string\" ? node : undefined;\n}\n\nexport interface Translator {\n messages: ContentKitUiMessages;\n /** The UI's BCP 47 language (dates, plurals); undefined: the browser's. */\n language?: string;\n t(key: MessageKey, vars?: MessageVars): string;\n /** key_one or key_other by count (as the language's plural rules pick), with {count}. */\n plural(key: string, count: number, vars?: MessageVars): string;\n /** Message for a ContentKitError (or its code). */\n error(error: unknown): string;\n}\n\nexport function createTranslator(messages: ContentKitUiMessages, hostT?: ContentKitUiTranslate, language?: string): Translator {\n const translate = (key: string, vars?: MessageVars) => {\n const hosted = hostT?.(key, vars);\n if (hosted && hosted !== key) return hosted;\n const own = lookup(messages, key);\n return own === undefined ? undefined : interpolate(own, vars);\n };\n let rules: Intl.PluralRules | undefined;\n return {\n messages,\n language,\n t: (key, vars) => translate(key, vars) ?? key,\n plural(key, count, vars) {\n rules ??= new Intl.PluralRules(language);\n const all = { ...vars, count };\n return translate(`${key}_${rules.select(count)}`, all) ?? translate(`${key}_other`, all) ?? key;\n },\n error(error) {\n if (typeof error === \"string\") return translate(`errors.${error}`, { seconds: 60 }) ?? messages.errors.generic;\n const e = (error ?? {}) as { code?: unknown; message?: unknown; status?: number; retryAfter?: number; details?: ErrorDetails; refusal?: boolean; unknownCode?: string };\n const code = transportFailure(error) ?? (typeof e.code === \"string\" ? e.code : undefined);\n const server = typeof e.message === \"string\" && e.message ? sentence(e.message) : undefined;\n // A code from a newer server: its own wording beats our line for the status.\n if (e.unknownCode && server) return server;\n const d = e.details ?? {};\n const vars: MessageVars = {\n seconds: e.retryAfter ?? 60,\n width: d.width ?? \"\",\n height: d.height ?? \"\",\n min: d.min_width ?? \"\",\n megapixels: d.max_pixels ? Math.round(d.max_pixels / 1e6) : \"\",\n format: formatName(d.type),\n allowed: (d.allowed ?? []).map(formatName).join(\", \"),\n size: d.size ? megabytes(d.size) : \"\",\n max: d.max_bytes ? megabytes(d.max_bytes) : \"\",\n frames: d.frames ?? \"\",\n maxFrames: d.max_frames ?? \"\",\n maxSeconds: d.max_seconds ?? \"\",\n duration: d.seconds ?? \"\",\n shape: d.width && d.height ? ratioLabel(d.width / d.height) : \"\",\n minAspect: d.min_aspect ? ratioLabel(d.min_aspect) : \"\",\n maxAspect: d.max_aspect ? ratioLabel(d.max_aspect) : \"\",\n maxFiles: d.max ?? \"\",\n maxChars: d.max ?? \"\",\n };\n // A refusal the server words itself states its rule; show it rather than a vaguer line.\n if (code === \"invalid_request\" && server) return server;\n if (code === \"type_not_allowed\" && d.allowed?.length) return `${translate(\"errors.type_not_allowed\", vars)} ${translate(\"errors.allowedTypes\", vars)}`;\n if (code === \"comment_too_long\" && d.max) return translate(\"errors.commentTooLongBy\", vars) ?? messages.errors.comment_too_long;\n if (code === \"too_large\" && d.max_bytes) return translate(\"errors.tooLargeBy\", vars) ?? messages.errors.too_large;\n if (code === \"image_too_large\" && (d.frames ?? 0) > 1) return translate(\"errors.animationTooLarge\", vars) ?? messages.errors.image_too_large;\n if (code === \"animation_too_long\" && (d.max_frames || d.max_seconds)) return translate(d.max_frames ? \"errors.animationFrames\" : \"errors.animationSeconds\", vars) ?? messages.errors.generic;\n if (code === \"video_too_long\" && d.max_seconds) return translate(\"errors.videoTooLongBy\", vars) ?? messages.errors.video_too_long;\n if (code === \"video_too_large\" && d.max_pixels) return translate(\"errors.videoTooLargeBy\", vars) ?? messages.errors.video_too_large;\n if (code === \"video_aspect_unsupported\" && d.width && d.height && d.min_aspect && d.max_aspect) return translate(\"errors.videoAspectBy\", vars) ?? messages.errors.video_aspect_unsupported;\n if (code === \"too_many_files\" && d.max) return translate(\"errors.tooManyFilesBy\", vars) ?? messages.errors.too_many_files;\n const own = code && translate(`errors.${code}`, vars);\n if (own) return own;\n // An unknown refusal (4xx) says what is wrong; faults get the generic line.\n if (server && (e.refusal ?? (e.status !== undefined && e.status >= 400 && e.status < 500))) return server;\n return messages.errors.generic;\n },\n };\n}\n\n/** \"image/avif\" → \"AVIF\". */\nexport function formatName(type?: string): string {\n if (!type) return \"\";\n const sub = type.split(\"/\")[1] ?? type;\n return (sub.split(\"+\")[0] ?? sub).replace(/^x-/, \"\").toUpperCase().replace(/^JPG$/, \"JPEG\").replace(/^WEBP$/, \"WebP\");\n}\n\n/** A byte size as the messages state it: \"2.5 MB\", \"25 MB\", \"20 GB\". */\nexport function megabytes(n: number): string {\n const mb = n / (1024 * 1024);\n return mb >= 1024 ? `${+(mb / 1024).toFixed(1)} GB` : `${+mb.toFixed(mb < 10 ? 1 : 0)} MB`;\n}\n\nfunction sentence(s: string): string {\n const t = s.replace(/^media(\\/\\w+)?: /, \"\");\n return t.charAt(0).toUpperCase() + t.slice(1) + (/[.!?]$/.test(t) ? \"\" : \".\");\n}\n"],"mappings":"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"}