@nxgt/material 2.5.0 → 2.6.1
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 -7
- package/dist/{_Uint8Array-DuTT6911.js → _Uint8Array-CDlDeQmw.js} +1 -1
- package/dist/{_overRest-93z6TD9V.js → _overRest-CWIWQwDJ.js} +1 -1
- package/dist/{async-slice-B8Xv2BLH.js → async-slice-Qoen0Mqm.js} +2 -2
- package/dist/{blockDiagram-BEXU5L5S-C8UXdLfB.js → blockDiagram-BEXU5L5S-_6EVgQ2-.js} +2 -2
- package/dist/{chunk-3FUC2YCW-4gCRt6fO.js → chunk-3FUC2YCW-CRQHl-Jx.js} +2 -2
- package/dist/{chunk-7M6MHVWA-DnPXbiTM.js → chunk-7M6MHVWA-DqXpf6CM.js} +1 -1
- package/dist/{chunk-GNY47TPC-DLqgU2SJ.js → chunk-GNY47TPC-BgMsLbCS.js} +4 -4
- package/dist/{chunk-NETBCI7D-CBowDvwz.js → chunk-NETBCI7D-CsyH43bj.js} +1 -1
- package/dist/{chunk-Z7XXMR3K-dRJc1Z30.js → chunk-Z7XXMR3K-CoCjTVVx.js} +1 -1
- package/dist/{classDiagram-v2-NBCMYWYE-CQmePeL4.js → classDiagram-v2-NBCMYWYE-j4vk04t-.js} +2 -2
- package/dist/{components-CUkJhBwK.js → components-C3wIUrWw.js} +25959 -25227
- package/dist/components.js +5 -5
- package/dist/{dagre-6A5THRUB-BhyJENrD.js → dagre-6A5THRUB-DXq_YBNL.js} +54 -54
- package/dist/{diagram-22UHCM2B-CJc0JoTV.js → diagram-22UHCM2B-He8NDldw.js} +2 -2
- package/dist/{diagram-3UASUU5V-0P3Cnq5H.js → diagram-3UASUU5V-CeILva4U.js} +1 -1
- package/dist/dnd.js +1 -1
- package/dist/{elk-276RUBZZ-CvgDuHoY.js → elk-276RUBZZ-DFn4kTey.js} +3 -3
- package/dist/{erDiagram-OPXOYQCR-BFgRy8E9.js → erDiagram-OPXOYQCR-BzVUcUwh.js} +2 -2
- package/dist/{field-blur-D1eQk-49.js → field-blur-BlrE9fOD.js} +1 -1
- package/dist/{flowDiagram-KWPJA3E3-DGaa9iT2.js → flowDiagram-KWPJA3E3-B4pJCj2Q.js} +3 -3
- package/dist/{ganttDiagram-FUAMR5RP-CDGrtGHY.js → ganttDiagram-FUAMR5RP-B4A4UFFi.js} +1 -1
- package/dist/{graphlib-Dt-isUVV.js → graphlib-CQ3hLS1N.js} +6 -6
- package/dist/hooks.js +2 -2
- package/dist/{i18n-provider-Drsc2YXX.js → i18n-provider-CbYD2KxP.js} +1 -1
- package/dist/i18n.js +6 -6
- package/dist/{isArrayLikeObject-BhWbq65y.js → isArrayLikeObject-5rnYwEK7.js} +3 -3
- package/dist/{isEmpty-DdlzV8Ue.js → isEmpty-DChvniYe.js} +3 -3
- package/dist/{journeyDiagram-ZHPQQLJL-BuLKqWS3.js → journeyDiagram-ZHPQQLJL-C91SPPkY.js} +1 -1
- package/dist/lib/components/ui/collections/tree/use-tree.d.ts +2 -0
- package/dist/lib/components/ui/dates/date-range-field/date-range-field-trigger.d.ts +1 -1
- package/dist/lib/components/ui/dates/date-range-field/date-range-field.d.ts +10 -1
- package/dist/lib/components/ui/dates/date-range-field/date-range-field.utils.d.ts +13 -0
- package/dist/lib/components/ui/dates/date-range-field/index.d.ts +1 -0
- package/dist/lib/components/ui/dates/date-range-field/partials/date-range-field-content.d.ts +25 -0
- package/dist/lib/components/ui/dates/date-range-field/partials/date-range-presets.d.ts +11 -0
- package/dist/lib/components/ui/dates/date-range-field/partials/date-range-times.d.ts +11 -0
- package/dist/lib/components/ui/dates/date-range-field/use-date-range-presets.d.ts +22 -0
- package/dist/lib/components/ui/dates/time-picker/time-picker-utils.d.ts +7 -0
- package/dist/lib/components/ui/fields/number-field/number-field.d.ts +3 -1
- package/dist/lib/components/ui/fields/slider/slider-header.d.ts +5 -1
- package/dist/lib/components/ui/fields/slider/slider-readout.d.ts +5 -1
- package/dist/lib/components/ui/media/file-preview/file-preview-pdf.lazy.d.ts +9 -0
- package/dist/lib/components/ui/media/file-preview/file-preview.d.ts +12 -0
- package/dist/lib/components/ui/media/file-preview/index.d.ts +3 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-body.d.ts +9 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-card.d.ts +20 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-media.d.ts +11 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-pdf.d.ts +10 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-status.d.ts +17 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-text.d.ts +13 -0
- package/dist/lib/components/ui/media/file-preview/types.d.ts +23 -0
- package/dist/lib/components/ui/media/file-preview/use-file-preview.d.ts +22 -0
- package/dist/lib/components/ui/media/file-preview/use-text-preview.d.ts +15 -0
- package/dist/lib/components/ui/media/index.d.ts +1 -0
- package/dist/lib/components/ui/media/upload/network-upload-field/use-image-preview.d.ts +6 -0
- package/dist/lib/components/ui/selection/index.d.ts +1 -0
- package/dist/lib/components/ui/selection/tree-select-field/index.d.ts +2 -0
- package/dist/lib/components/ui/selection/tree-select-field/partials/tree-select-content.d.ts +13 -0
- package/dist/lib/components/ui/selection/tree-select-field/partials/tree-select-panel.d.ts +19 -0
- package/dist/lib/components/ui/selection/tree-select-field/partials/tree-select-trigger.d.ts +24 -0
- package/dist/lib/components/ui/selection/tree-select-field/tree-select-field.d.ts +9 -0
- package/dist/lib/components/ui/selection/tree-select-field/tree-select-form-field.d.ts +8 -0
- package/dist/lib/components/ui/selection/tree-select-field/tree-select.utils.d.ts +35 -0
- package/dist/lib/components/ui/selection/tree-select-field/types.d.ts +37 -0
- package/dist/lib/components/ui/selection/tree-select-field/use-tree-select-field.d.ts +20 -0
- package/dist/lib/i18n/resources/en/en.d.ts +33 -0
- package/dist/lib/i18n/resources/en/material.json.d.ts +36 -3
- package/dist/lib/i18n/resources/fr/fr.d.ts +33 -0
- package/dist/lib/i18n/resources/fr/material.json.d.ts +36 -3
- package/dist/lib/i18n/resources/resources.d.ts +66 -0
- package/dist/lib/i18n/translator.d.ts +1 -1
- package/dist/lib.js +3 -3
- package/dist/main.js +15 -15
- package/dist/map.js +2 -2
- package/dist/material.css +1 -1
- package/dist/{merge-a7J0YkZX.js → merge-_Awk4ywA.js} +4 -4
- package/dist/{mermaid.core-CE34byhz.js → mermaid.core-DciYB1MV.js} +21 -21
- package/dist/{mindmap-definition-NLK3R4M7-emoij-nW.js → mindmap-definition-NLK3R4M7-Brf_2jIE.js} +2 -2
- package/dist/{pieDiagram-5QR66LMP-BdG1tWLn.js → pieDiagram-5QR66LMP-MPh-EWf-.js} +1 -1
- package/dist/print.js +2 -2
- package/dist/{quadrantDiagram-O4NWA36T-BCd-NwsO.js → quadrantDiagram-O4NWA36T-CwDeE9KB.js} +1 -1
- package/dist/{requirementDiagram-PLB6GJNP-CCcH5uSr.js → requirementDiagram-PLB6GJNP-CCP3YtvB.js} +2 -2
- package/dist/{sankeyDiagram-IPEJSGJF-78cK-bfe.js → sankeyDiagram-IPEJSGJF-vgVchd2a.js} +1 -1
- package/dist/{sortable-provider-VCxPasNp.js → sortable-provider-CzSnl6It.js} +1 -1
- package/dist/{stateDiagram-v2-GCMORJYK-B4ghJrhD.js → stateDiagram-v2-GCMORJYK-T-oIXh-8.js} +2 -2
- package/dist/{stored-language-CeD7kHui.js → stored-language-DmUUhRb5.js} +72 -6
- package/dist/{swimlanes-2SLR337P-DmHm2yJS.js → swimlanes-2SLR337P-tW3_wBWO.js} +3 -3
- package/dist/{swimlanesDiagram-TC7HE7FX-Dq3gGsPj.js → swimlanesDiagram-TC7HE7FX-B1lWzHp1.js} +3 -3
- package/dist/{timeline-definition-EJHVYXUP-EqJV_QKn.js → timeline-definition-EJHVYXUP-SdA6wt2-.js} +1 -1
- package/dist/{translate-material-DgRdhz5d.js → translate-material-DuY12xca.js} +2 -2
- package/dist/{translator-B4zUVm7j.js → translator-CaIYjyFP.js} +1 -1
- package/dist/{use-heading-spy-1BHMXjIn.js → use-heading-spy-Crdz4OH5.js} +2 -2
- package/dist/{use-material-translation-UbARR81K.js → use-material-translation-Od0QsFPA.js} +2 -2
- package/dist/{usecaseDiagram-POWQR4AR-CvCl0p5N.js → usecaseDiagram-POWQR4AR-B3rBcR4E.js} +2 -2
- package/dist/{xychartDiagram-PMCCYNJV-BphsHFKA.js → xychartDiagram-PMCCYNJV-stQWLgCx.js} +1 -1
- package/docs/components/README.md +2 -1
- package/docs/components/data-display.md +3 -3
- package/docs/components/data-table-filter-and-lists.md +5 -0
- package/docs/components/date-and-time.md +106 -6
- package/docs/components/feedback-and-status.md +1 -1
- package/docs/components/form-fields.md +8 -2
- package/docs/components/media-and-files.md +71 -1
- package/docs/components/primitives.md +1 -1
- package/docs/components/rich-widgets.md +1 -1
- package/docs/components/selection-and-choice.md +79 -2
- package/docs/guides/forms.md +2 -1
- package/docs/guides/i18n.md +47 -4
- package/docs/previews/date-time-daterangefield.webp +0 -0
- package/docs/previews/media-files-filepreview.webp +0 -0
- package/docs/previews/selection-choice-treeselectfield.webp +0 -0
- package/docs/roadmap.md +33 -27
- package/docs/troubleshooting.md +111 -0
- package/package.json +2 -2
- package/dist/lib/components/ui/fields/slider/slider-ticks.d.ts +0 -1
|
@@ -105,7 +105,7 @@ calendar is labelled by the trigger, so named by the label.
|
|
|
105
105
|
**Emits:** `Date | undefined`.
|
|
106
106
|
**Form wrapper:** `DateFormField` — `control` and `name`, see
|
|
107
107
|
[forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
|
|
108
|
-
**Storybook:** `Date & time/DateField` · **Vue:** `DateField`, `DateFormField`
|
|
108
|
+
**Storybook:** `Date & time/DateField` · **Vue:** `DateField`, `DateFormField` (`disabled-days`, same rules)
|
|
109
109
|
|
|
110
110
|
---
|
|
111
111
|
|
|
@@ -113,7 +113,7 @@ calendar is labelled by the trigger, so named by the label.
|
|
|
113
113
|
|
|
114
114
|

|
|
115
115
|
|
|
116
|
-
From / to range picked in a popover calendar.
|
|
116
|
+
From / to range picked in a popover calendar, with presets and times.
|
|
117
117
|
|
|
118
118
|
```tsx
|
|
119
119
|
import { type DateRange, DateRangeField } from '@nxgt/material/components';
|
|
@@ -128,10 +128,13 @@ export function Stay() {
|
|
|
128
128
|
| Prop | Type | Default | Effect |
|
|
129
129
|
| --- | --- | --- | --- |
|
|
130
130
|
| `value` | `DateRange` | — | `{ from: Date \| undefined; to?: Date }` |
|
|
131
|
-
| `onValueChange` | `(value?: DateRange) => void` | — | called on each click: `to` is
|
|
131
|
+
| `onValueChange` | `(value?: DateRange) => void` | — | called on each click: after the first, `to` is the same day as `from` |
|
|
132
132
|
| `placeholder`, `label`, `helperText`, `error`, `required` | | — | `placeholder` is the trigger's text; `label` and `helperText` sit beside it; `error` and `required` its state |
|
|
133
133
|
| `disabled` | `boolean` | — | disables the field: the trigger cannot be focused or opened |
|
|
134
134
|
| `disabledDays` | react-day-picker's `Matcher \| Matcher[]` | — | days that cannot be picked (the calendar's `disabled`) |
|
|
135
|
+
| `presets` | `readonly DateRangePresetOption[]` | — (no list) | one-click ranges beside the calendar: built-in ids (`DATE_RANGE_PRESET_IDS`) and `{ label, range }` of your own |
|
|
136
|
+
| `withTime` | `boolean` | `false` | a time of day on each end, under the calendar, and on the trigger; the popover stays open until OK |
|
|
137
|
+
| `minDate`, `maxDate` | `Date` | — | the first and last day that can be picked (the calendar's, as are `disablePast` / `disableFuture`) |
|
|
135
138
|
|
|
136
139
|
Every other `Calendar` prop is passed to the calendar; it opens on the
|
|
137
140
|
month of `value.from`. `id`, `aria-describedby` and `data-*` attributes go on
|
|
@@ -148,11 +151,103 @@ trigger in the field's root `div` (`data-slot="date-range-field"`, which takes
|
|
|
148
151
|
rendered alone, shows only the value: use the field for the label and the
|
|
149
152
|
helper text. The open calendar is labelled by the trigger.
|
|
150
153
|
|
|
151
|
-
|
|
152
|
-
|
|
154
|
+
### Presets
|
|
155
|
+
|
|
156
|
+
`presets` lists one-click ranges beside the calendar (above it on a narrow
|
|
157
|
+
screen), in the order you give them. A built-in id is translated
|
|
158
|
+
(`material.date-range-field.preset.<id>`); a preset of your own is
|
|
159
|
+
`{ label, range }`, where `range` is `{ from, to }` or `(now) => ({ from, to })`.
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
import {
|
|
163
|
+
type DateRange,
|
|
164
|
+
DateRangeField,
|
|
165
|
+
type DateRangePreset,
|
|
166
|
+
} from '@nxgt/material/components';
|
|
167
|
+
import { useState } from 'react';
|
|
168
|
+
|
|
169
|
+
const lastQuarter: DateRangePreset = {
|
|
170
|
+
label: 'Last quarter',
|
|
171
|
+
range: (now) => {
|
|
172
|
+
const start = new Date(now.getFullYear(), Math.floor(now.getMonth() / 3) * 3 - 3, 1);
|
|
173
|
+
return { from: start, to: new Date(start.getFullYear(), start.getMonth() + 3, 0) };
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
export function Report() {
|
|
178
|
+
const [period, setPeriod] = useState<DateRange | undefined>();
|
|
179
|
+
return (
|
|
180
|
+
<DateRangeField
|
|
181
|
+
label="Period"
|
|
182
|
+
value={period}
|
|
183
|
+
onValueChange={setPeriod}
|
|
184
|
+
maxDate={new Date()}
|
|
185
|
+
presets={['today', 'last-7-days', 'this-month', 'last-month', lastQuarter]}
|
|
186
|
+
/>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
| Built-in id | Range |
|
|
192
|
+
| --- | --- |
|
|
193
|
+
| `today`, `yesterday` | that day |
|
|
194
|
+
| `last-7-days`, `last-30-days` | ends today and counts it |
|
|
195
|
+
| `this-month`, `this-year` | from the first day to today |
|
|
196
|
+
| `last-month` | the whole previous month |
|
|
197
|
+
|
|
198
|
+
A built-in range starts at 00:00 (and with `withTime` ends at 23:59); your
|
|
199
|
+
own ranges keep the times you gave them. Picking a preset sets the value and
|
|
200
|
+
closes the popover (with `withTime` it stays open); open again, the calendar
|
|
201
|
+
is on that range's month. The list is a group named "Presets"
|
|
202
|
+
(`material.date-range-field.presets`) of buttons in the tab order, and the
|
|
203
|
+
one whose days are the value's has `aria-pressed="true"`. A preset is
|
|
204
|
+
disabled when its range starts before `minDate`, ends after `maxDate`, or
|
|
205
|
+
either end is one of `disabledDays`; the days between are not checked, as the
|
|
206
|
+
calendar lets a range span a disabled day.
|
|
207
|
+
The built-in presets use the current date when the popover opens; there is
|
|
208
|
+
no `now` prop, and none is planned. A preset of your own whose end comes
|
|
209
|
+
before its start is disabled.
|
|
210
|
+
|
|
211
|
+
### Times
|
|
212
|
+
|
|
213
|
+
`withTime` adds two `TimePicker`s under the calendar, in groups named
|
|
214
|
+
"Start time" and "End time" (`material.date-range-field.start-time`,
|
|
215
|
+
`.end-time`), each disabled until its end has a day, and an OK button
|
|
216
|
+
(`material.buttons.ok`) that closes the popover. The trigger shows each end
|
|
217
|
+
with its time (date-fns `Pp`).
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
import { type DateRange, DateRangeField } from '@nxgt/material/components';
|
|
221
|
+
import { useState } from 'react';
|
|
222
|
+
|
|
223
|
+
export function Booking() {
|
|
224
|
+
const [slot, setSlot] = useState<DateRange | undefined>();
|
|
225
|
+
return (
|
|
226
|
+
<DateRangeField
|
|
227
|
+
label="Booking"
|
|
228
|
+
value={slot}
|
|
229
|
+
onValueChange={setSlot}
|
|
230
|
+
withTime
|
|
231
|
+
presets={['today']}
|
|
232
|
+
/>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
A day picked on the calendar keeps the time that end had; a new start is
|
|
238
|
+
00:00 and a new end 23:59, as a built-in preset ends, so a filter on
|
|
239
|
+
`<= to` keeps the last day. On the same day, an end time set before the
|
|
240
|
+
start time becomes the start time.
|
|
241
|
+
|
|
242
|
+
Without `withTime`, a picked day is at 00:00. (`@nxgt/material-vue` gives
|
|
243
|
+
it the current time of day.)
|
|
244
|
+
|
|
245
|
+
**Emits:** `DateRange | undefined` — `{ from, to }`, where the first day
|
|
246
|
+
picked is both `from` and `to` (react-day-picker's `addToRange`) until the
|
|
247
|
+
second day is picked.
|
|
153
248
|
**Form wrapper:** `DateRangeFormField` — `control` and `name`, see
|
|
154
249
|
[forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
|
|
155
|
-
**Storybook:** `Date & time/DateRangeField` · **Vue:** `DateRangeField`, `DateRangeFormField`
|
|
250
|
+
**Storybook:** `Date & time/DateRangeField` (stories `DisabledDays`, `MinMaxDates`, `Presets`, `DisabledPresets`, `WithTime`) · **Vue:** `DateRangeField`, `DateRangeFormField` (`disabled-days`, `presets`, `with-time`, `min-date` / `max-date`; without time, a picked day carries the current time of day there, 00:00 here)
|
|
156
251
|
|
|
157
252
|
---
|
|
158
253
|
|
|
@@ -235,6 +330,11 @@ export function Clock() {
|
|
|
235
330
|
| `label` | `ReactNode` | — | header text |
|
|
236
331
|
| `footer` | `ReactNode` | — | under the inputs (the OK button in `TimeField`) |
|
|
237
332
|
|
|
333
|
+
The hours and minutes inputs are named "Hours" and "Minutes"
|
|
334
|
+
(`material.time-picker.hours`, `.minutes`). AM / PM shows the half of the day
|
|
335
|
+
`date` is in, so a date changed from outside shows its own; switching it moves
|
|
336
|
+
the time 12 hours, and a click on the pressed half changes nothing.
|
|
337
|
+
|
|
238
338
|
**Emits:** `Date | undefined`. No form wrapper — use `TimeFormField`.
|
|
239
339
|
**Storybook:** `Date & time/TimePicker` · **Vue:** `TimePicker`
|
|
240
340
|
|
|
@@ -227,7 +227,7 @@ built on `AlertDialog`, so it does not close on an outside click. Put
|
|
|
227
227
|
`AlertDialogCancel` / `AlertDialogAction` in its `footer`.
|
|
228
228
|
|
|
229
229
|
**Storybook:** `Feedback & status/ConfirmDialog`, `Feedback & status/ConfirmationDialog`,
|
|
230
|
-
`Feedback & status/CustomAlertDialog` · **Vue:** `ConfirmDialog`, `ConfirmationDialog
|
|
230
|
+
`Feedback & status/CustomAlertDialog` · **Vue:** `ConfirmDialog`, `ConfirmationDialog` (`form-options` + `#form` slot for `renderForm`), `CustomAlertDialog`
|
|
231
231
|
|
|
232
232
|
---
|
|
233
233
|
|
|
@@ -218,6 +218,7 @@ export function Quantity() {
|
|
|
218
218
|
| `hideSteppers` | `boolean` | `false` | hides the +/− buttons |
|
|
219
219
|
| `suffix` | `ReactNode` | — | unit after the input |
|
|
220
220
|
| `aria-label` | `string` | — | names the input when it has no `label` (a part of a larger field) |
|
|
221
|
+
| `aria-labelledby` | `string` | — | names the input by another element's id (a part of a larger field) |
|
|
221
222
|
|
|
222
223
|
**Emits:** `number | null`.
|
|
223
224
|
**Form wrapper:** `NumberFormField` — `control` and `name`, see
|
|
@@ -506,6 +507,9 @@ import { InlineEdit } from '@nxgt/material/components';
|
|
|
506
507
|
| `placeholder` | `string` | "Click to edit" | shown while empty |
|
|
507
508
|
| `disabled` | `boolean` | `false` | read-only text |
|
|
508
509
|
|
|
510
|
+
Enter, Escape, Save and Cancel return focus to the field, while a click
|
|
511
|
+
elsewhere saves and leaves focus where it went.
|
|
512
|
+
|
|
509
513
|
**Emits:** `string`, trimmed, on save only.
|
|
510
514
|
**Form wrapper:** `InlineEditFormField` — `control` and `name`, see
|
|
511
515
|
[forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
|
|
@@ -639,7 +643,9 @@ names the thumbs); a range's thumbs add "Minimum" and "Maximum":
|
|
|
639
643
|
`getByRole('slider', { name: 'Price Minimum' })`. A labelled range is also a
|
|
640
644
|
`role="group"` named by the label, and its readout inputs are named
|
|
641
645
|
"Minimum" and "Maximum" (`material.slider.minimum` / `maximum`), so two range
|
|
642
|
-
sliders are told apart.
|
|
646
|
+
sliders are told apart. A single value's readout input is named as its thumb
|
|
647
|
+
is, and "Value" (`material.slider.value`) when nothing names the slider.
|
|
648
|
+
`aria-invalid` (or `error`) goes on every thumb too,
|
|
643
649
|
not on the root `span`.
|
|
644
650
|
|
|
645
651
|
`SliderField` is the same component under `@nxgt/material-vue`'s name (an
|
|
@@ -652,7 +658,7 @@ form's value is a number, and `number[]` when it is an array — the default
|
|
|
652
658
|
value decides.
|
|
653
659
|
**Form wrapper:** `SliderFormField` — `control` and `name`, see
|
|
654
660
|
[forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
|
|
655
|
-
**Storybook:** `Form fields/Slider` · **Vue:** `Slider`, `SliderField`, `SliderFormField`
|
|
661
|
+
**Storybook:** `Form fields/Slider` · **Vue:** `Slider`, `SliderField` (`ticks`, `leading` / `trailing` or their slots), `SliderFormField`
|
|
656
662
|
|
|
657
663
|
---
|
|
658
664
|
|
|
@@ -11,6 +11,7 @@ them into a form.
|
|
|
11
11
|
| <img src="../previews/media-files-s3uploadfield.webp" width="96" alt=""> | [S3UploadField, NetworkUploadField](#s3uploadfield-networkuploadfield) | Drag-and-drop uploader with progress, retry, previews and size / count limits |
|
|
12
12
|
| <img src="../previews/media-files-uploadfield.webp" width="96" alt=""> | [UploadField](#uploadfield) | Labelled file input showing the chosen file's name |
|
|
13
13
|
| <img src="../previews/media-files-filelist.webp" width="96" alt=""> | [FileList](#filelist) | File list with type icons, size, download and remove |
|
|
14
|
+
| <img src="../previews/media-files-filepreview.webp" width="96" alt=""> | [FilePreview](#filepreview) | One file previewed by its type: image, PDF, video, audio, text, or a download card |
|
|
14
15
|
| | [FilesFormField](#filesformfield) | Free-solo autocomplete of file URLs, with image thumbnails |
|
|
15
16
|
| <img src="../previews/media-files-imagefield.webp" width="96" alt=""> | [ImageField](#imagefield) | Single image upload with preview and progress |
|
|
16
17
|
| <img src="../previews/media-files-imagecropper.webp" width="96" alt=""> | [ImageCropper](#imagecropper) | Crop with zoom, rotation, aspect presets and a round shape |
|
|
@@ -221,6 +222,75 @@ dropzone as well read the error twice, and the group still says it once
|
|
|
221
222
|
|
|
222
223
|
---
|
|
223
224
|
|
|
225
|
+
## FilePreview
|
|
226
|
+
|
|
227
|
+

|
|
228
|
+
|
|
229
|
+
Previews one file, picked by its MIME type (else its extension): an image, a PDF, a video or audio file, the text of a text, JSON, CSV or Markdown file, and a download card for anything else.
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
import { useState } from 'react';
|
|
233
|
+
import { FilePreview } from '@nxgt/material/components';
|
|
234
|
+
|
|
235
|
+
export function Attachment() {
|
|
236
|
+
const [file, setFile] = useState<File | null>(null);
|
|
237
|
+
return (
|
|
238
|
+
<>
|
|
239
|
+
<input type="file" onChange={(event) => setFile(event.target.files?.[0] ?? null)} />
|
|
240
|
+
{/* A File or Blob: shown through an object URL, revoked on change and unmount. */}
|
|
241
|
+
<FilePreview file={file} onError={(error) => console.warn(error)} />
|
|
242
|
+
{/* A URL: the kind comes from `type`, else the extension; `name` is the alt text. */}
|
|
243
|
+
<FilePreview file="/api/files/42" type="application/pdf" name="contract.pdf" />
|
|
244
|
+
</>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
| Prop | Type | Default | Effect |
|
|
250
|
+
| --- | --- | --- | --- |
|
|
251
|
+
| `file` | `File \| Blob \| string \| null` | — | the file, or its URL; nothing renders without one. A URL must be `http(s):`, relative, `blob:`, or a `data:` URL of an image, video, audio, plain text, CSV, Markdown, JSON or PDF; any other (`javascript:`, `data:text/html`, and also a `data:` URL of XML, TSV or YAML) shows the error state, with no link and nothing loaded |
|
|
252
|
+
| `type` | `string` | the `Blob`'s, or a `data:` URL's | MIME type; picks the kind before the extension does |
|
|
253
|
+
| `name` | `string` | the `File`'s, else the URL's last segment | shown on the card, the image's alt text and the download's file name; "Untitled file" when there is none |
|
|
254
|
+
| `maxTextBytes` | `number` | `262144` (`TEXT_PREVIEW_MAX_BYTES`, 256 KB) | how much of a text kind is read; past it, the preview shows the beginning and says so |
|
|
255
|
+
| `onError` | `(error: unknown) => void` | — | the file could not be read (an HTTP error: `FilePreviewHttpError`, with its `status`; a refused URL: `FilePreviewUnsafeUrlError`) or shown (a broken image, video or audio file) |
|
|
256
|
+
| `className`, other `<figure>` props | | | on the root `<figure>` |
|
|
257
|
+
|
|
258
|
+
| Kind | Picked by | Renders |
|
|
259
|
+
| --- | --- | --- |
|
|
260
|
+
| `image` | `image/*`; `.png` `.jpg` `.jpeg` `.gif` `.webp` `.avif` `.svg` `.bmp` `.ico` | `<img>`, its alt text the file name |
|
|
261
|
+
| `pdf` | `application/pdf`; `.pdf` | [`PdfReader`](#pdfreader), imported the first time a PDF is previewed; the card when the viewer cannot be loaded. A PDF the reader fails to open leaves the preview `ready`: `PdfReader` shows its own error, and `onError` is not called |
|
|
262
|
+
| `video` | `video/*`; `.mp4` `.m4v` `.webm` `.ogv` `.mov` | `<video controls>` |
|
|
263
|
+
| `audio` | `audio/*`; `.mp3` `.wav` `.ogg` `.oga` `.m4a` `.aac` `.flac` `.opus` | `<audio controls>` |
|
|
264
|
+
| `json` | `application/json`, `text/json`, `*+json`; `.json` | [`JsonViewer`](data-display.md#codeblock) |
|
|
265
|
+
| `markdown` | `text/markdown`, `text/x-markdown`; `.md` `.markdown` | [`Markdown`](data-display.md#markdown), rendered; its links are sanitized like any `Markdown`, but a remote image in it still loads, so an untrusted `.md` can make the browser request a URL of its choosing |
|
|
266
|
+
| `csv` | `text/csv`, `application/csv`, `text/tab-separated-values`; `.csv` `.tsv` | the text, in a `<pre>` |
|
|
267
|
+
| `text` | any other `text/*`, `application/xml`, `application/yaml`, `application/javascript`…; `.txt` `.log` `.xml` `.yaml` `.yml` `.ini` `.toml` | the text, in a `<pre>` |
|
|
268
|
+
| `other` | anything else, `application/octet-stream` without a known extension | a [`FileCard`](data-display.md#card-presets): icon, name, size and type, and a Download link |
|
|
269
|
+
|
|
270
|
+
A text kind is fetched (a URL) or read (a `Blob`) up to `maxTextBytes` and
|
|
271
|
+
decoded with the `charset` of the response's `Content-Type` (or of the
|
|
272
|
+
`Blob`'s `type`) when the browser's `TextDecoder` supports it, else as UTF-8;
|
|
273
|
+
a JSON or Markdown file cut by the cap is shown as plain text, with "Showing
|
|
274
|
+
the first 256.0 KB of this file." below it. The `<pre>` and the Markdown box
|
|
275
|
+
are regions named "Contents of {name}"; they scroll and take focus, so a
|
|
276
|
+
keyboard can scroll them.
|
|
277
|
+
|
|
278
|
+
The root is a `<figure>` named "Preview of {name}", with `data-kind` and
|
|
279
|
+
`data-state`: `pending` on the server and in the first client render — an
|
|
280
|
+
empty placeholder, with no object URL made and nothing fetched, so it hydrates
|
|
281
|
+
without a mismatch — then `loading` ("Loading preview…", put into a `status` live region that
|
|
282
|
+
stays mounted, so it is announced), `ready`
|
|
283
|
+
or `error` ("This file could not be previewed.", an `alert`, with a Download
|
|
284
|
+
link when there is something to download). The kind comes from
|
|
285
|
+
`fileKind({ type, name, url })`, exported too, from
|
|
286
|
+
[`@nxgt/material-core/file-preview`](https://cdn.jsdelivr.net/npm/@nxgt/material-core@0/README.md#a-files-preview-file-preview).
|
|
287
|
+
Every string is translated (`material.file-preview.*`, see the
|
|
288
|
+
[i18n guide](../guides/i18n.md)).
|
|
289
|
+
|
|
290
|
+
**Storybook:** `Media & files/FilePreview` · **Vue:** `FilePreview`
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
224
294
|
## FilesFormField
|
|
225
295
|
|
|
226
296
|
No preview: it has no story of its own. It is an [`Autocomplete`](selection-and-choice.md)
|
|
@@ -257,7 +327,7 @@ function Gallery() {
|
|
|
257
327
|
| `freeSolo` | `boolean` | `true` | accept values that are not in `options` |
|
|
258
328
|
|
|
259
329
|
**Form wrapper:** it is one — `control` and `name`, see [forms](../guides/forms.md).
|
|
260
|
-
**Storybook:** — · **Vue:**
|
|
330
|
+
**Storybook:** — · **Vue:** `FilesFormField`
|
|
261
331
|
|
|
262
332
|
---
|
|
263
333
|
|
|
@@ -593,7 +593,7 @@ Parts: `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent`.
|
|
|
593
593
|
| `onValueChange` (`Tabs`) | `(value: string) => void` | — | called when a trigger is selected |
|
|
594
594
|
| `icon` (`TabsTrigger`) | `ReactNode` | — | shown before the label (above it on the phone in `bar`) |
|
|
595
595
|
|
|
596
|
-
**Storybook:** `Primitives/Tabs` · **Vue:** `Tabs` (same parts)
|
|
596
|
+
**Storybook:** `Primitives/Tabs` · **Vue:** `Tabs` (same parts, `variant="line"`)
|
|
597
597
|
|
|
598
598
|
---
|
|
599
599
|
|
|
@@ -372,7 +372,7 @@ function Config() {
|
|
|
372
372
|
|
|
373
373
|
**Form wrapper:** `CodeEditorFormField` — `control` and `name`, see
|
|
374
374
|
[forms](../guides/forms.md).
|
|
375
|
-
**Storybook:** `Rich widgets/CodeEditor` · **Vue:** `CodeEditor
|
|
375
|
+
**Storybook:** `Rich widgets/CodeEditor` · **Vue:** `CodeEditor` (`options`), `CodeEditorFormField`
|
|
376
376
|
|
|
377
377
|
---
|
|
378
378
|
|
|
@@ -23,6 +23,7 @@ value type each one writes. Everything is imported from
|
|
|
23
23
|
| <img src="../previews/selection-choice-selectchipfield.webp" width="96" alt=""> | [SelectChipField](#selectchipfield) | Choice shown as chips |
|
|
24
24
|
| <img src="../previews/selection-choice-transferlist.webp" width="96" alt=""> | [TransferList](#transferlist) | Two-pane picker |
|
|
25
25
|
| <img src="../previews/selection-choice-sortablelist.webp" width="96" alt=""> | [SortableList](#sortablelist) | Reorderable list of strings |
|
|
26
|
+
| <img src="../previews/selection-choice-treeselectfield.webp" width="96" alt=""> | [TreeSelectField](#treeselectfield) | Pick from a tree, single or multiple |
|
|
26
27
|
| <img src="../previews/selection-choice-switcher.webp" width="96" alt=""> | [Switcher](#switcher) | Workspace or account switcher |
|
|
27
28
|
|
|
28
29
|
## Select
|
|
@@ -137,7 +138,7 @@ export function Framework() {
|
|
|
137
138
|
**Emits:** `string`.
|
|
138
139
|
**Form wrapper:** `SelectFormField` — `control` and `name`, see
|
|
139
140
|
[forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
|
|
140
|
-
**Storybook:** `Selection & choice/SelectField` · **Vue:** `SelectField`, `SelectFormField`
|
|
141
|
+
**Storybook:** `Selection & choice/SelectField` · **Vue:** `SelectField`, `SelectFormField` (`#option` slot for `renderOption`)
|
|
141
142
|
|
|
142
143
|
---
|
|
143
144
|
|
|
@@ -291,7 +292,7 @@ Parts: `Autocomplete`, `AutocompleteChips` (the chips row it uses in
|
|
|
291
292
|
**Emits:** `string | null` in `single` mode, `string[]` in `multiple`.
|
|
292
293
|
**Form wrapper:** `AutocompleteFormField` — `control` and `name`, see
|
|
293
294
|
[forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
|
|
294
|
-
**Storybook:** `Selection & choice/Autocomplete` · **Vue:** `Autocomplete`, `AutocompleteFormField`
|
|
295
|
+
**Storybook:** `Selection & choice/Autocomplete` · **Vue:** `Autocomplete`, `AutocompleteFormField` (generic; `#option`, `#selected-leading`, `#actions` slots)
|
|
295
296
|
|
|
296
297
|
---
|
|
297
298
|
|
|
@@ -627,6 +628,82 @@ export function Ranking() {
|
|
|
627
628
|
|
|
628
629
|
---
|
|
629
630
|
|
|
631
|
+
## TreeSelectField
|
|
632
|
+
|
|
633
|
+

|
|
634
|
+
|
|
635
|
+
A field that opens a `Tree` in a popover: pick one node, or several as chips,
|
|
636
|
+
with an optional filter.
|
|
637
|
+
|
|
638
|
+
The field is controlled only: it holds no value of its own. Pass `value` and update it in `onValueChange`;
|
|
639
|
+
without it, a pick changes nothing on screen.
|
|
640
|
+
|
|
641
|
+
```tsx
|
|
642
|
+
import { TreeSelectField, type TreeNode } from '@nxgt/material/components';
|
|
643
|
+
import { useState } from 'react';
|
|
644
|
+
|
|
645
|
+
const regions: TreeNode[] = [
|
|
646
|
+
{
|
|
647
|
+
id: 'europe',
|
|
648
|
+
label: 'Europe',
|
|
649
|
+
children: [
|
|
650
|
+
{ id: 'france', label: 'France' },
|
|
651
|
+
{ id: 'spain', label: 'Spain' },
|
|
652
|
+
],
|
|
653
|
+
},
|
|
654
|
+
{ id: 'africa', label: 'Africa', children: [{ id: 'cameroon', label: 'Cameroon' }] },
|
|
655
|
+
];
|
|
656
|
+
|
|
657
|
+
export function Regions() {
|
|
658
|
+
const [value, setValue] = useState<string[]>(['france']);
|
|
659
|
+
return (
|
|
660
|
+
<TreeSelectField
|
|
661
|
+
label="Regions"
|
|
662
|
+
items={regions}
|
|
663
|
+
multiple
|
|
664
|
+
searchable
|
|
665
|
+
value={value}
|
|
666
|
+
onValueChange={setValue}
|
|
667
|
+
/>
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
Single mode (no `multiple`): a pick closes the popover and the trigger shows
|
|
673
|
+
the node's label. Multiple: the tree has checkboxes, and each pick is a
|
|
674
|
+
dismissible `Chip` beside the trigger, its remove button named "Remove
|
|
675
|
+
{label}" (`material.chip.dismiss-label`). The trigger is a `combobox`, named by
|
|
676
|
+
the label, with `aria-expanded` and, while open, `aria-controls`. Opening moves
|
|
677
|
+
focus into the filter, else into the tree on the pick (its branches unfolded);
|
|
678
|
+
the tree keeps its own keys (arrows, Home / End, Enter / Space), ↓ from the
|
|
679
|
+
filter enters it, and Escape closes the popover and hands focus back to the
|
|
680
|
+
trigger.
|
|
681
|
+
|
|
682
|
+
| Prop | Type | Default | Effect |
|
|
683
|
+
| --- | --- | --- | --- |
|
|
684
|
+
| `items` | `TreeNode[]` | — | required; `Tree`'s nodes: `{ id, label, icon?, trailing?, disabled?, children? }` |
|
|
685
|
+
| `multiple` | `boolean` | `false` | checkboxes and chips; decides the `value` type |
|
|
686
|
+
| `value` | `string \| null` / `string[]` | — | the picked id, or ids with `multiple` |
|
|
687
|
+
| `onValueChange` | `(value: string \| null) => void` / `(value: string[]) => void` | — | per `multiple` |
|
|
688
|
+
| `searchable` | `boolean` | `false` | a filter above the tree; each match stays under its ancestors, which open |
|
|
689
|
+
| `placeholder` | `string` | "Select…" | shown while nothing is picked (`material.tree-select-field.placeholder`) |
|
|
690
|
+
| `searchPlaceholder` | `string` | "Search" | the filter's placeholder and name (`material.tree-select-field.search`) |
|
|
691
|
+
| `required` | `boolean` | — | the asterisk, and `aria-required` on the `combobox` |
|
|
692
|
+
| `disabled` | `boolean` | — | disables the trigger and each chip's remove button |
|
|
693
|
+
| `error` | `boolean` | — | error border, error helper text, `aria-invalid` on the `combobox` |
|
|
694
|
+
| `id`, `aria-describedby`, `data-*` | | — | on the trigger: the label is `for` the `id`, the description follows the helper text's |
|
|
695
|
+
|
|
696
|
+
Its copy is `material.tree-select-field.*`: `placeholder`, `search`, `empty` ("No
|
|
697
|
+
match found.") and `selected` ("{count} selected", the trigger's text in
|
|
698
|
+
multiple mode).
|
|
699
|
+
|
|
700
|
+
**Emits:** `string | null` (single), `string[]` (multiple).
|
|
701
|
+
**Form wrapper:** `TreeSelectFormField` — `control`, `name` and `multiple`, see
|
|
702
|
+
[forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
|
|
703
|
+
**Storybook:** `Selection & choice/TreeSelectField` · **Vue:** `TreeSelectField`, `TreeSelectFormField`
|
|
704
|
+
|
|
705
|
+
---
|
|
706
|
+
|
|
630
707
|
## Switcher
|
|
631
708
|
|
|
632
709
|

|
package/docs/guides/forms.md
CHANGED
|
@@ -116,7 +116,7 @@ export function PlanForm() {
|
|
|
116
116
|
| --- | --- |
|
|
117
117
|
| one input (`TextFormField`, `EmailFormField`, `TextareaFormField`, `SwitchFormField`, `CheckboxFormField`, …) | its input loses focus, as a native `blur` |
|
|
118
118
|
| several controls (`PasswordFormField` and its eye button, `NumberFormField` and its steppers, `PhoneFormField`, `OtpFormField`, `SliderFormField` with two thumbs, `DurationFormField`, `RatingFormField`, `RadioGroupFormField`, `CheckboxGroupFormField`, `SelectChipFormField`, `SelectCardFormField`, `SortableListFormField`, `TransferListFormField`, `InlineEditFormField`, `AttributeValuesFormFieldSet`, …) | focus leaves all of them; moving between them is not leaving |
|
|
119
|
-
| a picker (`SelectFormField`, `ComboboxFormField`, `AutocompleteFormField`, `CountryFormField`, `TimezoneFormField`, `ColorFormField`, `DateFormField`, `DateRangeFormField`, `TimeFormField`, …) | focus leaves the trigger **and** the popover it opened. Opening the popover, or picking in it, is not leaving; closing it hands focus back to the trigger, and the next Tab or click elsewhere is |
|
|
119
|
+
| a picker (`SelectFormField`, `ComboboxFormField`, `AutocompleteFormField`, `TreeSelectFormField`, `CountryFormField`, `TimezoneFormField`, `ColorFormField`, `DateFormField`, `DateRangeFormField`, `TimeFormField`, …) | focus leaves the trigger **and** the popover it opened. Opening the popover, or picking in it, is not leaving; closing it hands focus back to the trigger, and the next Tab or click elsewhere is |
|
|
120
120
|
| a dialog editor (`PostalAddressFormField`, `ContactsFormField`, `OpeningHoursFormField`, `AttributesFormField`, and `LocationFormField` from `@nxgt/material/map`) | focus leaves its buttons and the dialog they open. Closing the dialog hands focus back to the button that opened it |
|
|
121
121
|
| an upload (`UploadFormField`, `NetworkUploadFormField`, `S3UploadFormField`, `ImageFormField`, `ImageS3FormField`, `FileListFormField`, `FileListS3FormField`) | focus leaves the drop zone and its buttons. Choosing a file in the browser's own dialog is not leaving |
|
|
122
122
|
| `RichTextEditorFormField`, `CodeEditorFormField` | focus leaves the editor and its toolbar |
|
|
@@ -343,6 +343,7 @@ or fails validation.
|
|
|
343
343
|
| `SelectChipField` · `SelectChipFormField` | same as `SelectCardField` | `''` / `[]` |
|
|
344
344
|
| `TransferList` · `TransferListFormField` | `string[]`: the selected `value`s, in order | `[]` |
|
|
345
345
|
| `SortableList` · `SortableListFormField` | `string[]`: the `value`s, in the user's order | `[]` |
|
|
346
|
+
| `TreeSelectField` · `TreeSelectFormField` | `string \| null` (a node `id`). With `multiple`: `string[]`, in the order picked | `null` / `[]` |
|
|
346
347
|
|
|
347
348
|
### Media & files
|
|
348
349
|
|
package/docs/guides/i18n.md
CHANGED
|
@@ -204,7 +204,9 @@ presets and `Min`/`Max` fields, the `variant="4"` spinner's label,
|
|
|
204
204
|
`You are here` and zoom buttons, and the icon-only close button of
|
|
205
205
|
`DialogClose`, `DrawerClose`, `SheetClose` and `SheetContent`'s
|
|
206
206
|
`withCloseButton`. A range `Slider`'s readout inputs read
|
|
207
|
-
`material.slider.minimum` / `maximum` ("Minimum", "Maximum")
|
|
207
|
+
`material.slider.minimum` / `maximum` ("Minimum", "Maximum"), and a
|
|
208
|
+
single value's input, when nothing names the slider, `material.slider.value`
|
|
209
|
+
("Value", "Valeur"). The other icon-only buttons are named from it too: the
|
|
208
210
|
`Sidebar` toggle (`material.sidebar.toggle`), the data table's row expander
|
|
209
211
|
(`material.table.labels.toggle-row`), its loading status, "Loading data…" /
|
|
210
212
|
"Chargement des données…" (`material.table.loading`), a chip's remove button — `Chip`,
|
|
@@ -220,7 +222,10 @@ reads `material.print.table.total` ("Total", "Total") for its totals row and
|
|
|
220
222
|
unless you pass `totalLabel` or `emptyText`; a PDF does not see your
|
|
221
223
|
app's provider, so pass `PrintDocument` its `language` (see
|
|
222
224
|
[printing](printing.md#translating-built-in-strings-in-a-pdf)). The keys and the French
|
|
223
|
-
are the same in `@nxgt/material-vue`, so one set of overrides fits both.
|
|
225
|
+
are the same in `@nxgt/material-vue`, so one set of overrides fits both. Some
|
|
226
|
+
keys are read there only, such as `material.confirm-dialog.form-failed` ("The form could
|
|
227
|
+
not be loaded."), which `@nxgt/material-vue`'s `ConfirmationDialog` shows when
|
|
228
|
+
its on-demand form fails to load. Text
|
|
224
229
|
you pass yourself always wins over the translation: a `label`,
|
|
225
230
|
`Autocomplete`'s `freeSoloLabel` and `empty`, the editor's `options.labels`,
|
|
226
231
|
`QRCode`'s `title`, `Barecode`'s `aria-label`, `CarouselPrevious`/`CarouselNext`
|
|
@@ -252,8 +257,46 @@ French); and the names of `DurationField`'s inputs, "Hours" and "Minutes"
|
|
|
252
257
|
(`material['duration-field']['hours-label']` / `minutes-label`); the status a
|
|
253
258
|
`Stepper` step announces after its title, "Completed" or "Error"
|
|
254
259
|
(`material.stepper.completed` / `error`, "Terminée" / "Erreur" in French); and
|
|
255
|
-
|
|
256
|
-
|
|
260
|
+
the pagination buttons' names and text: `PaginationPrevious` /
|
|
261
|
+
`PaginationNext`'s "Previous" / "Next" (`material.pagination.previous` /
|
|
262
|
+
`next`), `PaginationFirst` / `PaginationLast`'s "First" / "Last"
|
|
263
|
+
(`material.pagination.first` / `last`), `PaginationBar`'s "Page {page}" on
|
|
264
|
+
each page button (`material.pagination.page`) and `PaginationEllipsis`'s
|
|
265
|
+
"More pages" (`material.pagination.more`). `TreeSelectField`'s placeholder,
|
|
266
|
+
search box, empty message and "{count} selected" follow the language too
|
|
267
|
+
(`material['tree-select-field'].placeholder` / `search` / `empty` /
|
|
268
|
+
`selected`; in French `selected` is an ICU plural, `{count, plural, …}`); the
|
|
269
|
+
`placeholder` and `searchPlaceholder` props take precedence over them. The names of
|
|
270
|
+
`TimePicker`'s inputs read `material.time-picker.hours` and
|
|
271
|
+
`material.time-picker.minutes` ("Hours" / "Minutes", "Heures" / "Minutes").
|
|
272
|
+
`DateRangeField`'s preset list is a group named by
|
|
273
|
+
`material.date-range-field.presets` ("Presets", "Plages prédéfinies"); its
|
|
274
|
+
built-in presets read `material.date-range-field.preset.today`,
|
|
275
|
+
`material.date-range-field.preset.yesterday`,
|
|
276
|
+
`material.date-range-field.preset.last-7-days`,
|
|
277
|
+
`material.date-range-field.preset.last-30-days`,
|
|
278
|
+
`material.date-range-field.preset.this-month`,
|
|
279
|
+
`material.date-range-field.preset.last-month` and
|
|
280
|
+
`material.date-range-field.preset.this-year` ("Today", "Yesterday", "Last 7
|
|
281
|
+
days", "Last 30 days", "This month", "Last month", "This year"; "Aujourd’hui",
|
|
282
|
+
"Hier", "7 derniers jours", "30 derniers jours", "Ce mois-ci", "Le mois
|
|
283
|
+
dernier", "Cette année"), and with times its two groups
|
|
284
|
+
`material.date-range-field.start-time` and `material.date-range-field.end-time`
|
|
285
|
+
("Start time" / "End time", "Heure de début" / "Heure de fin"); its OK button
|
|
286
|
+
reads `material.buttons.ok`. The label of a preset of your own is yours.
|
|
287
|
+
`FilePreview`'s figure is named by `material.file-preview.label` ("Preview
|
|
288
|
+
of {name}", "Aperçu de {name}"), with `material.file-preview.untitled`
|
|
289
|
+
("Untitled file", "Fichier sans nom") as the name of a file that has none; it
|
|
290
|
+
reads `material.file-preview.loading` ("Loading preview…", "Chargement de
|
|
291
|
+
l’aperçu…") while it reads the file, `material.file-preview.error` ("This
|
|
292
|
+
file could not be previewed.", "Impossible d’afficher l’aperçu de ce
|
|
293
|
+
fichier.") when it cannot show it, `material.file-preview.download`
|
|
294
|
+
("Download", "Télécharger") on its download link, and
|
|
295
|
+
`material.file-preview.truncated` ("Showing the first {size} of this file.",
|
|
296
|
+
"Seuls les premiers {size} de ce fichier sont affichés.") under a text cut
|
|
297
|
+
by the size cap; the text or Markdown it shows scrolls in a region named by
|
|
298
|
+
`material.file-preview.content` ("Contents of {name}", "Contenu de {name}").
|
|
299
|
+
`material.carousel.roledescription` /
|
|
257
300
|
`slide` and `material.attributes.buttons.add-option` are there for
|
|
258
301
|
`@nxgt/material-vue`'s carousel and attribute options, so the bundles hold
|
|
259
302
|
the same keys. Your `placeholder`, `sheetTitle` and `aria-label` still
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/roadmap.md
CHANGED
|
@@ -6,27 +6,7 @@ the version something shipped in.
|
|
|
6
6
|
|
|
7
7
|
## Now
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
its light ring, for loading states on dark or coloured surfaces.
|
|
11
|
-
- **Range filters announce their field name** — the slider thumbs and the
|
|
12
|
-
`Min`/`Max` inputs of a `slider-range` or `number-range` filter are named
|
|
13
|
-
after the field, so a screen reader says which range is changing.
|
|
14
|
-
- **Alert keeps long content inside** — a long title, description or unbroken
|
|
15
|
-
string wraps inside the `Alert` instead of running past its edge.
|
|
16
|
-
- **Stepper: unique ids, announced steps and truncated titles** — two steppers
|
|
17
|
-
on one page no longer share ids, a screen reader hears which step is current
|
|
18
|
-
and whether each is done or in error, and a long step title truncates.
|
|
19
|
-
- **Layouts that hold long content** — `ListTile`, `StatCard` and `Banner`
|
|
20
|
-
keep long titles, values and actions inside their box instead of overflowing.
|
|
21
|
-
- **The same exports as `@nxgt/material-vue`** — `Camera`, `NativeSelect`, the
|
|
22
|
-
`InputOTP` parts, `PaginationFirst` and `PaginationLast`, `TableEmpty`,
|
|
23
|
-
`DialogScrollContent` and `ToastAction`, `Button`'s sizes, and the
|
|
24
|
-
`RadioGroupField`, `SliderField` and `SwitchField` names, so code moves
|
|
25
|
-
between the two libraries without renaming.
|
|
26
|
-
- **DataTable loading and empty states** — skeleton rows while the data loads
|
|
27
|
-
(the rows already shown stay in place, dimmed, during a refresh), the table
|
|
28
|
-
announced as busy, and your own content when there are no rows, told
|
|
29
|
-
whether a filter emptied it.
|
|
9
|
+
Nothing in progress right now; see Next.
|
|
30
10
|
|
|
31
11
|
## Next
|
|
32
12
|
|
|
@@ -35,12 +15,6 @@ the version something shipped in.
|
|
|
35
15
|
- **Previews that cannot go stale** — a CI check that fails when a story changes
|
|
36
16
|
but its preview image does not, so the picture in the docs is the component
|
|
37
17
|
you install.
|
|
38
|
-
- **DateRangeField presets and time** — one-click ranges such as Today, Last 7
|
|
39
|
-
days and This month, and a time of day on each end of the range.
|
|
40
|
-
- **TreeSelectField** — pick one or several items from a tree inside a form
|
|
41
|
-
field.
|
|
42
|
-
- **FilePreview** — preview an image, PDF, video or text file, chosen by its
|
|
43
|
-
type, in one component.
|
|
44
18
|
|
|
45
19
|
## Later
|
|
46
20
|
|
|
@@ -111,6 +85,38 @@ the version something shipped in.
|
|
|
111
85
|
|
|
112
86
|
## Shipped
|
|
113
87
|
|
|
88
|
+
- **TreeSelectField** — pick one or several items from a tree inside a form
|
|
89
|
+
field, as chips when several, with an optional filter that keeps each match
|
|
90
|
+
under its ancestors (`TreeSelectField`, `TreeSelectFormField`). 2.6.0.
|
|
91
|
+
- **DateRangeField presets and time** — one-click ranges such as Today, Last 7
|
|
92
|
+
days and This month, or your own, beside the calendar (`presets`), and a time
|
|
93
|
+
of day on each end of the range (`withTime`). 2.6.0.
|
|
94
|
+
- **FilePreview** — preview a file picked by its type, in one component: an
|
|
95
|
+
image, a PDF in `PdfReader`, a video or audio file, the text of a text, JSON,
|
|
96
|
+
CSV or Markdown file, or a card with a download link for anything else
|
|
97
|
+
(`FilePreview`, `onError`). Safe on a server. 2.6.0.
|
|
98
|
+
- **Spinner `light` colour renders** — a `Spinner` with `color="light"` shows
|
|
99
|
+
its light ring, for loading states on dark or coloured surfaces. 2.5.0.
|
|
100
|
+
- **Range filters announce their field name** — the slider thumbs and the
|
|
101
|
+
`Min`/`Max` inputs of a `slider-range` or `number-range` filter are named
|
|
102
|
+
after the field, so a screen reader says which range is changing. 2.5.0.
|
|
103
|
+
- **Alert keeps long content inside** — a long title, description or unbroken
|
|
104
|
+
string wraps inside the `Alert` instead of running past its edge. 2.5.0.
|
|
105
|
+
- **Stepper: unique ids, announced steps and truncated titles** — two steppers
|
|
106
|
+
on one page no longer share ids, a screen reader hears which step is current
|
|
107
|
+
and whether each is done or in error, and a long step title truncates. 2.5.0.
|
|
108
|
+
- **Layouts that hold long content** — `ListTile`, `StatCard` and `Banner`
|
|
109
|
+
keep long titles, values and actions inside their box instead of overflowing.
|
|
110
|
+
2.5.0.
|
|
111
|
+
- **The same exports as `@nxgt/material-vue`** — `Camera`, `NativeSelect`, the
|
|
112
|
+
`InputOTP` parts, `PaginationFirst` and `PaginationLast`, `TableEmpty`,
|
|
113
|
+
`DialogScrollContent` and `ToastAction`, `Button`'s sizes, and the
|
|
114
|
+
`RadioGroupField`, `SliderField` and `SwitchField` names, so code moves
|
|
115
|
+
between the two libraries without renaming. 2.5.0.
|
|
116
|
+
- **DataTable loading and empty states** — skeleton rows while the data loads
|
|
117
|
+
(the rows already shown stay in place, dimmed, during a refresh), the table
|
|
118
|
+
announced as busy, and your own content when there are no rows, told
|
|
119
|
+
whether a filter emptied it. 2.5.0.
|
|
114
120
|
- **PDFs from a Next.js route handler in one line of config** —
|
|
115
121
|
`withNxgtPrint(nextConfig)` from `@nxgt/material/next` adds what `/print`
|
|
116
122
|
needs to `next.config.ts` — the library in `serverExternalPackages`, and
|