@eifi1/ui-kit 0.17.0 → 0.18.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 (167) hide show
  1. package/README.md +29 -4
  2. package/dist/chart.d.ts +10 -1
  3. package/dist/components/account-chips.d.ts +153 -0
  4. package/dist/components/account-chips.js +135 -0
  5. package/dist/components/account-chips.js.map +1 -0
  6. package/dist/components/account-settings-labels.d.ts +10 -2
  7. package/dist/components/account-settings-labels.js +3 -0
  8. package/dist/components/account-settings-labels.js.map +1 -1
  9. package/dist/components/amount-input.d.ts +10 -1
  10. package/dist/components/button-group.d.ts +10 -1
  11. package/dist/components/calculator.d.ts +10 -1
  12. package/dist/components/chip.d.ts +25 -1
  13. package/dist/components/chip.js +143 -6
  14. package/dist/components/chip.js.map +1 -1
  15. package/dist/components/confirm-dialog.d.ts +42 -1
  16. package/dist/components/confirm-dialog.js +36 -5
  17. package/dist/components/confirm-dialog.js.map +1 -1
  18. package/dist/components/copy-button.d.ts +10 -1
  19. package/dist/components/danger-confirm.d.ts +55 -4
  20. package/dist/components/danger-confirm.js +67 -30
  21. package/dist/components/danger-confirm.js.map +1 -1
  22. package/dist/components/data-table-cells.d.ts +1 -1
  23. package/dist/components/data-table-filter-popover.d.ts +1 -1
  24. package/dist/components/data-table-filters.d.ts +1 -1
  25. package/dist/components/data-table.d.ts +1 -1
  26. package/dist/components/data-table.js +2 -0
  27. package/dist/components/data-table.js.map +1 -1
  28. package/dist/components/facing-pair.d.ts +10 -1
  29. package/dist/components/file-button.d.ts +10 -1
  30. package/dist/components/file-dropzone.d.ts +10 -1
  31. package/dist/components/form-actions.d.ts +10 -1
  32. package/dist/components/form-actions.js +3 -0
  33. package/dist/components/form-actions.js.map +1 -1
  34. package/dist/components/money-field.d.ts +10 -1
  35. package/dist/components/number-field.d.ts +11 -2
  36. package/dist/components/number-field.js +23 -22
  37. package/dist/components/number-field.js.map +1 -1
  38. package/dist/components/number-input.d.ts +10 -1
  39. package/dist/components/numpad-sheet.d.ts +10 -1
  40. package/dist/components/passkeys-setting.d.ts +27 -1
  41. package/dist/components/passkeys-setting.js +31 -5
  42. package/dist/components/passkeys-setting.js.map +1 -1
  43. package/dist/components/progress-bar.d.ts +15 -1
  44. package/dist/components/progress-bar.js +8 -1
  45. package/dist/components/progress-bar.js.map +1 -1
  46. package/dist/components/reauth-dialog.d.ts +90 -0
  47. package/dist/components/reauth-dialog.js +158 -0
  48. package/dist/components/reauth-dialog.js.map +1 -0
  49. package/dist/components/series-chart.d.ts +10 -1
  50. package/dist/components/server-wake.d.ts +58 -0
  51. package/dist/components/server-wake.js +58 -0
  52. package/dist/components/server-wake.js.map +1 -0
  53. package/dist/components/settings-fields.d.ts +10 -1
  54. package/dist/components/share-card.d.ts +61 -0
  55. package/dist/components/share-card.js +350 -0
  56. package/dist/components/share-card.js.map +1 -0
  57. package/dist/components/status-dot.d.ts +2 -0
  58. package/dist/components/text-link.d.ts +10 -1
  59. package/dist/components/time-input.d.ts +10 -1
  60. package/dist/components/toast.d.ts +10 -1
  61. package/dist/components/toast.js +42 -2
  62. package/dist/components/toast.js.map +1 -1
  63. package/dist/components/toggle-group.js +5 -2
  64. package/dist/components/toggle-group.js.map +1 -1
  65. package/dist/components/ui.d.ts +10 -1
  66. package/dist/components/ui.js +43 -28
  67. package/dist/components/ui.js.map +1 -1
  68. package/dist/components/use-table-state.d.ts +1 -1
  69. package/dist/components/user-avatar.d.ts +2 -0
  70. package/dist/components/write-lock.d.ts +68 -0
  71. package/dist/components/write-lock.js +33 -0
  72. package/dist/components/write-lock.js.map +1 -0
  73. package/dist/{data-table-CpkWUJBY.d.ts → data-table-3mi2R3so.d.ts} +19 -1
  74. package/dist/data-table.d.ts +1 -1
  75. package/dist/hooks/use-file-drop.d.ts +10 -1
  76. package/dist/hooks/use-overlay-history.js +16 -0
  77. package/dist/hooks/use-overlay-history.js.map +1 -1
  78. package/dist/i18n/defaults.d.ts +10 -1
  79. package/dist/i18n/defaults.js +11 -1
  80. package/dist/i18n/defaults.js.map +1 -1
  81. package/dist/i18n/german.d.ts +78 -0
  82. package/dist/i18n/{locales/de.js → german.js} +59 -9
  83. package/dist/i18n/german.js.map +1 -0
  84. package/dist/i18n/kit-labels.d.ts +10 -1
  85. package/dist/i18n/kit-labels.js +5 -0
  86. package/dist/i18n/kit-labels.js.map +1 -1
  87. package/dist/i18n/locales/de-CH.d.ts +23 -8
  88. package/dist/i18n/locales/de-CH.js +7 -3
  89. package/dist/i18n/locales/de-CH.js.map +1 -1
  90. package/dist/i18n/locales/en.d.ts +10 -1
  91. package/dist/i18n/locales/es.d.ts +10 -1
  92. package/dist/i18n/locales/es.js +51 -1
  93. package/dist/i18n/locales/es.js.map +1 -1
  94. package/dist/i18n/locales/fr.d.ts +10 -1
  95. package/dist/i18n/locales/fr.js +51 -1
  96. package/dist/i18n/locales/fr.js.map +1 -1
  97. package/dist/i18n/locales/hu.d.ts +10 -1
  98. package/dist/i18n/locales/hu.js +54 -1
  99. package/dist/i18n/locales/hu.js.map +1 -1
  100. package/dist/i18n/locales/it.d.ts +10 -1
  101. package/dist/i18n/locales/it.js +51 -1
  102. package/dist/i18n/locales/it.js.map +1 -1
  103. package/dist/i18n/locales/zh.d.ts +10 -1
  104. package/dist/i18n/locales/zh.js +50 -1
  105. package/dist/i18n/locales/zh.js.map +1 -1
  106. package/dist/i18n/swiss.d.ts +3 -3
  107. package/dist/i18n/swiss.js.map +1 -1
  108. package/dist/index.d.ts +9 -4
  109. package/dist/index.js +33 -1
  110. package/dist/index.js.map +1 -1
  111. package/dist/{kit-labels-C4uB_zmg.d.ts → kit-labels-CPbsjlXr.d.ts} +229 -9
  112. package/dist/lib/server-wake.d.ts +130 -0
  113. package/dist/lib/server-wake.js +121 -0
  114. package/dist/lib/server-wake.js.map +1 -0
  115. package/dist/rhf/fields.d.ts +10 -1
  116. package/dist/rhf/form.d.ts +10 -1
  117. package/dist/rhf.d.ts +10 -1
  118. package/dist/search/global-search.d.ts +3 -1
  119. package/dist/search/global-search.js.map +1 -1
  120. package/dist/shell/app-shell.d.ts +10 -1
  121. package/dist/shell/top-bar-brand.d.ts +10 -1
  122. package/dist/shell/topbar-action-menu.d.ts +2 -0
  123. package/dist/shell.d.ts +10 -1
  124. package/dist/wizard/stepper-nav.d.ts +10 -1
  125. package/dist/wizard.d.ts +10 -1
  126. package/package.json +1 -1
  127. package/src/components/account-chips.tsx +302 -0
  128. package/src/components/account-settings-labels.ts +16 -2
  129. package/src/components/chip.tsx +239 -6
  130. package/src/components/confirm-dialog.tsx +82 -7
  131. package/src/components/danger-confirm.tsx +118 -33
  132. package/src/components/data-table.tsx +20 -0
  133. package/src/components/form-actions.tsx +22 -3
  134. package/src/components/number-field.tsx +32 -26
  135. package/src/components/passkeys-setting.tsx +68 -7
  136. package/src/components/progress-bar.tsx +21 -1
  137. package/src/components/reauth-dialog.tsx +273 -0
  138. package/src/components/server-wake.tsx +124 -0
  139. package/src/components/share-card.tsx +615 -0
  140. package/src/components/toast.tsx +72 -2
  141. package/src/components/toggle-group.tsx +5 -2
  142. package/src/components/ui.tsx +89 -32
  143. package/src/components/write-lock.tsx +96 -0
  144. package/src/hooks/use-overlay-history.ts +51 -0
  145. package/src/i18n/defaults.ts +10 -0
  146. package/src/i18n/{locales/de.ts → german.ts} +68 -13
  147. package/src/i18n/kit-labels.tsx +22 -2
  148. package/src/i18n/locales/de-CH.ts +17 -8
  149. package/src/i18n/locales/es.ts +51 -0
  150. package/src/i18n/locales/fr.ts +52 -0
  151. package/src/i18n/locales/hu.ts +55 -0
  152. package/src/i18n/locales/it.ts +51 -0
  153. package/src/i18n/locales/zh.ts +50 -0
  154. package/src/i18n/swiss.ts +3 -3
  155. package/src/index.ts +23 -1
  156. package/src/lib/server-wake.ts +270 -0
  157. package/src/search/global-search.tsx +3 -1
  158. package/dist/i18n/locales/de-CH-informal.d.ts +0 -61
  159. package/dist/i18n/locales/de-CH-informal.js +0 -8
  160. package/dist/i18n/locales/de-CH-informal.js.map +0 -1
  161. package/dist/i18n/locales/de-informal.d.ts +0 -82
  162. package/dist/i18n/locales/de-informal.js +0 -37
  163. package/dist/i18n/locales/de-informal.js.map +0 -1
  164. package/dist/i18n/locales/de.d.ts +0 -66
  165. package/dist/i18n/locales/de.js.map +0 -1
  166. package/src/i18n/locales/de-CH-informal.ts +0 -10
  167. package/src/i18n/locales/de-informal.ts +0 -61
