@cosmicdrift/kumiko-renderer-web 0.64.0 → 0.65.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-web",
3
- "version": "0.64.0",
3
+ "version": "0.65.0",
4
4
  "description": "Web-platform bindings for @cosmicdrift/kumiko-renderer. HTML default-primitives, browser history-based navigation, EventSource-backed live events, and a one-call createKumikoApp that mounts the whole stack via react-dom.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -16,9 +16,9 @@
16
16
  "./styles.css": "./src/styles.css"
17
17
  },
18
18
  "dependencies": {
19
- "@cosmicdrift/kumiko-dispatcher-live": "0.57.2",
20
- "@cosmicdrift/kumiko-headless": "0.57.2",
21
- "@cosmicdrift/kumiko-renderer": "0.57.2",
19
+ "@cosmicdrift/kumiko-dispatcher-live": "0.65.0",
20
+ "@cosmicdrift/kumiko-headless": "0.65.0",
21
+ "@cosmicdrift/kumiko-renderer": "0.65.0",
22
22
  "@radix-ui/react-dialog": "^1.1.15",
23
23
  "@radix-ui/react-dropdown-menu": "^2.1.16",
24
24
  "@radix-ui/react-label": "^2.1.8",
@@ -6,9 +6,10 @@
6
6
  // nach Timezone den Vortag.
7
7
 
8
8
  import { describe, expect, mock, test } from "bun:test";
9
- import { fireEvent, render, screen } from "@testing-library/react";
9
+ import { fireEvent, screen } from "@testing-library/react";
10
10
  import userEvent from "@testing-library/user-event";
11
11
  import { DateInput } from "../primitives/date-input";
12
+ import { render } from "./test-utils";
12
13
 
13
14
  describe("DateInput", () => {
14
15
  test("Eingabefeld zeigt locale-numerisches Datum (de-DE)", () => {
@@ -6,9 +6,10 @@
6
6
  // Tick (Counter-Race-Bug).
7
7
 
8
8
  import { describe, expect, test } from "bun:test";
9
- import { act, fireEvent, render, screen } from "@testing-library/react";
9
+ import { act, fireEvent, screen } from "@testing-library/react";
10
10
  import { type ReactNode, useEffect } from "react";
11
11
  import { type ToastOptions, ToastProvider, useToast } from "../primitives/toast";
12
+ import { render } from "./test-utils";
12
13
 
13
14
  // Trigger-Component die im Mount toast() aufruft. So testen wir den
14
15
  // Hook ohne userEvent-Klick-Pfad und ohne fragile timer.
@@ -41,7 +42,7 @@ describe("ToastProvider + useToast", () => {
41
42
  expect(screen.getByText("Copied")).toBeTruthy();
42
43
  });
43
44
 
44
- test("docsUrl: rendert 'Mehr erfahren →' Link mit target=_blank", () => {
45
+ test("docsUrl: rendert Learn-more-Link (i18n-Default) mit target=_blank", () => {
45
46
  render(
46
47
  <ToastProvider>
47
48
  <ToastTrigger
@@ -55,7 +56,7 @@ describe("ToastProvider + useToast", () => {
55
56
  />
56
57
  </ToastProvider>,
57
58
  );
58
- const link = screen.getByRole("link", { name: /Mehr erfahren/i });
59
+ const link = screen.getByRole("link", { name: /Learn more/i });
59
60
  expect(link.getAttribute("href")).toBe("https://docs.kumiko.rocks/errors/stale_state");
60
61
  expect(link.getAttribute("target")).toBe("_blank");
61
62
  expect(link.getAttribute("rel")).toBe("noopener noreferrer");
@@ -7,6 +7,7 @@
7
7
  // Datums-Teil neben dem Uhrzeit-Input. So teilen `date` und `timestamp`
8
8
  // dieselbe Tipp-/Navigations-UX statt zweier divergenter Primitives (#369).
9
9
 
10
+ import { useTranslation } from "@cosmicdrift/kumiko-renderer";
10
11
  import { type ReactNode, useState } from "react";
11
12
  import { cn } from "../lib/cn";
12
13
  import { CalendarPopover } from "./calendar-popover";
@@ -47,6 +48,7 @@ export function DateField({
47
48
  min,
48
49
  max,
49
50
  }: DateFieldProps): ReactNode {
51
+ const t = useTranslation();
50
52
  const resolvedLocale = locale ?? guessLocale();
51
53
  const selected = parseIso(value);
52
54
 
@@ -101,7 +103,7 @@ export function DateField({
101
103
  {...(maxDate !== undefined && { max: maxDate })}
102
104
  {...(disabled !== undefined && { disabled })}
103
105
  {...(hasError !== undefined && { hasError })}
104
- triggerLabel="Kalender öffnen"
106
+ triggerLabel={t("kumiko.field.open-calendar")}
105
107
  />
106
108
  </div>
107
109
  );
@@ -10,6 +10,7 @@
10
10
  // inputValueToTimestamp kapseln die UTC↔Wall-Clock-Umrechnung (Bug-Bash-2,
11
11
  // 2026-06-08) und sind separat getestet.
12
12
 
13
+ import { useTranslation } from "@cosmicdrift/kumiko-renderer";
13
14
  import { type ReactNode, useState } from "react";
14
15
  import { cn } from "../lib/cn";
15
16
  import { DateField } from "./date-field";
@@ -89,6 +90,7 @@ export function TimestampInput({
89
90
  min,
90
91
  max,
91
92
  }: TimestampInputProps): ReactNode {
93
+ const t = useTranslation();
92
94
  const local = timestampToInputValue(value);
93
95
  const isoDate = local !== "" ? local.slice(0, 10) : "";
94
96
  // Uhrzeit ohne gesetztes Datum würde im Wire-Wert verschwinden — lokal
@@ -125,7 +127,7 @@ export function TimestampInput({
125
127
  />
126
128
  <input
127
129
  type="time"
128
- aria-label="Uhrzeit"
130
+ aria-label={t("kumiko.field.time")}
129
131
  disabled={disabled}
130
132
  aria-invalid={hasError === true ? true : undefined}
131
133
  value={effectiveTime}
@@ -7,6 +7,7 @@
7
7
  // Auto-dismiss nach 5s, manuell schließbar via X-Button. Der ARIA-
8
8
  // Live-Region-Setup kommt komplett aus Radix.
9
9
 
10
+ import { useTranslation } from "@cosmicdrift/kumiko-renderer";
10
11
  import * as Primitive from "@radix-ui/react-toast";
11
12
  import { X } from "lucide-react";
12
13
  import {
@@ -29,7 +30,8 @@ export type ToastOptions = {
29
30
  readonly variant?: ToastVariant;
30
31
  // Self-service deep-link (z.B. KumikoError.docsUrl). Wenn gesetzt
31
32
  // rendert der Toast einen "Mehr erfahren →" Link der in neuem Tab
32
- // öffnet. Label override via `docsLinkLabel` (Default: deutsch).
33
+ // öffnet. Label override via `docsLinkLabel` (Default: i18n
34
+ // kumiko.toast.learn-more).
33
35
  readonly docsUrl?: string;
34
36
  readonly docsLinkLabel?: string;
35
37
  };
@@ -116,6 +118,8 @@ function ToastItem({
116
118
  readonly entry: ToastEntry;
117
119
  readonly onClose: () => void;
118
120
  }): ReactNode {
121
+ const t = useTranslation();
122
+ const learnMore = entry.docsLinkLabel ?? t("kumiko.toast.learn-more");
119
123
  const variantClass =
120
124
  entry.variant === "destructive"
121
125
  ? "destructive group border-destructive bg-destructive text-destructive-foreground"
@@ -135,7 +139,7 @@ function ToastItem({
135
139
  </Primitive.Description>
136
140
  )}
137
141
  {entry.docsUrl !== undefined && (
138
- <Primitive.Action altText={entry.docsLinkLabel ?? "Mehr erfahren"} asChild>
142
+ <Primitive.Action altText={learnMore} asChild>
139
143
  <a
140
144
  href={entry.docsUrl}
141
145
  target="_blank"
@@ -145,7 +149,7 @@ function ToastItem({
145
149
  "focus:outline-none focus:ring-1 focus:ring-current rounded",
146
150
  )}
147
151
  >
148
- {entry.docsLinkLabel ?? "Mehr erfahren"} →
152
+ {learnMore} →
149
153
  </a>
150
154
  </Primitive.Action>
151
155
  )}
@@ -157,7 +161,7 @@ function ToastItem({
157
161
  "group-hover:opacity-100",
158
162
  "group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50",
159
163
  )}
160
- aria-label="Close"
164
+ aria-label={t("kumiko.dialog.close")}
161
165
  >
162
166
  <X className="h-4 w-4" />
163
167
  </Primitive.Close>