@cosmicdrift/kumiko-renderer 0.327.0 → 0.328.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/dist/app/action-form-shim.d.ts +14 -0
  2. package/{src/app/action-form-shim.ts → dist/app/action-form-shim.js} +26 -44
  3. package/dist/app/app-features-context.d.ts +8 -0
  4. package/dist/app/app-features-context.js +16 -0
  5. package/dist/app/column-renderers.d.ts +30 -0
  6. package/dist/app/column-renderers.js +34 -0
  7. package/dist/app/config-edit-shim.d.ts +11 -0
  8. package/{src/app/config-edit-shim.ts → dist/app/config-edit-shim.js} +12 -25
  9. package/dist/app/content-editors.d.ts +38 -0
  10. package/dist/app/content-editors.js +26 -0
  11. package/dist/app/content-preview.d.ts +11 -0
  12. package/dist/app/content-preview.js +30 -0
  13. package/dist/app/custom-screens.d.ts +11 -0
  14. package/dist/app/custom-screens.js +20 -0
  15. package/dist/app/dashboard-body.d.ts +16 -0
  16. package/dist/app/dashboard-body.js +11 -0
  17. package/dist/app/extension-form-submit.d.ts +32 -0
  18. package/dist/app/extension-form-submit.js +73 -0
  19. package/dist/app/extension-sections.d.ts +72 -0
  20. package/dist/app/extension-sections.js +34 -0
  21. package/dist/app/feature-schema.d.ts +4 -0
  22. package/{src/app/feature-schema.ts → dist/app/feature-schema.js} +12 -22
  23. package/dist/app/form-schema.d.ts +4 -0
  24. package/dist/app/form-schema.js +85 -0
  25. package/dist/app/kumiko-screen.d.ts +43 -0
  26. package/dist/app/kumiko-screen.js +2206 -0
  27. package/dist/app/layout-fields.d.ts +3 -0
  28. package/dist/app/layout-fields.js +20 -0
  29. package/dist/app/list-facets.d.ts +48 -0
  30. package/dist/app/list-facets.js +185 -0
  31. package/dist/app/nav.d.ts +61 -0
  32. package/dist/app/nav.js +139 -0
  33. package/dist/app/projection-detail-shim.d.ts +8 -0
  34. package/dist/app/projection-detail-shim.js +71 -0
  35. package/dist/app/projection-list-shim.d.ts +13 -0
  36. package/{src/app/projection-list-shim.ts → dist/app/projection-list-shim.js} +26 -38
  37. package/dist/app/qn.d.ts +7 -0
  38. package/{src/app/qn.ts → dist/app/qn.js} +9 -11
  39. package/dist/app/qualify-screen-id.d.ts +2 -0
  40. package/{src/app/qualify-screen-id.ts → dist/app/qualify-screen-id.js} +5 -6
  41. package/dist/app/reference-facet-bridge.d.ts +10 -0
  42. package/dist/app/reference-facet-bridge.js +22 -0
  43. package/dist/app/return-to.d.ts +31 -0
  44. package/dist/app/return-to.js +188 -0
  45. package/dist/app/row-actions.d.ts +77 -0
  46. package/dist/app/row-actions.js +416 -0
  47. package/dist/app/screen-access.d.ts +8 -0
  48. package/dist/app/screen-access.js +48 -0
  49. package/dist/app/secret-mint-body.d.ts +10 -0
  50. package/dist/app/secret-mint-body.js +140 -0
  51. package/dist/app/secrets-edit-body.d.ts +8 -0
  52. package/dist/app/secrets-edit-body.js +76 -0
  53. package/dist/app/use-embedded-screen.d.ts +6 -0
  54. package/dist/app/use-embedded-screen.js +19 -0
  55. package/dist/app/variable-chips.d.ts +7 -0
  56. package/dist/app/variable-chips.js +16 -0
  57. package/dist/app/write-failed-error.d.ts +6 -0
  58. package/dist/app/write-failed-error.js +21 -0
  59. package/dist/components/embedded-list-field.d.ts +10 -0
  60. package/dist/components/embedded-list-field.js +259 -0
  61. package/dist/components/grid-cell-for-field.d.ts +25 -0
  62. package/dist/components/grid-cell-for-field.js +31 -0
  63. package/dist/components/multi-select-checkboxes.d.ts +14 -0
  64. package/dist/components/multi-select-checkboxes.js +36 -0
  65. package/dist/components/reference-create-dialog.d.ts +13 -0
  66. package/dist/components/reference-create-dialog.js +46 -0
  67. package/dist/components/related-list-section.d.ts +25 -0
  68. package/dist/components/related-list-section.js +273 -0
  69. package/dist/components/render-edit-action-button.d.ts +22 -0
  70. package/dist/components/render-edit-action-button.js +43 -0
  71. package/dist/components/render-edit-logic.d.ts +6 -0
  72. package/dist/components/render-edit-logic.js +63 -0
  73. package/dist/components/render-edit-types.d.ts +209 -0
  74. package/dist/components/render-edit-types.js +1 -0
  75. package/dist/components/render-edit.d.ts +6 -0
  76. package/dist/components/render-edit.js +1169 -0
  77. package/dist/components/render-field.d.ts +38 -0
  78. package/dist/components/render-field.js +544 -0
  79. package/dist/components/render-list.d.ts +117 -0
  80. package/dist/components/render-list.js +232 -0
  81. package/dist/components/write-form-section.d.ts +17 -0
  82. package/dist/components/write-form-section.js +104 -0
  83. package/dist/context/dispatcher-context.d.ts +10 -0
  84. package/{src/context/dispatcher-context.tsx → dist/context/dispatcher-context.js} +16 -29
  85. package/dist/context/draft-storage-context.d.ts +12 -0
  86. package/dist/context/draft-storage-context.js +18 -0
  87. package/dist/context/user-roles-context.d.ts +7 -0
  88. package/{src/context/user-roles-context.tsx → dist/context/user-roles-context.js} +7 -15
  89. package/dist/format-when.d.ts +1 -0
  90. package/{src/format-when.ts → dist/format-when.js} +7 -7
  91. package/dist/hooks/reference-limits.d.ts +3 -0
  92. package/{src/hooks/reference-limits.ts → dist/hooks/reference-limits.js} +0 -1
  93. package/dist/hooks/use-ai-text.d.ts +52 -0
  94. package/dist/hooks/use-ai-text.js +90 -0
  95. package/dist/hooks/use-disclosure.d.ts +7 -0
  96. package/dist/hooks/use-disclosure.js +8 -0
  97. package/dist/hooks/use-form.d.ts +7 -0
  98. package/dist/hooks/use-form.js +36 -0
  99. package/dist/hooks/use-list-url-state.d.ts +43 -0
  100. package/dist/hooks/use-list-url-state.js +131 -0
  101. package/dist/hooks/use-mutation.d.ts +9 -0
  102. package/dist/hooks/use-mutation.js +37 -0
  103. package/dist/hooks/use-query.d.ts +14 -0
  104. package/dist/hooks/use-query.js +118 -0
  105. package/dist/hooks/use-reference-lookup.d.ts +14 -0
  106. package/dist/hooks/use-reference-lookup.js +63 -0
  107. package/dist/hooks/use-store.d.ts +3 -0
  108. package/dist/hooks/use-store.js +38 -0
  109. package/dist/hooks/use-stream-handler.d.ts +14 -0
  110. package/dist/hooks/use-stream-handler.js +93 -0
  111. package/dist/i18n-defaults.d.ts +2 -0
  112. package/dist/i18n-defaults.js +201 -0
  113. package/dist/i18n.d.ts +64 -0
  114. package/dist/i18n.js +166 -0
  115. package/dist/index.d.ts +77 -0
  116. package/dist/index.js +55 -0
  117. package/dist/inside-drawer.d.ts +2 -0
  118. package/dist/inside-drawer.js +9 -0
  119. package/dist/page-header-slot.d.ts +2 -0
  120. package/dist/page-header-slot.js +9 -0
  121. package/dist/primitives.d.ts +1351 -0
  122. package/dist/primitives.js +73 -0
  123. package/dist/screen-fills-height.d.ts +3 -0
  124. package/dist/screen-fills-height.js +3 -0
  125. package/dist/share-links.d.ts +4 -0
  126. package/dist/share-links.js +11 -0
  127. package/dist/sort-by-accessor.d.ts +5 -0
  128. package/dist/sort-by-accessor.js +16 -0
  129. package/dist/sse/live-events.d.ts +23 -0
  130. package/dist/sse/live-events.js +28 -0
  131. package/dist/tokens.d.ts +83 -0
  132. package/dist/tokens.js +80 -0
  133. package/package.json +16 -9
  134. package/src/changes.json +52 -0
  135. package/src/__tests__/error-i18n-defaults.test.ts +0 -82
  136. package/src/__tests__/format-when.test.ts +0 -12
  137. package/src/__tests__/i18n.test.tsx +0 -283
  138. package/src/__tests__/merge-search-params-into-initial.test.ts +0 -525
  139. package/src/__tests__/qn.test.ts +0 -83
  140. package/src/__tests__/share-links.test.ts +0 -26
  141. package/src/__tests__/sort-by-accessor.test.ts +0 -48
  142. package/src/__tests__/stringify-nav-params.test.ts +0 -33
  143. package/src/__tests__/use-list-url-state.test.tsx +0 -250
  144. package/src/app/__tests__/action-form-field-labels.test.tsx +0 -92
  145. package/src/app/__tests__/action-form-shim.test.ts +0 -137
  146. package/src/app/__tests__/build-list-query-payload.test.ts +0 -107
  147. package/src/app/__tests__/config-edit-shim.test.ts +0 -57
  148. package/src/app/__tests__/content-editors.test.tsx +0 -128
  149. package/src/app/__tests__/content-preview.test.tsx +0 -184
  150. package/src/app/__tests__/entity-edit-create-search-params.test.tsx +0 -236
  151. package/src/app/__tests__/entity-edit-jsonb-embedded-submit.test.tsx +0 -239
  152. package/src/app/__tests__/entity-list-create-singleton.test.tsx +0 -128
  153. package/src/app/__tests__/entity-list-row-action-entity-target.test.tsx +0 -424
  154. package/src/app/__tests__/entity-list-row-action-icon.test.tsx +0 -248
  155. package/src/app/__tests__/entity-list-row-action-kumiko-actions-view.test.tsx +0 -162
  156. package/src/app/__tests__/entity-list-row-action-refetch.test.tsx +0 -401
  157. package/src/app/__tests__/entity-list-screen-padding.test.tsx +0 -111
  158. package/src/app/__tests__/feature-schema.test.ts +0 -40
  159. package/src/app/__tests__/form-schema.test.ts +0 -247
  160. package/src/app/__tests__/list-daterange-facet.test.ts +0 -165
  161. package/src/app/__tests__/list-filter-facets.test.tsx +0 -521
  162. package/src/app/__tests__/nav.test.ts +0 -198
  163. package/src/app/__tests__/projection-detail-actions.test.tsx +0 -719
  164. package/src/app/__tests__/projection-detail-reference-field.test.tsx +0 -165
  165. package/src/app/__tests__/projection-detail-shim.test.ts +0 -188
  166. package/src/app/__tests__/projection-detail-singleton.test.tsx +0 -191
  167. package/src/app/__tests__/projection-list-bad-shape.test.tsx +0 -152
  168. package/src/app/__tests__/projection-list-reference-column.test.tsx +0 -219
  169. package/src/app/__tests__/projection-list-search-sort.test.tsx +0 -212
  170. package/src/app/__tests__/qualified-names.test.ts +0 -37
  171. package/src/app/__tests__/return-to.test.ts +0 -396
  172. package/src/app/__tests__/row-actions-navigate-tab.test.ts +0 -223
  173. package/src/app/__tests__/row-default-edit-action.test.tsx +0 -324
  174. package/src/app/__tests__/screen-access-allows.test.ts +0 -34
  175. package/src/app/__tests__/secret-mint-body.test.tsx +0 -404
  176. package/src/app/__tests__/variable-chips.test.tsx +0 -70
  177. package/src/app/app-features-context.tsx +0 -25
  178. package/src/app/column-renderers.tsx +0 -68
  179. package/src/app/content-editors.tsx +0 -85
  180. package/src/app/content-preview.tsx +0 -67
  181. package/src/app/custom-screens.tsx +0 -29
  182. package/src/app/dashboard-body.tsx +0 -33
  183. package/src/app/extension-form-submit.tsx +0 -123
  184. package/src/app/extension-sections.tsx +0 -111
  185. package/src/app/form-schema.ts +0 -91
  186. package/src/app/kumiko-screen.tsx +0 -3614
  187. package/src/app/layout-fields.ts +0 -31
  188. package/src/app/list-facets.ts +0 -259
  189. package/src/app/nav.tsx +0 -258
  190. package/src/app/projection-detail-shim.ts +0 -85
  191. package/src/app/reference-facet-bridge.tsx +0 -58
  192. package/src/app/return-to.tsx +0 -234
  193. package/src/app/row-actions.ts +0 -639
  194. package/src/app/screen-access.ts +0 -63
  195. package/src/app/secret-mint-body.tsx +0 -259
  196. package/src/app/secrets-edit-body.tsx +0 -194
  197. package/src/app/use-embedded-screen.ts +0 -27
  198. package/src/app/variable-chips.tsx +0 -39
  199. package/src/app/write-failed-error.ts +0 -27
  200. package/src/components/__tests__/embedded-list-field.test.tsx +0 -531
  201. package/src/components/__tests__/multi-select-checkboxes.test.tsx +0 -162
  202. package/src/components/__tests__/related-list-section-empty-state.test.tsx +0 -143
  203. package/src/components/__tests__/related-list-section.test.tsx +0 -1669
  204. package/src/components/__tests__/render-edit-action-button.test.tsx +0 -205
  205. package/src/components/__tests__/render-edit-hidden-section.test.tsx +0 -128
  206. package/src/components/__tests__/render-edit-logic.test.ts +0 -314
  207. package/src/components/__tests__/render-edit-screen-description.test.tsx +0 -152
  208. package/src/components/__tests__/render-edit-submit-actions.test.tsx +0 -460
  209. package/src/components/__tests__/render-field-app-locale.test.tsx +0 -142
  210. package/src/components/__tests__/render-field-enum-option.test.tsx +0 -99
  211. package/src/components/__tests__/render-field-icon-derivation.test.tsx +0 -119
  212. package/src/components/__tests__/render-field-json-format.test.tsx +0 -164
  213. package/src/components/__tests__/render-field-money-embedded-list-consistency.test.tsx +0 -212
  214. package/src/components/__tests__/render-field-money-roundtrip.test.tsx +0 -217
  215. package/src/components/__tests__/render-field-number-grouping.test.tsx +0 -76
  216. package/src/components/__tests__/render-field-number-unit.test.tsx +0 -227
  217. package/src/components/__tests__/render-field-password-format.test.tsx +0 -101
  218. package/src/components/__tests__/render-field-select-display.test.tsx +0 -134
  219. package/src/components/__tests__/render-field-unit-format.test.tsx +0 -107
  220. package/src/components/__tests__/render-field-unsupported-types.test.tsx +0 -195
  221. package/src/components/__tests__/render-list-toolbar-icon-only.test.tsx +0 -146
  222. package/src/components/__tests__/write-form-section.test.tsx +0 -375
  223. package/src/components/embedded-list-field.tsx +0 -354
  224. package/src/components/grid-cell-for-field.tsx +0 -60
  225. package/src/components/multi-select-checkboxes.tsx +0 -93
  226. package/src/components/reference-create-dialog.tsx +0 -91
  227. package/src/components/related-list-section.tsx +0 -467
  228. package/src/components/render-edit-action-button.tsx +0 -106
  229. package/src/components/render-edit-logic.ts +0 -85
  230. package/src/components/render-edit-types.ts +0 -216
  231. package/src/components/render-edit.tsx +0 -1700
  232. package/src/components/render-field.tsx +0 -942
  233. package/src/components/render-list.tsx +0 -561
  234. package/src/components/write-form-section.tsx +0 -199
  235. package/src/context/draft-storage-context.tsx +0 -39
  236. package/src/hooks/__tests__/use-ai-text.test.tsx +0 -177
  237. package/src/hooks/__tests__/use-disclosure.test.tsx +0 -25
  238. package/src/hooks/__tests__/use-form.test.tsx +0 -65
  239. package/src/hooks/__tests__/use-mutation.test.tsx +0 -77
  240. package/src/hooks/__tests__/use-stream-handler.test.tsx +0 -107
  241. package/src/hooks/use-ai-text.ts +0 -172
  242. package/src/hooks/use-disclosure.ts +0 -20
  243. package/src/hooks/use-form.ts +0 -78
  244. package/src/hooks/use-list-url-state.ts +0 -171
  245. package/src/hooks/use-mutation.ts +0 -61
  246. package/src/hooks/use-query.ts +0 -132
  247. package/src/hooks/use-reference-lookup.ts +0 -76
  248. package/src/hooks/use-store.ts +0 -48
  249. package/src/hooks/use-stream-handler.ts +0 -134
  250. package/src/i18n-defaults.ts +0 -220
  251. package/src/i18n.tsx +0 -286
  252. package/src/index.ts +0 -272
  253. package/src/primitives.tsx +0 -1446
  254. package/src/share-links.ts +0 -12
  255. package/src/sort-by-accessor.ts +0 -20
  256. package/src/sse/live-events.tsx +0 -56
  257. package/src/tokens.tsx +0 -170