@@ -1,16 +1,20 @@
1
- import { formatFileSize } from "../kit-labels";
2
- import type { UiKitLabels } from "../kit-labels";
1
+ import { formatFileSize } from "./kit-labels";
2
+ import type { UiKitLabels } from "./kit-labels";
3
3
 
4
4
  /**
5
- * The kit's words in German: every namespace of {@link UiKitLabels}, for
6
- * `<UiKitProvider labels={UI_KIT_LABELS_DE}>`.
5
+ * The kit's German, formal ("Sie"), written in standard spelling with "ß" — the SOURCE
6
+ * the public `de-CH` catalogue is derived from (via `swiss()`), not a catalogue itself.
7
7
  *
8
- * Self-contained on purpose — nothing but the kit's own `formatFileSize` — so it works
9
- * as a starting point to copy and adjust. Counts and sizes are formatted with
10
- * `de-DE` digits; {@link uiKitLabelsDe} takes another number locale
11
- * (e.g. `"de-CH"` for 1’234) without touching the words.
8
+ * Internal on purpose: it lives outside `src/i18n/locales/` because every file there is
9
+ * a public `@eifi1/ui-kit/i18n/<code>` subpath, and the kit ships ONE German — Swiss,
10
+ * formal (0.18.0 removed `/i18n/de`, `/i18n/de-informal` and `/i18n/de-CH-informal`).
11
+ * The text stays written with "ß" because `swiss()` respells at runtime, so a Swiss app
12
+ * also gets an argument it passes in (a file name, a phrase to type) respelled; writing
13
+ * "ss" here instead would change that behaviour for every function label.
14
+ *
15
+ * Counts and sizes are formatted with `numberLocale`'s digits; the words never change.
12
16
  */
