@nxgt/material 3.50.0 → 3.52.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/{async-slice-3loEtzUY.js → async-slice-BGtmF3K5.js} +2 -2
- package/dist/{button-BRUaHD8z.js → button-Ct0KRBsN.js} +1 -1
- package/dist/charts.js +3 -3
- package/dist/{chip-DneTrtNj.js → chip-Ca1SEd70.js} +2 -2
- package/dist/{code-editor-R_nPN_-d.js → code-editor-DtwRhK8B.js} +6 -6
- package/dist/code-editor.js +5 -5
- package/dist/{code-language-items-BKEUhQlF.js → code-language-items-CEclGxhA.js} +2 -2
- package/dist/components/ui/layout/app-shell/activity-backdrop-shapes.css +14 -9
- package/dist/components/ui/layout/auth-card/auth-card-backdrop.css +2 -2
- package/dist/{components-D6xFLcoE.js → components-CzELzsOi.js} +6006 -5824
- package/dist/components.js +19 -19
- package/dist/{dialog-S7dLsYRZ.js → dialog-BIy04Hpd.js} +4 -4
- package/dist/dnd.js +1 -1
- package/dist/{dropdown-menu-XLlxfDgq.js → dropdown-menu-B0Kd8x3G.js} +1 -1
- package/dist/editor.js +9 -9
- package/dist/{empty-state-Dsf6R-Zo.js → empty-state-CKxORwFE.js} +2 -2
- package/dist/{escape-owner-B9eCwjLw.js → escape-owner-BGKjiglh.js} +1 -1
- package/dist/{field-blur-5uRDFHvB.js → field-blur-Dz1zPaYK.js} +1 -1
- package/dist/{field-blur-context-Cwt4TuBq.js → field-blur-context-1T6GkSNc.js} +1 -1
- package/dist/hooks.js +2 -2
- package/dist/{hover-card-PHUgRSjJ.js → hover-card-BwQ9IRxa.js} +2 -2
- package/dist/{i18n-provider-DPM_ALQ4.js → i18n-provider-BFNrM0Qu.js} +14 -12
- package/dist/i18n.js +5 -5
- package/dist/{icon-badge-Dh6-FNOF.js → icon-badge-D5Ns7ndZ.js} +3 -3
- package/dist/{icon-button-DSC2-IAG.js → icon-button-VzdqY_Tv.js} +1 -1
- package/dist/lib/components/ui/collections/data-table/data-table-selection-host.d.ts +7 -0
- package/dist/lib/components/ui/collections/data-table/internal.d.ts +1 -0
- package/dist/lib/components/ui/collections/data-table/partials/layouts/data-table-list-bar.d.ts +2 -1
- package/dist/lib/components/ui/collections/server-table/partials/filtered-server-table.d.ts +9 -0
- package/dist/lib/components/ui/collections/server-table/partials/server-table-band-view.d.ts +18 -0
- package/dist/lib/components/ui/collections/server-table/partials/server-table-band.d.ts +10 -1
- package/dist/lib/components/ui/collections/server-table/partials/server-table-bulk-buttons.d.ts +3 -2
- package/dist/lib/components/ui/collections/server-table/partials/server-table-bulk-more.d.ts +4 -2
- package/dist/lib/components/ui/collections/server-table/partials/server-table-bulk.d.ts +2 -1
- package/dist/lib/components/ui/collections/server-table/partials/server-table-controls.d.ts +16 -0
- package/dist/lib/components/ui/collections/server-table/partials/server-table-grid.d.ts +3 -1
- package/dist/lib/components/ui/collections/server-table/partials/server-table-selection-bar.d.ts +17 -0
- package/dist/lib/components/ui/collections/server-table/partials/server-table-view.d.ts +15 -0
- package/dist/lib/components/ui/collections/server-table/partials/use-server-table-list-root.d.ts +10 -0
- package/dist/lib/components/ui/collections/server-table/partials/use-server-table-phone-row.d.ts +15 -0
- package/dist/lib/components/ui/collections/server-table/partials/use-server-table-selection-slots.d.ts +24 -0
- package/dist/lib/components/ui/collections/server-table/use-selection-band.d.ts +14 -0
- package/dist/lib/components/ui/display/change-history/types.d.ts +2 -1
- package/dist/lib/components/ui/display/description/description.d.ts +2 -2
- package/dist/lib/components/ui/fields/contacts/placeholders.d.ts +1 -1
- package/dist/lib/components/ui/fields/verification-code/use-resend-focus.d.ts +4 -1
- package/dist/lib/components/ui/layout/app-shell/use-keep-shapes-inside.d.ts +12 -1
- package/dist/lib/components/ui/primitives/tabs/tabs-overflow-classes.d.ts +8 -5
- package/dist/lib/components/ui/primitives/tabs/use-tabs-overflow.d.ts +4 -3
- package/dist/lib/i18n/i18n-provider.d.ts +14 -3
- package/dist/lib/i18n/resources/en/en.d.ts +3 -0
- package/dist/lib/i18n/resources/en/material.json.d.ts +4 -1
- package/dist/lib/i18n/resources/fr/fr.d.ts +3 -0
- package/dist/lib/i18n/resources/fr/material.json.d.ts +4 -1
- package/dist/lib/i18n/resources/resources.d.ts +6 -0
- package/dist/lib/i18n/translate-material.d.ts +7 -1
- package/dist/lib/i18n/translator.d.ts +1 -1
- package/dist/lib/i18n/types.d.ts +6 -0
- package/dist/lib/i18n/use-material-translation.d.ts +4 -0
- package/dist/lib.js +1 -1
- package/dist/main.js +25 -25
- package/dist/map.js +8 -8
- package/dist/material.css +1 -1
- package/dist/pdf-reader.js +1 -1
- package/dist/print.js +5 -4
- package/dist/{public-vxiijIJF.js → public-D-J3nZFm.js} +9 -9
- package/dist/{rich-code-block-BwvCXPqq.js → rich-code-block-Ig0ERAa2.js} +5 -5
- package/dist/{sortable-provider-D2pAFWQB.js → sortable-provider-DfPkSN90.js} +2 -2
- package/dist/{spinner-BpVwI1ps.js → spinner-KQb3YuR_.js} +1 -1
- package/dist/{stored-language-Beyj2ult.js → stored-language-Cb9FMEwk.js} +8 -2
- package/dist/theme-picker.js +2 -2
- package/dist/{theme-toggle-BTYRPkP4.js → theme-toggle-BY-SpsFV.js} +1 -1
- package/dist/{toolbar-items-CIMo4F9q.js → toolbar-items-30w9rG5h.js} +4 -4
- package/dist/translate-material-BPl8TQLg.js +20 -0
- package/dist/{translator-CBgIb3zP.js → translator-BnQXtpSZ.js} +1 -1
- package/dist/{use-chat-composer-D8UAsX0f.js → use-chat-composer-BSKJRYMB.js} +1678 -1656
- package/dist/{use-heading-spy-C5LXtA8Z.js → use-heading-spy-BgXA8uz6.js} +1 -1
- package/dist/use-material-translation-ByM3gD9R.js +14 -0
- package/docs/components/data-display.md +3 -3
- package/docs/components/data-table-filter-and-lists.md +38 -5
- package/docs/components/primitives.md +1 -1
- package/docs/guides/backgrounds.md +3 -1
- package/docs/guides/cards-and-tiles.md +3 -0
- package/docs/guides/helpers.md +1 -1
- package/docs/guides/i18n.md +30 -8
- package/docs/guides/two-factor.md +2 -1
- package/docs/previews/guides-i18n-i18nprovider.webp +0 -0
- package/docs/previews/guides-i18n-translated-components.webp +0 -0
- package/docs/troubleshooting.md +3 -2
- package/lib/components/ui/layout/app-shell/activity-backdrop-shapes.css +14 -9
- package/lib/components/ui/layout/auth-card/auth-card-backdrop.css +2 -2
- package/package.json +1 -1
- package/dist/translate-material-DEUlaL_1.js +0 -12
- package/dist/use-material-translation-DWWeeg-B.js +0 -14
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as e } from "./i18n-provider-
|
|
1
|
+
import { r as e } from "./i18n-provider-BFNrM0Qu.js";
|
|
2
2
|
import { _ as t, g as n, h as r, n as i, v as a, y as o } from "./number.utils-BG_eEt5g.js";
|
|
3
3
|
import { useCallback as s, useEffect as c, useMemo as l, useRef as u, useState as d } from "react";
|
|
4
4
|
import { busySettler as f, busySettler as p, createSubmitGuard as m, createSubmitGuard as h } from "@nxgt/material-core/submit-guard";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { r as e } from "./i18n-provider-BFNrM0Qu.js";
|
|
2
|
+
import { t } from "./translate-material-BPl8TQLg.js";
|
|
3
|
+
import { useCallback as n } from "react";
|
|
4
|
+
//#region lib/i18n/use-material-translation.ts
|
|
5
|
+
function r() {
|
|
6
|
+
let r = e(), i = r?.language, a = r?.resources;
|
|
7
|
+
return {
|
|
8
|
+
t: n((e, n, r) => t(i, e, n, r, a), [i, a]),
|
|
9
|
+
language: i,
|
|
10
|
+
hasProvider: !!r
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { r as t };
|
|
@@ -642,7 +642,7 @@ import { Description } from '@nxgt/material/components';
|
|
|
642
642
|
</div>
|
|
643
643
|
```
|
|
644
644
|
|
|
645
|
-
`label` and `value` are its main props; the rest go to the `div`. A `value` of `null`, `undefined`, `false` or `''` renders nothing (`0` is shown), so optional fields need no guard. Inside a `variant="panels"` list a `Description` must sit in a `DescriptionList.Group`; otherwise it renders its stand-alone markup. The label is a small
|
|
645
|
+
`label` and `value` are its main props; the rest go to the `div`. A `value` of `null`, `undefined`, `false` or `''` with no `lines` and no `children` renders nothing (`0` is shown), so optional fields need no guard. `children` alone are the value (`<Description label="Note">text</Description>`); after a `value` they follow it. Inside a `variant="panels"` list a `Description` must sit in a `DescriptionList.Group`; otherwise it renders its stand-alone markup. The label is a small
|
|
646
646
|
muted caption above the value (not a title). `Description` takes one cell of
|
|
647
647
|
the grid it is in; pass `className="col-start-full"` for a full-width row. It takes `lines` anywhere; inside a [`DescriptionList`](#descriptionlist) also `span` and `labelPosition`.
|
|
648
648
|
|
|
@@ -686,7 +686,7 @@ row) or a number of columns (used once that many fit; at most `maxColumns`, and
|
|
|
686
686
|
field uses dense packing: the fields after it fill the cells before it, so they
|
|
687
687
|
may be drawn above it while the DOM and reading order stay the source order.
|
|
688
688
|
Put the full-width field where that reads fine, or last. A multi-line value
|
|
689
|
-
(an address) takes `lines={[…]}` or `children`, never a string to split. Entries of `lines` that are `null`, `false` or `""` are skipped, and a `Description` whose `lines` are all empty and that has no `value` renders nothing.
|
|
689
|
+
(an address) takes `lines={[…]}` or `children`, never a string to split. Entries of `lines` that are `null`, `false` or `""` are skipped, and a `Description` whose `lines` are all empty and that has no `value` or `children` renders nothing.
|
|
690
690
|
|
|
691
691
|
```tsx
|
|
692
692
|
<DescriptionList variant="panels">
|
|
@@ -1087,7 +1087,7 @@ yours, the component names no domain.
|
|
|
1087
1087
|
|
|
1088
1088
|
| Prop | Type | Default | Effect |
|
|
1089
1089
|
| --- | --- | --- | --- |
|
|
1090
|
-
| `entries` | `ChangeHistoryEntry[]` | — | `id`, `kind`, `at` (`Date`, string or number), `author` (`name`, `src`), `changes` (`ChangeHistoryChange[]`: `field`, `before`, `after`, `redacted`) |
|
|
1090
|
+
| `entries` | `ChangeHistoryEntry[]` | — | `id`, `kind`, `at` (`Date`, string or number), `author` (`name`, `src`), `changes` (optional, `ChangeHistoryChange[]`: `field`, `before`, `after`, `redacted`; left out or `[]`, the entry shows its sentence, author and time with no change list) |
|
|
1091
1091
|
| `kinds` | `Record<string, ChangeHistoryKindOverride>` | built-ins | `label`, `verb`, `icon` (`null` removes it), `tone` per kind; `creation` (default true for `created`) makes an entry list values only |
|
|
1092
1092
|
| `variant` | `'rail' \| 'cards'` | `'rail'` | the look |
|
|
1093
1093
|
| `groupBy` | `'day' \| 'none'` | `'day'` | a heading per day (sticky on the rail), or one list in the order given |
|
|
@@ -244,8 +244,10 @@ with a `select` column and `actions`, the toolbar keeps its band while
|
|
|
244
244
|
nothing is selected, so the first selection does not move the rows (on a
|
|
245
245
|
wide screen; on a phone the extra lines still push them down). Below 768px
|
|
246
246
|
the declarative `bulkActions` fold past the third into a "More" menu in the
|
|
247
|
-
toolbar
|
|
248
|
-
|
|
247
|
+
toolbar (a `ServerTable` without `filter`, or with the facets panel) and in a
|
|
248
|
+
phone's second row (#1719), as the cards and tiles do (#1797). The
|
|
249
|
+
[selection band](#the-selection-band) keeps one action and puts the rest in
|
|
250
|
+
"More".
|
|
249
251
|
|
|
250
252
|
```tsx
|
|
251
253
|
<DataTable
|
|
@@ -293,6 +295,33 @@ press elsewhere is never pulled back. The footer's selected count is a polite
|
|
|
293
295
|
status, so the first selection is announced ("1 row selected") when its bar
|
|
294
296
|
shows up.
|
|
295
297
|
|
|
298
|
+
### The selection band
|
|
299
|
+
|
|
300
|
+
With `bulkActions` and a `filter` (not `variant: 'facets'`), the first
|
|
301
|
+
selected row turns the band that holds the filter bar into a selection bar, in
|
|
302
|
+
place and on the same row: "N selected", the bulk actions, and a tonal
|
|
303
|
+
"Cancel" that clears the selection (#1718). The search and the page's
|
|
304
|
+
`actions` stay mounted, hidden (`invisible`, `inert`) and keep their size, so
|
|
305
|
+
the table does not move; clearing the selection brings them back. The bar's
|
|
306
|
+
height is the row's (40px, 44px on a coarse pointer). From 768px every
|
|
307
|
+
declarative action keeps its button; below it the bar is one row: the first
|
|
308
|
+
action keeps its button, the others go into "More" (an icon, still named),
|
|
309
|
+
and "Cancel" is an icon (its name and tooltip stay). Bulk actions written as a
|
|
310
|
+
function are rendered as they are, in the same place.
|
|
311
|
+
|
|
312
|
+
After "Cancel" the focus goes back to the control that started the selection
|
|
313
|
+
(the row's or the header's checkbox) when it is still on the page, else to the
|
|
314
|
+
list; a selection cleared another way (a bulk action's `selection.clear()`, a
|
|
315
|
+
new query) keeps its own focus rule. While rows are selected the search is
|
|
316
|
+
`inert`, so `filterRef.focus()` does nothing: cancel the selection first. The count is told once, politely, by the
|
|
317
|
+
footer's status ("N rows selected"); the bar's own count is plain text. The
|
|
318
|
+
cards' and tiles' list bar leaves its count and "Clear selection" to the bar.
|
|
319
|
+
A phone's second row of a list in cards or tiles with `actions` (#1719) is the
|
|
320
|
+
selection bar there, as before. Without `filter` (or with the facets panel) the
|
|
321
|
+
band has no filter bar to replace, and the bulk actions stay in the table's
|
|
322
|
+
toolbar. Text keys: `material.server-table.bulk-selected`, `bulk-cancel`,
|
|
323
|
+
`bulk-bar` (English and French).
|
|
324
|
+
|
|
296
325
|
### Focus after a bulk action
|
|
297
326
|
|
|
298
327
|
When a bulk action clears the selection, its buttons unmount and the focus
|
|
@@ -410,7 +439,9 @@ grow the toolbar. Without the `select` column, or without `actions`, no band
|
|
|
410
439
|
is kept above the table. `reserveActions={false}` keeps none either: the bar
|
|
411
440
|
arrives on the first selection with a short grow (none under reduced motion),
|
|
412
441
|
and the rows move down by its height. `ServerTable` passes `false`, so its
|
|
413
|
-
bulk bar leaves no empty row under the band while nothing is selected.
|
|
442
|
+
bulk bar leaves no empty row under the band while nothing is selected. With
|
|
443
|
+
`filter` it has no toolbar row at all: the band's selection bar holds the bulk
|
|
444
|
+
actions ([the selection band](#the-selection-band)).
|
|
414
445
|
|
|
415
446
|
```tsx
|
|
416
447
|
<DataTable
|
|
@@ -843,7 +874,8 @@ export default function Students() {
|
|
|
843
874
|
onRetry={() => fetcher.reload()}
|
|
844
875
|
/>
|
|
845
876
|
```
|
|
846
|
-
- **Selection.** With `bulkActions(ids, selection)`, rows are selectable
|
|
877
|
+
- **Selection.** With `bulkActions(ids, selection)`, rows are selectable
|
|
878
|
+
(see [the selection band](#the-selection-band) for where the bulk actions show);
|
|
847
879
|
the selection is kept across pages and drops on a new query.
|
|
848
880
|
`selection.clear()` empties it and moves the focus to the table
|
|
849
881
|
(`tabindex="-1"`, by script only; the list of cards or tiles in those layouts); `selection.deselect(ids)` drops rows
|
|
@@ -1036,7 +1068,8 @@ rows (the bulk bar is not drawn under it). With the declarative list form of
|
|
|
1036
1068
|
(2)", named "Publish 2 rows"), hidden at 0 rows; the buttons wrap onto a second
|
|
1037
1069
|
line rather than scroll, and past the third action the rest go into a "More"
|
|
1038
1070
|
menu (`material.server-table.bulk-more`), each item keeping its count (the same
|
|
1039
|
-
fold applies below 768px to every layout
|
|
1071
|
+
fold applies below 768px to every layout in the toolbar and in this row; the
|
|
1072
|
+
[selection band](#the-selection-band) of a list with `filter` keeps one action). From
|
|
1040
1073
|
768px the buttons read "Label (n)" as before. When the focused button
|
|
1041
1074
|
disappears the focus goes to the next one, else to "More", else to "Select all"; an action past `max` shows its notice there (an inline text, or a disabled More item). The function
|
|
1042
1075
|
form (`bulkActions={(ids) => node}`) is drawn whole in the row, so keep it to
|
|
@@ -735,7 +735,7 @@ reached with the arrow keys. The list scrolls sideways when the tabs do not
|
|
|
735
735
|
fit (its scrollbar hidden), which suits a phone or a narrow popover. While it
|
|
736
736
|
overflows, each side with hidden tabs fades and gets a small scroll button
|
|
737
737
|
("Scroll tabs left" / "Scroll tabs right", from `material.tabs.*`; out of the
|
|
738
|
-
tab order
|
|
738
|
+
tab order; on a touch screen 44px wide and as tall as the list, so it never covers content); the selected and the focused tab are
|
|
739
739
|
scrolled into view, instantly under reduced motion. A list that fits has
|
|
740
740
|
neither, and neither is in the server markup. `segmented` does the same.
|
|
741
741
|
|
|
@@ -545,7 +545,9 @@ good.
|
|
|
545
545
|
- The server renders every glyph. The drop happens after the first measure, on the client, in one frame (boxes read
|
|
546
546
|
before any write), so the markup never differs between server and client.
|
|
547
547
|
- A dropped glyph fades out in 150 ms (none under `prefers-reduced-motion`) and fades back when the content moves
|
|
548
|
-
away. It runs again on resize and when the content changes.
|
|
548
|
+
away. It runs again on resize and when the content changes. A glyph the first pass drops is hidden at once: the fade
|
|
549
|
+
starts a frame later (`data-settled` on the scene), so no glyph is seen over a paragraph for the length of a fade on
|
|
550
|
+
a reload.
|
|
549
551
|
- The open areas keep their glyphs; the space behind and between cards is empty. `keepClear={false}` on an `AuthCard`
|
|
550
552
|
lets the glyphs run under the card.
|
|
551
553
|
- **`keepClear="gaps"`** (on `ActivityLayout` and `AuthCard`, opt-in; `true` stays the default) lets a glyph stay between
|
|
@@ -144,6 +144,9 @@ is not `focusable`). On a narrow list (under 30rem) the bar stays on one row and
|
|
|
144
144
|
Clear shrinks to an icon button; its label stays its accessible name, and it has
|
|
145
145
|
a tooltip. Do not add your own in `actions`: that one is the bulk bar's.
|
|
146
146
|
Once a bulk action clears the selection and the focus is lost, the list takes it.
|
|
147
|
+
In a `ServerTable` with `filter` and `bulkActions`, the band's own selection bar
|
|
148
|
+
tells the count and has "Cancel" (#1718), so the list bar leaves its count and
|
|
149
|
+
"Clear selection" out ([the selection band](../components/data-table-filter-and-lists.md#the-selection-band)).
|
|
147
150
|
|
|
148
151
|
Inside a `ServerTable` with `filter` and `actions`, below 768px, the bar has no
|
|
149
152
|
row of its own: its "Select all" (with a short visible label, "Select all"),
|
package/docs/guides/helpers.md
CHANGED
|
@@ -265,7 +265,7 @@ flag. Storybook: `Guides/Hooks/useSubmitOnce`.
|
|
|
265
265
|
| `formatMessage(message, language, values?, { onError }?)` | Formats one ICU message (`{name}`, plurals, selects) in any BCP 47 `language` with the translator's engine, for a message that is not in a bundle (a server-side catalogue). Cached per message; one that does not format is logged and returned unformatted, or passed to `onError` as a `FormatMessageError` (reason, key, source) without logging. |
|
|
266
266
|
| `createTypedTranslation(translate)` | Turns a translator into a typed `useTranslation()` hook. |
|
|
267
267
|
| `translate`, `useMaterialTranslation()` | Translator / hook bound to the package's own `material.*` keys. `useMaterialTranslation().t(key, fallback)` returns `fallback` without a provider. |
|
|
268
|
-
| `translateMaterial(language, key, fallback, values?)` | The same as `useMaterialTranslation().t`, with the language passed as a value: no provider, no hook. For a PDF `footer` function or a server. `'fr-CA'` reads `fr`; an unknown language formats `fallback`. |
|
|
268
|
+
| `translateMaterial(language, key, fallback, values?, resources?)` | The same as `useMaterialTranslation().t`, with the language passed as a value: no provider, no hook. `resources` is your merged bundle (stable object), read before the base one. For a PDF `footer` function or a server. `'fr-CA'` reads `fr`; an unknown language formats `fallback`. |
|
|
269
269
|
| `getLanguage()` | Language read from `localStorage`, else `FALLBACK_LANGUAGE`. |
|
|
270
270
|
| `LANGUAGE_KEY`, `FALLBACK_LANGUAGE`, `SUPPORTED_LANGUAGES` | Storage key (`'language'`), fallback (`'en'`) and supported languages (`en`, `fr`). |
|
|
271
271
|
|
package/docs/guides/i18n.md
CHANGED
|
@@ -63,6 +63,7 @@ function translateMaterial(
|
|
|
63
63
|
key: MaterialLocaleKey,
|
|
64
64
|
fallback: string,
|
|
65
65
|
values?: TranslationContext,
|
|
66
|
+
resources?: ResourceBundle, // your merged bundle, a stable object (module scope)
|
|
66
67
|
): string;
|
|
67
68
|
```
|
|
68
69
|
|
|
@@ -189,6 +190,7 @@ if (failure) {
|
|
|
189
190
|
| `initialLanguage` | `Language` | — | Used as-is for the first render when supported, and `localStorage` is not read. Set it in SSR. See [below](#server-rendering) |
|
|
190
191
|
| `storageKey` | `string` | `'language'` | `localStorage` key the choice is read from and written to |
|
|
191
192
|
| `supportedLanguages` | `Language[]` | `['en', 'fr']` | What `changeLanguage` accepts and `LanguageSwitcher` lists |
|
|
193
|
+
| `resources` | `ResourceBundle` | — | Your `mergeResources(...)` result: the components read their `material.*` words from it before the base bundle. Pass a stable object (module scope) |
|
|
192
194
|
| `onLanguageChange` | `(language) => void` | — | Called after a successful change: save it to a cookie, a profile, analytics |
|
|
193
195
|
|
|
194
196
|
`changeLanguage` with an unsupported value logs
|
|
@@ -208,7 +210,8 @@ const context = useOptionalI18nContext(); // null outside the provider
|
|
|
208
210
|
third language is not in the type today, so adding one to
|
|
209
211
|
`supportedLanguages` takes a cast. The runtime accepts it: your translator
|
|
210
212
|
uses your strings for it, and the components fall back to their English copy,
|
|
211
|
-
formatted.
|
|
213
|
+
formatted. A third language you define under `material.*` and give through
|
|
214
|
+
`resources` now reaches the components.
|
|
212
215
|
|
|
213
216
|
```tsx
|
|
214
217
|
const LANGUAGES = ['en', 'fr', 'de'] as Language[];
|
|
@@ -498,8 +501,8 @@ material.emoji.groups.flags; // "Flags" / "Drapeaux"
|
|
|
498
501
|
|
|
499
502
|
A group your `EmojiItem`s name that is not in this list (`hand_signs`) reads
|
|
500
503
|
as its words in English (`Hand signs`). As for every `material.*` key above,
|
|
501
|
-
|
|
502
|
-
the
|
|
504
|
+
your own translator sees a key you add; the components see it too once you hand
|
|
505
|
+
them the merged resources (see "Overriding a component's words" below).
|
|
503
506
|
|
|
504
507
|
```tsx
|
|
505
508
|
// Under <I18nProvider defaultLanguage="fr">
|
|
@@ -509,11 +512,30 @@ the tab does not.
|
|
|
509
512
|
<Spinner variant="4" /> // role="img" aria-label="Chargement..."
|
|
510
513
|
```
|
|
511
514
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
515
|
+
### Overriding a component's words
|
|
516
|
+
|
|
517
|
+
Give the provider the merged resources and every component translates through
|
|
518
|
+
them, so an override under `material.*` changes what it renders:
|
|
519
|
+
|
|
520
|
+
```tsx
|
|
521
|
+
import { mergeResources, resources as materialResources } from '@nxgt/material/i18n';
|
|
522
|
+
|
|
523
|
+
const resources = mergeResources(materialResources, {
|
|
524
|
+
en: { material: { 'recovery-codes-status': { title: 'Backup codes' } } },
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
<I18nProvider defaultLanguage="en" resources={resources}>
|
|
528
|
+
<RecoveryCodesStatus remaining={3} onRegenerate={regenerate} /> {/* title: "Backup codes" */}
|
|
529
|
+
</I18nProvider>
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
Without `resources`, the components read the package's own bundle: an override
|
|
533
|
+
is visible only through **your** translator, and defining `material.command.title`
|
|
534
|
+
does not change the title `CommandDialog` renders. Pass a stable object
|
|
535
|
+
(module scope), not one built in a render. A component's `labels` prop still
|
|
536
|
+
wins over both. Outside a component, `translateMaterial` takes the merged
|
|
537
|
+
resources as a fifth argument and `zodLocaleError` takes `translate`; the
|
|
538
|
+
toast presets and the toast close label still read the package's bundle.
|
|
517
539
|
|
|
518
540
|
Each time `mergeResources` runs outside production, overlapping leaves are
|
|
519
541
|
reported, one line per language:
|
|
@@ -62,7 +62,8 @@ in `@nxgt/material-core/two-factor`.
|
|
|
62
62
|
What stays in the app: every request, the mapping of a server error to the
|
|
63
63
|
props above, where the challenge is kept, the replay of the action a step-up
|
|
64
64
|
unblocked, the leave guard around the new recovery codes, and all wording
|
|
65
|
-
(`labels`, or your translations under `material
|
|
65
|
+
(`labels`, or your translations under `material.*`, given to
|
|
66
|
+
`I18nProvider` as `resources`, see [i18n](i18n.md#overriding-a-components-words)).
|
|
66
67
|
|
|
67
68
|
## On a phone and for assistive technology
|
|
68
69
|
|
|
Binary file
|
|
Binary file
|
package/docs/troubleshooting.md
CHANGED
|
@@ -3902,8 +3902,9 @@ followed by the list of keys, e.g. `"en": material.command.title. App resources
|
|
|
3902
3902
|
take precedence over the base bundle at these keys.`
|
|
3903
3903
|
**Why:** your resources define leaves under the `material` namespace, which
|
|
3904
3904
|
this package reserves for its own strings. The override reaches your app's
|
|
3905
|
-
own translator only
|
|
3906
|
-
|
|
3905
|
+
own translator only, unless you also give the merged object to
|
|
3906
|
+
`<I18nProvider resources={resources}>`: without it the package's components
|
|
3907
|
+
translate from their own bundle, so their text does **not** change.
|
|
3907
3908
|
**Fix:**
|
|
3908
3909
|
|
|
3909
3910
|
```ts
|
|
@@ -18,15 +18,20 @@
|
|
|
18
18
|
visibility: hidden;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
/* A shape over the page's text, controls or surfaces (cards, tables, lists)
|
|
22
|
-
* clear (watch-content.ts): it is hidden,
|
|
23
|
-
* moon, the planet, the eclipse: `.pt.mg`)
|
|
24
|
-
* (`.pt.mh`). The scene stays invisible until
|
|
25
|
-
* flashes over the content.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
[data-
|
|
29
|
-
[data-
|
|
21
|
+
/* A shape over the page's text, controls or surfaces (cards, tables, lists)
|
|
22
|
+
* fades out and comes back once clear (watch-content.ts): it is hidden,
|
|
23
|
+
* never moved. A compound body (the moon, the planet, the eclipse: `.pt.mg`)
|
|
24
|
+
* is hidden whole, with its halo (`.pt.mh`). The scene stays invisible until
|
|
25
|
+
* the first check, so nothing flashes over the content. The fade waits for
|
|
26
|
+
* `data-settled`, set a frame after the first pass: a shape that pass drops
|
|
27
|
+
* is hidden at once, never seen fading out over the text on a reload. */
|
|
28
|
+
[data-keep-inside][data-settled] .mo > *,
|
|
29
|
+
[data-keep-inside][data-settled] .pt,
|
|
30
|
+
[data-slot="activity-layout-backdrop"]
|
|
31
|
+
[data-background][data-settled]
|
|
32
|
+
.mo
|
|
33
|
+
> *,
|
|
34
|
+
[data-slot="activity-layout-backdrop"] [data-background][data-settled] .pt {
|
|
30
35
|
transition: opacity 150ms ease;
|
|
31
36
|
}
|
|
32
37
|
/* Important: a preset sets its own opacity on a body (`.md`, the dark
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
visibility: hidden;
|
|
14
14
|
}
|
|
15
15
|
/* A shape over the card or the brand row fades out (watch-content.ts). */
|
|
16
|
-
[data-slot="auth-card-backdrop"] [data-background] .mo > *,
|
|
17
|
-
[data-slot="auth-card-backdrop"] [data-background] .pt {
|
|
16
|
+
[data-slot="auth-card-backdrop"] [data-background][data-settled] .mo > *,
|
|
17
|
+
[data-slot="auth-card-backdrop"] [data-background][data-settled] .pt {
|
|
18
18
|
transition: opacity 150ms ease;
|
|
19
19
|
}
|
|
20
20
|
[data-slot="auth-card-backdrop"] [data-background] .mo > [data-hidden],
|
package/package.json
CHANGED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import "./stored-language-Beyj2ult.js";
|
|
2
|
-
import { a as e, r as t } from "./translator-CBgIb3zP.js";
|
|
3
|
-
//#region lib/i18n/translate-material.ts
|
|
4
|
-
function n(n, r, i, a) {
|
|
5
|
-
if (n) for (let e of /* @__PURE__ */ new Set([n, n.split("-")[0]])) {
|
|
6
|
-
let n = t(r, a, () => e);
|
|
7
|
-
if (n !== r) return n;
|
|
8
|
-
}
|
|
9
|
-
return e(i, n || "en", a);
|
|
10
|
-
}
|
|
11
|
-
//#endregion
|
|
12
|
-
export { n as t };
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { r as e } from "./i18n-provider-DPM_ALQ4.js";
|
|
2
|
-
import { t } from "./translate-material-DEUlaL_1.js";
|
|
3
|
-
import { useCallback as n } from "react";
|
|
4
|
-
//#region lib/i18n/use-material-translation.ts
|
|
5
|
-
function r() {
|
|
6
|
-
let r = e(), i = r?.language;
|
|
7
|
-
return {
|
|
8
|
-
t: n((e, n, r) => t(i, e, n, r), [i]),
|
|
9
|
-
language: i,
|
|
10
|
-
hasProvider: !!r
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
//#endregion
|
|
14
|
-
export { r as t };
|