@nxgt/material 3.96.2 → 3.97.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 +26 -0
- package/README.md +2 -2
- package/dist/calculator-field.js +2 -2
- package/dist/{calculator-BVuQG9PG.js → calculator-kdSjeRhf.js} +1 -1
- package/dist/calculator.js +1 -1
- package/dist/{components-B125euHt.js → components-Bk8KDjaj.js} +11542 -11417
- package/dist/components.js +5 -5
- package/dist/{currency-field-Dj1mBZ9n.js → currency-field-5Zg_sjY1.js} +91 -57
- package/dist/editor.js +1 -1
- package/dist/{financial-variant-DnHWDZ8t.js → financial-variant-DR7pCGqi.js} +2 -2
- package/dist/lib/components/ui/collections/filter/use-filter-field-config.d.ts +1 -0
- package/dist/lib/components/ui/collections/row-menu/use-row-menu-focus.d.ts +4 -2
- package/dist/lib/components/ui/display/event-chip/event-chip-badges.d.ts +2 -1
- package/dist/lib/components/ui/display/event-chip/event-chip-content.d.ts +2 -0
- package/dist/lib/components/ui/display/event-chip/event-chip.d.ts +3 -1
- package/dist/lib/components/ui/fields/currency-field/currency-field.d.ts +9 -1
- package/dist/lib/components/ui/fields/currency-field/use-currency-amount.d.ts +3 -1
- package/dist/lib/components/ui/fields/currency-field/use-minor-units.d.ts +9 -0
- package/dist/lib/components/ui/fields/repeatable-group/partials/repeatable-group-heading.d.ts +12 -0
- package/dist/lib/components/ui/fields/repeatable-group/repeatable-group.d.ts +1 -1
- package/dist/lib/components/ui/fields/repeatable-group/types.d.ts +5 -0
- package/dist/lib/components/ui/fields/repeatable-group/use-repeatable-group-text.d.ts +19 -0
- package/dist/lib/components/ui/fields/textarea-field/textarea-field.d.ts +3 -1
- package/dist/lib/components/ui/media/image-cropper/image-cropper.d.ts +6 -1
- package/dist/lib/components/ui/media/image-cropper/use-apply-crop.d.ts +16 -0
- package/dist/lib/components/ui/media/image-cropper/use-image-cropper.d.ts +2 -2
- package/dist/lib/components/ui/widgets/education/questions/partials/content-lang.d.ts +14 -0
- package/dist/lib/components/ui/widgets/education/questions/partials/question-content.d.ts +1 -1
- package/dist/lib/components/ui/widgets/education/questions/question-props.types.d.ts +87 -0
- package/dist/lib/components/ui/widgets/education/questions/question.d.ts +1 -1
- package/dist/lib/components/ui/widgets/education/questions/types.d.ts +1 -74
- package/dist/lib/components/ui/widgets/event-calendar/partials/calendar-event-chip.d.ts +3 -1
- package/dist/main.js +5 -5
- package/dist/material.css +1 -1
- package/dist/{pdf-MkmivNXn.js → pdf-9BAZhzg9.js} +9777 -7726
- package/dist/pdf-reader.js +1 -1
- package/dist/pdf.worker.min.mjs +5 -5
- package/dist/{percent-field-DT4qNaCH.js → percent-field-D1Y4HUPt.js} +1 -1
- package/dist/{public-BxLp7Qn8.js → public-BuRnxJOK.js} +2 -2
- package/dist/{use-chat-composer-U7jZfdQN.js → use-chat-composer-4cs6opDX.js} +2092 -2085
- package/docs/components/data-display.md +3 -2
- package/docs/components/data-table-filter-and-lists.md +3 -1
- package/docs/components/form-fields.md +6 -2
- package/docs/components/media-and-files.md +20 -2
- package/docs/components/rich-widgets.md +13 -3
- package/docs/guides/csp.md +0 -1
- package/docs/guides/event-calendar.md +7 -2
- package/docs/guides/forms.md +1 -1
- package/docs/guides/i18n.md +1 -1
- package/docs/guides/pdf-reader.md +13 -2
- package/docs/troubleshooting.md +7 -0
- package/package.json +3 -3
|
@@ -1632,8 +1632,9 @@ import { EventChip } from '@nxgt/material/components';
|
|
|
1632
1632
|
| `allDay` | `boolean` | `false` | no time |
|
|
1633
1633
|
| `compact` | `boolean` | `false` | one line, the time before the title, for month cells |
|
|
1634
1634
|
| `continuesBefore`, `continuesAfter` | `boolean` | `false` | square edges for a multi-day event |
|
|
1635
|
-
| `
|
|
1636
|
-
| `
|
|
1635
|
+
| `short` | `boolean` | `false` | the box is too short (under 60px) for title, time and a badge row: the badges join the time's line, as a tone dot under 10rem wide. `EventCalendar` sets it in the week and day views |
|
|
1636
|
+
| `badge` | `{ label: string; tone?: Tone }` | — | a small tinted label after the title (neutral without a `tone`); cut with an ellipsis; in a box under 60px tall (`short`) it joins the time's line, and under 10rem wide there it becomes a tone dot; in a box under 20px tall or 7rem wide it is a tone dot too (its tooltip is the label) while the label stays in the chip's accessible name. `EventCalendar` sets it from `CalendarEvent.badge` |
|
|
1637
|
+
| `badges` | `{ label: string; tone?: Tone }[]` | — | further badges after `badge`, each with the same time-line placement, pill and tone-dot behaviour and each in the accessible name. `EventCalendar` sets it from `CalendarEvent.badges` |
|
|
1637
1638
|
| `tone` | `Tone` | — | draws the chip in a tone of the library (or one your app declared) when it sets no `color`; a `color` wins |
|
|
1638
1639
|
| `cancelled` | `boolean` | `false` | a muted chip with a dashed outline, the title struck through (`<del>`) and "Cancelled" in its accessible name (`material.event-chip.cancelled`, English and French) |
|
|
1639
1640
|
| `selected`, `disabled` | `boolean` | `false` | state |
|
|
@@ -1334,7 +1334,9 @@ a toast takes it, so it is safe to call right after the action settles or the
|
|
|
1334
1334
|
dialog closes. For those two frames the focus is claimed back to the trigger
|
|
1335
1335
|
whatever took it, so a deliberate focus move (Tab, or a dialog or toast opened
|
|
1336
1336
|
right after the call) within them is overridden: call it once the follow-up UI
|
|
1337
|
-
is done.
|
|
1337
|
+
is done. The reclaim stops when the component unmounts (a navigation right
|
|
1338
|
+
after the call is safe) or when the `focusRef` element is disconnected. It
|
|
1339
|
+
returns `true` when the button was found and holds the focus,
|
|
1338
1340
|
and `false` when the row is gone (archived) or the button cannot take it
|
|
1339
1341
|
(disabled, inert); the focus then stays where it is.
|
|
1340
1342
|
|
|
@@ -218,6 +218,7 @@ export function PlanForm({ onSave }: { onSave: (values: Values) => void }) {
|
|
|
218
218
|
control={control}
|
|
219
219
|
name="periods"
|
|
220
220
|
label="Periods"
|
|
221
|
+
description="One period per term."
|
|
221
222
|
rowLabel="period"
|
|
222
223
|
addLabel="Add period"
|
|
223
224
|
max={6}
|
|
@@ -247,6 +248,7 @@ export function PlanForm({ onSave }: { onSave: (values: Values) => void }) {
|
|
|
247
248
|
| `newRow` | `() => FieldArray<T, N>` | — | the value Add appends |
|
|
248
249
|
| `renderRow` | `(row) => ReactNode` | — | one row's fields; `row` is `{ field, index, position, path }` (`index` 0-based, `position` 1-based, `path` `${name}.${index}`) |
|
|
249
250
|
| `label` | `ReactNode` | — | names the group (the list inside it is not named again) |
|
|
251
|
+
| `description` | `ReactNode` | — | help text under the label; the group's `aria-describedby` points at it (with the group error), so it is announced with the group |
|
|
250
252
|
| `rowLabel` | `string` | `'row'` (translated) | names each row's buttons ("Remove period 2") and the announcements |
|
|
251
253
|
| `addLabel` | `string` | `'Add {rowLabel}'` | the Add button's text |
|
|
252
254
|
| `reorderable` | `boolean` | `false` | move up / move down buttons on each row |
|
|
@@ -521,6 +523,7 @@ import { TextareaField } from '@nxgt/material/components';
|
|
|
521
523
|
| `maxRows` | `number` | — | maximum height in lines, then it scrolls |
|
|
522
524
|
| `maxLength` | `number` | — | shows an `n/max` counter, red when over |
|
|
523
525
|
| `showCount` | `boolean` | `true` when `maxLength` is set | force the counter on or off |
|
|
526
|
+
| `monospace` | `boolean` | `false` | React only; `TextareaFormField` takes it too. Sets the theme's monospace font (`--font-mono`) on the textarea, for code-like plain text such as test input and expected output |
|
|
524
527
|
| `error` | `boolean` | — | error outline and helper colour |
|
|
525
528
|
|
|
526
529
|
**Emits:** the native `ChangeEvent<HTMLTextAreaElement>`; `TextareaFormField`
|
|
@@ -857,11 +860,12 @@ export function Amount() {
|
|
|
857
860
|
| `currency` | `string` | `'EUR'` | the suffix text; formatting follows the `I18nProvider` language |
|
|
858
861
|
| `trailingAction` | `ReactNode` | — | a button after the currency code, inside the field (`CalculatorField`'s "Open calculator" uses it); it keeps its own name and focus, and the input leaves room for it |
|
|
859
862
|
| `fractionDigits` | `number` | the currency's own | decimals shown once the amount is committed (on blur): ISO 4217 by default — `JPY` 0, `EUR` 2, `KWD` 3 (2 for a code `Intl` does not know). Pass `2` to keep two decimals whatever the currency; the value is clamped to 0–20 (the range every `Intl` accepts), and `NaN` or `Infinity` counts as not given. What is typed is not rounded, on screen until blur nor in the emitted number: a `JPY` field shows `1,235` for `1234.5` and emits `1234.5` |
|
|
863
|
+
| `minorUnits` | `boolean` | `false` | `value`, `defaultValue` and `onChange` are whole minor units (cents, centimes, yen) instead of major units: `<CurrencyField currency="EUR" minorUnits value={1999} />` shows `19.99` and emits `1999`. The decimals are the currency's own (`EUR` 2, `XAF` 0, `KWD` 3), or `fractionDigits` when given, the same rule as `formatAmount`'s `minorUnits` option; an amount typed with more decimals is rounded half away from zero to a whole minor unit (`1.005` emits `101`). Also a prop of `CurrencyFormField`, whose form value is then the integer |
|
|
860
864
|
|
|
861
|
-
**Emits:** `number | null` — never the formatted string.
|
|
865
|
+
**Emits:** `number | null` (major units, whole minor units with `minorUnits`) — never the formatted string.
|
|
862
866
|
**Form wrapper:** `CurrencyFormField` — `control` and `name`, see
|
|
863
867
|
[forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
|
|
864
|
-
**Storybook:** `Form fields/CurrencyField` · **Vue:** `CurrencyField`, `CurrencyFormField`
|
|
868
|
+
**Storybook:** `Form fields/CurrencyField` · **Vue:** `CurrencyField`, `CurrencyFormField` (`minorUnits` is React only for now, #2772)
|
|
865
869
|
|
|
866
870
|
---
|
|
867
871
|
|
|
@@ -484,12 +484,12 @@ import { Button, ImageCropper, ImageCropperDialog } from '@nxgt/material/compone
|
|
|
484
484
|
```
|
|
485
485
|
|
|
486
486
|
Parts: `ImageCropper` (inline), `ImageCropperDialog` (the same in a dialog, closed
|
|
487
|
-
after `onCrop
|
|
487
|
+
after `onCrop`, or after its promise resolves).
|
|
488
488
|
|
|
489
489
|
| Prop | Type | Default | Effect |
|
|
490
490
|
| --- | --- | --- | --- |
|
|
491
491
|
| `src` | `string` | — | image to crop (URL or object URL) |
|
|
492
|
-
| `onCrop` | `({ file, area }) => void
|
|
492
|
+
| `onCrop` | `({ file, area }) => void \| Promise<void>` | — | receives the cropped `File` and the pixel area. Return a promise (an upload) and Apply stays busy (`aria-busy`, disabled) and Cancel is disabled until it settles; a rejection keeps the crop (and the dialog open) so the user can apply again, and the error is yours to show |
|
|
493
493
|
| `aspect` | `number` | — | fixes the ratio and hides the presets; omitted, the user picks free / 1:1 / 4:3 / 16:9 / 3:4 |
|
|
494
494
|
| `cropShape` | `'rect' \| 'round'` | `'rect'` | round mask for avatars |
|
|
495
495
|
| `fileName` | `string` | — | name of the produced `File` |
|
|
@@ -497,6 +497,24 @@ after `onCrop`).
|
|
|
497
497
|
| `cancelVariant` | `ButtonVariant` | `'tonal'` | `ImageCropper`: the Cancel button's variant; `'ghost'` restores the earlier look |
|
|
498
498
|
| `open` / `onOpenChange` / `trigger` | | — | `ImageCropperDialog`: controlled or trigger-opened |
|
|
499
499
|
|
|
500
|
+
A rejection from `onCrop` is swallowed: the dialog stays open and Apply is usable
|
|
501
|
+
again, but nothing is shown. Handle the error inside `onCrop` (try/catch, then a
|
|
502
|
+
toast), and rethrow it so the dialog stays open:
|
|
503
|
+
|
|
504
|
+
```tsx
|
|
505
|
+
<ImageCropperDialog
|
|
506
|
+
src={src}
|
|
507
|
+
onCrop={async ({ file }) => {
|
|
508
|
+
try {
|
|
509
|
+
await uploadAvatar(file);
|
|
510
|
+
} catch (error) {
|
|
511
|
+
toast.error('Upload failed, try again');
|
|
512
|
+
throw error; // keeps the dialog open
|
|
513
|
+
}
|
|
514
|
+
}}
|
|
515
|
+
/>
|
|
516
|
+
```
|
|
517
|
+
|
|
500
518
|
**Storybook:** `Media & files/ImageCropper` · **Vue:** `ImageCropper`, `ImageCropperDialog`
|
|
501
519
|
|
|
502
520
|
---
|
|
@@ -400,7 +400,10 @@ const events: CalendarEvent[] = [
|
|
|
400
400
|
- **Small boxes.** A long label is cut with an ellipsis inside its chip. In a
|
|
401
401
|
box under 20px tall or 7rem wide (a phone's week column) it falls back to a
|
|
402
402
|
small dot in the badge's tone, with the label as its tooltip; the label stays
|
|
403
|
-
in the event's accessible name.
|
|
403
|
+
in the event's accessible name. In a week or day box under 60px tall (a
|
|
404
|
+
one-hour event at the default slot height) the badge sits on the time's line
|
|
405
|
+
instead of a row of its own, and becomes the dot under 10rem of chip width.
|
|
406
|
+
The agenda view wraps a long description
|
|
404
407
|
instead of cutting it.
|
|
405
408
|
|
|
406
409
|
For a status and a priority together, add `badges` (`CalendarEventBadge[]`):
|
|
@@ -2828,7 +2831,7 @@ French bundle — see [i18n](../guides/i18n.md).
|
|
|
2828
2831
|
| `QuestionCard` `value` / `onValueChange` | `QuestionAnswer` | — | controlled answer |
|
|
2829
2832
|
| `Question` `kind: 'open'` | `maxLength?` | — | a multi-line answer in a textarea named by the prompt; a counter shows while editable when `maxLength` is set. No `correct`: pass the grader's `verdict` |
|
|
2830
2833
|
| `Question` `kind: 'code'` | `language?`, `maxLength?` | — | source code: drawn by `renderCode`, else a monospace textarea |
|
|
2831
|
-
| `QuestionCard` `renderCode` | `(field: QuestionCodeField) => ReactNode` | — | the code field of a `code` question; `field` is `{ value, onChange, label, labelledBy, describedBy, language, maxLength, readOnly, disabled }`. Keeps Monaco out of the card's bundle |
|
|
2834
|
+
| `QuestionCard` `renderCode` | `(field: QuestionCodeField) => ReactNode` | — | the code field of a `code` question; `field` is `{ value, onChange, label, labelledBy, describedBy, language, maxLength, readOnly, disabled, lang }`. Keeps Monaco out of the card's bundle |
|
|
2832
2835
|
| `Question` `description` | `string` | — | `open`, `code`: a persistent helper line under the answer field ("A person will mark this answer"), linked to it by `aria-describedby` and passed to `renderCode` as `field.describedBy`; always shown, unlike `hint` (a reveal button). Its id is `${promptId}-description` |
|
|
2833
2836
|
| `QuestionCard` `promptId` | `string` | generated | the id of the prompt text: point a wrapping section's `aria-labelledby` at it (and `aria-describedby` at `${promptId}-description`) |
|
|
2834
2837
|
| `QuestionCard` `preview` | `boolean` | `false` | an author's preview, `<QuestionCard question={q} preview />`: forces `revealed` and `readOnly`, drops `onValueChange`, and shows the marks (the `question.correct` options marked, the expected text or number filled in) and the `explanation`, with no verdict banner. `verdict` and `showFeedback` are always ignored in a preview; `value` is ignored when the question has a `correct` — an `open` or `code` question has none, so pass its reference answer as `value`. Not for a learner's attempt |
|
|
@@ -2840,8 +2843,15 @@ French bundle — see [i18n](../guides/i18n.md).
|
|
|
2840
2843
|
| `Question` `references` | `{ title: string; url?: string }[]` | — | a labelled "References" list once revealed or in a `preview`; a safe `url` is a link, an external one with `rel="noopener noreferrer"` |
|
|
2841
2844
|
| `Question` `kind: 'code'` | `starterCode?`, `examples?: { input, expected }[]` | — | `starterCode` fills the field while there is no draft (`value` null or undefined; an empty string is a draft), it reaches `onValueChange` on the first edit only; `examples` is a table (Input, Expected) above the field |
|
|
2842
2845
|
| new strings | `material.quiz.rich.*` | — | English fallbacks and a French bundle (React only for now) |
|
|
2846
|
+
| `QuestionCard` `contentLang` | `string` | — | the language of the question's content (a BCP 47 tag, `"en"`): sets `lang` on the prompt, the options (and their descriptions), the hints, the explanation, the option explanations, the references, the code examples and the starter code (and `lang` on the `renderCode` field). The card's own strings (hint button, kind and number labels, headings, notes) keep the page's language, which a `lang` on a wrapper around the card would also change. A grader's `feedback` and the typed answer keep the page's language (the code textarea takes the `lang` for the starter code). Without it no `lang` is set. Applies wherever the card renders: the player, a results review (`revealed`, `verdict`) and an author `preview` |
|
|
2843
2847
|
| `QuestionCard` `variant` / `density` / `showShortcuts` / `number` / `showFeedback` | — | `'card'`, `'comfortable'`, `false`, —, `true` | framed or plain, spacing, key badges, "Question 2", the verdict banner (for a card with marks and no banner, use `preview`) |
|
|
2844
2848
|
|
|
2849
|
+
An English quiz in a French interface: `contentLang` labels the content only, the card's own strings stay in the page's language (set it only when the content differs from the page; `Quiz` does not forward it):
|
|
2850
|
+
|
|
2851
|
+
```tsx
|
|
2852
|
+
<QuestionCard question={question} contentLang="en" />
|
|
2853
|
+
```
|
|
2854
|
+
|
|
2845
2855
|
A quiz question with Markdown, math, progressive hints and references:
|
|
2846
2856
|
|
|
2847
2857
|
```tsx
|
|
@@ -2908,7 +2918,7 @@ A server-graded answer, shown as given (no comparison in the browser):
|
|
|
2908
2918
|
/>
|
|
2909
2919
|
```
|
|
2910
2920
|
|
|
2911
|
-
**Storybook:** `Rich widgets/Quiz`, `Rich widgets/QuestionCard` · **Vue:** `Quiz`, `QuestionCard` (the modes, results, number kind and
|
|
2921
|
+
**Storybook:** `Rich widgets/Quiz`, `Rich widgets/QuestionCard` · **Vue:** `Quiz`, `QuestionCard` (the modes, results, number kind, shortcuts and `contentLang` are React only for now, #890)
|
|
2912
2922
|
|
|
2913
2923
|
### QuestionMediaView
|
|
2914
2924
|
|
package/docs/guides/csp.md
CHANGED
|
@@ -240,7 +240,6 @@ library avoids:
|
|
|
240
240
|
| --- | --- | --- |
|
|
241
241
|
| `Resizable` (react-resizable-panels) | `insertRule` | on a constructed stylesheet (`adoptedStyleSheets`), which CSP does not govern |
|
|
242
242
|
| `ImageCropper` (react-easy-crop) | `createElement('style')` | the branch is skipped: `disableAutomaticStylesInjection` is passed |
|
|
243
|
-
| `PdfReader` (pdf.js), both readers | the `isEvalSupported` probe, `new Function("")` | unreachable: `PdfReader` passes `isEvalSupported: false`. If you call `pdfjs.getDocument` yourself, pass it too |
|
|
244
243
|
| `MermaidDiagram` (mermaid's lodash-es, cytoscape and parser) | `Function("return this")()` | only when neither `global` nor `self` exists: never in a browser |
|
|
245
244
|
| `InputOTP` (input-otp) | a `<style>` inside `<noscript>` | rendered only with scripts off, where no CSP report is sent |
|
|
246
245
|
|
|
@@ -100,6 +100,11 @@ A cancelled event strikes its title (`<del>`) and adds "Cancelled" to its
|
|
|
100
100
|
accessible name, so the state is never carried by style alone. The preview
|
|
101
101
|
shows such an event's title struck and named the same way (and read-only, since
|
|
102
102
|
its title is not an input then). `tone` and
|
|
103
|
+
A short event (under 60px tall, such as one hour at the default slot height) in
|
|
104
|
+
the week and day views draws its badges on the time's line instead of a row of
|
|
105
|
+
its own, and a tone dot under 10rem of chip width; the label stays in the
|
|
106
|
+
accessible name and tooltip.
|
|
107
|
+
|
|
103
108
|
`badges` work in every view and in `mode="template"`. `EventChip` takes the same
|
|
104
109
|
`tone`, `badges` and `cancelled`.
|
|
105
110
|
|
|
@@ -124,8 +129,8 @@ read-only one leaves out. The preview shows no Edit or Delete button, so
|
|
|
124
129
|
| View | Spans | Day badge | Week badge | Event tone and cancelled |
|
|
125
130
|
| --- | --- | --- | --- | --- |
|
|
126
131
|
| Month | shades the cell, or its half for a half day; the label shows from 7rem of cell width, with a dot under it | next to the day number | on the first cell of the row, with room below its events | chip tone; struck title, dashed outline |
|
|
127
|
-
| Week / workweek | hatched band under the hours with its label, and a bar in the all-day strip (a half day only the band) | in the day's header | in the gutter corner | block tone; struck title, dashed outline |
|
|
128
|
-
| Day | the same as the week; with `resources`, a span shades its own column | in the day's header | in the gutter corner | the same |
|
|
132
|
+
| Week / workweek | hatched band under the hours with its label, and a bar in the all-day strip (a half day only the band) | in the day's header | in the gutter corner | block tone; struck title, dashed outline; a short block keeps its badge on the time line |
|
|
133
|
+
| Day | the same as the week; with `resources`, a span shades its own column | in the day's header | in the gutter corner | the same, badge on the time line in a short block |
|
|
129
134
|
| Agenda, phone day list | a plain, non-clickable row | in the day's heading | in the week's heading | tone dot; struck title, "Cancelled" in words |
|
|
130
135
|
|
|
131
136
|
## weekStartsOn
|
package/docs/guides/forms.md
CHANGED
|
@@ -496,7 +496,7 @@ or fails validation.
|
|
|
496
496
|
| `NumberField` · `NumberFormField` | `number \| null`. `null` when cleared; clamped to `min` / `max` on blur | `null` |
|
|
497
497
|
| `PercentField` · `PercentFormField` | `number \| null`, `min` 0, `max` 100, `step` 1 by default | `null` |
|
|
498
498
|
| `QuantityField` · `QuantityFormField` | `{ value: number \| null, unit: string }`. An error on the field, `.value` or `.unit` shows as one message under the pair | `{ value: null, unit: '' }` |
|
|
499
|
-
| `CurrencyField` · `CurrencyFormField` | `number \| null`, the amount only, not rounded. `currency` (default `'EUR'`) and `fractionDigits` (the currency's own decimals by default) are display | `null` |
|
|
499
|
+
| `CurrencyField` · `CurrencyFormField` | `number \| null`, the amount only, not rounded; with `minorUnits`, a whole number of minor units (`1999` for `19.99` EUR, the digits of the currency or `fractionDigits`). `currency` (default `'EUR'`) and `fractionDigits` (the currency's own decimals by default) are display | `null` |
|
|
500
500
|
| `CalculatorField` · `CalculatorFormField` (`@nxgt/material/calculator-field`) | `number \| null`. `null` when empty; what Apply writes (a currency amount rounded half-up to its decimals, held to `min` / `max`). `onExactValueChange` gets the exact decimal string | `null` |
|
|
501
501
|
| `PhoneField` · `PhoneFormField` | E.164 `string` (`'+33612345678'`), or `null` when empty. `PhoneFormField` reports a non-empty number that is not yet possible as the field error `material.phone-field.incomplete`; `PhoneField` signals it with `onValidityChange`. `defaultCountry` is `'FR'` | `null` |
|
|
502
502
|
| `UrlField` · `UrlFormField` | `string` (as typed) | `''` |
|
package/docs/guides/i18n.md
CHANGED
|
@@ -247,7 +247,7 @@ until the bar is drawn), the `ThreadLayout` stepper's `nav` name `material.navig
|
|
|
247
247
|
single value's input, when nothing names the slider, `material.slider.value`
|
|
248
248
|
("Value", "Valeur"). `CopyButton` reads `material.copy.copy`, `copied` and `failed` ("Copy", "Copied",
|
|
249
249
|
"Copy failed"). An overflowing `TabsList`'s scroll buttons read
|
|
250
|
-
`material.tabs.scroll-left` / `scroll-right` ("Scroll tabs left" / "Scroll tabs right"). `QuestionCard`'s rich content reads `material.quiz.rich.*` (the hint button and names "Show hint 1 of 3" / "Hint 1 of 3", "About each answer", "References", "Examples" with its Input / Expected headers). The other icon-only buttons are named from it too: the
|
|
250
|
+
`material.tabs.scroll-left` / `scroll-right` ("Scroll tabs left" / "Scroll tabs right"). `QuestionCard`'s own strings follow the UI language while a quiz in another language sets `contentLang` for its content (see the `QuestionCard` table in `components/rich-widgets.md`). Its rich content reads `material.quiz.rich.*` (the hint button and names "Show hint 1 of 3" / "Hint 1 of 3", "About each answer", "References", "Examples" with its Input / Expected headers). The other icon-only buttons are named from it too: the
|
|
251
251
|
`Sidebar` toggle (`material.sidebar.toggle`), the data table's row expander
|
|
252
252
|
(`material.table.labels.toggle-row`) and its header, a hidden "Expand" / "Déplier"
|
|
253
253
|
(`material.table.labels.expand`), its loading status, "Loading data…" /
|
|
@@ -16,11 +16,22 @@ import { PdfReader } from '@nxgt/material/pdf-reader';
|
|
|
16
16
|
</div>
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
- [Browser support](#browser-support)
|
|
19
20
|
- [Setup](#setup)
|
|
20
21
|
- [Server rendering](#server-rendering)
|
|
21
22
|
- [Content-Security-Policy](#content-security-policy)
|
|
22
23
|
- [Moving from the classic reader](#moving-from-the-classic-reader)
|
|
23
24
|
|
|
25
|
+
## Browser support
|
|
26
|
+
|
|
27
|
+
The reader runs on pdf.js 6, which needs Chrome 125, Safari 18 and a current
|
|
28
|
+
Firefox ESR (the target pdf.js 6 keeps; the features it needs are in Firefox
|
|
29
|
+
124 and later): `AbortSignal.any()`, `:dir()`, `light-dark()` and CSS nesting.
|
|
30
|
+
An older browser fails to open the reader, see
|
|
31
|
+
[troubleshooting](../troubleshooting.md#the-pdf-reader-does-not-open-in-an-older-browser).
|
|
32
|
+
The floor is the PDF reader's only; the rest of the library keeps its own. The
|
|
33
|
+
build and the tests of an app that bundles pdf.js need Node 22.13 or later.
|
|
34
|
+
|
|
24
35
|
## Setup
|
|
25
36
|
|
|
26
37
|
The pdf.js **worker** ships with the package as a file, with nothing to copy.
|
|
@@ -158,8 +169,8 @@ policy of the response that serves its script). Without it:
|
|
|
158
169
|
little, text and layout are unaffected.
|
|
159
170
|
|
|
160
171
|
`'wasm-unsafe-eval'` allows WebAssembly only; it does not allow `eval()` or
|
|
161
|
-
`new Function()`.
|
|
162
|
-
|
|
172
|
+
`new Function()`. pdf.js 6 no longer probes for `eval`, so the reader needs
|
|
173
|
+
neither. The full policy and the rest of the library:
|
|
163
174
|
[CSP](csp.md).
|
|
164
175
|
|
|
165
176
|
## Moving from the classic reader
|
package/docs/troubleshooting.md
CHANGED
|
@@ -199,6 +199,7 @@ words in your error.
|
|
|
199
199
|
- [A chart does not announce a point when I hover it](#a-chart-does-not-announce-a-point-when-i-hover-it)
|
|
200
200
|
- [The server HTML holds a client-render marker (`data-dgst`)](#the-server-html-holds-a-client-render-marker-data-dgst)
|
|
201
201
|
- [The PDF reader is empty in the server HTML, then appears](#the-pdf-reader-is-empty-in-the-server-html-then-appears)
|
|
202
|
+
- [The PDF reader does not open in an older browser](#the-pdf-reader-does-not-open-in-an-older-browser)
|
|
202
203
|
|
|
203
204
|
**Printing**
|
|
204
205
|
|
|
@@ -3590,6 +3591,12 @@ The marker is `<!--$!--><template data-dgst=""></template><!--/$-->`.
|
|
|
3590
3591
|
**Why:** the reader is client-only by design. pdf.js needs the browser, so on the server it leaves only a client-render marker (`<!--$!--><template data-dgst=""></template><!--/$-->`) and React renders it in the browser. This is not a hydration mismatch; see [the client-render marker](#the-server-html-holds-a-client-render-marker-data-dgst).
|
|
3591
3592
|
**Fix:** nothing to fix. Reserve the reader's height in your layout so the page does not jump when it appears, and do not import `pdfjs-dist` in your own server code. See the [SSR section of the guide](./guides/pdf-reader.md#server-rendering).
|
|
3592
3593
|
|
|
3594
|
+
### The PDF reader does not open in an older browser
|
|
3595
|
+
|
|
3596
|
+
**When:** `PdfReader` (or the PDF viewer) shows its error state, or stays blank, on Chrome older than 125, Safari older than 18, or an old Firefox, with an error such as `AbortSignal.any is not a function` in the console.
|
|
3597
|
+
**Why:** pdf.js 6 dropped the older browsers and relies on `AbortSignal.any()`, `:dir()`, `light-dark()` and CSS nesting. Only the PDF reader has this floor; the rest of the library is unchanged.
|
|
3598
|
+
**Fix:** ask for Chrome 125, Safari 18 or a current Firefox ESR, or offer a download link next to the reader for older browsers. A build or test run that bundles pdf.js also needs Node 22.13 or later. See [browser support](./guides/pdf-reader.md#browser-support).
|
|
3599
|
+
|
|
3593
3600
|
## Printing
|
|
3594
3601
|
|
|
3595
3602
|
### `RecoveryCodes`' Print button prints the whole page
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/material",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.97.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"email": "stevegires@gmail.com"
|
|
@@ -390,7 +390,7 @@
|
|
|
390
390
|
"docs:previews": "rm -rf node_modules/.cache/nxgt-preview-free/missing && NXGT_PREVIEW_FREE=1 vitest run --project previews && bun .storybook/preview-free-report.ts"
|
|
391
391
|
},
|
|
392
392
|
"dependencies": {
|
|
393
|
-
"@nxgt/material-core": "^0.
|
|
393
|
+
"@nxgt/material-core": "^0.56.0",
|
|
394
394
|
"@base-ui/react": "^1.6.0",
|
|
395
395
|
"@dnd-kit/core": "^6.3.1",
|
|
396
396
|
"@dnd-kit/sortable": "^10.0.0",
|
|
@@ -451,7 +451,7 @@
|
|
|
451
451
|
"lucide-react": "^1.26.0",
|
|
452
452
|
"mermaid": "^12.0.0",
|
|
453
453
|
"next-themes": "^0.4.6",
|
|
454
|
-
"pdfjs-dist": "5.
|
|
454
|
+
"pdfjs-dist": "6.5.438",
|
|
455
455
|
"qrcode-generator": "^2.0.4",
|
|
456
456
|
"radix-ui": "^1.6.5",
|
|
457
457
|
"react-barcode": "^1.6.1",
|