13
- export function uiKitLabelsDe(numberLocale = "de-DE"): UiKitLabels {
17
+ export function germanLabels(numberLocale: string): UiKitLabels {
14
18
  const num = new Intl.NumberFormat(numberLocale);
15
19
  const n = (value: number) => num.format(value);
16
20
 
@@ -40,8 +44,8 @@ export function uiKitLabelsDe(numberLocale = "de-DE"): UiKitLabels {
40
44
  thread: "Kommentare",
41
45
  empty: "Noch keine Kommentare",
42
46
  loading: "Kommentare werden geladen…",
43
- // The reader's own messages. "Ich" rather than "Sie"/"Du": it is the same word in
44
- // both registers, so the informal catalogue inherits it unchanged.
47
+ // The reader's own messages. "Ich" rather than "Sie": it reads the same whether
48
+ // the app addresses its users with "Sie" or "du", so neither has to override it.
45
49
  you: "Ich",
46
50
  staff: "Team",
47
51
  attachments: "Anhänge",
@@ -91,6 +95,7 @@ export function uiKitLabelsDe(numberLocale = "de-DE"): UiKitLabels {
91
95
  passkeys: {
92
96
  title: "Passkeys",
93
97
  description: "Mit Fingerabdruck, Gesichtserkennung oder Geräte-PIN statt Passwort anmelden.",
98
+ descriptionAlongside: "Mit Fingerabdruck, Gesichtserkennung oder Geräte-PIN anmelden. Das Passwort funktioniert weiterhin.",
94
99
  empty: "Noch keine Passkeys",
95
100
  loading: "Passkeys werden geladen…",
96
101
  list: "Registrierte Passkeys",
@@ -506,6 +511,7 @@ export function uiKitLabelsDe(numberLocale = "de-DE"): UiKitLabels {
506
511
  confirmDialog: {
507
512
  confirm: "Bestätigen",
508
513
  cancel: "Abbrechen",
514
+ typed: (text) => `Geben Sie zur Bestätigung „${text}“ ein`,
509
515
  },
510
516
  floatingPanel: {
511
517
  close: "Schließen",
@@ -591,7 +597,56 @@ export function uiKitLabelsDe(numberLocale = "de-DE"): UiKitLabels {
591
597
  noPreview: "Für diese Datei ist keine Vorschau verfügbar",
592
598
  openInNewTab: "In neuem Tab öffnen",
593
599
  },
600
+ writeLock: {
601
+ // Impersonal, like the rest of this catalogue where it can be: an app that
602
+ // addresses its users with "du" then has fewer keys to override.
603
+ reason: "Nur zum Ansehen – Änderungen sind hier nicht möglich.",
604
+ },
605
+ accountState: {
606
+ active: "Aktiv",
607
+ inactive: "Inaktiv",
608
+ invited: "Eingeladen",
609
+ registered: "Registriert",
610
+ unverified: "Nicht bestätigt",
611
+ passwordChange: "Passwortänderung erforderlich",
612
+ },
613
+ shareCard: {
614
+ dialogTitle: "Teilen",
615
+ close: "Schließen",
616
+ email: "E-Mail-Adresse",
617
+ emailOptional: "E-Mail-Adresse (optional)",
618
+ // example.com is reserved for examples (RFC 2606); a German-looking domain is
619
+ // somebody's real one.
620
+ emailPlaceholder: "name@example.com",
621
+ invalidEmail: "Bitte eine vollständige E-Mail-Adresse eingeben.",
622
+ role: "Rolle",
623
+ roleOf: (name) => `Rolle von ${name}`,
624
+ add: "Teilen",
625
+ whoHasAccess: "Wer hat Zugriff",
626
+ nobodyYet: "Bisher hat niemand sonst Zugriff.",
627
+ pending: "Ausstehend",
628
+ openInvite: "Offener Einladungslink",
629
+ copyLink: "Link kopieren",
630
+ team: "Team",
631
+ teamHint: (name) => `Alle in ${name} erhalten Zugriff.`,
632
+ remove: "Zugriff entfernen",
633
+ removeConfirm: (name) => `Zugriff für ${name} entfernen?`,
634
+ revokePending: "Einladung zurückziehen",
635
+ revokePendingConfirm: (name) => `Einladung für ${name} zurückziehen?`,
636
+ failed: "Das hat nicht geklappt. Bitte erneut versuchen.",
637
+ loading: "Wird geladen…",
638
+ },
639
+ reauthDialog: {
640
+ title: "Identität bestätigen",
641
+ description: "Zum Fortfahren das aktuelle Passwort eingeben.",
642
+ password: "Aktuelles Passwort",
643
+ submit: "Weiter",
644
+ cancel: "Abbrechen",
645
+ },
646
+ serverWake: {
647
+ slow: "Lädt noch – das dauert länger als sonst.",
648
+ waking: (appName) =>
649
+ `Der Server schläft ein, wenn ${appName ?? "die App"} gerade niemand benutzt. Die erste Anfrage nach einer Pause muss ihn erst wieder starten. Das kann einen Moment dauern – es geht nichts verloren, die Seite füllt sich von selbst.`,
650
+ },
594
651
  };
595
652
  }
596
-
597
- export const UI_KIT_LABELS_DE: UiKitLabels = uiKitLabelsDe();
@@ -46,6 +46,11 @@ import type { ErrorBoundaryLabels } from "../components/error-boundary";
46
46
  import type { AuthedImageLabels } from "../components/authed-image";
47
47
  import type { ImageGridLabels } from "../components/image-grid";
48
48
  import type { LightboxLabels } from "../components/lightbox";
49
+ import type { WriteLockLabels } from "../components/write-lock";
50
+ import type { AccountStateLabels } from "../components/account-chips";
51
+ import type { ShareCardLabels } from "../components/share-card";
52
+ import type { ReauthDialogLabels } from "../components/reauth-dialog";
53
+ import type { ServerWakeLabels } from "../components/server-wake";
49
54
 
50
55
  /**
51
56
  * EVERY string the kit renders, as one typed tree — and an optional provider that
@@ -274,6 +279,14 @@ export interface UiKitLabels {
274
279
  authedImage: AuthedImageLabels;
275
280
  imageGrid: ImageGridLabels;
276
281
  lightbox: LightboxLabels;
282
+ /** 0.18.0: `WriteLockProvider`'s fallback reason, `AccountStateChip`, `SharePanel` /
283
+ * `ShareCard` / `ShareDialog`, `ReauthDialog`. */
284
+ writeLock: WriteLockLabels;
285
+ accountState: AccountStateLabels;
286
+ shareCard: ShareCardLabels;
287
+ reauthDialog: ReauthDialogLabels;
288
+ /** 0.18.0: `ServerWakeNotice` — keksdose's cold-start notice, for every app. */
289
+ serverWake: ServerWakeLabels;
277
290
  }
278
291
 
279
292
  /**
@@ -621,17 +634,24 @@ export function useKitFileLabels(prop?: Partial<FileLabels>): FileLabels {
621
634
  * The dot paths of every key `labels` does NOT supply — the ones a translated app is
622
635
  * still showing in English. Assert on it in the app's own test:
623
636
  *
624
- * expect(missingKitLabels(de)).toEqual([]);
637
+ * expect(missingKitLabels(labels, DEFAULT_UI_KIT_LABELS)).toEqual([]);
625
638
  *
626
639
  * `reference` is the complete tree to check against — pass
627
640
  * {@link DEFAULT_UI_KIT_LABELS} (src/i18n/defaults.ts). It is a parameter rather than an import
628
641
  * because the defaults live beside their components, and this module is imported BY
629
- * those components.
642
+ * those components. Left out (a test file is not type-checked), it throws saying so
643
+ * rather than "Cannot convert undefined or null to object" (keksdose, 0.18).
630
644
  */
631
645
  export function missingKitLabels(
632
646
  labels: UiKitLabelOverrides | undefined,
633
647
  reference: UiKitLabels,
634
648
  ): string[] {
649
+ if (!isRecord(reference)) {
650
+ throw new TypeError(
651
+ "missingKitLabels(labels, reference): pass DEFAULT_UI_KIT_LABELS as the reference — " +
652
+ "it is the tree the labels are checked against.",
653
+ );
654
+ }
635
655
  const missing: string[] = [];
636
656
  for (const [ns, keys] of Object.entries(reference)) {
637
657
  const given = (labels as Record<string, Record<string, unknown> | undefined> | undefined)?.[ns];
@@ -1,15 +1,24 @@
1
1
  import type { UiKitLabels } from "../kit-labels";
2
+ import { germanLabels } from "../german";
2
3
  import { swiss } from "../swiss";
3
- import { uiKitLabelsDe } from "./de";
4
4
 
5
5
  /**
6
- * Swiss Standard German: the German labels with Swiss spelling — "ss" for every "ß"
7
- * (Schliessen, Grösse), which is the one systematic difference in UI text — and
6
+ * The kit's words in German — Swiss Standard German, formal ("Sie"), the kit's ONE German
7
+ * catalogue: `<UiKitProvider labels={UI_KIT_LABELS_DE_CH}>`. Swiss spelling — "ss" for
8
+ * every "ß" (Schliessen, Grösse), which is the one systematic difference in UI text — and
8
9
  * `de-CH` number formatting (1’234.5).
9
10
  *
10
- * Derived rather than duplicated, so a key added to the German labels is Swiss the
11
- * moment it lands. Function labels are wrapped: their RESULT is respelled, so an
12
- * argument the app passes in (a file name, a phrase to type) is respelled too — which
13
- * is what a Swiss app writing "ss" everywhere wants.
11
+ * Derived from the internal German source (`../german`) rather than written out, so a
12
+ * key added there is Swiss the moment it lands. Function labels are wrapped: their
13
+ * RESULT is respelled, so an argument the app passes in (a file name, a phrase to type)
14
+ * is respelled too — which is what a Swiss app writing "ss" everywhere wants.
15
+ *
16
+ * {@link uiKitLabelsDeCh} takes another number locale (e.g. `"de-DE"` for 1.234,5, or
17
+ * `"de-AT"`) without touching the words — the spelling stays Swiss, as the factories of
18
+ * the other catalogues keep their words.
14
19
  */
15
- export const UI_KIT_LABELS_DE_CH: UiKitLabels = swiss(uiKitLabelsDe("de-CH"));
20
+ export function uiKitLabelsDeCh(numberLocale = "de-CH"): UiKitLabels {
21
+ return swiss(germanLabels(numberLocale));
22
+ }
23
+
24
+ export const UI_KIT_LABELS_DE_CH: UiKitLabels = uiKitLabelsDeCh();
@@ -88,6 +88,7 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
88
88
  passkeys: {
89
89
  title: "Llaves de acceso",
90
90
  description: "Inicia sesión con tu huella, tu cara o el PIN del dispositivo en lugar de una contraseña.",
91
+ descriptionAlongside: "Inicia sesión con tu huella, tu cara o el PIN del dispositivo. Tu contraseña sigue funcionando.",
91
92
  empty: "Aún no hay llaves de acceso",
92
93
  loading: "Cargando llaves de acceso…",
93
94
  list: "Tus llaves de acceso",
@@ -495,6 +496,7 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
495
496
  confirmDialog: {
496
497
  confirm: "Confirmar",
497
498
  cancel: "Cancelar",
499
+ typed: (text) => `Escribe «${text}» para confirmar`,
498
500
  },
499
501
  floatingPanel: {
500
502
  close: "Cerrar",
@@ -580,6 +582,55 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
580
582
  noPreview: "No hay vista previa disponible para este archivo",
581
583
  openInNewTab: "Abrir en una pestaña nueva",
582
584
  },
585
+ writeLock: {
586
+ reason: "Puedes verlo, pero no modificarlo.",
587
+ },
588
+ accountState: {
589
+ // Agreeing with "cuenta" (feminine): the chip is the state of an account.
590
+ active: "Activa",
591
+ inactive: "Inactiva",
592
+ invited: "Invitación enviada",
593
+ registered: "Registrada",
594
+ unverified: "Sin verificar",
595
+ passwordChange: "Debe cambiar la contraseña",
596
+ },
597
+ shareCard: {
598
+ dialogTitle: "Compartir",
599
+ close: "Cerrar",
600
+ email: "Correo electrónico",
601
+ emailOptional: "Correo electrónico (opcional)",
602
+ // example.com is reserved for examples (RFC 2606); a localised domain is real.
603
+ emailPlaceholder: "nombre@example.com",
604
+ invalidEmail: "Introduce una dirección de correo completa.",
605
+ role: "Rol",
606
+ roleOf: (name) => `Rol de ${name}`,
607
+ add: "Compartir",
608
+ whoHasAccess: "Quién tiene acceso",
609
+ nobodyYet: "Nadie más tiene acceso todavía.",
610
+ pending: "Pendiente",
611
+ openInvite: "Enlace de invitación abierto",
612
+ copyLink: "Copiar enlace",
613
+ team: "Equipo",
614
+ teamHint: (name) => `Todos los miembros de ${name} tendrán acceso.`,
615
+ remove: "Quitar acceso",
616
+ removeConfirm: (name) => `¿Quitar el acceso a ${name}?`,
617
+ revokePending: "Retirar invitación",
618
+ revokePendingConfirm: (name) => `¿Retirar la invitación para ${name}?`,
619
+ failed: "No ha funcionado. Inténtalo de nuevo.",
620
+ loading: "Cargando…",
621
+ },
622
+ reauthDialog: {
623
+ title: "Confirma que eres tú",
624
+ description: "Introduce tu contraseña actual para continuar.",
625
+ password: "Contraseña actual",
626
+ submit: "Continuar",
627
+ cancel: "Cancelar",
628
+ },
629
+ serverWake: {
630
+ slow: "Sigue cargando: está tardando más de lo habitual.",
631
+ waking: (appName) =>
632
+ `El servidor se duerme cuando nadie usa ${appName ?? "la aplicación"}, así que la primera solicitud tras una pausa tiene que volver a arrancarlo. Puede tardar un momento; no se pierde nada y la página se completará sola.`,
633
+ },
583
634
  };
584
635
  }
585
636
 
@@ -90,6 +90,8 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
90
90
  title: "Clés d’accès",
91
91
  description:
92
92
  "Connectez-vous avec votre empreinte, votre visage ou le code PIN de l’appareil plutôt qu’avec un mot de passe.",
93
+ descriptionAlongside:
94
+ "Connectez-vous avec votre empreinte, votre visage ou le code PIN de l’appareil. Votre mot de passe reste valable.",
93
95
  empty: "Aucune clé d’accès pour l’instant",
94
96
  loading: "Chargement des clés d’accès…",
95
97
  list: "Vos clés d’accès",
@@ -511,6 +513,7 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
511
513
  confirmDialog: {
512
514
  confirm: "Confirmer",
513
515
  cancel: "Annuler",
516
+ typed: (text) => `Saisissez «\u202f${text}\u202f» pour confirmer`,
514
517
  },
515
518
  floatingPanel: {
516
519
  close: "Fermer",
@@ -596,6 +599,55 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
596
599
  noPreview: "Aucun aperçu disponible pour ce fichier",
597
600
  openInNewTab: "Ouvrir dans un nouvel onglet",
598
601
  },
602
+ writeLock: {
603
+ reason: "Vous pouvez consulter ceci, mais pas le modifier.",
604
+ },
605
+ accountState: {
606
+ // Agreeing with "compte" (masculine): the chip is the state of an account.
607
+ active: "Actif",
608
+ inactive: "Inactif",
609
+ invited: "Invité",
610
+ registered: "Inscrit",
611
+ unverified: "Non vérifié",
612
+ passwordChange: "Doit changer de mot de passe",
613
+ },
614
+ shareCard: {
615
+ dialogTitle: "Partager",
616
+ close: "Fermer",
617
+ email: "Adresse e-mail",
618
+ emailOptional: "Adresse e-mail (facultatif)",
619
+ // example.com is reserved for examples (RFC 2606); a localised domain is real.
620
+ emailPlaceholder: "nom@example.com",
621
+ invalidEmail: "Saisissez une adresse e-mail complète.",
622
+ role: "Rôle",
623
+ roleOf: (name) => `Rôle de ${name}`,
624
+ add: "Partager",
625
+ whoHasAccess: "Qui a accès",
626
+ nobodyYet: "Personne d’autre n’y a encore accès.",
627
+ pending: "En attente",
628
+ openInvite: "Lien d’invitation ouvert",
629
+ copyLink: "Copier le lien",
630
+ team: "Équipe",
631
+ teamHint: (name) => `Tous les membres de ${name} y auront accès.`,
632
+ remove: "Retirer l’accès",
633
+ removeConfirm: (name) => `Retirer l’accès de ${name}\u202f?`,
634
+ revokePending: "Révoquer l’invitation",
635
+ revokePendingConfirm: (name) => `Révoquer l’invitation de ${name}\u202f?`,
636
+ failed: "Cela n’a pas fonctionné. Veuillez réessayer.",
637
+ loading: "Chargement…",
638
+ },
639
+ reauthDialog: {
640
+ title: "Confirmez votre identité",
641
+ description: "Saisissez votre mot de passe actuel pour continuer.",
642
+ password: "Mot de passe actuel",
643
+ submit: "Continuer",
644
+ cancel: "Annuler",
645
+ },
646
+ serverWake: {
647
+ slow: "Chargement en cours — cela prend plus de temps que d’habitude.",
648
+ waking: (appName) =>
649
+ `Le serveur se met en veille quand personne n’utilise ${appName ?? "l’application"}, donc la première requête après une pause doit le redémarrer. Cela peut prendre un moment — rien n’est perdu, la page se remplira d’elle-même.`,
650
+ },
599
651
  };
600
652
  }
601
653
 
@@ -88,6 +88,8 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
88
88
  title: "Hozzáférési kulcsok",
89
89
  description:
90
90
  "Jelentkezzen be ujjlenyomattal, arcfelismeréssel vagy az eszköz PIN-kódjával jelszó helyett.",
91
+ descriptionAlongside:
92
+ "Jelentkezzen be ujjlenyomattal, arcfelismeréssel vagy az eszköz PIN-kódjával. A jelszava továbbra is működik.",
91
93
  empty: "Még nincs hozzáférési kulcs",
92
94
  loading: "Hozzáférési kulcsok betöltése…",
93
95
  list: "Az Ön hozzáférési kulcsai",
@@ -497,6 +499,7 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
497
499
  confirmDialog: {
498
500
  confirm: "Megerősítés",
499
501
  cancel: "Mégse",
502
+ typed: (text) => `A megerősítéshez írja be: „${text}”`,
500
503
  },
501
504
  floatingPanel: {
502
505
  close: "Bezárás",
@@ -582,6 +585,58 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
582
585
  noPreview: "Ehhez a fájlhoz nincs előnézet",
583
586
  openInNewTab: "Megnyitás új lapon",
584
587
  },
588
+ writeLock: {
589
+ reason: "Ezt megtekintheti, de nem módosíthatja.",
590
+ },
591
+ accountState: {
592
+ active: "Aktív",
593
+ inactive: "Inaktív",
594
+ invited: "Meghívva",
595
+ registered: "Regisztrált",
596
+ unverified: "Nincs megerősítve",
597
+ passwordChange: "Jelszócsere szükséges",
598
+ },
599
+ shareCard: {
600
+ dialogTitle: "Megosztás",
601
+ close: "Bezárás",
602
+ email: "E-mail-cím",
603
+ emailOptional: "E-mail-cím (nem kötelező)",
604
+ // example.com is reserved for examples (RFC 2606); a localised domain is real.
605
+ emailPlaceholder: "nev@example.com",
606
+ invalidEmail: "Adjon meg egy teljes e-mail-címet.",
607
+ role: "Szerepkör",
608
+ // The name after a colon, never inflected: the article before it (a/az) and a
609
+ // possessive suffix on it both depend on how the name sounds. As `deleteConfirm`.
610
+ roleOf: (name) => `Szerepkör (${name})`,
611
+ add: "Megosztás",
612
+ whoHasAccess: "Hozzáféréssel rendelkezők",
613
+ nobodyYet: "Még senki más nem fér hozzá.",
614
+ pending: "Függőben",
615
+ openInvite: "Nyitott meghívólink",
616
+ copyLink: "Link másolása",
617
+ team: "Csapat",
618
+ teamHint: (name) => `A(z) ${name} minden tagja hozzáférést kap.`,
619
+ remove: "Hozzáférés megvonása",
620
+ removeConfirm: (name) => `Megvonja a hozzáférést: ${name}?`,
621
+ revokePending: "Meghívás visszavonása",
622
+ revokePendingConfirm: (name) => `Visszavonja a meghívást: ${name}?`,
623
+ failed: "Ez nem sikerült. Kérjük, próbálja újra.",
624
+ loading: "Betöltés…",
625
+ },
626
+ reauthDialog: {
627
+ title: "Személyazonosság megerősítése",
628
+ description: "A folytatáshoz adja meg jelenlegi jelszavát.",
629
+ password: "Jelenlegi jelszó",
630
+ submit: "Folytatás",
631
+ cancel: "Mégse",
632
+ },
633
+ serverWake: {
634
+ slow: "Még tölt – ez a szokásosnál tovább tart.",
635
+ // The name stays in the nominative behind "a(z) … alkalmazást", as in
636
+ // `confirmRemove`: a Hungarian case ending on an arbitrary product name is a guess.
637
+ waking: (appName) =>
638
+ `A szerver elalszik, ha senki sem használja ${appName ? `a(z) ${appName} alkalmazást` : "az alkalmazást"}, ezért egy szünet utáni első kérésnek újra el kell indítania. Ez eltarthat egy ideig – semmi sem vész el, az oldal magától betöltődik.`,
639
+ },
585
640
  };
586
641
  }
587
642
 
@@ -89,6 +89,7 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
89
89
  passkeys: {
90
90
  title: "Passkey",
91
91
  description: "Accedi con impronta, volto o PIN del dispositivo invece che con una password.",
92
+ descriptionAlongside: "Accedi con impronta, volto o PIN del dispositivo. La tua password continua a funzionare.",
92
93
  empty: "Ancora nessuna passkey",
93
94
  loading: "Caricamento delle passkey…",
94
95
  list: "Le tue passkey",
@@ -498,6 +499,7 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
498
499
  confirmDialog: {
499
500
  confirm: "Conferma",
500
501
  cancel: "Annulla",
502
+ typed: (text) => `Digita «${text}» per confermare`,
501
503
  },
502
504
  floatingPanel: {
503
505
  close: "Chiudi",
@@ -583,6 +585,55 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
583
585
  noPreview: "Nessuna anteprima disponibile per questo file",
584
586
  openInNewTab: "Apri in una nuova scheda",
585
587
  },
588
+ writeLock: {
589
+ reason: "Puoi visualizzarlo, ma non modificarlo.",
590
+ },
591
+ accountState: {
592
+ // Agreeing with "account" (masculine): the chip is the state of an account.
593
+ active: "Attivo",
594
+ inactive: "Non attivo",
595
+ invited: "Invitato",
596
+ registered: "Registrato",
597
+ unverified: "Non verificato",
598
+ passwordChange: "Deve cambiare la password",
599
+ },
600
+ shareCard: {
601
+ dialogTitle: "Condividi",
602
+ close: "Chiudi",
603
+ email: "Indirizzo email",
604
+ emailOptional: "Indirizzo email (facoltativo)",
605
+ // example.com is reserved for examples (RFC 2606); a localised domain is real.
606
+ emailPlaceholder: "nome@example.com",
607
+ invalidEmail: "Inserisci un indirizzo email completo.",
608
+ role: "Ruolo",
609
+ roleOf: (name) => `Ruolo di ${name}`,
610
+ add: "Condividi",
611
+ whoHasAccess: "Chi ha accesso",
612
+ nobodyYet: "Nessun altro ha ancora accesso.",
613
+ pending: "In attesa",
614
+ openInvite: "Link di invito aperto",
615
+ copyLink: "Copia link",
616
+ team: "Team",
617
+ teamHint: (name) => `Tutti i membri di ${name} avranno accesso.`,
618
+ remove: "Rimuovi accesso",
619
+ removeConfirm: (name) => `Rimuovere l’accesso di ${name}?`,
620
+ revokePending: "Ritira invito",
621
+ revokePendingConfirm: (name) => `Ritirare l’invito per ${name}?`,
622
+ failed: "Non ha funzionato. Riprova.",
623
+ loading: "Caricamento…",
624
+ },
625
+ reauthDialog: {
626
+ title: "Conferma la tua identità",
627
+ description: "Inserisci la password attuale per continuare.",
628
+ password: "Password attuale",
629
+ submit: "Continua",
630
+ cancel: "Annulla",
631
+ },
632
+ serverWake: {
633
+ slow: "Caricamento in corso: ci vuole più del solito.",
634
+ waking: (appName) =>
635
+ `Il server va in sospensione quando nessuno usa ${appName ?? "l’app"}, quindi la prima richiesta dopo una pausa deve riavviarlo. Può volerci un momento: non si perde nulla, la pagina si completa da sola.`,
636
+ },
586
637
  };
587
638
  }