package/src/i18n.tsx DELETED
@@ -1,286 +0,0 @@
1
- // Locale handling for React consumers of the Kumiko renderer. A thin layer
2
- // around the platform-agnostic `LocaleResolver` contract from
3
- // @cosmicdrift/kumiko-headless: provider, hooks, a default no-op resolver,
4
- // and a fallback-bundle merge for feature-supplied translations.
5
- //
6
- // Architecture:
7
- // 1. The app supplies exactly one `LocaleResolver` via `<LocaleProvider>`
8
- // (or none at all → the default resolver returns keys as-is).
9
- // 2. Feature plugins may bring fallback bundles: when the app resolver
10
- // can't resolve a key, `useTranslation` tries the plugin bundles.
11
- // This keeps feature UI independent of the app's own i18next instance
12
- // and works out of the box, while staying fully overridable.
13
- // 3. Re-render on locale change via `useSyncExternalStore` on the
14
- // resolver's `subscribe()` — app code can switch language mid-session
15
- // without a reload.
16
-
17
- import {
18
- type Formality,
19
- formalLocaleTag,
20
- resolveTranslationValue,
21
- type TranslationValue,
22
- } from "@cosmicdrift/kumiko-framework/ui-types";
23
- import type { LocaleResolver } from "@cosmicdrift/kumiko-headless";
24
- import {
25
- createContext,
26
- type ReactNode,
27
- useCallback,
28
- useContext,
29
- useMemo,
30
- useSyncExternalStore,
31
- } from "react";
32
-
33
- /** Map of i18n key → TranslationValue. Strings may contain `{name}`
34
- * placeholders (same semantics as i18next t); plural entries resolve via
35
- * `resolveTranslationValue`. */
36
- export type TranslationBundle = Readonly<Record<string, TranslationValue>>;
37
-
38
- /** Map von Locale-Code (BCP-47, z.B. `"de"`, `"en-US"`) → Bundle. */
39
- export type TranslationsByLocale = Readonly<Record<string, TranslationBundle>>;
40
-
41
- /** Key-first shape for `r.translations({ keys })` — each key maps locale → TranslationValue. */
42
- export type TranslationsByKey = Readonly<
43
- Record<string, Readonly<Record<string, TranslationValue>>>
44
- >;
45
-
46
- /** Pivot key-first server translations to locale-first client bundles. */
47
- export function translationsByLocaleFromKeys(source: TranslationsByKey): TranslationsByLocale {
48
- const out: Record<string, Record<string, TranslationValue>> = {};
49
- for (const [key, byLocale] of Object.entries(source)) {
50
- for (const [locale, value] of Object.entries(byLocale)) {
51
- out[locale] ??= {};
52
- out[locale][key] = value;
53
- }
54
- }
55
- return out;
56
- }
57
-
58
- /** Merged zwei TranslationsByLocale-Maps — der override gewinnt pro Key,
59
- * die Locales werden zusammengeführt. Standard-Baustein für Client-
60
- * Plugins, die App-Overrides über ihre Default-Bundles legen. */
61
- export function mergeTranslations(
62
- base: TranslationsByLocale,
63
- override: TranslationsByLocale,
64
- ): TranslationsByLocale {
65
- const locales = new Set([...Object.keys(base), ...Object.keys(override)]);
66
- const merged: Record<string, Record<string, TranslationValue>> = {};
67
- for (const locale of locales) {
68
- merged[locale] = { ...(base[locale] ?? {}), ...(override[locale] ?? {}) };
69
- }
70
- return merged;
71
- }
72
-
73
- type LocaleContextValue = {
74
- readonly resolver: LocaleResolver;
75
- readonly fallbackBundles: readonly TranslationsByLocale[];
76
- readonly fallbackLocale: string;
77
- };
78
-
79
- const LocaleContext = createContext<LocaleContextValue | undefined>(undefined);
80
- const FormalityContext = createContext<Formality>("informal");
81
-
82
- // Stabile Referenz statt `fallbackBundles = []` als Default-Parameter:
83
- // ein Literal-Default wird bei JEDEM Aufruf neu allokiert und würde die
84
- // useMemo-Referenzprüfung im Provider unten aushebeln, sobald der
85
- // Aufrufer fallbackBundles weglässt.
86
- const EMPTY_FALLBACK_BUNDLES: readonly TranslationsByLocale[] = [];
87
-
88
- export type LocaleProviderProps = {
89
- readonly resolver: LocaleResolver;
90
- /** Default bundles supplied by feature plugins. Lookup order per key:
91
- * (1) app resolver, (2) these bundles in array order, (3) key as-is.
92
- * Apps can thus override individual keys without swapping out whole
93
- * feature bundles. */
94
- readonly fallbackBundles?: readonly TranslationsByLocale[];
95
- /** Falls back to fallbackLocale when neither the current-locale nor the
96
- * key lookup hits in a plugin bundle. Default: `"en"`. */
97
- readonly fallbackLocale?: string;
98
- readonly children: ReactNode;
99
- };
100
-
101
- export function LocaleProvider({
102
- resolver,
103
- fallbackBundles = EMPTY_FALLBACK_BUNDLES,
104
- fallbackLocale = "en",
105
- children,
106
- }: LocaleProviderProps): ReactNode {
107
- // Without memoization every re-render of the provider (e.g. because an
108
- // ancestor component re-renders) builds a new context-value object —
109
- // every consumer of useTranslation()/useLocale() then sees a new `ctx`
110
- // reference and, even with useCallback memoization, a new `t`.
111
- // Consequence: `t` in a useEffect dependency array triggers an infinite
112
- // loop (see admin-shell Overview screens, prod incident).
113
- const value = useMemo(
114
- () => ({ resolver, fallbackBundles, fallbackLocale }),
115
- [resolver, fallbackBundles, fallbackLocale],
116
- );
117
- return <LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>;
118
- }
119
-
120
- /** Liefert den aktuellen LocaleResolver und abonniert automatisch
121
- * Locale-Änderungen — der aufrufende Component re-rendert sobald die
122
- * Sprache gewechselt wird. Wirft wenn kein Provider im Baum ist. */
123
- export function useLocale(): LocaleResolver {
124
- const ctx = useContext(LocaleContext);
125
- if (ctx === undefined) {
126
- throw new Error("useLocale must be used inside <LocaleProvider>");
127
- }
128
- // Subscribe + current locale-snapshot. Wir brauchen den Rückgabewert
129
- // selbst nicht — wichtig ist nur der re-render-trigger.
130
- useSyncExternalStore(
131
- ctx.resolver.subscribe,
132
- () => ctx.resolver.locale(),
133
- () => ctx.resolver.locale(),
134
- );
135
- return ctx.resolver;
136
- }
137
-
138
- /** `t("key", params)` resolves in this order:
139
- * 1. App resolver (e.g. i18next)
140
- * 2. Plugin fallback bundles for the current locale (under a "formal"
141
- * FormalityProvider, `<locale>-x-formal` across all bundles first)
142
- * 3. Plugin fallback bundles for fallbackLocale
143
- * 4. The key as-is
144
- * `{name}` interpolation applies to every source, fallback strings included. */
145
- export function useTranslation(): (
146
- key: string,
147
- params?: Readonly<Record<string, unknown>>,
148
- ) => string {
149
- const ctx = useContext(LocaleContext);
150
- if (ctx === undefined) {
151
- throw new Error("useTranslation must be used inside <LocaleProvider>");
152
- }
153
- // Re-Render bei Sprach-Wechsel. `ctx.resolver.subscribe` ist bereits
154
- // eine stable-reference aus dem Resolver, daher hier keine eigene
155
- // Memoization der Subscribe-Callback nötig.
156
- const locale = useSyncExternalStore(
157
- ctx.resolver.subscribe,
158
- () => ctx.resolver.locale(),
159
- () => ctx.resolver.locale(),
160
- );
161
-
162
- // `t` MUSS referenz-stabil sein solange sich Resolver/Bundles/Locale
163
- // nicht ändern — Consumer nutzen `t` regelmäßig in useEffect-Deps
164
- // (z.B. um Queries neu zu laden wenn sich die Sprache ändert). Ein neu
165
- // erzeugtes `t` pro Render führt sonst zu einem Render/Effect-Endlos-
166
- // Loop (siehe admin-shell Overview-Screens, Prod-Incident 2026-07-07).
167
- const formality = useContext(FormalityContext);
168
- return useCallback(
169
- (key: string, params?: Readonly<Record<string, unknown>>): string =>
170
- translateWithFallbacks(ctx, locale, formality, key, params),
171
- [ctx, locale, formality],
172
- );
173
- }
174
-
175
- /** Wording for the subtree: `formal` makes `t` prefer the `<locale>-x-formal`
176
- * bundle entries (e.g. "Sie" on public pages) over plain `<locale>`. */
177
- export function FormalityProvider({
178
- formality,
179
- children,
180
- }: {
181
- readonly formality: Formality;
182
- readonly children: ReactNode;
183
- }): ReactNode {
184
- return <FormalityContext.Provider value={formality}>{children}</FormalityContext.Provider>;
185
- }
186
-
187
- export function useFormality(): Formality {
188
- return useContext(FormalityContext);
189
- }
190
-
191
- // Lookup order: (1) app resolver — it returns the key itself when it has no
192
- // entry, which is the invitation to try the plugin bundles; (2) the bundles in
193
- // array order per locale tier; (3) the key as-is. Under "formal" the formal
194
- // tier is searched across ALL bundles before any plain tier, so a plain "de"
195
- // app override never puts "du" on a formal page when locale-de has a formal
196
- // variant; an app rewording such a key must also ship its "de-x-formal" text.
197
- function translateWithFallbacks(
198
- ctx: LocaleContextValue,
199
- locale: string,
200
- formality: Formality,
201
- key: string,
202
- params?: Readonly<Record<string, unknown>>,
203
- ): string {
204
- const resolved = ctx.resolver.translate(key, params);
205
- if (resolved !== key) return resolved;
206
- for (const localesToTry of bundleLocaleTiers(locale, ctx.fallbackLocale, formality)) {
207
- for (const bundle of ctx.fallbackBundles) {
208
- for (const localeToTry of localesToTry) {
209
- const value = bundle[localeToTry]?.[key];
210
- if (value !== undefined) return resolveTranslationValue(value, localeToTry, params);
211
- }
212
- }
213
- }
214
- return key;
215
- }
216
-
217
- function bundleLocaleTiers(
218
- locale: string,
219
- fallbackLocale: string,
220
- formality: Formality,
221
- ): readonly (readonly string[])[] {
222
- const languageRoot = locale.split("-")[0] ?? locale;
223
- const plainTier = [locale, languageRoot, fallbackLocale];
224
- if (formality === "informal") return [plainTier];
225
- return [[formalLocaleTag(locale), formalLocaleTag(languageRoot)], plainTier];
226
- }
227
-
228
- /** Non-throwing LocaleContext read — undefined outside LocaleProvider.
229
- * Used by DataTable FormatCell so plain tables without a provider do not crash. */
230
- export function useOptionalLocale(): string | undefined {
231
- const ctx = useContext(LocaleContext);
232
- useSyncExternalStore(
233
- (onStoreChange) => (ctx ? ctx.resolver.subscribe(onStoreChange) : () => {}),
234
- () => (ctx ? ctx.resolver.locale() : "en"),
235
- () => (ctx ? ctx.resolver.locale() : "en"),
236
- );
237
- return ctx === undefined ? undefined : ctx.resolver.locale();
238
- }
239
-
240
- /** Non-throwing time-zone read — "UTC" outside LocaleProvider, matching
241
- * createStaticLocaleResolver's own default. */
242
- export function useOptionalTimeZone(): string {
243
- const ctx = useContext(LocaleContext);
244
- return useSyncExternalStore(
245
- (onStoreChange) => (ctx ? ctx.resolver.subscribe(onStoreChange) : () => {}),
246
- () => (ctx ? ctx.resolver.timeZone() : "UTC"),
247
- () => (ctx ? ctx.resolver.timeZone() : "UTC"),
248
- );
249
- }
250
-
251
- /** Non-throwing translate — undefined outside LocaleProvider. */
252
- export function useOptionalTranslation():
253
- | ((key: string, params?: Readonly<Record<string, unknown>>) => string)
254
- | undefined {
255
- const ctx = useContext(LocaleContext);
256
- const locale = useSyncExternalStore(
257
- (onStoreChange) => (ctx ? ctx.resolver.subscribe(onStoreChange) : () => {}),
258
- () => (ctx ? ctx.resolver.locale() : "en"),
259
- () => (ctx ? ctx.resolver.locale() : "en"),
260
- );
261
- const formality = useContext(FormalityContext);
262
- const t = useCallback(
263
- (key: string, params?: Readonly<Record<string, unknown>>): string =>
264
- ctx === undefined ? key : translateWithFallbacks(ctx, locale, formality, key, params),
265
- [ctx, locale, formality],
266
- );
267
- return ctx === undefined ? undefined : t;
268
- }
269
-
270
- /** Default-Resolver für Apps ohne eigene i18n-Schicht. Gibt jeden Key
271
- * unverändert zurück — die Plugin-Fallback-Bundles erledigen dann die
272
- * echte Übersetzung. Nützlich auch als Basis für Tests. */
273
- export function createStaticLocaleResolver(
274
- options: { readonly locale?: string; readonly timeZone?: string } = {},
275
- ): LocaleResolver {
276
- const locale = options.locale ?? "en";
277
- const timeZone = options.timeZone ?? "UTC";
278
- return {
279
- translate: (key: string) => key,
280
- locale: () => locale,
281
- timeZone: () => timeZone,
282
- // No-op subscribe: unsere Locale ist statisch, es gibt nie ein
283
- // Change-Event. Unsubscribe ist ebenfalls no-op.
284
- subscribe: () => () => {},
285
- };
286
- }
package/src/index.ts DELETED
@@ -1,272 +0,0 @@
1
- // Platform-agnostic React renderer for Kumiko screens. Das ist der
2
- // Shared-Layer: Components, Hooks, Contexts, Types. Plattform-Impls
3
- // (Web-DOM, React-Native) leben in den jeweiligen Plattform-Packages
4
- // und reichen ihre konkreten Primitives/Nav/SSE-Impls via Provider
5
- // in diesen Baum.
6
- //
7
- // Wer diesen Layer direkt konsumiert: andere Renderer-Packages
8
- // (@cosmicdrift/kumiko-renderer-web, später -native) oder eine App die ihren
9
- // eigenen Bootstrap schreiben will. Normale Samples gehen über
10
- // @cosmicdrift/kumiko-renderer-web/createKumikoApp, das alle Provider verdrahtet.
11
-
12
- export { type Formality, formalLocaleTag } from "@cosmicdrift/kumiko-framework/ui-types";
13
- export { synthesizeActionFormEntity, synthesizeActionFormScreen } from "./app/action-form-shim";
14
- export type { AppFeaturesProviderProps } from "./app/app-features-context";
15
- export { AppFeaturesProvider, useAppFeatures } from "./app/app-features-context";
16
- export type {
17
- ColumnRendererComponent,
18
- ColumnRendererProps,
19
- ColumnRenderersMap,
20
- ColumnRenderersProviderProps,
21
- } from "./app/column-renderers";
22
- export { ColumnRenderersProvider, useColumnRenderer } from "./app/column-renderers";
23
- export type {
24
- ContentEditorComponent,
25
- ContentEditorProps,
26
- ContentEditorsMap,
27
- ContentEditorsProviderProps,
28
- } from "./app/content-editors";
29
- export {
30
- CONTENT_EDITOR_ELEMENT_ID,
31
- ContentEditorsProvider,
32
- TextareaContentEditor,
33
- useContentEditor,
34
- } from "./app/content-editors";
35
- export type { ContentPreviewProps } from "./app/content-preview";
36
- export { ContentPreview, substituteVariables } from "./app/content-preview";
37
- export type { CustomScreensMap, CustomScreensProviderProps } from "./app/custom-screens";
38
- export { CustomScreensProvider, useCustomScreenComponent } from "./app/custom-screens";
39
- export type { DashboardBodyProps, DashboardBodyProviderProps } from "./app/dashboard-body";
40
- export { DashboardBodyProvider, useDashboardBody } from "./app/dashboard-body";
41
- export type {
42
- ExtensionFormRegistry,
43
- ExtensionFormSubmitHandler,
44
- ExtensionSubmitContext,
45
- ExtensionSubmitResult,
46
- } from "./app/extension-form-submit";
47
- export { ExtensionFormRegistryProvider, useExtensionFormSubmit } from "./app/extension-form-submit";
48
- export type {
49
- ExtensionSectionComponent,
50
- ExtensionSectionProps,
51
- ExtensionSectionsMap,
52
- ExtensionSectionsProviderProps,
53
- } from "./app/extension-sections";
54
- export {
55
- ExtensionSectionsProvider,
56
- extensionSectionName,
57
- useExtensionSectionComponent,
58
- } from "./app/extension-sections";
59
- export type {
60
- AppSchema,
61
- FeatureSchema,
62
- QualifiedContentCollection,
63
- WorkspaceSchema,
64
- } from "./app/feature-schema";
65
- export { isAppSchema, toAppSchema } from "./app/feature-schema";
66
- export type { KumikoScreenProps } from "./app/kumiko-screen";
67
- export { KumikoScreen, qualifyNavId, qualifyScreenId } from "./app/kumiko-screen";
68
- export type { DateRangeBound, DateRangeValue, ResolvedDateRangeFacet } from "./app/list-facets";
69
- export {
70
- buildDateRangePayload,
71
- clampDateRange,
72
- readDateRange,
73
- resolveDateRangeFacets,
74
- } from "./app/list-facets";
75
- export type {
76
- NavApi,
77
- NavProviderProps,
78
- NavRoute,
79
- NavTarget,
80
- ObjectTarget,
81
- ScreenTarget,
82
- } from "./app/nav";
83
- export {
84
- formatPath,
85
- hasDetailScreen,
86
- NavProvider,
87
- parsePath,
88
- resolveTarget,
89
- useNav,
90
- useNavigateWithInitialValues,
91
- } from "./app/nav";
92
- export { lastSegment } from "./app/qn";
93
- export type { ReturnHost, ReturnTo } from "./app/return-to";
94
- export {
95
- navigateToReturn,
96
- navigateToReturnOr,
97
- navigateWithReturnTo,
98
- RETURN_TO_PARAM,
99
- ReturnHostProvider,
100
- resolveReturnTarget,
101
- splitReturnTo,
102
- useReturnHost,
103
- useReturnTarget,
104
- } from "./app/return-to";
105
- export type { EmbeddedScreenTarget } from "./app/use-embedded-screen";
106
- export { useEmbeddedScreen } from "./app/use-embedded-screen";
107
- export type { VariableChipsProps } from "./app/variable-chips";
108
- export { VariableChips } from "./app/variable-chips";
109
- export { dispatcherErrorText, WriteFailedError } from "./app/write-failed-error";
110
- export { RelatedListSection } from "./components/related-list-section";
111
- export type {
112
- RenderEditAction,
113
- RenderEditChangeState,
114
- RenderEditControls,
115
- RenderEditProps,
116
- } from "./components/render-edit";
117
- export { RenderEdit } from "./components/render-edit";
118
- export type { RenderFieldProps } from "./components/render-field";
119
- export { RenderField } from "./components/render-field";
120
- export type { RenderListProps } from "./components/render-list";
121
- export { RenderList } from "./components/render-list";
122
- export type { DispatcherProviderProps } from "./context/dispatcher-context";
123
- export {
124
- DispatcherProvider,
125
- useDispatcher,
126
- useDispatcherStatus,
127
- useOptionalDispatcher,
128
- } from "./context/dispatcher-context";
129
- export type { DraftStorage, DraftStorageProviderProps } from "./context/draft-storage-context";
130
- export { DraftStorageProvider, useDraftStorage } from "./context/draft-storage-context";
131
- export type { UserRolesProviderProps } from "./context/user-roles-context";
132
- export { UserRolesProvider, useUserRoles } from "./context/user-roles-context";
133
- export { formatWhen } from "./format-when";
134
- export {
135
- REFERENCE_COMBOBOX_LIMIT,
136
- REFERENCE_LIST_LOOKUP_LIMIT,
137
- REFERENCE_SEARCH_DEBOUNCE_MS,
138
- } from "./hooks/reference-limits";
139
- export type {
140
- AiTextActionState,
141
- AiTextMode,
142
- AiTextRewriteStyle,
143
- AiTextRunPayload,
144
- AiTextRunResult,
145
- AiTextUsage,
146
- UseAiTextActionResult,
147
- UseCompletionResult,
148
- } from "./hooks/use-ai-text";
149
- export { AI_TEXT_RUN_QN, useAiTextAction, useCompletion } from "./hooks/use-ai-text";
150
- export type { UseDisclosureResult } from "./hooks/use-disclosure";
151
- export { useDisclosure } from "./hooks/use-disclosure";
152
- export type { UseFormOptions, UseFormResult } from "./hooks/use-form";
153
- export { useForm } from "./hooks/use-form";
154
- export type {
155
- ListSort,
156
- ListSortDir,
157
- ListUrlState,
158
- ListUrlStateApi,
159
- } from "./hooks/use-list-url-state";
160
- export { useListUrlState } from "./hooks/use-list-url-state";
161
- export type { UseMutationResult } from "./hooks/use-mutation";
162
- export { useMutation } from "./hooks/use-mutation";
163
- export type { UseQueryOptions, UseQueryResult } from "./hooks/use-query";
164
- export { entityFromQueryType, useQuery } from "./hooks/use-query";
165
- export { useStore, useStoreSelector } from "./hooks/use-store";
166
- export type {
167
- StreamStatus,
168
- UseStreamHandlerOptions,
169
- UseStreamHandlerResult,
170
- } from "./hooks/use-stream-handler";
171
- export { useStreamHandler } from "./hooks/use-stream-handler";
172
- export type {
173
- LocaleProviderProps,
174
- TranslationBundle,
175
- TranslationsByKey,
176
- TranslationsByLocale,
177
- } from "./i18n";
178
- export {
179
- createStaticLocaleResolver,
180
- FormalityProvider,
181
- LocaleProvider,
182
- mergeTranslations,
183
- translationsByLocaleFromKeys,
184
- useFormality,
185
- useLocale,
186
- useOptionalLocale,
187
- useOptionalTranslation,
188
- useTranslation,
189
- } from "./i18n";
190
- export { kumikoDefaultTranslations } from "./i18n-defaults";
191
- export type {
192
- ActionMenuItemSpec,
193
- ActionOverflowMenuProps,
194
- AppPrimitives,
195
- BannerProps,
196
- ButtonProps,
197
- CardOptions,
198
- CardProps,
199
- CardSlots,
200
- CopyButtonProps,
201
- CorePrimitives,
202
- DataTableDateRangeFacet,
203
- DataTableFacet,
204
- DataTableProps,
205
- DataTableRowAction,
206
- DataTableRowActionMode,
207
- DataTableSort,
208
- DataTableSortDir,
209
- DialogProps,
210
- DrawerProps,
211
- EmbeddedListCellType,
212
- EmbeddedListColumn,
213
- EmbeddedListInputProps,
214
- EmbeddedListTotal,
215
- FieldProps,
216
- FillContainerProps,
217
- FormProps,
218
- FormWidth,
219
- GridCellProps,
220
- GridProps,
221
- HeadingProps,
222
- InputProps,
223
- JsonViewProps,
224
- LightboxProps,
225
- LinkProps,
226
- MetricProps,
227
- ModalProps,
228
- PrimitivesProviderProps,
229
- PrimitivesRegistry,
230
- ProgressProps,
231
- ProgressTone,
232
- PromoPanelAction,
233
- PromoPanelProps,
234
- RuntimeRenderer,
235
- SecretRevealProps,
236
- SecretRevealValue,
237
- SectionProps,
238
- ShareButtonProps,
239
- StatusBadgeProps,
240
- StatusTone,
241
- StepBarProps,
242
- StickyActionBarProps,
243
- StickyPrimaryActionMarker,
244
- TabsProps,
245
- TextProps,
246
- WizardStepGroupProps,
247
- } from "./primitives";
248
- export {
249
- PrimitivesProvider,
250
- STICKY_PRIMARY_ACTION_PROP,
251
- shouldRenderActionsIconOnly,
252
- statusToneForValue,
253
- usePrimitives,
254
- } from "./primitives";
255
- export { buildWhatsAppShareUrl } from "./share-links";
256
- export { sortByAccessor } from "./sort-by-accessor";
257
- export type { LiveEvent, LiveEventSubscriber, LiveEventsProviderProps } from "./sse/live-events";
258
- export { LiveEventsProvider, useLiveEvents } from "./sse/live-events";
259
- export type {
260
- AppTokens,
261
- ColorTokens,
262
- CoreTokens,
263
- FontTokens,
264
- RadiusTokens,
265
- ShadowTokens,
266
- SpacingTokens,
267
- ThemeMode,
268
- Tokens,
269
- TokensApi,
270
- TokensProviderProps,
271
- } from "./tokens";
272
- export { cssVarTokens, TokensProvider, useTokenController, useTokens } from "./tokens";