@eifi1/ui-kit 0.51.2 → 0.51.4
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/README.md +5 -5
- package/dist/components/combobox-core.js +4 -5
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/currency-option-list.js +3 -3
- package/dist/components/currency-option-list.js.map +1 -1
- package/dist/components/data-table-fit.js +7 -5
- package/dist/components/data-table-fit.js.map +1 -1
- package/dist/components/data-table-head.js +5 -1
- package/dist/components/data-table-head.js.map +1 -1
- package/dist/components/data-table.d.ts +8 -0
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/grouped-picker.js +5 -4
- package/dist/components/grouped-picker.js.map +1 -1
- package/dist/components/icon-picker.js +5 -4
- package/dist/components/icon-picker.js.map +1 -1
- package/dist/components/inline-entity-combobox.js +4 -4
- package/dist/components/inline-entity-combobox.js.map +1 -1
- package/dist/components/legal-labels.js +9 -2
- package/dist/components/legal-labels.js.map +1 -1
- package/dist/components/legal-page.d.ts +35 -3
- package/dist/components/legal-page.js +22 -0
- package/dist/components/legal-page.js.map +1 -1
- package/dist/components/legal.d.ts +49 -5
- package/dist/components/legal.js +31 -3
- package/dist/components/legal.js.map +1 -1
- package/dist/components/list-labels.js +3 -1
- package/dist/components/list-labels.js.map +1 -1
- package/dist/components/list.d.ts +18 -1
- package/dist/components/list.js +32 -3
- package/dist/components/list.js.map +1 -1
- package/dist/eslint/index.js +1 -1
- package/dist/feedback/feedback-table.d.ts +3 -1
- package/dist/feedback/feedback-table.js +18 -4
- package/dist/feedback/feedback-table.js.map +1 -1
- package/dist/i18n/german.js +12 -3
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/locales/en.js +16 -3
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/es.js +12 -3
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +12 -3
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +12 -3
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +12 -3
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +12 -3
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +4 -0
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/text-match.d.ts +16 -0
- package/dist/lib/text-match.js +11 -1
- package/dist/lib/text-match.js.map +1 -1
- package/dist/settings/use-settings-focus.d.ts +7 -0
- package/dist/settings/use-settings-focus.js +2 -0
- package/dist/settings/use-settings-focus.js.map +1 -1
- package/dist/shell/dev-menu.d.ts +5 -0
- package/dist/shell/dev-menu.js +2 -1
- package/dist/shell/dev-menu.js.map +1 -1
- package/dist/shell/topbar-action-menu.d.ts +14 -1
- package/dist/shell/topbar-action-menu.js +85 -34
- package/dist/shell/topbar-action-menu.js.map +1 -1
- package/dist/shell.d.ts +1 -1
- package/dist/shell.js +2 -1
- package/dist/shell.js.map +1 -1
- package/package.json +1 -1
- package/src/components/combobox-core.tsx +5 -5
- package/src/components/currency-option-list.tsx +4 -5
- package/src/components/data-table-fit.ts +7 -5
- package/src/components/data-table-head.tsx +5 -1
- package/src/components/data-table.tsx +8 -0
- package/src/components/grouped-picker.tsx +15 -8
- package/src/components/icon-picker.tsx +6 -4
- package/src/components/inline-entity-combobox.tsx +5 -4
- package/src/components/legal-labels.ts +8 -1
- package/src/components/legal-page.tsx +72 -2
- package/src/components/legal.tsx +80 -5
- package/src/components/list-labels.ts +2 -0
- package/src/components/list.tsx +52 -2
- package/src/feedback/feedback-table.tsx +17 -1
- package/src/i18n/german.ts +10 -1
- package/src/i18n/locales/en.ts +4 -0
- package/src/i18n/locales/es.ts +10 -1
- package/src/i18n/locales/fr.ts +10 -1
- package/src/i18n/locales/hu.ts +10 -1
- package/src/i18n/locales/it.ts +10 -1
- package/src/i18n/locales/zh.ts +10 -1
- package/src/i18n/review.ts +4 -0
- package/src/index.ts +1 -0
- package/src/lib/text-match.ts +30 -0
- package/src/settings/use-settings-focus.ts +8 -0
- package/src/shell/dev-menu.tsx +6 -0
- package/src/shell/topbar-action-menu.tsx +122 -38
- package/src/shell.ts +1 -1
package/src/components/list.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useContext, useId, useState } from "react";
|
|
1
|
+
import { Children, createContext, useContext, useId, useState } from "react";
|
|
2
2
|
import type { ComponentPropsWithoutRef, HTMLAttributes, MouseEvent, ReactElement, ReactNode, Ref } from "react";
|
|
3
3
|
import { ChevronDown, ExternalLink } from "lucide-react";
|
|
4
4
|
import type { LucideIcon } from "lucide-react";
|
|
@@ -14,6 +14,7 @@ import { pickLinkRenderer } from "./text-link";
|
|
|
14
14
|
import { LockedReason, mergeDescribedBy, useLockReason, type DisabledReasonDisplay } from "./field-parts";
|
|
15
15
|
import type { CommitScope } from "./write-lock";
|
|
16
16
|
import { DEFAULT_LIST_LABELS } from "./list-labels";
|
|
17
|
+
import { Button } from "./button";
|
|
17
18
|
|
|
18
19
|
/* ── Labels ───────────────────────────────────────────────────────────────── */
|
|
19
20
|
|
|
@@ -22,6 +23,12 @@ export interface ListLabels {
|
|
|
22
23
|
unread: string;
|
|
23
24
|
/** Read after an external row's title: the row leaves the app in a new tab. */
|
|
24
25
|
opensInNewTab: string;
|
|
26
|
+
/** 0.51.4: the row under a {@link ListProps.limit}ed list that opens the rest, with
|
|
27
|
+
* the WHOLE list's count — "Show all (12)". Optional, as every key added to a
|
|
28
|
+
* namespace an app may annotate: left out, the provider's, then English. */
|
|
29
|
+
showAll?: (count: number) => string;
|
|
30
|
+
/** 0.51.4: the same row once the list is open, folding it back. */
|
|
31
|
+
showFewer?: string;
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
// Defined in ./list-labels, which holds no component code (0.34, KS U8).
|
|
@@ -53,8 +60,26 @@ export interface ListProps extends Omit<ComponentPropsWithoutRef<"ul">, "role">
|
|
|
53
60
|
/** The `<ul>` (or `<ol>`). A React 19 ref prop since 0.34 (MOD-4, refactor audit
|
|
54
61
|
* 2026-10); it was `forwardRef`. */
|
|
55
62
|
ref?: Ref<HTMLUListElement>;
|
|
63
|
+
/**
|
|
64
|
+
* Show the first `limit` rows, then a "Show all (n)" row that opens the rest and turns
|
|
65
|
+
* into "Show fewer" (0.51.4, keksdose run 89: a long "Placed only roughly" list on its
|
|
66
|
+
* Matching report could only fold as a whole, so it opened as nothing or everything).
|
|
67
|
+
* A list of `limit` rows or fewer draws them all, with no such row. Rows are counted as
|
|
68
|
+
* `Children` counts them: one per `ListItem`, a fragment as one.
|
|
69
|
+
*
|
|
70
|
+
* The row is a button with `aria-expanded`, controlling the list; it sits in the list
|
|
71
|
+
* as `role="none"`, so a reader still hears "list, 5 items" for five rows.
|
|
72
|
+
*/
|
|
73
|
+
limit?: number;
|
|
56
74
|
}
|
|
57
75
|
|
|
76
|
+
/** The show-all row's inset, in step with each density's row padding (`PAD`). */
|
|
77
|
+
const MORE_PAD: Record<ListDensity, string> = {
|
|
78
|
+
compact: "px-2 py-1",
|
|
79
|
+
default: "px-3 py-1.5",
|
|
80
|
+
comfortable: "px-4 py-2",
|
|
81
|
+
};
|
|
82
|
+
|
|
58
83
|
/**
|
|
59
84
|
* The list of {@link ListItem}s.
|
|
60
85
|
*
|
|
@@ -67,15 +92,23 @@ export function List({
|
|
|
67
92
|
as = "ul",
|
|
68
93
|
density = "default",
|
|
69
94
|
separator = "gap",
|
|
95
|
+
limit,
|
|
70
96
|
className,
|
|
71
97
|
children,
|
|
72
98
|
...rest
|
|
73
99
|
}: ListProps) {
|
|
74
100
|
const Tag = as;
|
|
101
|
+
const labels = useKitLabels("list", DEFAULT_LIST_LABELS);
|
|
102
|
+
const [open, setOpen] = useState(false);
|
|
103
|
+
const generatedId = useId();
|
|
104
|
+
const id = rest.id ?? generatedId;
|
|
105
|
+
const rows = limit === undefined ? null : Children.toArray(children);
|
|
106
|
+
const folds = rows !== null && rows.length > Math.max(0, limit!);
|
|
75
107
|
return (
|
|
76
108
|
<ListContext.Provider value={{ density, separator }}>
|
|
77
109
|
<Tag
|
|
78
110
|
{...rest}
|
|
111
|
+
id={folds ? id : rest.id}
|
|
79
112
|
ref={ref as Ref<HTMLUListElement & HTMLOListElement>}
|
|
80
113
|
role="list"
|
|
81
114
|
className={cn(
|
|
@@ -84,7 +117,24 @@ export function List({
|
|
|
84
117
|
className,
|
|
85
118
|
)}
|
|
86
119
|
>
|
|
87
|
-
{children}
|
|
120
|
+
{folds && !open ? rows.slice(0, Math.max(0, limit!)) : children}
|
|
121
|
+
{folds && (
|
|
122
|
+
<li role="none" className={MORE_PAD[density]}>
|
|
123
|
+
<Button
|
|
124
|
+
type="button"
|
|
125
|
+
variant="link"
|
|
126
|
+
size="sm"
|
|
127
|
+
className="h-auto p-0"
|
|
128
|
+
aria-expanded={open}
|
|
129
|
+
aria-controls={id}
|
|
130
|
+
onClick={() => setOpen((was) => !was)}
|
|
131
|
+
>
|
|
132
|
+
{open
|
|
133
|
+
? (labels.showFewer ?? DEFAULT_LIST_LABELS.showFewer)
|
|
134
|
+
: (labels.showAll ?? DEFAULT_LIST_LABELS.showAll!)(rows.length)}
|
|
135
|
+
</Button>
|
|
136
|
+
</li>
|
|
137
|
+
)}
|
|
88
138
|
</Tag>
|
|
89
139
|
</ListContext.Provider>
|
|
90
140
|
);
|
|
@@ -453,7 +453,9 @@ function statusRank(status: FeedbackStatus): number {
|
|
|
453
453
|
* - Fitted to the table's width (0.48, keksdose live #451): Subject `grow`s and
|
|
454
454
|
* ellipsises, and a narrow table leaves out URL, then Email, then Resolved
|
|
455
455
|
* (`fitPriority` 1–3) — the open report repeats all three — then Votes and Category
|
|
456
|
-
* (4, 5)
|
|
456
|
+
* (4, 5), then User, Date and # (6–8, 0.51.4) before Subject would drop below 8rem
|
|
457
|
+
* (`growMin`, 0.51.4; the table's default floor is 10).
|
|
458
|
+
* Drop the two keys with
|
|
457
459
|
* `{ ...col, grow: undefined, fitPriority: undefined }` for the 0.47 layout.
|
|
458
460
|
* - `/my-feedback` shows the same nine: the Email cell's context fallback exists for it
|
|
459
461
|
* (the admin list's join is absent there, §3.1), and its phone card drops the submitter
|
|
@@ -499,6 +501,9 @@ export function feedbackColumns<T extends FeedbackTableRow>({
|
|
|
499
501
|
sortBy: (row) => row.id,
|
|
500
502
|
filter: { type: "number", getValue: (row) => row.id },
|
|
501
503
|
mobileHidden: true,
|
|
504
|
+
// The very last to go (0.51.4, Kurvenschmiede): replies and the feedback loop name a
|
|
505
|
+
// report by its number, so it stays while anything else can give way.
|
|
506
|
+
fitPriority: 8,
|
|
502
507
|
},
|
|
503
508
|
{
|
|
504
509
|
key: "date",
|
|
@@ -506,6 +511,8 @@ export function feedbackColumns<T extends FeedbackTableRow>({
|
|
|
506
511
|
cell: (row) => <FeedbackDate value={row.created_at} renderDate={renderDate} />,
|
|
507
512
|
sortBy: (row) => instant(row.created_at),
|
|
508
513
|
filter: { type: "date", getValue: (row) => row.created_at },
|
|
514
|
+
// Seventh to go (0.51.4): the open report shows it.
|
|
515
|
+
fitPriority: 7,
|
|
509
516
|
},
|
|
510
517
|
{
|
|
511
518
|
key: "category",
|
|
@@ -536,6 +543,11 @@ export function feedbackColumns<T extends FeedbackTableRow>({
|
|
|
536
543
|
// The rest of the row, one line and an ellipsis (0.48, keksdose live #451: one long
|
|
537
544
|
// crash title pushed Status and the row actions off the edge).
|
|
538
545
|
grow: true,
|
|
546
|
+
// 8rem, not the table's 10 (0.51.4, Kurvenschmiede): at 768px beside a sidebar only
|
|
547
|
+
// Subject, Status (a fixed 13.5rem) and the row actions are left, and they were up
|
|
548
|
+
// to 20px too wide (Hungarian). A subject's first words carry it; the open report
|
|
549
|
+
// has the rest.
|
|
550
|
+
growMin: 8,
|
|
539
551
|
},
|
|
540
552
|
{
|
|
541
553
|
key: "user",
|
|
@@ -559,6 +571,10 @@ export function feedbackColumns<T extends FeedbackTableRow>({
|
|
|
559
571
|
row.user_id == null
|
|
560
572
|
? labels.deletedUser
|
|
561
573
|
: `${feedbackSubmitter(row, labels)} ${feedbackSubmitterEmail(row)}`,
|
|
574
|
+
// Sixth to go (0.51.4, Kurvenschmiede): with only 1–5, Subject reached its floor while
|
|
575
|
+
// #, Date and User were still drawn, and the inbox scrolled sideways from 768 to
|
|
576
|
+
// ~1115px beside an open sidebar. The open report names the submitter.
|
|
577
|
+
fitPriority: 6,
|
|
562
578
|
},
|
|
563
579
|
{
|
|
564
580
|
key: "email",
|
package/src/i18n/german.ts
CHANGED
|
@@ -782,6 +782,8 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
782
782
|
list: {
|
|
783
783
|
unread: "Ungelesen",
|
|
784
784
|
opensInNewTab: "öffnet in einem neuen Tab",
|
|
785
|
+
showAll: (count) => `Alle anzeigen (${n(count)})`,
|
|
786
|
+
showFewer: "Weniger anzeigen",
|
|
785
787
|
},
|
|
786
788
|
breadcrumbs: {
|
|
787
789
|
label: "Brotkrümelnavigation",
|
|
@@ -917,6 +919,8 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
917
919
|
impressum: "Impressum",
|
|
918
920
|
privacy: "Datenschutz",
|
|
919
921
|
terms: "Nutzungsbedingungen",
|
|
922
|
+
security: "Sicherheit",
|
|
923
|
+
accessibility: "Barrierefreiheit",
|
|
920
924
|
},
|
|
921
925
|
titles: {
|
|
922
926
|
impressum: "Impressum",
|
|
@@ -935,6 +939,11 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
935
939
|
`Dies ist eine Übersetzung zu Ihrer Information. Massgebend ist die Fassung auf ${o.bindingLanguage}.`,
|
|
936
940
|
show: (o) => `Fassung auf ${o.bindingLanguage} anzeigen`,
|
|
937
941
|
},
|
|
942
|
+
updated: (date) => `Stand: ${date}`,
|
|
943
|
+
summary: {
|
|
944
|
+
title: "Das Wichtigste in Kürze",
|
|
945
|
+
note: "Diese Zusammenfassung dient der Orientierung; verbindlich ist allein der vollständige Text.",
|
|
946
|
+
},
|
|
938
947
|
sections: {
|
|
939
948
|
impressum: {
|
|
940
949
|
operator: {
|
|
@@ -991,7 +1000,7 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
991
1000
|
},
|
|
992
1001
|
changes: {
|
|
993
1002
|
title: "Änderungen dieser Bedingungen",
|
|
994
|
-
body: "
|
|
1003
|
+
body: "Wir können diese Bedingungen im Zuge der Weiterentwicklung des Dienstes anpassen. Wesentliche Änderungen kündigen wir mindestens 30 Tage vor ihrem Inkrafttreten per E-Mail und in der App an, zusammen mit dem neuen Text. Wenn Sie nicht einverstanden sind, können Sie vor diesem Datum widersprechen oder Ihr Konto löschen und bis dahin Ihre Daten exportieren. Nutzen Sie den Dienst nach diesem Datum weiter, gelten die geänderten Bedingungen. Änderungen, die nur zu Ihrem Vorteil sind oder gesetzlich vorgeschrieben sind, gelten ohne diese Ankündigung; ihnen kann nicht widersprochen werden. Widersprechen Sie einer Änderung, können wir Ihr Konto auf den Tag ihres Inkrafttretens schließen. Haben Sie einen Zeitraum bezahlt, der über dieses Datum hinausgeht, erstatten wir den nicht genutzten Teil.",
|
|
995
1004
|
},
|
|
996
1005
|
language: {
|
|
997
1006
|
title: "Sprache",
|
package/src/i18n/locales/en.ts
CHANGED
|
@@ -95,6 +95,10 @@ export function uiKitLabelsEn(numberLocale = "en-US"): UiKitLabels {
|
|
|
95
95
|
...d.chipInput,
|
|
96
96
|
atLimit: (max) => `Limit of ${n(max)} reached`,
|
|
97
97
|
},
|
|
98
|
+
list: {
|
|
99
|
+
...d.list,
|
|
100
|
+
showAll: (count) => `Show all (${n(count)})`,
|
|
101
|
+
},
|
|
98
102
|
iconPicker: {
|
|
99
103
|
...d.iconPicker,
|
|
100
104
|
resultCount: (count) => (count === 1 ? "1 icon" : `${n(count)} icons`),
|
package/src/i18n/locales/es.ts
CHANGED
|
@@ -765,6 +765,8 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
765
765
|
list: {
|
|
766
766
|
unread: "No leído",
|
|
767
767
|
opensInNewTab: "se abre en una pestaña nueva",
|
|
768
|
+
showAll: (count) => `Mostrar todo (${n(count)})`,
|
|
769
|
+
showFewer: "Mostrar menos",
|
|
768
770
|
},
|
|
769
771
|
breadcrumbs: {
|
|
770
772
|
label: "Ruta de navegación",
|
|
@@ -897,6 +899,8 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
897
899
|
impressum: "Aviso legal",
|
|
898
900
|
privacy: "Política de privacidad",
|
|
899
901
|
terms: "Condiciones de uso",
|
|
902
|
+
security: "Seguridad",
|
|
903
|
+
accessibility: "Accesibilidad",
|
|
900
904
|
},
|
|
901
905
|
titles: {
|
|
902
906
|
impressum: "Aviso legal",
|
|
@@ -915,6 +919,11 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
915
919
|
`Esta es una traducción ofrecida para su comodidad; solo la versión en ${o.bindingLanguage} es vinculante.`,
|
|
916
920
|
show: (o) => `Ver la versión en ${o.bindingLanguage}`,
|
|
917
921
|
},
|
|
922
|
+
updated: (date) => `Última actualización: ${date}`,
|
|
923
|
+
summary: {
|
|
924
|
+
title: "En resumen",
|
|
925
|
+
note: "Este resumen es solo orientativo; únicamente el texto completo es vinculante.",
|
|
926
|
+
},
|
|
918
927
|
sections: {
|
|
919
928
|
impressum: {
|
|
920
929
|
operator: {
|
|
@@ -971,7 +980,7 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
971
980
|
},
|
|
972
981
|
changes: {
|
|
973
982
|
title: "Cambios en estas condiciones",
|
|
974
|
-
body: "
|
|
983
|
+
body: "Podemos actualizar estas condiciones a medida que evolucione el servicio. Anunciamos cualquier cambio importante al menos 30 días antes de que entre en vigor, por correo electrónico y en la aplicación, junto con el nuevo texto. Si no está de acuerdo, puede oponerse o eliminar su cuenta antes de esa fecha, y puede exportar sus datos hasta entonces. Si sigue usando el servicio después de esa fecha, se aplican las condiciones modificadas. Los cambios que solo le benefician, o que exige la ley, se aplican sin este preaviso y no admiten oposición. Si se opone a un cambio, podemos cerrar su cuenta en la fecha en que entre en vigor. Si ha pagado un periodo que va más allá de esa fecha, le reembolsamos la parte no utilizada.",
|
|
975
984
|
},
|
|
976
985
|
language: {
|
|
977
986
|
title: "Idioma",
|
package/src/i18n/locales/fr.ts
CHANGED
|
@@ -781,6 +781,8 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
781
781
|
list: {
|
|
782
782
|
unread: "Non lu",
|
|
783
783
|
opensInNewTab: "s’ouvre dans un nouvel onglet",
|
|
784
|
+
showAll: (count) => `Tout afficher (${n(count)})`,
|
|
785
|
+
showFewer: "Afficher moins",
|
|
784
786
|
},
|
|
785
787
|
breadcrumbs: {
|
|
786
788
|
label: "Fil d’Ariane",
|
|
@@ -916,6 +918,8 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
916
918
|
impressum: "Mentions légales",
|
|
917
919
|
privacy: "Confidentialité",
|
|
918
920
|
terms: "Conditions d’utilisation",
|
|
921
|
+
security: "Sécurité",
|
|
922
|
+
accessibility: "Accessibilité",
|
|
919
923
|
},
|
|
920
924
|
titles: {
|
|
921
925
|
impressum: "Mentions légales",
|
|
@@ -934,6 +938,11 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
934
938
|
`Ceci est une traduction fournie pour votre commodité. Seule la version en ${o.bindingLanguage} fait foi.`,
|
|
935
939
|
show: (o) => `Afficher la version en ${o.bindingLanguage}`,
|
|
936
940
|
},
|
|
941
|
+
updated: (date) => `Dernière mise à jour\u00a0: ${date}`,
|
|
942
|
+
summary: {
|
|
943
|
+
title: "En bref",
|
|
944
|
+
note: "Ce résumé sert d’orientation\u202f; seul le texte complet fait foi.",
|
|
945
|
+
},
|
|
937
946
|
sections: {
|
|
938
947
|
impressum: {
|
|
939
948
|
operator: {
|
|
@@ -990,7 +999,7 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
990
999
|
},
|
|
991
1000
|
changes: {
|
|
992
1001
|
title: "Modifications des présentes conditions",
|
|
993
|
-
body: "
|
|
1002
|
+
body: "Nous pouvons mettre à jour ces conditions au fil de l’évolution du service. Nous annonçons toute modification importante au moins 30 jours avant son entrée en vigueur, par e-mail et dans l’app, avec le nouveau texte. Si vous n’êtes pas d’accord, vous pouvez vous y opposer ou supprimer votre compte avant cette date, et exporter vos données jusque-là. Si vous continuez à utiliser le service après cette date, les conditions modifiées s’appliquent. Les modifications qui sont uniquement à votre avantage, ou que la loi impose, s’appliquent sans ce préavis et ne peuvent pas faire l’objet d’une opposition. Si vous vous opposez à une modification, nous pouvons fermer votre compte à la date de son entrée en vigueur. Si vous avez payé une période qui s’étend au-delà de cette date, nous remboursons la part non utilisée.",
|
|
994
1003
|
},
|
|
995
1004
|
language: {
|
|
996
1005
|
title: "Langue",
|
package/src/i18n/locales/hu.ts
CHANGED
|
@@ -766,6 +766,8 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
766
766
|
list: {
|
|
767
767
|
unread: "Olvasatlan",
|
|
768
768
|
opensInNewTab: "új lapon nyílik meg",
|
|
769
|
+
showAll: (count) => `Összes megjelenítése (${n(count)})`,
|
|
770
|
+
showFewer: "Kevesebb megjelenítése",
|
|
769
771
|
},
|
|
770
772
|
breadcrumbs: {
|
|
771
773
|
label: "Morzsamenü",
|
|
@@ -901,6 +903,8 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
901
903
|
impressum: "Impresszum",
|
|
902
904
|
privacy: "Adatvédelmi tájékoztató",
|
|
903
905
|
terms: "Felhasználási feltételek",
|
|
906
|
+
security: "Biztonság",
|
|
907
|
+
accessibility: "Akadálymentesség",
|
|
904
908
|
},
|
|
905
909
|
titles: {
|
|
906
910
|
impressum: "Impresszum",
|
|
@@ -922,6 +926,11 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
922
926
|
`Ez a szöveg tájékoztató jellegű fordítás; az irányadó változat nyelve: ${o.bindingLanguage}.`,
|
|
923
927
|
show: (o) => `Az irányadó változat megjelenítése (${o.bindingLanguage})`,
|
|
924
928
|
},
|
|
929
|
+
updated: (date) => `Utolsó frissítés: ${date}`,
|
|
930
|
+
summary: {
|
|
931
|
+
title: "Röviden",
|
|
932
|
+
note: "Ez az összefoglaló tájékoztató jellegű; kizárólag a teljes szöveg az irányadó.",
|
|
933
|
+
},
|
|
925
934
|
sections: {
|
|
926
935
|
impressum: {
|
|
927
936
|
operator: {
|
|
@@ -978,7 +987,7 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
978
987
|
},
|
|
979
988
|
changes: {
|
|
980
989
|
title: "A feltételek módosítása",
|
|
981
|
-
body: "
|
|
990
|
+
body: "Ezeket a feltételeket a szolgáltatás fejlődésével módosíthatjuk. A lényeges változásokat legalább 30 nappal a hatálybalépésük előtt bejelentjük e-mailben és az alkalmazásban, az új szöveggel együtt. Ha nem ért egyet, ezen időpont előtt tiltakozhat, vagy törölheti a fiókját, és addig exportálhatja az adatait. Ha ezen időpont után is használja a szolgáltatást, a módosított feltételek érvényesek. Azok a változások, amelyek kizárólag az Ön javát szolgálják, vagy amelyeket jogszabály ír elő, e bejelentés nélkül is hatályosak, és ellenük nem lehet tiltakozni. Ha tiltakozik egy változás ellen, a hatálybalépés napjával megszüntethetjük a fiókját. Ha olyan időszakra fizetett, amely ezen a napon túlnyúlik, a fel nem használt részt visszatérítjük.",
|
|
982
991
|
},
|
|
983
992
|
language: {
|
|
984
993
|
title: "Nyelv",
|
package/src/i18n/locales/it.ts
CHANGED
|
@@ -769,6 +769,8 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
|
|
|
769
769
|
list: {
|
|
770
770
|
unread: "Non letto",
|
|
771
771
|
opensInNewTab: "si apre in una nuova scheda",
|
|
772
|
+
showAll: (count) => `Mostra tutto (${n(count)})`,
|
|
773
|
+
showFewer: "Mostra meno",
|
|
772
774
|
},
|
|
773
775
|
breadcrumbs: {
|
|
774
776
|
label: "Percorso di navigazione",
|
|
@@ -902,6 +904,8 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
|
|
|
902
904
|
impressum: "Impressum",
|
|
903
905
|
privacy: "Privacy",
|
|
904
906
|
terms: "Condizioni d’uso",
|
|
907
|
+
security: "Sicurezza",
|
|
908
|
+
accessibility: "Accessibilità",
|
|
905
909
|
},
|
|
906
910
|
titles: {
|
|
907
911
|
impressum: "Impressum",
|
|
@@ -921,6 +925,11 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
|
|
|
921
925
|
`Questa è una traduzione fornita per Sua comodità. Fa fede la versione in ${o.bindingLanguage}.`,
|
|
922
926
|
show: (o) => `Mostra la versione in ${o.bindingLanguage}`,
|
|
923
927
|
},
|
|
928
|
+
updated: (date) => `Ultimo aggiornamento: ${date}`,
|
|
929
|
+
summary: {
|
|
930
|
+
title: "In breve",
|
|
931
|
+
note: "Questo riepilogo serve da orientamento; fa fede solo il testo completo.",
|
|
932
|
+
},
|
|
924
933
|
sections: {
|
|
925
934
|
impressum: {
|
|
926
935
|
operator: {
|
|
@@ -979,7 +988,7 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
|
|
|
979
988
|
},
|
|
980
989
|
changes: {
|
|
981
990
|
title: "Modifiche a queste condizioni",
|
|
982
|
-
body: "
|
|
991
|
+
body: "Possiamo aggiornare queste condizioni con l’evoluzione del servizio. Annunciamo ogni modifica sostanziale almeno 30 giorni prima della sua entrata in vigore, via email e nell’app, insieme al nuovo testo. Se non è d’accordo, può opporsi o eliminare il Suo account prima di tale data, e può esportare i Suoi dati fino ad allora. Se continua a usare il servizio dopo tale data, si applicano le condizioni modificate. Le modifiche che vanno solo a Suo vantaggio, o che sono imposte dalla legge, si applicano senza questo preavviso e non è possibile opporvisi. Se si oppone a una modifica, possiamo chiudere il Suo account alla data della sua entrata in vigore. Se ha pagato un periodo che va oltre tale data, Le rimborsiamo la parte non utilizzata.",
|
|
983
992
|
},
|
|
984
993
|
language: {
|
|
985
994
|
title: "Lingua",
|
package/src/i18n/locales/zh.ts
CHANGED
|
@@ -746,6 +746,8 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
|
|
|
746
746
|
list: {
|
|
747
747
|
unread: "未读",
|
|
748
748
|
opensInNewTab: "在新标签页中打开",
|
|
749
|
+
showAll: (count) => `显示全部(${n(count)})`,
|
|
750
|
+
showFewer: "收起",
|
|
749
751
|
},
|
|
750
752
|
breadcrumbs: {
|
|
751
753
|
label: "面包屑导航",
|
|
@@ -876,6 +878,8 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
|
|
|
876
878
|
impressum: "运营者信息",
|
|
877
879
|
privacy: "隐私政策",
|
|
878
880
|
terms: "使用条款",
|
|
881
|
+
security: "安全",
|
|
882
|
+
accessibility: "无障碍",
|
|
879
883
|
},
|
|
880
884
|
titles: {
|
|
881
885
|
impressum: "运营者信息",
|
|
@@ -895,6 +899,11 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
|
|
|
895
899
|
`本页为方便阅读而提供的译文,以${o.bindingLanguage}版本为准。`,
|
|
896
900
|
show: (o) => `查看${o.bindingLanguage}版本`,
|
|
897
901
|
},
|
|
902
|
+
updated: (date) => `最后更新:${date}`,
|
|
903
|
+
summary: {
|
|
904
|
+
title: "要点",
|
|
905
|
+
note: "本摘要仅供参考;只有完整文本具有约束力。",
|
|
906
|
+
},
|
|
898
907
|
sections: {
|
|
899
908
|
impressum: {
|
|
900
909
|
operator: {
|
|
@@ -951,7 +960,7 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
|
|
|
951
960
|
},
|
|
952
961
|
changes: {
|
|
953
962
|
title: "条款变更",
|
|
954
|
-
body: "
|
|
963
|
+
body: "我们可能会随着服务的发展更新本条款。重大变更将至少在生效前 30 天通过电子邮件和应用程序公布,并附上新文本。如您不同意,可在该日期前提出异议或删除您的账户,并可在此之前导出您的数据。如您在该日期后继续使用本服务,则适用变更后的条款。仅对您有利的变更或法律要求的变更,无需上述提前通知即可生效,且不得提出异议。如您对某项变更提出异议,我们可在该变更生效之日关闭您的账户。如您已付费的期间超过该日期,我们将退还未使用部分的费用。",
|
|
955
964
|
},
|
|
956
965
|
language: {
|
|
957
966
|
title: "语言",
|
package/src/i18n/review.ts
CHANGED
|
@@ -309,6 +309,10 @@ export const KIT_LABEL_SAMPLES: Readonly<Record<string, readonly (readonly unkno
|
|
|
309
309
|
"legal.sections.terms.language.body": operatorSample,
|
|
310
310
|
"legal.translation.note": operatorSample,
|
|
311
311
|
"legal.translation.show": operatorSample,
|
|
312
|
+
// 0.51.3: the as-of line, with the date already written out.
|
|
313
|
+
"legal.updated": [["{{date}}"]],
|
|
314
|
+
// 0.51.4: a limited list's "Show all (n)", with the whole list's count.
|
|
315
|
+
"list.showAll": [[12], [1240]],
|
|
312
316
|
// 0.29.0: the sign-in and sign-up parts (docs/auth-harmonization.md).
|
|
313
317
|
"signIn.tagHint": [["{{taggedAddress}}"]],
|
|
314
318
|
"register.emailTagUse": [["{{address}}"]],
|
package/src/index.ts
CHANGED
package/src/lib/text-match.ts
CHANGED
|
@@ -29,6 +29,36 @@ export function foldForSearch(text: string, locale?: string): string {
|
|
|
29
29
|
return lower.normalize("NFD").replace(/\p{M}+/gu, "").replace(/ß/g, "ss");
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* A picker's query as its words, each folded (0.51.4, keksdose's /prices shop picker):
|
|
34
|
+
* "Migros Zürich" → `["migros", "zurich"]`. An empty or blank query has no words.
|
|
35
|
+
*/
|
|
36
|
+
export function searchWords(query: string, locale?: string): string[] {
|
|
37
|
+
return foldForSearch(query, locale).split(/\s+/).filter((word) => word !== "");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Whether a row matches a picker's query: EVERY word appears in at least one of the row's
|
|
42
|
+
* texts — "migros 8004" finds a row named "Migros · 8004 Zürich", and a row whose chain is
|
|
43
|
+
* its group and whose place is its label (pass both). Until 0.51.4 the whole query had to
|
|
44
|
+
* be ONE substring of one text, so two words found nothing unless they stood side by side
|
|
45
|
+
* in that order. One word matches exactly as before, and so does the old query when it
|
|
46
|
+
* was a substring. No words match everything.
|
|
47
|
+
*
|
|
48
|
+
* `words` from {@link searchWords}; `texts` as they are (folded here), `undefined` skipped.
|
|
49
|
+
*/
|
|
50
|
+
export function matchesSearch(
|
|
51
|
+
words: readonly string[],
|
|
52
|
+
texts: readonly (string | undefined)[],
|
|
53
|
+
locale?: string,
|
|
54
|
+
): boolean {
|
|
55
|
+
if (words.length === 0) return true;
|
|
56
|
+
// One haystack per row; a word holds no whitespace, so it cannot match across the
|
|
57
|
+
// newline between two texts.
|
|
58
|
+
const hay = texts.filter((t): t is string => t !== undefined).map((t) => foldForSearch(t, locale)).join("\n");
|
|
59
|
+
return words.every((word) => hay.includes(word));
|
|
60
|
+
}
|
|
61
|
+
|
|
32
62
|
/** {@link rankMatch}'s answer: lower is better, `-1` is no match. */
|
|
33
63
|
export type MatchRank = -1 | 0 | 1 | 2;
|
|
34
64
|
|
|
@@ -115,3 +115,11 @@ export function useSettingsFocus(anchor?: string | null): void {
|
|
|
115
115
|
[],
|
|
116
116
|
);
|
|
117
117
|
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* {@link useSettingsFocus} under a name for any page (0.51.4, keksdose run 89): the hook
|
|
121
|
+
* was always allowed on an app's own pages (keksdose's /reports/matching lands
|
|
122
|
+
* `?focus=matching-unmatched` on a card), but its name said Settings at every such call
|
|
123
|
+
* site. The same function, so the two cannot drift; `useSettingsFocus` stays.
|
|
124
|
+
*/
|
|
125
|
+
export const useFocusParam: typeof useSettingsFocus = useSettingsFocus;
|
package/src/shell/dev-menu.tsx
CHANGED
|
@@ -126,6 +126,11 @@ const isRow = (entry: TopBarMenuEntry) => entry.kind !== "heading" && entry.kind
|
|
|
126
126
|
*
|
|
127
127
|
* Nothing renders unless `enabled`, and nothing with no row to show. The panel scrolls
|
|
128
128
|
* (`TopBarActionMenu`'s `scrollable`): some 25 rows ran off a 390×844 phone.
|
|
129
|
+
*
|
|
130
|
+
* From `md` up the groups stand side by side, one column each, in that order (0.51.4,
|
|
131
|
+
* `TopBarActionMenu`'s `columns`; keksdose dev #640, Marcel: "Each group gets a column").
|
|
132
|
+
* "Back to {role}" stays under the roles. A desktop too narrow for all of them wraps
|
|
133
|
+
* the columns onto a second row; a phone keeps the one scrolling column.
|
|
129
134
|
*/
|
|
130
135
|
export function DevMenu<R extends string, P extends string>({
|
|
131
136
|
enabled,
|
|
@@ -254,6 +259,7 @@ export function DevMenu<R extends string, P extends string>({
|
|
|
254
259
|
aria-label={name}
|
|
255
260
|
entries={entries}
|
|
256
261
|
scrollable
|
|
262
|
+
columns
|
|
257
263
|
/>
|
|
258
264
|
);
|
|
259
265
|
}
|