588
639
 
@@ -87,6 +87,7 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
87
87
  passkeys: {
88
88
  title: "通行密钥",
89
89
  description: "使用指纹、面容或设备 PIN 登录,无需密码。",
90
+ descriptionAlongside: "使用指纹、面容或设备 PIN 登录,密码仍可照常使用。",
90
91
  empty: "暂无通行密钥",
91
92
  loading: "正在加载通行密钥…",
92
93
  list: "已注册的通行密钥",
@@ -485,6 +486,7 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
485
486
  confirmDialog: {
486
487
  confirm: "确认",
487
488
  cancel: "取消",
489
+ typed: (text) => `输入“${text}”以确认`,
488
490
  },
489
491
  floatingPanel: {
490
492
  close: "关闭",
@@ -570,6 +572,54 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
570
572
  noPreview: "此文件无法预览",
571
573
  openInNewTab: "在新标签页中打开",
572
574
  },
575
+ writeLock: {
576
+ reason: "仅可查看,无法修改。",
577
+ },
578
+ accountState: {
579
+ active: "已启用",
580
+ inactive: "已停用",
581
+ invited: "已邀请",
582
+ registered: "已注册",
583
+ unverified: "未验证",
584
+ passwordChange: "需修改密码",
585
+ },
586
+ shareCard: {
587
+ dialogTitle: "共享",
588
+ close: "关闭",
589
+ email: "电子邮箱地址",
590
+ emailOptional: "电子邮箱地址(可选)",
591
+ emailPlaceholder: "name@example.com",
592
+ invalidEmail: "请输入完整的电子邮箱地址。",
593
+ role: "角色",
594
+ roleOf: (name) => `${name} 的角色`,
595
+ add: "共享",
596
+ whoHasAccess: "有权访问的人",
597
+ nobodyYet: "目前还没有其他人有权访问。",
598
+ pending: "待接受",
599
+ openInvite: "公开邀请链接",
600
+ copyLink: "复制链接",
601
+ team: "团队",
602
+ teamHint: (name) => `${name} 的所有成员都将获得访问权限。`,
603
+ remove: "移除访问权限",
604
+ removeConfirm: (name) => `移除 ${name} 的访问权限?`,
605
+ revokePending: "撤回邀请",
606
+ revokePendingConfirm: (name) => `撤回对 ${name} 的邀请?`,
607
+ failed: "操作未成功,请重试。",
608
+ loading: "加载中…",
609
+ },
610
+ reauthDialog: {
611
+ title: "验证身份",
612
+ description: "请输入当前密码以继续。",
613
+ password: "当前密码",
614
+ submit: "继续",
615
+ cancel: "取消",
616
+ },
617
+ serverWake: {
618
+ slow: "仍在加载,比平时耗时更长。",
619
+ // A Latin product name gets a space either side, as everywhere in this catalogue.
620
+ waking: (appName) =>
621
+ `无人使用${appName ? ` ${appName} ` : "本应用"}时,服务器会进入休眠,因此暂停后的第一个请求需要重新启动它。这可能需要一点时间——不会丢失任何内容,页面会自动加载完成。`,
622
+ },
573
623
  };
