@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
@@ -1,195 +0,0 @@
1
- // Regression #1834: field types without a dedicated widget (embedded
2
- // without embeddedListCells, jsonb, files, images) must render read-only
3
- // instead of falling back to a text input. The old default-branch
4
- // fallback ran the value through stringValue() — an object/array turned
5
- // into "[object Object]"/"a,b", and saving that overwrote the real data.
6
- // #1925 gave multiSelect a real combobox widget (so it dropped out of this
7
- // list) and moved files/images in (no multi-upload widget yet, deliberately
8
- // deferred — they used to hit the same text-input corruption via the
9
- // default branch).
10
- //
11
- // Capture-Input/Banner instead of real primitives, same pattern as
12
- // render-field-app-locale.test.tsx.
13
-
14
- import { describe, expect, test } from "bun:test";
15
- import type { EditFieldViewModel } from "@cosmicdrift/kumiko-headless";
16
- import { render } from "@testing-library/react";
17
- import type { ComponentType, ReactNode } from "react";
18
- import { createStaticLocaleResolver, LocaleProvider } from "../../i18n";
19
- import { kumikoDefaultTranslations } from "../../i18n-defaults";
20
- import {
21
- type BannerProps,
22
- type CorePrimitives,
23
- type InputProps,
24
- PrimitivesProvider,
25
- } from "../../primitives";
26
- import { RenderField } from "../render-field";
27
-
28
- let capturedInput: InputProps | undefined;
29
- let capturedBanner: BannerProps | undefined;
30
- const captureInput: ComponentType<InputProps> = (props) => {
31
- capturedInput = props;
32
- return null;
33
- };
34
- const captureBanner: ComponentType<BannerProps> = (props) => {
35
- capturedBanner = props;
36
- return null;
37
- };
38
- const noop = (): ReactNode => null;
39
- const passChildren = ({ children }: { readonly children?: ReactNode }): ReactNode => children;
40
-
41
- const testPrimitives: CorePrimitives = {
42
- Button: noop,
43
- Banner: captureBanner,
44
- Field: passChildren,
45
- Input: captureInput,
46
- DataTable: noop,
47
- Form: noop,
48
- Section: noop,
49
- Card: noop,
50
- Grid: noop,
51
- GridCell: noop,
52
- Text: noop,
53
- Heading: noop,
54
- Dialog: noop,
55
- Modal: noop,
56
- Lightbox: noop,
57
- ConfigSourceBadge: noop,
58
- ConfigCascadeView: noop,
59
- Link: noop,
60
- };
61
-
62
- function baseField(overrides: Partial<EditFieldViewModel>): EditFieldViewModel {
63
- return {
64
- field: "positions",
65
- label: "Positionen",
66
- type: "text",
67
- value: null,
68
- visible: true,
69
- readOnly: false,
70
- required: false,
71
- ...overrides,
72
- };
73
- }
74
-
75
- function renderField(field: EditFieldViewModel): void {
76
- capturedInput = undefined;
77
- capturedBanner = undefined;
78
- render(
79
- <LocaleProvider
80
- resolver={createStaticLocaleResolver({ locale: "en" })}
81
- fallbackBundles={[kumikoDefaultTranslations]}
82
- >
83
- <PrimitivesProvider value={testPrimitives}>
84
- <RenderField field={field} onChange={() => {}} />
85
- </PrimitivesProvider>
86
- </LocaleProvider>,
87
- );
88
- }
89
-
90
- describe.each([
91
- ["embedded (kein embeddedListCells)", baseField({ type: "embedded", value: { note: "x" } })],
92
- ["jsonb", baseField({ type: "jsonb", value: { a: 1 } })],
93
- ["files", baseField({ type: "files", value: ["11111111-1111-1111-1111-111111111111"] })],
94
- ["images", baseField({ type: "images", value: ["11111111-1111-1111-1111-111111111111"] })],
95
- ])("RenderField — %s ohne Widget", (_name, field) => {
96
- test("rendert einen schreibgeschützten Banner statt eines editierbaren Text-Inputs", () => {
97
- renderField(field);
98
- expect(capturedInput).toBeUndefined();
99
- expect(capturedBanner).toBeDefined();
100
- expect(capturedBanner?.variant).toBe("info");
101
- // The surrounding <Field> always renders a <label htmlFor={id}> —
102
- // without an id on the Banner itself that label points at nothing (#1834 review).
103
- expect(capturedBanner?.id).toBe("kumiko-edit-positions");
104
- });
105
-
106
- // #1847#6: the Banner used to show only the generic hint, hiding the
107
- // actual field value from the user entirely (not even read-only).
108
- test("shows the underlying value read-only alongside the generic hint", () => {
109
- renderField(field);
110
- const children = capturedBanner?.children;
111
- const childArray = Array.isArray(children) ? children : [children];
112
- expect(childArray[0]).toBe("This field type can't be edited here yet.");
113
- const valuePreview = childArray[1] as { props: { children: unknown } } | false | undefined;
114
- if (!valuePreview) throw new Error("expected a value-preview element");
115
- expect(valuePreview.props.children).toBe(JSON.stringify(field.value));
116
- });
117
- });
118
-
119
- describe("RenderField — unsupported-type Banner ohne Wert", () => {
120
- test("kein Value-Preview-Element wenn field.value leer ist", () => {
121
- renderField(baseField({ type: "jsonb", value: null }));
122
- const children = capturedBanner?.children;
123
- const childArray = Array.isArray(children) ? children : [children];
124
- expect(childArray[0]).toBe("This field type can't be edited here yet.");
125
- expect(childArray[1]).toBeFalsy();
126
- });
127
- });
128
-
129
- describe("RenderField — text bleibt weiterhin editierbar", () => {
130
- test("plain text-Feld rendert weiterhin ein Text-Input, kein Banner", () => {
131
- renderField(baseField({ type: "text", value: "hallo" }));
132
- expect(capturedBanner).toBeUndefined();
133
- expect(capturedInput).toBeDefined();
134
- expect(capturedInput?.kind).toBe("text");
135
- });
136
- });
137
-
138
- // #1925: field types that gained a real widget on the auto-wired
139
- // entityEdit path (previously either no widget at all or a type-mismatched
140
- // text-input fallback).
141
- describe("RenderField — #1925 neue Widgets", () => {
142
- test("multiSelect rendert eine Multi-Combobox statt eines Banners", () => {
143
- renderField(
144
- baseField({
145
- type: "multiSelect",
146
- value: ["a"],
147
- options: ["a", "b"],
148
- }),
149
- );
150
- expect(capturedBanner).toBeUndefined();
151
- expect(capturedInput).toBeDefined();
152
- expect(capturedInput?.kind).toBe("combobox");
153
- if (capturedInput?.kind !== "combobox") return;
154
- expect(capturedInput.multiple).toBe(true);
155
- expect(capturedInput.value).toEqual(["a"]);
156
- expect(capturedInput.options).toEqual([
157
- { value: "a", label: "a" },
158
- { value: "b", label: "b" },
159
- ]);
160
- });
161
-
162
- test("decimal rendert ein number-Input statt Text (kein String-Fallback mehr)", () => {
163
- renderField(baseField({ type: "decimal", value: 12.5 }));
164
- expect(capturedBanner).toBeUndefined();
165
- expect(capturedInput).toBeDefined();
166
- expect(capturedInput?.kind).toBe("number");
167
- if (capturedInput?.kind !== "number") return;
168
- expect(capturedInput.value).toBe(12.5);
169
- });
170
-
171
- test("bigInt rendert ein number-Input statt Text (kein String-Fallback mehr)", () => {
172
- renderField(baseField({ type: "bigInt", value: 42 }));
173
- expect(capturedBanner).toBeUndefined();
174
- expect(capturedInput).toBeDefined();
175
- expect(capturedInput?.kind).toBe("number");
176
- if (capturedInput?.kind !== "number") return;
177
- expect(capturedInput.value).toBe(42);
178
- });
179
-
180
- test("tz rendert ein dediziertes tz-Input statt Text", () => {
181
- renderField(baseField({ type: "tz", value: "Europe/Berlin" }));
182
- expect(capturedBanner).toBeUndefined();
183
- expect(capturedInput).toBeDefined();
184
- expect(capturedInput?.kind).toBe("tz");
185
- if (capturedInput?.kind !== "tz") return;
186
- expect(capturedInput.value).toBe("Europe/Berlin");
187
- });
188
-
189
- test("longText rendert immer ein textarea, auch ohne explizites multiline-Flag", () => {
190
- renderField(baseField({ type: "longText", value: "lange Notiz" }));
191
- expect(capturedBanner).toBeUndefined();
192
- expect(capturedInput).toBeDefined();
193
- expect(capturedInput?.kind).toBe("textarea");
194
- });
195
- });
@@ -1,146 +0,0 @@
1
- // ToolbarActionView collapses a group of >2 icon-carrying toolbar actions to
2
- // icon-only buttons (`shouldRenderActionsIconOnly`). The button then has no
3
- // accessible name from its children, so the label has to move to `ariaLabel`
4
- // and must NOT stay in the children — otherwise the text renders inside a
5
- // button sized for an icon.
6
-
7
- import { describe, expect, test } from "bun:test";
8
- import type {
9
- EntityDefinition,
10
- EntityListScreenDefinition,
11
- } from "@cosmicdrift/kumiko-framework/ui-types";
12
- import { render, screen as rtlScreen } from "@testing-library/react";
13
- import type { ComponentType, ReactNode } from "react";
14
- import { createStaticLocaleResolver, LocaleProvider } from "../../i18n";
15
- import { kumikoDefaultTranslations } from "../../i18n-defaults";
16
- import {
17
- type ButtonProps,
18
- type CorePrimitives,
19
- type DataTableProps,
20
- PrimitivesProvider,
21
- } from "../../primitives";
22
- import { RenderList, type ToolbarActionButton } from "../render-list";
23
-
24
- const TestButton: ComponentType<ButtonProps> = ({ children, onClick, testId, ariaLabel, size }) => (
25
- <button
26
- type="button"
27
- data-testid={testId}
28
- data-size={size ?? "md"}
29
- aria-label={ariaLabel}
30
- onClick={() => {
31
- void onClick?.();
32
- }}
33
- >
34
- {children}
35
- </button>
36
- );
37
-
38
- const toolbarOnlyDataTable: ComponentType<DataTableProps> = ({ toolbarEnd }) => (
39
- <div>{toolbarEnd}</div>
40
- );
41
-
42
- const noop = (): ReactNode => null;
43
- const passChildren = ({ children }: { readonly children?: ReactNode }): ReactNode => children;
44
-
45
- const testPrimitives: CorePrimitives = {
46
- Button: TestButton,
47
- Banner: passChildren,
48
- Field: passChildren,
49
- Input: noop,
50
- DataTable: toolbarOnlyDataTable,
51
- Form: passChildren,
52
- Section: passChildren,
53
- Card: passChildren,
54
- Grid: passChildren,
55
- GridCell: passChildren,
56
- Text: passChildren,
57
- Heading: noop,
58
- Dialog: noop,
59
- Modal: noop,
60
- Lightbox: noop,
61
- ConfigSourceBadge: noop,
62
- ConfigCascadeView: noop,
63
- Link: noop,
64
- };
65
-
66
- const entity: EntityDefinition = {
67
- fields: {
68
- name: { type: "text", maxLength: 50, required: false, searchable: false, sortable: false },
69
- },
70
- };
71
-
72
- const listScreen: EntityListScreenDefinition = {
73
- id: "widget-list",
74
- type: "entityList",
75
- entity: "widget",
76
- columns: ["name"],
77
- };
78
-
79
- function toolbarAction(id: string, label: string, withIcon: boolean): ToolbarActionButton {
80
- return {
81
- id,
82
- label,
83
- onTrigger: () => {},
84
- ...(withIcon && { icon: "archive" as const }),
85
- };
86
- }
87
-
88
- function renderToolbar(actions: readonly ToolbarActionButton[]): void {
89
- render(
90
- <LocaleProvider
91
- resolver={createStaticLocaleResolver({ locale: "en" })}
92
- fallbackBundles={[kumikoDefaultTranslations]}
93
- >
94
- <PrimitivesProvider value={testPrimitives}>
95
- <RenderList
96
- screen={listScreen}
97
- entity={entity}
98
- rows={[]}
99
- featureName="toolbar-fixture"
100
- toolbarActions={actions}
101
- />
102
- </PrimitivesProvider>
103
- </LocaleProvider>,
104
- );
105
- }
106
-
107
- describe("RenderList toolbar actions collapse to icon-only", () => {
108
- test("three icon actions render buttons with no visible text but an aria-label", () => {
109
- renderToolbar([
110
- toolbarAction("sync", "Sync", true),
111
- toolbarAction("export", "Export", true),
112
- toolbarAction("archive", "Archive", true),
113
- ]);
114
-
115
- for (const [id, label] of [
116
- ["sync", "Sync"],
117
- ["export", "Export"],
118
- ["archive", "Archive"],
119
- ] as const) {
120
- const button = rtlScreen.getByTestId(`render-list-toolbar-action-${id}`);
121
- expect(button.getAttribute("data-size")).toBe("icon");
122
- expect(button.getAttribute("aria-label")).toBe(label);
123
- expect(button.textContent).toBe("");
124
- }
125
- });
126
-
127
- test("two actions stay on text buttons carrying the label as children", () => {
128
- renderToolbar([toolbarAction("sync", "Sync", true), toolbarAction("export", "Export", true)]);
129
-
130
- const button = rtlScreen.getByTestId("render-list-toolbar-action-sync");
131
- expect(button.getAttribute("data-size")).toBe("md");
132
- expect(button.textContent).toBe("Sync");
133
- });
134
-
135
- test("an icon-less member keeps the whole group on text buttons", () => {
136
- renderToolbar([
137
- toolbarAction("sync", "Sync", true),
138
- toolbarAction("export", "Export", true),
139
- toolbarAction("archive", "Archive", false),
140
- ]);
141
-
142
- const button = rtlScreen.getByTestId("render-list-toolbar-action-sync");
143
- expect(button.getAttribute("data-size")).toBe("md");
144
- expect(button.textContent).toBe("Sync");
145
- });
146
- });