@nxgt/material-vue 0.37.1 → 0.39.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 +101 -0
- package/README.md +1 -0
- package/dist/{Button-CurFF4Zt.js → Button-DVeAQorb.js} +1 -1
- package/dist/{DropdownMenuTrigger-BsuyNVzV.js → DropdownMenuTrigger-C7uYPf_9.js} +36 -36
- package/dist/{HoverCardTrigger-jCXl6TrX.js → HoverCardTrigger-VvXPswRz.js} +122 -120
- package/dist/{camera-CYwiFuGE.js → camera-CG6WfZNc.js} +4 -4
- package/dist/components/base-content.css +64 -4
- package/dist/components/base.css +3 -1
- package/dist/{components--v_k8diD.js → components-B2kSyBK0.js} +13277 -12751
- package/dist/components.js +8 -8
- package/dist/composables.js +2 -2
- package/dist/dnd.js +1 -1
- package/dist/{form-scope-B2oJ5fHr.js → form-scope-XhlaF5na.js} +1 -1
- package/dist/{i18n-provider-B2q6vp6H.js → i18n-provider-BBnUUGqM.js} +1 -1
- package/dist/i18n.js +4 -4
- package/dist/{icon-button-CIUc1bEp.js → icon-button-CSPfP615.js} +1 -1
- package/dist/in-dialog-Blhwwbyb.js +31 -0
- package/dist/lib/components/ui/collections/data-table/data-table-density.d.ts +15 -0
- package/dist/lib/components/ui/collections/data-table/data-table.stories.columns.d.ts +47 -0
- package/dist/lib/components/ui/collections/data-table/data-table.stories.template.d.ts +1 -0
- package/dist/lib/components/ui/collections/data-table/index.d.ts +1 -1
- package/dist/lib/components/ui/collections/data-table/types.d.ts +7 -0
- package/dist/lib/components/ui/feedback/banner/banner.vue.d.ts +1 -1
- package/dist/lib/components/ui/fields/contacts/consts.d.ts +1 -1
- package/dist/lib/components/ui/fields/index.d.ts +1 -0
- package/dist/lib/components/ui/fields/repeatable-group/index.d.ts +4 -0
- package/dist/lib/components/ui/fields/repeatable-group/partials/repeatable-group-footer.vue.d.ts +14 -0
- package/dist/lib/components/ui/fields/repeatable-group/partials/repeatable-group-row.vue.d.ts +33 -0
- package/dist/lib/components/ui/fields/repeatable-group/repeatable-group-classes.d.ts +33 -0
- package/dist/lib/components/ui/fields/repeatable-group/repeatable-group-form-field.vue.d.ts +44 -0
- package/dist/lib/components/ui/fields/repeatable-group/repeatable-group-names.d.ts +16 -0
- package/dist/lib/components/ui/fields/repeatable-group/repeatable-group.vue.d.ts +69 -0
- package/dist/lib/components/ui/fields/repeatable-group/use-repeatable-group.d.ts +39 -0
- package/dist/lib/components/ui/fields/search-field/search-field.vue.d.ts +10 -1
- package/dist/lib/components/ui/media/stx-player/stx-player-extras.vue.d.ts +1 -1
- package/dist/lib/components/ui/overlays/command/CommandItem.vue.d.ts +10 -3
- package/dist/lib/components/ui/overlays/command/CommandList.vue.d.ts +4 -2
- package/dist/lib/components/ui/overlays/dialog/in-dialog.d.ts +12 -0
- package/dist/lib/components/ui/primitives/typography/typography.variants.d.ts +1 -0
- package/dist/lib/components/ui/primitives/typography/typography.vue.d.ts +2 -0
- package/dist/lib/components/ui/selection/checkbox-group/checkbox-group.vue.d.ts +2 -0
- package/dist/lib/components/ui/selection/option-count/option-count.vue.d.ts +25 -0
- package/dist/lib/components/ui/selection/option-count/use-option-count-text.d.ts +10 -0
- package/dist/lib/components/ui/selection/radio-group/radio-group-field.vue.d.ts +2 -0
- package/dist/lib/components/ui/selection/select-chip-field/select-chip-field.vue.d.ts +11 -0
- package/dist/lib/components/ui/selection/sortable-list/sortable-list.vue.d.ts +1 -1
- package/dist/lib/components/ui/selection/transfer-list/transfer-list.vue.d.ts +1 -1
- package/dist/lib/i18n/resources/en/en.d.ts +15 -0
- package/dist/lib/i18n/resources/en/material.json.d.ts +15 -0
- package/dist/lib/i18n/resources/fr/fr.d.ts +15 -0
- package/dist/lib/i18n/resources/fr/material.json.d.ts +15 -0
- package/dist/lib/i18n/resources/resources.d.ts +30 -0
- package/dist/lib/i18n/translator.d.ts +1 -1
- package/dist/lib/nuxt/component-names.d.ts +1 -1
- package/dist/lib.js +1 -1
- package/dist/main.js +17 -17
- package/dist/map.js +4 -4
- package/dist/material-vue.css +1 -1
- package/dist/{pdf-outline-sidebar-DJJ-ARco.js → pdf-outline-sidebar-aQ5Lhbss.js} +2 -2
- package/dist/{pdf-page-CRt6KXdJ.js → pdf-page-NCmScgMW.js} +1 -1
- package/dist/{pdf-page-list-BgCp5Asx.js → pdf-page-list-BnvE130d.js} +2 -2
- package/dist/{pdf-reader-BGxqEx8O.js → pdf-reader-CMt9dKZ-.js} +8 -8
- package/dist/{pdf-sidebar-Cvtuomgp.js → pdf-sidebar-BWzX3e0f.js} +3 -3
- package/dist/{pdf-thumbnail-sidebar-CeWPs7o7.js → pdf-thumbnail-sidebar-8nbYsI3d.js} +3 -3
- package/dist/{pdf-toolbar-BtXcyEpd.js → pdf-toolbar-DpQMG5rv.js} +5 -5
- package/dist/pdf.js +2 -2
- package/dist/{print-format.utils-keJqahvw.js → print-format.utils-oj5kle2P.js} +2 -2
- package/dist/{sortable-provider-DMu8DL2z.js → sortable-provider-2czx1jSW.js} +2 -2
- package/dist/{stored-language-dtksFoGO.js → stored-language-CKZMMJcz.js} +26 -0
- package/dist/{stx-player-nDsDyvc-.js → stx-player-CS1FYHVS.js} +5 -5
- package/dist/{translator-DqiGrSH_.js → translator-uh5FWiMq.js} +1 -1
- package/dist/{use-heading-spy-BZ7ctGZ5.js → use-heading-spy-CcJfoBA1.js} +1 -1
- package/dist/{use-material-translation-DRB6oPdF.js → use-material-translation-C6xccbic.js} +3 -3
- package/docs/components/README.md +1 -1
- package/docs/components/data-table-filter-and-lists.md +3 -1
- package/docs/components/form-fields.md +146 -0
- package/docs/components/overlays-and-menus.md +2 -0
- package/docs/components/primitives.md +3 -1
- package/docs/components/selection-and-choice.md +28 -4
- package/docs/guides/forms.md +89 -4
- package/docs/guides/i18n.md +2 -1
- package/docs/previews/form-fields-repeatablegroup.webp +0 -0
- package/docs/roadmap.md +7 -0
- package/docs/troubleshooting.md +70 -0
- package/lib/components/base-content.css +64 -4
- package/lib/components/base.css +3 -1
- package/lib/nuxt/component-names.ts +2 -0
- package/package.json +2 -2
- package/dist/use-inert-others-CtGqZKR8.js +0 -22
package/docs/guides/forms.md
CHANGED
|
@@ -293,6 +293,55 @@ in `[data-slot="form-actions"]`) and put each group of fields in a
|
|
|
293
293
|
fields still take a row of their own. A rule separates each section from the
|
|
294
294
|
one before it (`:separated="false"` drops it).
|
|
295
295
|
|
|
296
|
+
### One scroll, sticky actions
|
|
297
|
+
|
|
298
|
+
The form grid has no height of its own and its fields no scroll box: a long
|
|
299
|
+
form grows with the page, and the page is the one scroll. The actions
|
|
300
|
+
(`[data-slot="form-actions"]`) are sticky at the bottom of whatever scrolls
|
|
301
|
+
the form, on a translucent, blurred background, so Cancel and Save stay in
|
|
302
|
+
reach while the fields scroll under them; a form shorter than the screen
|
|
303
|
+
shows them right under its fields.
|
|
304
|
+
|
|
305
|
+
- In a `DialogContent` or a `SheetContent`, which are capped to the screen
|
|
306
|
+
and scroll themselves, the actions stick to the dialog's or the sheet's
|
|
307
|
+
bottom. A `DrawerContent` does not scroll: a form that is its direct child
|
|
308
|
+
is the scroll box there.
|
|
309
|
+
- In an `AlertDialogContent` (the rich text editor's edit dialogs use one),
|
|
310
|
+
the actions stick to its bottom the same way, over its padding.
|
|
311
|
+
- `ConfirmationDialog` holds a form when you pass it `form-options` (a schema and its `defaultValues`) and the `#form` slot: it renders the
|
|
312
|
+
fields in a `.form-grid-layout` with no `form-actions`, so its footer
|
|
313
|
+
(Cancel, Confirm) is what sticks to the dialog's bottom. Any `Dialog` or
|
|
314
|
+
`AlertDialog` whose content holds a `.form-grid-layout` without
|
|
315
|
+
`form-actions` gets the same sticky footer.
|
|
316
|
+
- A focused control or link is scrolled into view clear of the actions and
|
|
317
|
+
a line of helper text below it (`scroll-margin-bottom` on the fields'
|
|
318
|
+
controls: 6rem, plus a dialog's bottom padding, 7.5rem above a
|
|
319
|
+
`ConfirmationDialog`'s stacked footer), so a field you tab to is never
|
|
320
|
+
hidden behind them (WCAG 2.4.11). It is set on the controls, so it holds
|
|
321
|
+
in a scroll box of your own too.
|
|
322
|
+
- Taller actions (a third button, labels that wrap) or helper text on
|
|
323
|
+
several lines need more room: raise `--form-actions-clearance` on the
|
|
324
|
+
form. A dialog whose bottom padding is not the default 1.5rem (`p-0` and
|
|
325
|
+
`p-4` are recognised) sets `--form-actions-fill` to it:
|
|
326
|
+
|
|
327
|
+
```css
|
|
328
|
+
.edit-school-form {
|
|
329
|
+
--form-actions-clearance: 9rem;
|
|
330
|
+
}
|
|
331
|
+
.edit-school-dialog {
|
|
332
|
+
--form-actions-fill: 2rem; /* its pb-8 */
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
```vue
|
|
337
|
+
<form class="form-grid-layout edit-school-form">
|
|
338
|
+
```
|
|
339
|
+
- To scroll a form in a box of your own, give it a height and the scroll
|
|
340
|
+
(`class="form-grid-layout max-h-[60vh] overflow-y-auto"`); to keep the
|
|
341
|
+
actions in place, give them `class="static"`. The
|
|
342
|
+
[troubleshooting entry](../troubleshooting.md#a-forms-fields-no-longer-scroll-in-their-own-box-after-upgrading)
|
|
343
|
+
has the details.
|
|
344
|
+
|
|
296
345
|
## Validation messages
|
|
297
346
|
|
|
298
347
|
`zodLocaleError()` from `@nxgt/material-vue/lib` is a Zod v4 error map that
|
|
@@ -619,6 +668,40 @@ const onSubmit = handleSubmit((values) => emit('save', values));
|
|
|
619
668
|
`{ [attribute.name]: value }` to its `name`. Its starting values come from
|
|
620
669
|
its `default-values` prop, not from the form.
|
|
621
670
|
|
|
671
|
+
### Rows a user adds and removes
|
|
672
|
+
|
|
673
|
+
When the rows are fields of their own — a school year's periods, each with a
|
|
674
|
+
name, a start date and an end date — use
|
|
675
|
+
[`RepeatableGroupFormField`](../components/form-fields.md#repeatablegroup)
|
|
676
|
+
over vee-validate's `useFieldArray`, and render each row's fields with the
|
|
677
|
+
form's own wrappers in its `row` slot:
|
|
678
|
+
|
|
679
|
+
```vue
|
|
680
|
+
<RepeatableGroupFormField
|
|
681
|
+
name="periods"
|
|
682
|
+
label="Periods"
|
|
683
|
+
row-label="period"
|
|
684
|
+
:max="6"
|
|
685
|
+
reorderable
|
|
686
|
+
:new-row="() => ({ name: '' })"
|
|
687
|
+
>
|
|
688
|
+
<template #row="{ path }">
|
|
689
|
+
<TextFormField :name="`${path}.name`" label="Name" />
|
|
690
|
+
<DateFormField :name="`${path}.start`" label="Start date" />
|
|
691
|
+
</template>
|
|
692
|
+
</RepeatableGroupFormField>
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
- A row's field shows its own error (`periods[1].name`); the array's own
|
|
696
|
+
error (`.min(2)` on the array) shows under the rows and describes the group.
|
|
697
|
+
- The slot's `path` is `periods[1]`, not `name`: a slot's `name` attribute is
|
|
698
|
+
the slot's own.
|
|
699
|
+
- The group moves the focus as rows come and go (an added row's first field,
|
|
700
|
+
a removed row's neighbour or Add, a moved row's move button) and announces each change politely
|
|
701
|
+
("Added period 3"), after its own buttons only: a row your
|
|
702
|
+
own code pushes leaves the focus where it is
|
|
703
|
+
([what to do](../troubleshooting.md#the-focus-does-not-move-to-a-new-row-of-a-repeatablegroupformfield)).
|
|
704
|
+
|
|
622
705
|
## Config-driven forms
|
|
623
706
|
|
|
624
707
|
`Field` renders the field that matches a config `type`, which is useful when
|
|
@@ -868,10 +951,12 @@ const onSubmit = handleSubmit(() => {
|
|
|
868
951
|
|
|
869
952
|
- `meta.valid` keeps the button disabled until the schema passes; the form
|
|
870
953
|
runs a silent validation when it mounts, so it starts disabled.
|
|
871
|
-
- `ConfirmationDialog`
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
954
|
+
- `ConfirmationDialog` renders its default slot above Cancel / Confirm and
|
|
955
|
+
emits `confirm`, then closes. For a small form (a name to type before a
|
|
956
|
+
delete), pass `form-options` (a schema and its `defaultValues`) and render
|
|
957
|
+
the fields in its `#form` slot: Confirm stays disabled until the form is
|
|
958
|
+
valid, and `@confirm` receives the schema's output. Use the pattern above
|
|
959
|
+
for a larger form with its own submit.
|
|
875
960
|
- `ConfirmDialog` (controlled: `open` is required) awaits its `@confirm`
|
|
876
961
|
handler: while the promise is pending both buttons are disabled and the
|
|
877
962
|
confirm button reads "Processing..." (`material.confirm-dialog.processing`);
|
package/docs/guides/i18n.md
CHANGED
|
@@ -281,7 +281,8 @@ checkboxes, the filter's presets and `Min`/`Max` fields, the `variant="4"` spinn
|
|
|
281
281
|
`DialogFooter`. `CopyButton` reads `material.copy.copy`, `copied` and `failed` ("Copy", "Copied",
|
|
282
282
|
"Copy failed"). The other icon-only buttons are named from it too: the
|
|
283
283
|
`Sidebar` toggle (`material.sidebar.toggle`), the data table's row expander
|
|
284
|
-
(`material.table.labels.toggle-row`)
|
|
284
|
+
(`material.table.labels.toggle-row`) and its header, a hidden "Expand" / "Déplier"
|
|
285
|
+
(`material.table.labels.expand`), its loading status, "Loading data…" /
|
|
285
286
|
"Chargement des données…" (`material.table.loading`), its scroll region,
|
|
286
287
|
"Scrollable table" / "Tableau défilant"
|
|
287
288
|
(`material.table.labels.scroll-region`, or the `scroll-label` prop), a `Chip`'s remove button, which the
|
|
Binary file
|
package/docs/roadmap.md
CHANGED
|
@@ -162,6 +162,13 @@ version they shipped in, and planned entries may name the major they target.
|
|
|
162
162
|
|
|
163
163
|
## Shipped
|
|
164
164
|
|
|
165
|
+
- **Rows a user adds, removes and reorders** — `RepeatableGroup` and
|
|
166
|
+
`RepeatableGroupFormField` over the form library's field array: rows from
|
|
167
|
+
the `row` slot, a list for assistive tech, Remove and move buttons named after
|
|
168
|
+
the row ("Remove period 2"), `max` and `min`, an empty state, focus that
|
|
169
|
+
follows each change, polite announcements, and the array's own error under
|
|
170
|
+
the rows. One column on a phone. 0.38.0.
|
|
171
|
+
|
|
165
172
|
- **Signed-out pages and two-step verification** — `AuthCard`, the frame of a
|
|
166
173
|
sign-in page (one `main`, the card's title its `h1`, a status or alert
|
|
167
174
|
notice, safe-area padding); `EnrolmentSecret`, a TOTP enrolment's QR code,
|
package/docs/troubleshooting.md
CHANGED
|
@@ -27,6 +27,7 @@ words in your error.
|
|
|
27
27
|
- [A Content-Security-Policy reports a `data:` image on every form with a required field](#a-content-security-policy-reports-a-data-image-on-every-form-with-a-required-field)
|
|
28
28
|
- [A Button's label overflows a card on a phone](#a-buttons-label-overflows-a-card-on-a-phone)
|
|
29
29
|
- [A dialog or sheet scrolls, or clips a child, after upgrading](#a-dialog-or-sheet-scrolls-or-clips-a-child-after-upgrading)
|
|
30
|
+
- [A form's fields no longer scroll in their own box after upgrading](#a-forms-fields-no-longer-scroll-in-their-own-box-after-upgrading)
|
|
30
31
|
- [`JsBarcode is not a function`](#jsbarcode-is-not-a-function)
|
|
31
32
|
- [A `LinkButton` selected as a `button` stops matching](#a-linkbutton-selected-as-a-button-stops-matching)
|
|
32
33
|
- [A `Toc`, `Pager`, `SeeAlso` or `ScrollProgress` inside `Doc` selected by `data-slot` stops matching](#a-toc-pager-seealso-or-scrollprogress-inside-doc-selected-by-data-slot-stops-matching)
|
|
@@ -51,6 +52,7 @@ words in your error.
|
|
|
51
52
|
- [The app shell's page scrolls instead of its content, or a full-height screen collapses](#the-app-shells-page-scrolls-instead-of-its-content-or-a-full-height-screen-collapses)
|
|
52
53
|
- [A test finds a new heading or a second `main`, or no longer finds a title in a `div`](#a-test-finds-a-new-heading-or-a-second-main-or-no-longer-finds-a-title-in-a-div)
|
|
53
54
|
- [`[data-test="typogaphy"]` finds nothing](#data-testtypogaphy-finds-nothing)
|
|
55
|
+
- [Long text in `Typography` no longer scrolls](#long-text-in-typography-no-longer-scrolls)
|
|
54
56
|
- [A `class` on `ActivityLayout` now styles the whole shell](#a-class-on-activitylayout-now-styles-the-whole-shell)
|
|
55
57
|
- [A test no longer finds a calendar day by its number](#a-test-no-longer-finds-a-calendar-day-by-its-number)
|
|
56
58
|
- [A `QRCode`'s `aria-label` is no longer on its wrapper](#a-qrcodes-aria-label-is-no-longer-on-its-wrapper)
|
|
@@ -97,6 +99,7 @@ words in your error.
|
|
|
97
99
|
- [A failed submit does not focus the first invalid field](#a-failed-submit-does-not-focus-the-first-invalid-field)
|
|
98
100
|
- [A test that finds a chip by `aria-selected` or `getByRole('option')` no longer finds it](#a-test-that-finds-a-chip-by-aria-selected-or-getbyroleoption-no-longer-finds-it)
|
|
99
101
|
- [The `ref` of a `SelectChipField` focuses nothing](#the-ref-of-a-selectchipfield-focuses-nothing)
|
|
102
|
+
- [The focus does not move to a new row of a `RepeatableGroupFormField`](#the-focus-does-not-move-to-a-new-row-of-a-repeatablegroupformfield)
|
|
100
103
|
- [A multi-step form reopens at a later step](#a-multi-step-form-reopens-at-a-later-step)
|
|
101
104
|
- [The form could not be loaded.](#the-form-could-not-be-loaded)
|
|
102
105
|
|
|
@@ -836,6 +839,26 @@ with its own `<main>` passes `content-as="div"`.
|
|
|
836
839
|
**Fix:** select `[data-test="typography"]` — or better, the text or the role
|
|
837
840
|
the user sees.
|
|
838
841
|
|
|
842
|
+
### Long text in `Typography` no longer scrolls
|
|
843
|
+
|
|
844
|
+
**When:** after upgrading, a `Typography` with a fixed height or width used to
|
|
845
|
+
scroll its overflowing text; it now overflows its box (or `truncate` and
|
|
846
|
+
`line-clamp-*` are the only things that clip it).
|
|
847
|
+
**Why:** `Typography` always carried `overflow-auto`, which made every block
|
|
848
|
+
`Typography` a scroll region: Firefox counted a subpixel overflow, and axe
|
|
849
|
+
reported `scrollable-region-focusable`. It sets no `overflow` now, so it is no
|
|
850
|
+
longer a block formatting context (its margins can collapse with its
|
|
851
|
+
neighbours'), and a text flex or grid item no longer has the zero minimum width a scroll container has.
|
|
852
|
+
**Fix:** where you want scrolling, wrap the text in an element that owns it,
|
|
853
|
+
focusable and named so keyboard users can scroll it; where you want a flex
|
|
854
|
+
item to shrink, give it `min-w-0`:
|
|
855
|
+
|
|
856
|
+
```vue
|
|
857
|
+
<div class="max-h-40 overflow-auto" tabindex="0" aria-label="Release notes">
|
|
858
|
+
<Typography>{{ longText }}</Typography>
|
|
859
|
+
</div>
|
|
860
|
+
```
|
|
861
|
+
|
|
839
862
|
### A `class` on `ActivityLayout` now styles the whole shell
|
|
840
863
|
|
|
841
864
|
**When:** after upgrading, the classes passed to `<ActivityLayout class="…">`
|
|
@@ -1262,6 +1285,32 @@ with `class="max-h-none overflow-visible"`; to change the cap, pass your own
|
|
|
1262
1285
|
For a dialog that should grow taller than the screen and scroll inside the
|
|
1263
1286
|
overlay instead of capping, use `DialogScrollContent`.
|
|
1264
1287
|
|
|
1288
|
+
### A form's fields no longer scroll in their own box after upgrading
|
|
1289
|
+
|
|
1290
|
+
**When:** after upgrading, a `.form-grid-layout` form grows with the page
|
|
1291
|
+
instead of scrolling its fields in a box of its own, Cancel and Save stay at
|
|
1292
|
+
the bottom of the screen, or a form inside a box you gave a fixed height
|
|
1293
|
+
overflows it.
|
|
1294
|
+
**Why:** the form grid used to cap its height
|
|
1295
|
+
(`max-h-[calc(100lvh-184px)]`, more from `md`) and scroll
|
|
1296
|
+
`[data-slot="form-fields"]` inside it, so a page had two scrolls, one inside
|
|
1297
|
+
the other. It now has no cap and no scroll of its own: the page, or the
|
|
1298
|
+
`DialogContent` / `SheetContent` around it, is the one scroll, and
|
|
1299
|
+
`[data-slot="form-actions"]` is sticky at its bottom on a blurred background.
|
|
1300
|
+
A `Drawer`'s content does not scroll, so a form that is a direct child of
|
|
1301
|
+
`DrawerContent` is the scroll box there.
|
|
1302
|
+
**Fix:** to scroll a form inside a box again, give the box (or the form) a
|
|
1303
|
+
height and the scroll; the actions then stick to its bottom. To keep the
|
|
1304
|
+
actions where they are, make them static:
|
|
1305
|
+
|
|
1306
|
+
```vue
|
|
1307
|
+
<form class="form-grid-layout max-h-[60vh] overflow-y-auto">
|
|
1308
|
+
<div data-slot="form-actions" class="static">
|
|
1309
|
+
```
|
|
1310
|
+
|
|
1311
|
+
An app's own fixed bottom bar or floating action button now sits under the
|
|
1312
|
+
sticky actions (`z-index: 10`): give it a z-index above 10 (`class="z-20"`).
|
|
1313
|
+
|
|
1265
1314
|
## Feedback
|
|
1266
1315
|
|
|
1267
1316
|
### A toast with an action never goes away
|
|
@@ -1974,6 +2023,27 @@ yourself.
|
|
|
1974
2023
|
field.value?.$el.querySelector<HTMLElement>('[aria-pressed="true"], button')?.focus();
|
|
1975
2024
|
```
|
|
1976
2025
|
|
|
2026
|
+
### The focus does not move to a new row of a `RepeatableGroupFormField`
|
|
2027
|
+
|
|
2028
|
+
**When:** a row is added to a `RepeatableGroupFormField` by your own code (a
|
|
2029
|
+
second "Add" button, a "Duplicate" action) through vee-validate's
|
|
2030
|
+
`useFieldArray` `push`, `prepend` or `insert` on the same `name`, and the focus
|
|
2031
|
+
stays where it was, with nothing announced.
|
|
2032
|
+
**Why:** the group moves the focus and announces the change only after its
|
|
2033
|
+
own buttons (the new row's first field, a removed row's neighbour, a move
|
|
2034
|
+
button). A row added from outside is a value change it renders, not an action
|
|
2035
|
+
it took.
|
|
2036
|
+
**Fix:** let the group's Add button add rows (`new-row` is what it pushes).
|
|
2037
|
+
When your own code must add one, move the focus yourself once the row has
|
|
2038
|
+
rendered:
|
|
2039
|
+
|
|
2040
|
+
```ts
|
|
2041
|
+
const { push } = useFieldArray('periods');
|
|
2042
|
+
push({ name: '' });
|
|
2043
|
+
await nextTick();
|
|
2044
|
+
document.querySelector<HTMLElement>('[data-slot="repeatable-group-row"]:last-child input')?.focus();
|
|
2045
|
+
```
|
|
2046
|
+
|
|
1977
2047
|
### A multi-step form reopens at a later step
|
|
1978
2048
|
|
|
1979
2049
|
**When:** a wizard built on `defineStepFormStore` opens at the step (and with
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
.form-grid-layout {
|
|
98
98
|
@apply relative flex flex-col gap-2 @container;
|
|
99
99
|
[data-slot="form-fields"] {
|
|
100
|
-
@apply grid @2xl:grid-cols-2 @4xl:grid-cols-3 @6xl:grid-cols-4 gap-2 bg-background/80 p-4 place-items-start
|
|
100
|
+
@apply grid @2xl:grid-cols-2 @4xl:grid-cols-3 @6xl:grid-cols-4 gap-2 bg-background/80 p-4 place-items-start;
|
|
101
101
|
|
|
102
102
|
[data-slot="separator"] {
|
|
103
103
|
@apply col-start-full;
|
|
@@ -125,13 +125,73 @@
|
|
|
125
125
|
@apply col-start-full;
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
+
/* A focused control scrolls into view clear of the actions and a line
|
|
129
|
+
of helper text, in any scroll box (WCAG 2.4.11 Focus Not Obscured). */
|
|
130
|
+
[data-slot="form-fields"]
|
|
131
|
+
:is(
|
|
132
|
+
input,
|
|
133
|
+
textarea,
|
|
134
|
+
select,
|
|
135
|
+
button,
|
|
136
|
+
a[href],
|
|
137
|
+
summary,
|
|
138
|
+
[tabindex],
|
|
139
|
+
[contenteditable]
|
|
140
|
+
) {
|
|
141
|
+
scroll-margin-bottom: calc(
|
|
142
|
+
var(--form-actions-clearance, 6rem) +
|
|
143
|
+
var(--form-actions-fill, 0px)
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
/* Sticky at the bottom of whatever scrolls the form: in reach. */
|
|
128
147
|
[data-slot="form-actions"] {
|
|
129
|
-
@apply flex w-full justify-end gap-2
|
|
148
|
+
@apply sticky bottom-0 z-10 flex w-full justify-end gap-2 bg-background/90 p-4 backdrop-blur-sm max-sm:*:flex-1;
|
|
130
149
|
}
|
|
131
150
|
}
|
|
132
151
|
|
|
133
|
-
|
|
134
|
-
|
|
152
|
+
/* No height cap and no scroll of its own: the page (or the overlay) is
|
|
153
|
+
the one scroll. A Drawer's content does not scroll: the form does. */
|
|
154
|
+
[data-slot="drawer-content"] > .form-grid-layout {
|
|
155
|
+
@apply min-h-0 overflow-y-auto;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* In a dialog, the stuck actions sit above its bottom padding
|
|
159
|
+
(`--form-actions-fill`: p-6 by default; set it for another one). */
|
|
160
|
+
:is([data-slot="dialog-content"], [data-slot="alert-dialog-content"]) {
|
|
161
|
+
--form-actions-fill: 1.5rem;
|
|
162
|
+
&:is(.p-0, .py-0, .pb-0) {
|
|
163
|
+
--form-actions-fill: 0px;
|
|
164
|
+
}
|
|
165
|
+
&:is(.p-4, .py-4, .pb-4) {
|
|
166
|
+
--form-actions-fill: 1rem;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* ConfirmationDialog's form has no actions of its own: the dialog's
|
|
171
|
+
footer (two stacked buttons on a phone) sticks instead. */
|
|
172
|
+
:is([data-slot="dialog-content"], [data-slot="alert-dialog-content"]):has(
|
|
173
|
+
.form-grid-layout
|
|
174
|
+
):not(:has([data-slot="form-actions"])) {
|
|
175
|
+
--form-actions-clearance: 7.5rem;
|
|
176
|
+
> :is([data-slot="dialog-footer"], [data-slot="alert-dialog-footer"]) {
|
|
177
|
+
@apply sticky bottom-0 z-10 bg-background/90 backdrop-blur-sm;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/* A sticky element stops at the scroll box's padding: in a dialog, an
|
|
182
|
+
`::after` as tall as that padding fills the strip below the stuck
|
|
183
|
+
actions, so no field shows there, and adds no overflow. */
|
|
184
|
+
:is([data-slot="dialog-content"], [data-slot="alert-dialog-content"])
|
|
185
|
+
.form-grid-layout
|
|
186
|
+
> [data-slot="form-actions"]::after,
|
|
187
|
+
:is([data-slot="dialog-content"], [data-slot="alert-dialog-content"]):has(
|
|
188
|
+
.form-grid-layout
|
|
189
|
+
):not(:has([data-slot="form-actions"]))
|
|
190
|
+
> :is(
|
|
191
|
+
[data-slot="dialog-footer"],
|
|
192
|
+
[data-slot="alert-dialog-footer"]
|
|
193
|
+
)::after {
|
|
194
|
+
@apply absolute inset-x-0 top-full h-(--form-actions-fill) bg-background content-[""];
|
|
135
195
|
}
|
|
136
196
|
|
|
137
197
|
/* No height cap on `DataTable` here (it nested a scroll in the page's):
|
package/lib/components/base.css
CHANGED
|
@@ -55,7 +55,9 @@
|
|
|
55
55
|
font-size: var(--text-xs);
|
|
56
56
|
font-weight: var(--font-weight-medium);
|
|
57
57
|
}
|
|
58
|
-
a:
|
|
58
|
+
/* A sidebar entry is a link styled as a menu entry: the prose link style
|
|
59
|
+
(underline, info tint on hover and focus) must not reach it (#566). */
|
|
60
|
+
a:not(:has(> button)):not([data-slot="sidebar-menu-item"]) {
|
|
59
61
|
@apply focus:underline underline-offset-4 hover:underline cursor-pointer;
|
|
60
62
|
@apply text-info [&_svg]:data-[slot=icon]:text-info hover:bg-info/10 active:bg-info/5 focus:bg-info/15;
|
|
61
63
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/material-vue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"email": "stevegires@gmail.com"
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"docs:previews": "vitest run --project previews"
|
|
125
125
|
},
|
|
126
126
|
"dependencies": {
|
|
127
|
-
"@nxgt/material-core": "^0.
|
|
127
|
+
"@nxgt/material-core": "^0.11.0",
|
|
128
128
|
"@floating-ui/dom": "^1.8.0",
|
|
129
129
|
"@fortawesome/fontawesome-common-types": "7.3.1",
|
|
130
130
|
"@lucide/vue": "^1.45.0",
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { nextTick as e, useTemplateRef as t, watch as n } from "vue";
|
|
2
|
-
import { unrefElement as r } from "@vueuse/core";
|
|
3
|
-
import { inertOthers as i } from "@nxgt/material-core/inert-others";
|
|
4
|
-
//#region lib/components/ui/overlays/dialog/use-inert-others.ts
|
|
5
|
-
function a(a, o) {
|
|
6
|
-
let s = typeof a == "string" ? t(a) : a;
|
|
7
|
-
n(o, (t, n, a) => {
|
|
8
|
-
if (!t || typeof document > "u") return;
|
|
9
|
-
let o, c = !1;
|
|
10
|
-
e(() => {
|
|
11
|
-
let e = r(s);
|
|
12
|
-
!c && e instanceof Element && (o = i(e));
|
|
13
|
-
}), a(() => {
|
|
14
|
-
c = !0, o?.();
|
|
15
|
-
});
|
|
16
|
-
}, {
|
|
17
|
-
immediate: !0,
|
|
18
|
-
flush: "post"
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
//#endregion
|
|
22
|
-
export { a as t };
|