574
624
  }
575
625
 
package/src/i18n/swiss.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Swiss Standard German respelling, shared by the `de-CH` and `de-CH-informal`
3
- * translations. Internal: it lives outside `src/i18n/locales/` because every file there
4
- * becomes a public `@eifi1/ui-kit/i18n/<code>` subpath.
2
+ * Swiss Standard German respelling, applied to the internal German source (`german.ts`)
3
+ * to make the `de-CH` catalogue. Internal: it lives outside `src/i18n/locales/` because
4
+ * every file there becomes a public `@eifi1/ui-kit/i18n/<code>` subpath.
5
5
  *
6
6
  * "ss" for every "ß" (Schliessen, Grösse) is the one systematic difference in UI text.
7
7
  * Function labels are wrapped: their RESULT is respelled, so an argument the app passes
package/src/index.ts CHANGED
@@ -109,7 +109,13 @@ export * from "./components/password-strength";
109
109
  export * from "./components/page-contents";
110
110
  export * from "./components/disclosure";
111
111
  export * from "./components/dialog-frame";
112
- export * from "./components/danger-confirm";
112
+ // Named, not `*`: danger-confirm also holds the password field and pending hook that
113
+ // ReauthDialog shares with it, which are kit-internal.
114
+ export { DangerConfirm, DEFAULT_DANGER_CONFIRM_LABELS, typedMatches } from "./components/danger-confirm";
115
+ export type { DangerConfirmLabels, DangerConfirmProps, TypedMatch } from "./components/danger-confirm";
116
+ // 0.18: re-authentication before a sensitive action (Kurvenschmiede 4).
117
+ export { ReauthDialog, DEFAULT_REAUTH_DIALOG_LABELS } from "./components/reauth-dialog";
118
+ export type { ReauthDialogProps, ReauthDialogLabels } from "./components/reauth-dialog";
113
119
  // `useConfirm()` — the promise-based replacement for `window.confirm`, one host per app.
