@eifi1/ui-kit 0.51.3 → 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 +8 -2
- package/dist/components/legal-labels.js.map +1 -1
- package/dist/components/legal-page.d.ts +18 -1
- package/dist/components/legal-page.js +13 -0
- package/dist/components/legal-page.js.map +1 -1
- package/dist/components/legal.d.ts +40 -5
- package/dist/components/legal.js +29 -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 +11 -3
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/locales/en.js +15 -3
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/es.js +11 -3
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +11 -3
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +11 -3
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +11 -3
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +11 -3
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +2 -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 +7 -1
- package/src/components/legal-page.tsx +39 -0
- package/src/components/legal.tsx +69 -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 +9 -1
- package/src/i18n/locales/en.ts +4 -0
- package/src/i18n/locales/es.ts +9 -1
- package/src/i18n/locales/fr.ts +9 -1
- package/src/i18n/locales/hu.ts +9 -1
- package/src/i18n/locales/it.ts +9 -1
- package/src/i18n/locales/zh.ts +9 -1
- package/src/i18n/review.ts +2 -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
|
@@ -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",
|
|
@@ -936,6 +940,10 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
936
940
|
show: (o) => `Fassung auf ${o.bindingLanguage} anzeigen`,
|
|
937
941
|
},
|
|
938
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
|
+
},
|
|
939
947
|
sections: {
|
|
940
948
|
impressum: {
|
|
941
949
|
operator: {
|
|
@@ -992,7 +1000,7 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
992
1000
|
},
|
|
993
1001
|
changes: {
|
|
994
1002
|
title: "Änderungen dieser Bedingungen",
|
|
995
|
-
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.",
|
|
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.",
|
|
996
1004
|
},
|
|
997
1005
|
language: {
|
|
998
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",
|
|
@@ -916,6 +920,10 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
916
920
|
show: (o) => `Ver la versión en ${o.bindingLanguage}`,
|
|
917
921
|
},
|
|
918
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
|
+
},
|
|
919
927
|
sections: {
|
|
920
928
|
impressum: {
|
|
921
929
|
operator: {
|
|
@@ -972,7 +980,7 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
972
980
|
},
|
|
973
981
|
changes: {
|
|
974
982
|
title: "Cambios en estas condiciones",
|
|
975
|
-
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.",
|
|
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.",
|
|
976
984
|
},
|
|
977
985
|
language: {
|
|
978
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",
|
|
@@ -935,6 +939,10 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
935
939
|
show: (o) => `Afficher la version en ${o.bindingLanguage}`,
|
|
936
940
|
},
|
|
937
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
|
+
},
|
|
938
946
|
sections: {
|
|
939
947
|
impressum: {
|
|
940
948
|
operator: {
|
|
@@ -991,7 +999,7 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
991
999
|
},
|
|
992
1000
|
changes: {
|
|
993
1001
|
title: "Modifications des présentes conditions",
|
|
994
|
-
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.",
|
|
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.",
|
|
995
1003
|
},
|
|
996
1004
|
language: {
|
|
997
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",
|
|
@@ -923,6 +927,10 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
923
927
|
show: (o) => `Az irányadó változat megjelenítése (${o.bindingLanguage})`,
|
|
924
928
|
},
|
|
925
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
|
+
},
|
|
926
934
|
sections: {
|
|
927
935
|
impressum: {
|
|
928
936
|
operator: {
|
|
@@ -979,7 +987,7 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
979
987
|
},
|
|
980
988
|
changes: {
|
|
981
989
|
title: "A feltételek módosítása",
|
|
982
|
-
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.",
|
|
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.",
|
|
983
991
|
},
|
|
984
992
|
language: {
|
|
985
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",
|
|
@@ -922,6 +926,10 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
|
|
|
922
926
|
show: (o) => `Mostra la versione in ${o.bindingLanguage}`,
|
|
923
927
|
},
|
|
924
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
|
+
},
|
|
925
933
|
sections: {
|
|
926
934
|
impressum: {
|
|
927
935
|
operator: {
|
|
@@ -980,7 +988,7 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
|
|
|
980
988
|
},
|
|
981
989
|
changes: {
|
|
982
990
|
title: "Modifiche a queste condizioni",
|
|
983
|
-
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.",
|
|
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.",
|
|
984
992
|
},
|
|
985
993
|
language: {
|
|
986
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: "运营者信息",
|
|
@@ -896,6 +900,10 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
|
|
|
896
900
|
show: (o) => `查看${o.bindingLanguage}版本`,
|
|
897
901
|
},
|
|
898
902
|
updated: (date) => `最后更新:${date}`,
|
|
903
|
+
summary: {
|
|
904
|
+
title: "要点",
|
|
905
|
+
note: "本摘要仅供参考;只有完整文本具有约束力。",
|
|
906
|
+
},
|
|
899
907
|
sections: {
|
|
900
908
|
impressum: {
|
|
901
909
|
operator: {
|
|
@@ -952,7 +960,7 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
|
|
|
952
960
|
},
|
|
953
961
|
changes: {
|
|
954
962
|
title: "条款变更",
|
|
955
|
-
body: "我们可能会随着服务的发展更新本条款。重大变更将至少在生效前 30
|
|
963
|
+
body: "我们可能会随着服务的发展更新本条款。重大变更将至少在生效前 30 天通过电子邮件和应用程序公布,并附上新文本。如您不同意,可在该日期前提出异议或删除您的账户,并可在此之前导出您的数据。如您在该日期后继续使用本服务,则适用变更后的条款。仅对您有利的变更或法律要求的变更,无需上述提前通知即可生效,且不得提出异议。如您对某项变更提出异议,我们可在该变更生效之日关闭您的账户。如您已付费的期间超过该日期,我们将退还未使用部分的费用。",
|
|
956
964
|
},
|
|
957
965
|
language: {
|
|
958
966
|
title: "语言",
|
package/src/i18n/review.ts
CHANGED
|
@@ -311,6 +311,8 @@ export const KIT_LABEL_SAMPLES: Readonly<Record<string, readonly (readonly unkno
|
|
|
311
311
|
"legal.translation.show": operatorSample,
|
|
312
312
|
// 0.51.3: the as-of line, with the date already written out.
|
|
313
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]],
|
|
314
316
|
// 0.29.0: the sign-in and sign-up parts (docs/auth-harmonization.md).
|
|
315
317
|
"signIn.tagHint": [["{{taggedAddress}}"]],
|
|
316
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
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useId, useLayoutEffect, useRef } from "react";
|
|
2
|
-
import type { KeyboardEvent as ReactKeyboardEvent, ReactNode } from "react";
|
|
2
|
+
import type { CSSProperties, KeyboardEvent as ReactKeyboardEvent, ReactNode } from "react";
|
|
3
3
|
import { Link } from "react-router";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
5
|
import { HoverMenu, type HoverMenuProps } from "../components/hover-menu";
|
|
@@ -109,6 +109,40 @@ function toBlocks(entries: readonly TopBarMenuEntry[]): Block[] {
|
|
|
109
109
|
return blocks.filter((block) => block.kind === "loose" || block.rows.length > 0);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
/** One column of `columns` (0.51.4): a group and the loose entries after it, up to the
|
|
113
|
+
* next group — so a group's own way out behind a rule (DevMenu's "Back to {role}") stays
|
|
114
|
+
* under it instead of running across the panel. */
|
|
115
|
+
type LooseBlock = Extract<Block, { kind: "loose" }>;
|
|
116
|
+
type Column = { group: Extract<Block, { kind: "group" }>; after: Array<RowEntry | DividerEntry>; index: number };
|
|
117
|
+
|
|
118
|
+
/** `blocks` as the columns layout draws them: what comes before the first group, then a
|
|
119
|
+
* column per group. A rule that would end a column is dropped: the column's edge is the
|
|
120
|
+
* separation there. */
|
|
121
|
+
function toColumns(blocks: readonly Block[]): { lead: LooseBlock[]; columns: Column[] } {
|
|
122
|
+
const lead: LooseBlock[] = [];
|
|
123
|
+
const columns: Column[] = [];
|
|
124
|
+
blocks.forEach((block, index) => {
|
|
125
|
+
if (block.kind === "group") columns.push({ group: block, after: [], index });
|
|
126
|
+
else if (columns.length === 0) lead.push(block);
|
|
127
|
+
else columns[columns.length - 1]!.after.push(block.entry);
|
|
128
|
+
});
|
|
129
|
+
for (const column of columns) {
|
|
130
|
+
while (column.after.at(-1)?.kind === "divider") column.after.pop();
|
|
131
|
+
}
|
|
132
|
+
return { lead, columns };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* `columns`' panel: each column 14rem, the panel as wide as its columns (a CSS variable
|
|
137
|
+
* the list sets) but never wider than the glass, and from `md` up only. The grid places
|
|
138
|
+
* as many 14rem columns as that width holds, so a narrow desktop wraps the groups onto a
|
|
139
|
+
* second row instead of scrolling sideways. The header, the title and the footer span
|
|
140
|
+
* the row.
|
|
141
|
+
*/
|
|
142
|
+
const COLUMNS_PANEL =
|
|
143
|
+
"md:grid md:grid-cols-[repeat(auto-fill,minmax(14rem,1fr))] md:items-start md:gap-y-2 md:w-[min(calc(100vw-2rem),var(--menu-columns-width))]";
|
|
144
|
+
const SPAN_ALL = "md:col-span-full";
|
|
145
|
+
|
|
112
146
|
/**
|
|
113
147
|
* The non-interactive identity block at the top of an account menu — kastlan's name +
|
|
114
148
|
* role, keksdose's display name + email + role chip. It is text, not a `menuitem`: the
|
|
@@ -225,6 +259,7 @@ export function TopBarActionMenu({
|
|
|
225
259
|
align,
|
|
226
260
|
panelClassName,
|
|
227
261
|
scrollable = false,
|
|
262
|
+
columns = false,
|
|
228
263
|
triggerAttributes,
|
|
229
264
|
}: {
|
|
230
265
|
/** The trigger's face for the usual icon button. Ignored when `trigger` is given. */
|
|
@@ -308,6 +343,19 @@ export function TopBarActionMenu({
|
|
|
308
343
|
* header and the footer are inside the list and scroll with the rows.
|
|
309
344
|
*/
|
|
310
345
|
scrollable?: boolean;
|
|
346
|
+
/**
|
|
347
|
+
* From `md` up, lay the heading groups side by side, one column per group (0.51.4,
|
|
348
|
+
* `DevMenu`; keksdose dev #640, Marcel: "Each group gets a column. That way it would be
|
|
349
|
+
* much better visible for desktop users"). Below `md`, the one column as before.
|
|
350
|
+
*
|
|
351
|
+
* A column is a group and the loose rows after it up to the next heading, so a row
|
|
352
|
+
* behind a rule at the end of a group (DevMenu's "Back to {role}") stays in that
|
|
353
|
+
* group's column. Loose rows before the first heading, the header, the menu-wide
|
|
354
|
+
* `heading` and the footer span the panel. The DOM order is unchanged, so ↓/↑ walk the
|
|
355
|
+
* rows down one column and on into the next, as a reader reads them. `leading` and
|
|
356
|
+
* `children` rows take a cell each; add `md:col-span-full` to one that should span.
|
|
357
|
+
*/
|
|
358
|
+
columns?: boolean;
|
|
311
359
|
/** `data-*` attributes for the trigger itself — a tour's anchor (`data-tour`), a test
|
|
312
360
|
* hook. The parts built on this menu (`TourMenu`) pass theirs through here. */
|
|
313
361
|
triggerAttributes?: { [key: `data-${string}`]: string | number | boolean | undefined };
|
|
@@ -316,6 +364,10 @@ export function TopBarActionMenu({
|
|
|
316
364
|
// entry's `key`, which is the caller's text and may hold a space — and a space in
|
|
317
365
|
// `aria-labelledby` is a list separator.
|
|
318
366
|
const uid = useId();
|
|
367
|
+
const blocks = toBlocks(entries);
|
|
368
|
+
const grouped = columns ? toColumns(blocks) : null;
|
|
369
|
+
// A menu with no group has nothing to put side by side: the list as always.
|
|
370
|
+
const laidOut = grouped && grouped.columns.length > 0 ? grouped : null;
|
|
319
371
|
return (
|
|
320
372
|
<HoverMenu
|
|
321
373
|
aria-label={ariaLabel}
|
|
@@ -380,8 +432,8 @@ export function TopBarActionMenu({
|
|
|
380
432
|
const footerClass =
|
|
381
433
|
"flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted [&_a:hover]:text-primary [&_a]:rounded-sm [&_a:focus-visible]:outline-none [&_a:focus-visible]:ring-focus [&_a:focus-visible]:ring-brand";
|
|
382
434
|
/** One action or link row — loose, or inside a heading's group. */
|
|
383
|
-
const row = (entry: RowEntry) => (
|
|
384
|
-
<li key={entry.key}>
|
|
435
|
+
const row = (entry: RowEntry, className?: string) => (
|
|
436
|
+
<li key={entry.key} className={className}>
|
|
385
437
|
{entry.kind === "link" ? (
|
|
386
438
|
<MenuItem
|
|
387
439
|
href={entry.to}
|
|
@@ -413,11 +465,46 @@ export function TopBarActionMenu({
|
|
|
413
465
|
)}
|
|
414
466
|
</li>
|
|
415
467
|
);
|
|
468
|
+
/** A rule or a row outside any group; `span` stretches it across the columns. */
|
|
469
|
+
const loose = (block: LooseBlock, span: boolean) => {
|
|
470
|
+
const entry = block.entry;
|
|
471
|
+
if (entry.kind === "divider") {
|
|
472
|
+
return <li key={entry.key} className={cn("my-1 border-t border-subtle", span && SPAN_ALL)} />;
|
|
473
|
+
}
|
|
474
|
+
return row(entry, span ? SPAN_ALL : undefined);
|
|
475
|
+
};
|
|
476
|
+
/** A heading's group: its name, then its rows in a named `role="group"`. */
|
|
477
|
+
const group = (block: Extract<Block, { kind: "group" }>, i: number, tight: boolean, inColumn = false) => {
|
|
478
|
+
const headingId = `${uid}-group-${i}`;
|
|
479
|
+
return (
|
|
480
|
+
<li key={block.heading.key} role="none">
|
|
481
|
+
<div
|
|
482
|
+
id={headingId}
|
|
483
|
+
role="presentation"
|
|
484
|
+
className={cn(
|
|
485
|
+
"px-3 pb-0.5 text-caption font-semibold uppercase tracking-wide text-muted [overflow-wrap:anywhere]",
|
|
486
|
+
// A column's heading lines up with its neighbours' at the top of the
|
|
487
|
+
// grid row; under `md` the columns stack, and it spaces like the list's.
|
|
488
|
+
tight ? "pt-1" : cn("pt-2.5", inColumn && "md:pt-1"),
|
|
489
|
+
)}
|
|
490
|
+
>
|
|
491
|
+
{block.heading.label}
|
|
492
|
+
</div>
|
|
493
|
+
<ul role="group" aria-labelledby={headingId}>
|
|
494
|
+
{block.rows.map((entry) => row(entry))}
|
|
495
|
+
</ul>
|
|
496
|
+
</li>
|
|
497
|
+
);
|
|
498
|
+
};
|
|
416
499
|
return (
|
|
417
500
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- a Tab bubbling up from a row or footer link, see keepTabInsidePanel
|
|
418
|
-
<ul
|
|
501
|
+
<ul
|
|
502
|
+
className={cn("py-1", scrollable && SCROLLABLE_PANEL, laidOut && COLUMNS_PANEL, panelClassName)}
|
|
503
|
+
style={laidOut ? ({ "--menu-columns-width": `${laidOut.columns.length * 14}rem` } as CSSProperties) : undefined}
|
|
504
|
+
onKeyDown={keepTabInsidePanel}
|
|
505
|
+
>
|
|
419
506
|
{header && (
|
|
420
|
-
<MenuSection className="mb-1 border-b border-subtle px-3 py-2">
|
|
507
|
+
<MenuSection className={cn("mb-1 border-b border-subtle px-3 py-2", laidOut && SPAN_ALL)}>
|
|
421
508
|
<div className="truncate text-sm font-medium text-primary">{header.title}</div>
|
|
422
509
|
{header.subtitle != null && (
|
|
423
510
|
<div className="truncate text-xs text-muted">{header.subtitle}</div>
|
|
@@ -426,45 +513,42 @@ export function TopBarActionMenu({
|
|
|
426
513
|
</MenuSection>
|
|
427
514
|
)}
|
|
428
515
|
{heading && (
|
|
429
|
-
<li
|
|
516
|
+
<li
|
|
517
|
+
className={cn(
|
|
518
|
+
"px-3 py-1 text-micro font-semibold uppercase tracking-wide text-placeholder",
|
|
519
|
+
laidOut && SPAN_ALL,
|
|
520
|
+
)}
|
|
521
|
+
>
|
|
430
522
|
{heading}
|
|
431
523
|
</li>
|
|
432
524
|
)}
|
|
433
525
|
{leading?.(close)}
|
|
434
|
-
{
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
{block.heading.label}
|
|
458
|
-
</div>
|
|
459
|
-
<ul role="group" aria-labelledby={headingId}>
|
|
460
|
-
{block.rows.map(row)}
|
|
461
|
-
</ul>
|
|
462
|
-
</li>
|
|
463
|
-
);
|
|
464
|
-
})}
|
|
526
|
+
{laidOut ? (
|
|
527
|
+
<>
|
|
528
|
+
{laidOut.lead.map((block) => loose(block, true))}
|
|
529
|
+
{laidOut.columns.map((column, c) => (
|
|
530
|
+
// A column of the grid; under `md` a group as in the list, its rows
|
|
531
|
+
// following.
|
|
532
|
+
<li key={column.group.heading.key} role="none" data-menu-column="" className="min-w-0">
|
|
533
|
+
<ul role="none">
|
|
534
|
+
{group(column.group, column.index, c === 0 && laidOut.lead.length === 0, true)}
|
|
535
|
+
{column.after.map((entry) => loose({ kind: "loose", entry }, false))}
|
|
536
|
+
</ul>
|
|
537
|
+
</li>
|
|
538
|
+
))}
|
|
539
|
+
</>
|
|
540
|
+
) : (
|
|
541
|
+
blocks.map((block, i) => {
|
|
542
|
+
if (block.kind === "loose") return loose(block, false);
|
|
543
|
+
const before = blocks[i - 1];
|
|
544
|
+
// Under a rule (or at the top of the rows) the rule's margin is the gap;
|
|
545
|
+
// straight under another group's last row the heading makes its own.
|
|
546
|
+
return group(block, i, !before || (before.kind === "loose" && before.entry.kind === "divider"));
|
|
547
|
+
})
|
|
548
|
+
)}
|
|
465
549
|
{children?.(close)}
|
|
466
550
|
{footerBody != null && footerBody !== false && (
|
|
467
|
-
<MenuSection className="mt-1 border-t border-subtle px-3 py-2">
|
|
551
|
+
<MenuSection className={cn("mt-1 border-t border-subtle px-3 py-2", laidOut && SPAN_ALL)}>
|
|
468
552
|
{footerLabel ? (
|
|
469
553
|
<nav aria-label={footerLabel} className={footerClass}>
|
|
470
554
|
{footerBody}
|
package/src/shell.ts
CHANGED
|
@@ -41,7 +41,7 @@ export type {
|
|
|
41
41
|
SettingsLocationRules,
|
|
42
42
|
SettingsLocationResult,
|
|
43
43
|
} from "./settings/use-settings-route";
|
|
44
|
-
export { useSettingsFocus, SETTINGS_FOCUS_RING, SETTINGS_FOCUS_MS } from "./settings/use-settings-focus";
|
|
44
|
+
export { useSettingsFocus, useFocusParam, SETTINGS_FOCUS_RING, SETTINGS_FOCUS_MS } from "./settings/use-settings-focus";
|
|
45
45
|
export { SettingsSection } from "./settings/settings-section";
|
|
46
46
|
export type { SettingsSectionProps } from "./settings/settings-section";
|
|
47
47
|
export { useSettingsLayout } from "./settings/settings-context";
|