@cosmicdrift/kumiko-renderer 0.53.0 → 0.55.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-renderer",
3
- "version": "0.53.0",
3
+ "version": "0.55.0",
4
4
  "description": "Platform-agnostic React renderer for Kumiko screens. Contains the shared logic — primitives-contract, hooks, KumikoScreen, navigation & SSE abstractions — that any platform-specific renderer (web, native) composes. No DOM, no EventSource, no react-dom.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -97,3 +97,42 @@ describe("RenderField — App-Locale an date durchreichen", () => {
97
97
  if (captured?.kind === "date") expect(captured.locale).toBe("de-DE");
98
98
  });
99
99
  });
100
+
101
+ describe("RenderField — min/max/dateLocale ans Picker-Input durchreichen (#369)", () => {
102
+ test("date-Feld: min/max/dateLocale landen in den InputProps", () => {
103
+ const field: EditFieldViewModel = {
104
+ ...dateField(),
105
+ min: "2020-01-01",
106
+ max: "2026-12-31",
107
+ dateLocale: "en-US",
108
+ };
109
+ renderUnderLocale("de-DE", field);
110
+ expect(captured?.kind).toBe("date");
111
+ if (captured?.kind === "date") {
112
+ expect(captured.min).toBe("2020-01-01");
113
+ expect(captured.max).toBe("2026-12-31");
114
+ // dateLocale (per-Feld) hat Vorrang vor dem App-Locale (de-DE).
115
+ expect(captured.locale).toBe("en-US");
116
+ }
117
+ });
118
+
119
+ test("timestamp-Feld: min/max landen in den InputProps", () => {
120
+ const field: EditFieldViewModel = {
121
+ field: "at",
122
+ label: "Zeitpunkt",
123
+ type: "timestamp",
124
+ value: "",
125
+ visible: true,
126
+ readOnly: false,
127
+ required: false,
128
+ min: "2026-01-01T00:00:00Z",
129
+ max: "2026-12-31T23:59:59Z",
130
+ };
131
+ renderUnderLocale("de-DE", field);
132
+ expect(captured?.kind).toBe("timestamp");
133
+ if (captured?.kind === "timestamp") {
134
+ expect(captured.min).toBe("2026-01-01T00:00:00Z");
135
+ expect(captured.max).toBe("2026-12-31T23:59:59Z");
136
+ }
137
+ });
138
+ });
@@ -252,7 +252,9 @@ function renderInput({
252
252
  {...common}
253
253
  value={stringValue(field.value)}
254
254
  onChange={(v) => onChange(v)}
255
- locale={appLocale}
255
+ locale={field.dateLocale ?? appLocale}
256
+ {...(field.min !== undefined && { min: field.min })}
257
+ {...(field.max !== undefined && { max: field.max })}
256
258
  />
257
259
  );
258
260
  case "timestamp":
@@ -262,7 +264,10 @@ function renderInput({
262
264
  {...common}
263
265
  value={stringValue(field.value)}
264
266
  onChange={(v) => onChange(v)}
267
+ locale={field.dateLocale ?? appLocale}
265
268
  {...(field.wallClock !== undefined && { wallClock: field.wallClock })}
269
+ {...(field.min !== undefined && { min: field.min })}
270
+ {...(field.max !== undefined && { max: field.max })}
266
271
  />
267
272
  );
268
273
  case "select": {
@@ -176,10 +176,14 @@ export type InputProps =
176
176
  readonly name: string;
177
177
  readonly value: string;
178
178
  readonly onChange: (v: string | undefined) => void;
179
- /** Locale für die Datum-Formatierung im Trigger. Default = Browser-
180
- * Locale via navigator.language. Apps mit eigenem LocaleResolver
181
- * können ihren current locale durchreichen. */
179
+ /** Locale für Anzeige UND Eingabe-Parsing. Default = Browser-Locale
180
+ * via navigator.language. Apps mit eigenem LocaleResolver können
181
+ * ihren current locale durchreichen. */
182
182
  readonly locale?: string;
183
+ /** Datumsgrenzen als ISO `yyyy-mm-dd` — begrenzen Picker (Jahres-
184
+ * Dropdown-Range + ausgegraute Tage). */
185
+ readonly min?: string;
186
+ readonly max?: string;
183
187
  readonly disabled?: boolean;
184
188
  readonly required?: boolean;
185
189
  readonly hasError?: boolean;
@@ -267,13 +271,21 @@ export type InputProps =
267
271
  /** ISO-8601 Datetime-String. UTC-Instant mit `Z`
268
272
  * ("2026-04-25T13:45:00Z") oder Wall-Clock ohne Offset
269
273
  * ("2026-04-25T13:45", nur bei wallClock). Empty-State = `""`.
270
- * Web nutzt `<input type="datetime-local">` und konvertiert. */
274
+ * Web rendert getrennte Datums- (tippbar + Kalender) und
275
+ * Uhrzeit-Eingabe und konvertiert. */
271
276
  readonly value: string;
272
277
  readonly onChange: (v: string | undefined) => void;
273
278
  /** true = locatedTimestamp (Wall-Clock ohne Offset, Server
274
279
  * validiert z.iso.datetime({local:true})). false/undefined =
275
280
  * UTC-Instant, onChange MUSS mit `Z`-Suffix emittieren. */
276
281
  readonly wallClock?: boolean;
282
+ /** Locale für Anzeige UND Eingabe-Parsing des Datums-Teils.
283
+ * Default = Browser-Locale. */
284
+ readonly locale?: string;
285
+ /** Datumsgrenzen als ISO-Datetime — begrenzen den Kalender auf
286
+ * Tages-Granularität. */
287
+ readonly min?: string;
288
+ readonly max?: string;
277
289
  readonly disabled?: boolean;
278
290
  readonly required?: boolean;
279
291
  readonly hasError?: boolean;