114
120
  export * from "./components/confirm-dialog";
115
121
  // A non-modal corner panel and its round trigger (keksdose's assistant launcher).
@@ -174,6 +180,22 @@ export * from "./components/description-list";
174
180
  // The Save / Cancel row forms and dialogs end in, and the editable line-item repeater
175
181
  // (journal lines, lease components, invoice positions). 0.12.0.
176
182
  export * from "./components/form-actions";
183
+ // 0.18: lock every opted-in commit under one provider, the reason in its tooltip
184
+ // (Kurvenschmiede 2). `useCommitReason` stays internal.
185
+ export { WriteLockProvider, useWriteLock, DEFAULT_WRITE_LOCK_LABELS } from "./components/write-lock";
186
+ export type { WriteLock, WriteLockLabels, WriteLockProviderProps } from "./components/write-lock";
187
+ // 0.18: the parts both apps' admin rosters repeat (Kurvenschmiede 6).
188
+ export { RoleChip, AccountStateChip, DateMark, dateColumn, DEFAULT_ACCOUNT_STATE_LABELS, ACCOUNT_STATE_TONES } from "./components/account-chips";
189
+ export type { RoleChipProps, RoleDefinition, RoleVocabulary, AccountState, AccountStateLabels, AccountStateChipProps, DateMarkProps, DateColumnOptions } from "./components/account-chips";
190
+ // 0.18: the cold-start notice keksdose built (#199), for every app: a framework-free
191
+ // watchdog over the app's requests and the corner notice that explains the wait.
192
+ export { createServerWake, serverWake, watchReadsAnd, attachServerWake, wrapFetch } from "./lib/server-wake";
193
+ export type { ServerWakeStage, ServerWakeFilter, ServerWakeOptions, ServerWakeRequest, ServerWakeWatcher, ServerWakeAxiosConfig, AxiosLikeInstance } from "./lib/server-wake";
194
+ export { ServerWakeNotice, useServerWakeStage, DEFAULT_SERVER_WAKE_LABELS } from "./components/server-wake";
195
+ export type { ServerWakeLabels, ServerWakeNoticeProps } from "./components/server-wake";
196
+ // 0.18: sharing — grantees, roles, pending grants, candidates (Kurvenschmiede 1).
197
+ export { ShareCard, ShareDialog, SharePanel, DEFAULT_SHARE_CARD_LABELS } from "./components/share-card";
198
+ export type { ShareCardProps, ShareDialogProps, SharePanelProps, ShareCardLabels, ShareRole, ShareGrantee, SharePendingGrant, ShareCandidate, ShareAddRequest } from "./components/share-card";
177
199
  export * from "./components/line-items";
178
200
  export * from "./components/progress-bar";
179
201
  // Named: skeleton.tsx also holds SKELETON_CLASS, the look StatTile shares — internal.