@nxgt/material-vue 0.34.0 → 0.36.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.
Files changed (113) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/README.md +11 -5
  3. package/dist/{Button-DEA5W6O3.js → Button-CurFF4Zt.js} +1 -1
  4. package/dist/{HoverCardTrigger-CjSteFgk.js → HoverCardTrigger-C3r0oc5d.js} +2 -2
  5. package/dist/{camera-C52IuvMH.js → camera-CaQlF4JJ.js} +4 -4
  6. package/dist/components/components.css +1 -0
  7. package/dist/components/print-only.css +44 -0
  8. package/dist/{components-DFEmacXJ.js → components-D56FEfTa.js} +23597 -23041
  9. package/dist/components.js +8 -8
  10. package/dist/composables.js +35 -25
  11. package/dist/dnd.js +1 -1
  12. package/dist/{form-scope-CaYs-o2w.js → form-scope-DOL9MJL3.js} +1 -1
  13. package/dist/{i18n-provider-CiVi05fs.js → i18n-provider-B2q6vp6H.js} +1 -1
  14. package/dist/i18n.js +4 -4
  15. package/dist/{icon-button-CWcOcNHr.js → icon-button-CIUc1bEp.js} +1 -1
  16. package/dist/lib/components/index.d.ts +1 -0
  17. package/dist/lib/components/ui/actions/button/Button.vue.d.ts +1 -1
  18. package/dist/lib/components/ui/actions/button/button.variants.d.ts +1 -1
  19. package/dist/lib/components/ui/actions/copy-button/copy-button.vue.d.ts +1 -1
  20. package/dist/lib/components/ui/actions/copy-button/use-copy-status.d.ts +14 -0
  21. package/dist/lib/components/ui/actions/icon-button/icon-button.variants.d.ts +1 -1
  22. package/dist/lib/components/ui/actions/icon-button/icon-button.vue.d.ts +1 -1
  23. package/dist/lib/components/ui/actions/scroll-to-top/scroll-to-top.vue.d.ts +1 -1
  24. package/dist/lib/components/ui/display/badge/index.d.ts +1 -1
  25. package/dist/lib/components/ui/display/cards/cards.gallery.d.ts +3 -3
  26. package/dist/lib/components/ui/display/chip/chip.utils.d.ts +9 -0
  27. package/dist/lib/components/ui/display/chip/chip.vue.d.ts +29 -16
  28. package/dist/lib/components/ui/display/chip/index.d.ts +1 -0
  29. package/dist/lib/components/ui/display/count-badge/count-badge.vue.d.ts +1 -1
  30. package/dist/lib/components/ui/display/enrolment-secret/enrolment-secret.vue.d.ts +30 -0
  31. package/dist/lib/components/ui/display/enrolment-secret/index.d.ts +3 -0
  32. package/dist/lib/components/ui/display/index.d.ts +2 -0
  33. package/dist/lib/components/ui/display/recovery-codes/index.d.ts +5 -0
  34. package/dist/lib/components/ui/display/recovery-codes/partials/recovery-codes-actions.vue.d.ts +11 -0
  35. package/dist/lib/components/ui/display/recovery-codes/partials/recovery-codes-confirm.vue.d.ts +15 -0
  36. package/dist/lib/components/ui/display/recovery-codes/partials/recovery-codes-list.vue.d.ts +7 -0
  37. package/dist/lib/components/ui/display/recovery-codes/recovery-codes.vue.d.ts +56 -0
  38. package/dist/lib/components/ui/display/recovery-codes/types.d.ts +23 -0
  39. package/dist/lib/components/ui/display/recovery-codes/use-recovery-codes-labels.d.ts +18 -0
  40. package/dist/lib/components/ui/feedback/alert/alert.vue.d.ts +1 -1
  41. package/dist/lib/components/ui/feedback/circular-progress/circular-progress.vue.d.ts +2 -2
  42. package/dist/lib/components/ui/feedback/spinner/spinner.variants.d.ts +1 -1
  43. package/dist/lib/components/ui/feedback/spinner/spinner.vue.d.ts +1 -1
  44. package/dist/lib/components/ui/fields/contacts/consts.d.ts +1 -1
  45. package/dist/lib/components/ui/fields/form-section/form-section-classes.d.ts +30 -0
  46. package/dist/lib/components/ui/fields/form-section/form-section.vue.d.ts +37 -0
  47. package/dist/lib/components/ui/fields/form-section/index.d.ts +3 -0
  48. package/dist/lib/components/ui/fields/index.d.ts +1 -0
  49. package/dist/lib/components/ui/fields/rating-field/rating-field.variants.d.ts +1 -1
  50. package/dist/lib/components/ui/fields/rating-field/rating-field.vue.d.ts +1 -1
  51. package/dist/lib/components/ui/forms/form-scope-schema.d.ts +8 -2
  52. package/dist/lib/components/ui/forms/index.d.ts +1 -0
  53. package/dist/lib/components/ui/forms/use-code-resolver.d.ts +45 -0
  54. package/dist/lib/components/ui/layout/app-shell/activity-content.vue.d.ts +1 -1
  55. package/dist/lib/components/ui/layout/auth-card/auth-card-notice.vue.d.ts +18 -0
  56. package/dist/lib/components/ui/layout/auth-card/auth-card.vue.d.ts +45 -0
  57. package/dist/lib/components/ui/layout/auth-card/index.d.ts +3 -0
  58. package/dist/lib/components/ui/layout/auth-card/types.d.ts +2 -0
  59. package/dist/lib/components/ui/layout/index.d.ts +1 -0
  60. package/dist/lib/components/ui/selection/select-field/select-field.vue.d.ts +2 -0
  61. package/dist/lib/composables/index.d.ts +2 -0
  62. package/dist/lib/composables/use-focus-on-mount.d.ts +23 -0
  63. package/dist/lib/composables/use-submit-once.d.ts +33 -0
  64. package/dist/lib/i18n/resources/en/en.d.ts +21 -0
  65. package/dist/lib/i18n/resources/en/material.json.d.ts +22 -1
  66. package/dist/lib/i18n/resources/fr/fr.d.ts +21 -0
  67. package/dist/lib/i18n/resources/fr/material.json.d.ts +22 -1
  68. package/dist/lib/i18n/resources/resources.d.ts +42 -0
  69. package/dist/lib/i18n/translator.d.ts +1 -1
  70. package/dist/lib/lib/index.d.ts +1 -0
  71. package/dist/lib/nuxt/auto-imports.d.ts +1 -1
  72. package/dist/lib/nuxt/component-names.d.ts +1 -1
  73. package/dist/lib.js +59 -104
  74. package/dist/main.js +17 -17
  75. package/dist/map.js +4 -4
  76. package/dist/material-vue.css +1 -1
  77. package/dist/{pdf-outline-sidebar-C_iJ8gqD.js → pdf-outline-sidebar-Gmdd3RNG.js} +2 -2
  78. package/dist/{pdf-page-DOiJlWQn.js → pdf-page-C3XhLcrp.js} +1 -1
  79. package/dist/{pdf-page-list-BTmUd7Ga.js → pdf-page-list-BTIb5Y-Y.js} +2 -2
  80. package/dist/{pdf-reader-CEMMLJnB.js → pdf-reader-CX2owreo.js} +8 -8
  81. package/dist/{pdf-sidebar-KLd76E5S.js → pdf-sidebar-BmAJ8Q_m.js} +3 -3
  82. package/dist/{pdf-thumbnail-sidebar-B4JkT_LV.js → pdf-thumbnail-sidebar-C04OeZ9M.js} +3 -3
  83. package/dist/{pdf-toolbar-Da6UMt1O.js → pdf-toolbar-zI0_eNXV.js} +4 -4
  84. package/dist/pdf.js +2 -2
  85. package/dist/print-format.utils-keJqahvw.js +187 -0
  86. package/dist/{sortable-provider-Cvpqk8tp.js → sortable-provider-DMu8DL2z.js} +2 -2
  87. package/dist/{stored-language-GDRdeYD8.js → stored-language-dtksFoGO.js} +44 -2
  88. package/dist/{stx-player-B6-PSgzP.js → stx-player-BUo2Vs0j.js} +5 -5
  89. package/dist/{translator-BDFEmlcL.js → translator-DqiGrSH_.js} +1 -1
  90. package/dist/{use-heading-spy-ClhUg50z.js → use-heading-spy-BZ7ctGZ5.js} +58 -48
  91. package/dist/{use-material-translation-CaHS6oZz.js → use-material-translation-DRB6oPdF.js} +3 -3
  92. package/docs/components/README.md +3 -3
  93. package/docs/components/data-display.md +126 -2
  94. package/docs/components/data-table-filter-and-lists.md +2 -1
  95. package/docs/components/form-fields.md +81 -0
  96. package/docs/components/navigation-and-layout.md +64 -0
  97. package/docs/components/selection-and-choice.md +2 -1
  98. package/docs/guides/forms.md +120 -0
  99. package/docs/guides/helpers.md +85 -0
  100. package/docs/guides/i18n.md +17 -0
  101. package/docs/guides/printing.md +27 -0
  102. package/docs/previews/data-display-enrolmentsecret.webp +0 -0
  103. package/docs/previews/data-display-recoverycodes.webp +0 -0
  104. package/docs/previews/form-fields-formsection.webp +0 -0
  105. package/docs/previews/navigation-layout-authcard.webp +0 -0
  106. package/docs/roadmap.md +48 -15
  107. package/docs/troubleshooting.md +92 -0
  108. package/lib/components/components.css +1 -0
  109. package/lib/components/print-only.css +44 -0
  110. package/lib/nuxt/auto-imports.ts +2 -0
  111. package/lib/nuxt/component-names.ts +4 -0
  112. package/package.json +2 -2
  113. package/dist/print-format.utils-DpBtUJvL.js +0 -138
package/CHANGELOG.md CHANGED
@@ -1,5 +1,107 @@
1
1
  # @nxgt/material-vue
2
2
 
3
+ ## 0.36.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#535](https://github.com/softistx/nxgt-material/pull/535) [`a088c1c`](https://github.com/softistx/nxgt-material/commit/a088c1c8f08f8c4483fe0ba0e35eedfbe1b193f9) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Three form and focus helpers, the same names in both libraries (softistx/nxgt-material#500). Fixes [#500](https://github.com/softistx/nxgt-material/issues/500).
8
+
9
+ - **`useFocusOnMount<T>(focus?)`** (`@nxgt/material/hooks`, `@nxgt/material-vue/composables`, auto-imported by the Nuxt module): the element takes focus once mounted, and again whenever `focus` turns true. Put it on the heading of what replaced the content the user acted on (a wizard's next step, "Message sent"), with `tabIndex={-1}` / `tabindex="-1"`. React returns a `RefObject`, Vue a `ShallowRef` to bind with `ref="…"`.
10
+ - **`useSubmitOnce(busy?)`** (same entries): one submit in flight. `const submitOnce = useSubmitOnce(); <form onSubmit={submitOnce(handleSubmit(save))}>` (Vue: `const onSubmit = submitOnce(handleSubmit(save))`) drops a double click or a second Enter until `save` ends; a dropped call's event has its default prevented. Return the request's promise, or pass its busy flag (Vue: a ref or getter): the guard then opens once the flag was true and is false again, for the submit that was on its way when it rose. Without `busy`, a handler that returns no promise (an early `return`) opens the guard at once. The framework-free `createSubmitGuard()` and `busySettler(guard)` are re-exported by both from `@nxgt/material-core/submit-guard`.
11
+ - **`useCodeResolver(schema, { translate, codeOf?, language? })`** (`@nxgt/material/components`, `@nxgt/material-vue/components`): a zod 4 schema's errors worded in the page's language. A refinement carrying `params.code` (`.refine(isFree, { params: { code: 'errors.taken' } })`) reads as your translator's words for that code, every other issue as `zodLocaleError`'s, with your `material.zod.*` overrides. `createCodeErrorMap`, `defaultCodeOf`, `isEmptyRequired` and the type `CodeIssue` are exported beside it. React returns a react-hook-form `Resolver` (`useForm({ resolver })`); Vue a computed vee-validate `TypedSchema` (`useForm({ validationSchema })`), so a language switch re-words the errors on screen.
12
+ - `@nxgt/material-core` adds `/submit-guard` (`createSubmitGuard` with `once(run, { settleSync })`, a run-scoped `settle(run)` and `pendingRun()`, and `busySettler`) and `/code-errors` (`createCodeErrorMap`, `defaultCodeOf`, `isEmptyRequired`): the error map is typed by shape, with no zod dependency.
13
+
14
+ An app with a local copy marked `To extract to material (request [#500](https://github.com/softistx/nxgt-material/issues/500))` — `useFocusOnMount`, `createSubmitGuard` / `useSubmitOnce`, `useCodeResolver` and the code error map behind it — can delete it and import the same names from `@nxgt/material` / `@nxgt/material-vue` (`createSubmitGuard` and `createCodeErrorMap` from `@nxgt/material-core/submit-guard` and `/code-errors`). A local `useSubmitOnce(busy)` keeps its call; a local code error map becomes `useCodeResolver(schema, { translate, codeOf })`, with `codeOf: (issue) => (isEmptyRequired(issue) ? '<your required code>' : defaultCodeOf(issue))` where empty required fields had a code of their own.
15
+
16
+ - [#531](https://github.com/softistx/nxgt-material/pull/531) [`031a67c`](https://github.com/softistx/nxgt-material/commit/031a67ca5d837e4f0a55745c1be96566a19f578c) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Add `FormSection` (Storybook `Form fields/FormSection`), a titled section of a
17
+ long form: a heading (an `h2` by default, `titleAs` / `title-as` for `h3`–`h6`),
18
+ an optional description and actions beside the title, then its fields. Inside
19
+ the form grid (`.form-grid-layout` / `[data-slot="form-fields"]`) it spans the
20
+ whole row and lays its fields out in the grid's columns, one column on a
21
+ phone; switches, textareas, chips and file fields still take a row of their
22
+ own. A rule separates it from the section before (`separated`, default on).
23
+ It is a `role="group"` named by its heading and described by its
24
+ description, so `getByRole('group', { name: 'Profile' })` finds it.
25
+
26
+ ```tsx
27
+ <form className="form-grid-layout">
28
+ <div data-slot="form-fields">
29
+ <FormSection title="Profile" description="Shown on your public page.">
30
+ <TextFormField control={control} name="name" label="Name" />
31
+ </FormSection>
32
+ </div>
33
+ </form>
34
+ ```
35
+
36
+ ```vue
37
+ <FormSection title="Profile" description="Shown on your public page.">
38
+ <template #actions><Button size="sm">Add</Button></template>
39
+ <TextFormField name="name" label="Name" />
40
+ </FormSection>
41
+ ```
42
+
43
+ Fixes [#499](https://github.com/softistx/nxgt-material/issues/499).
44
+
45
+ Migration: an app with a local section shell marked `To extract to material
46
+ (request [#499](https://github.com/softistx/nxgt-material/issues/499))` — a `SectionTitle` heading (`text-sm font-semibold uppercase
47
+ tracking-wide text-muted-foreground`) followed by its fields, with a
48
+ `Separator` between sections inside `[data-slot="form-fields"]` — can delete
49
+ it and wrap each section's fields in `FormSection` from `@nxgt/material` /
50
+ `@nxgt/material-vue` instead: `title` replaces the `SectionTitle`, and the
51
+ `Separator` goes (the rule is drawn by the section).
52
+
53
+ - [#544](https://github.com/softistx/nxgt-material/pull/544) [`e071e15`](https://github.com/softistx/nxgt-material/commit/e071e15a1d3b31c7e8fe7ad83d5a206687d18d9f) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Signed-out pages and two-step verification: `AuthCard`, `EnrolmentSecret` and `RecoveryCodes`, the same names in both libraries (`@nxgt/material/components`, `@nxgt/material-vue/components`, registered by the Nuxt module). Fixes [#498](https://github.com/softistx/nxgt-material/issues/498).
54
+
55
+ - **`AuthCard`** (Storybook `Navigation & layout/AuthCard`): the frame of a sign-in, sign-up or reset page. One `<main tabIndex={-1}>` (focusable by script, never by Tab), a centred card whose `title` is the page's `h1`, a `description`, a `notice` above the form (`noticeTone` `'info'` | `'success'` | `'warning'` are `role="status"`, `'error'` is `role="alert"`), `focusTitle` to move the focus to the `h1` on an end state ("Check your inbox"), a row above the card for `brand` and `toolbar` (rendered only when one is given), a `banner` above it and a `footer` under the card. Padded with `max(1rem, env(safe-area-inset-*))` by classes, no inline style. Vue: the same props, and slots `title`, `description`, `notice`, `brand`, `toolbar`, `banner`, `footer`.
56
+ - **`EnrolmentSecret`** (`Data display/EnrolmentSecret`): a TOTP enrolment — the `otpauth://` URI's QR code (the library's `QRCode`, level M, named "QR code to scan with your authenticator app"), the URI as a link ("Open in your authenticator app": a phone cannot scan its own screen) and the secret in groups of four in a group named "Setup key", with a `CopyButton` that copies it without spaces and announces "Key copied". `uri`, `secret`, `showQrCode` (default `true`), `qrSize` (default `192`) and a prop per label. Side by side once the component is 28rem wide, stacked on a phone, the key wrapping inside the card.
57
+ - **`RecoveryCodes`** (`Data display/RecoveryCodes`): one-time codes shown once, in a card. An ordered list named "Recovery codes"; "Copy codes" (one per line, announced "Codes copied" / "Copy failed" by the component's own polite status region, no `Toaster` needed); "Download" (a text file: `fileHeading`, `fileNote`, a blank line, the codes; `fileName` defaults to `recovery-codes.txt`); "Print" (the card alone, through the new print rules in `styles.css`); and "I have saved these codes", which "Done" requires: pressed before, it moves the focus to the box, marks it `aria-invalid` and says "Tick the box once your codes are safe". `title` / `titleAs` (`h2` by default), `description`, `warning` (`false` hides it), `focusTitle` (default `true`), `onDone` (the "Done" button shows only with it; Vue: `@done`), `saved` / `onSavedChange` (Vue: `v-model:saved`) and `labels`.
58
+
59
+ ```tsx
60
+ <AuthCard title="Two-step verification" brand={<Logo />} toolbar={<LanguageSwitcher />}>
61
+ <EnrolmentSecret uri={enrolment.uri} secret={enrolment.secret} />
62
+ </AuthCard>
63
+ <RecoveryCodes codes={codes} fileHeading={`Recovery codes for ${email}`} saved={saved} onSavedChange={setSaved} onDone={done} />
64
+ ```
65
+
66
+ ```vue
67
+ <RecoveryCodes v-model:saved="saved" :codes="codes" :file-heading="`Recovery codes for ${email}`" @done="done" />
68
+ ```
69
+
70
+ `groupSecret`, `recoveryCodesText` and `downloadText` are re-exported beside them. `@nxgt/material-core` adds `/two-factor`: `groupSecret(secret, size = 4)`, `recoveryCodesText(codes, { heading?, note? })` and `downloadText(text, fileName, { type? })` (an object URL revoked a minute later, as `/pdf-download` does: both now share one helper). It also adds `/print-only`: `printOnly(element, name?)` prints one element of the page through `data-nxgt-print` on `<html>` and `data-nxgt-print-target` on the element, removed on `afterprint` or once a blocking `print()` returns; the rules are the new `print-only.css` in each library's `styles.css`, and both libraries re-export `printOnly`, `PRINT_ATTRIBUTE` and `PRINT_TARGET_ATTRIBUTE` from `/lib`. `CopyButton` and `RecoveryCodes` share the copy-and-announce state; `CopyButton` behaves as before. In `@nxgt/material-vue`, `Checkbox` now shows a `#helper-text` (or `#label`) slot that is added after the first render.
71
+
72
+ Migration: local copies marked `To extract to material (request [#498](https://github.com/softistx/nxgt-material/issues/498))` can be deleted. A local sign-in frame becomes `AuthCard` (its subtitle is `description`; brand, language switcher and banner go in `brand`, `toolbar` and `banner`). A local enrolment block becomes `EnrolmentSecret uri secret`, and a local grouping helper `groupSecret`. A local recovery-codes display becomes `RecoveryCodes`, a local file builder `recoveryCodesText(codes, { heading, note })`, and a local print-only rule `printOnly`; the app keeps its wording (`title`, `description`, `fileHeading`, `fileNote`, `labels`), its data loading and its navigation guard while `saved` is false.
73
+
74
+ ### Patch Changes
75
+
76
+ - Updated dependencies [[`a088c1c`](https://github.com/softistx/nxgt-material/commit/a088c1c8f08f8c4483fe0ba0e35eedfbe1b193f9), [`e071e15`](https://github.com/softistx/nxgt-material/commit/e071e15a1d3b31c7e8fe7ad83d5a206687d18d9f)]:
77
+ - @nxgt/material-core@0.10.0
78
+
79
+ ## 0.35.0
80
+
81
+ ### Minor Changes
82
+
83
+ - [#547](https://github.com/softistx/nxgt-material/pull/547) [`20f68b0`](https://github.com/softistx/nxgt-material/commit/20f68b02ff171ebda7cd0e30ada9103a633949b8) Thanks [@SteveGT96](https://github.com/SteveGT96)! - `Chip`: the ✕ is a 24px target (WCAG 2.5.8) on the same chip height. New
84
+ `dismissLabel` (a string, or a function of the label's text) names the ✕ instead
85
+ of "Remove {label}". `ref` (React) and the exposed `el` and `focus()` (Vue)
86
+ reach the chip's body in every mode. New `variant="dashed"`, a muted dashed pill
87
+ that turns solid once `active`, and `size="sm"` for a compact chip. The label-only span now has `tabindex="-1"`, so `focus()` works there, and a
88
+ consumer's `tabindex` still wins. `ChipVariant` and `ChipSize` are now exported.
89
+
90
+ - [#546](https://github.com/softistx/nxgt-material/pull/546) [`d284fd3`](https://github.com/softistx/nxgt-material/commit/d284fd32de610cd28db3b8066a64ccd913764ce6) Thanks [@SteveGT96](https://github.com/SteveGT96)! - `DataTablePagination`: the "Rows per page" select is named by its label, an
91
+ empty table shows no "Page 1 of 0", and the selection message now leads with
92
+ the count: "No rows selected of 128", "1 row selected of 128" (French: "Aucune
93
+ ligne sélectionnée sur 128"). This changes the `material.table.pagination.rows-selected`
94
+ copy; apps that override it should adopt the new ICU form. `SelectField` takes
95
+ `aria-labelledby` (React) / `ariaLabelledby` (Vue). The React `FilterChips`
96
+ removes a filter with a real "Remove" button, no longer by a click on the chip.
97
+
98
+ ### Patch Changes
99
+
100
+ - [#541](https://github.com/softistx/nxgt-material/pull/541) [`6d10133`](https://github.com/softistx/nxgt-material/commit/6d1013356e8c42631166b6281081811912e31323) Thanks [@SteveGT96](https://github.com/SteveGT96)! - The roadmaps plan one Vite plugin for the setup, and list the strict Content
101
+ Security Policy as shipped.
102
+ - Updated dependencies [[`6d10133`](https://github.com/softistx/nxgt-material/commit/6d1013356e8c42631166b6281081811912e31323)]:
103
+ - @nxgt/material-core@0.9.1
104
+
3
105
  ## 0.34.0
4
106
 
5
107
  ### Minor Changes
package/README.md CHANGED
@@ -19,11 +19,13 @@ lists the React equivalent for each entry.
19
19
  - **Form fields, standalone or vee-validate.** Each field works with `v-model`,
20
20
  and most have a `*FormField` wrapper that binds to a vee-validate form by
21
21
  `name`. The [forms guide](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/guides/forms.md) covers Zod
22
- validation, composite values, config-driven forms and server errors.
22
+ validation, errors worded by code in the page's language
23
+ (`useCodeResolver`), composite values, config-driven forms and server
24
+ errors.
23
25
  - **Helpers** ([helpers guide](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/guides/helpers.md)): `cn`,
24
26
  `clientOnly`, date, number and string utilities, a Zod error map, Pinia store
25
- factories in `/lib`, and composables (`useTheme`, `useIsMobile`, …) in
26
- `/composables`.
27
+ factories in `/lib`, and composables (`useTheme`, `useIsMobile`,
28
+ `useFocusOnMount`, `useSubmitOnce`, …) in `/composables`.
27
29
  - **i18n** ([i18n guide](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/guides/i18n.md)): an `I18nProvider`
28
30
  with ICU messages and shipped `en` / `fr` strings. Your app merges in its own
29
31
  resources.
@@ -175,10 +177,10 @@ does not add the stylesheet. Options and the client-only widgets are in
175
177
  | Specifier | What is in it |
176
178
  | --- | --- |
177
179
  | `@nxgt/material-vue` | every barrel below, plus the compiled `style` condition (`dist/material-vue.css`, for apps without Tailwind) |
178
- | `@nxgt/material-vue/components` | UI components and `*FormField` wrappers ([Components](#components)) |
180
+ | `@nxgt/material-vue/components` | UI components, `*FormField` wrappers and `useCodeResolver` ([Components](#components)) |
179
181
  | `@nxgt/material-vue/map` | Leaflet maps, markers, a location field — **its own entry, not in the barrel** ([maps guide](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/guides/maps.md)) |
180
182
  | `@nxgt/material-vue/pdf` | PDF files from plain data: builders, `usePdf`, `PdfDownloadButton`, `pdfResponse` — **its own entry, not in the barrel** ([PDF guide](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/guides/pdf.md)) |
181
- | `@nxgt/material-vue/composables` | `useTheme`, `useIsClient`, `useIsMobile`, `useSearchParam`, `useCspNonce`, … ([helpers](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/guides/helpers.md)) |
183
+ | `@nxgt/material-vue/composables` | `useTheme`, `useIsClient`, `useIsMobile`, `useSearchParam`, `useCspNonce`, `useFocusOnMount`, `useSubmitOnce`, … ([helpers](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/guides/helpers.md)) |
182
184
  | `@nxgt/material-vue/dnd` | drag-and-drop primitives ([helpers](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/guides/helpers.md)) |
183
185
  | `@nxgt/material-vue/i18n` | `I18nProvider`, `mergeResources`, `createTranslator`, `translateMaterial`, … ([i18n guide](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/guides/i18n.md)) |
184
186
  | `@nxgt/material-vue/lib` | `cn`, `clientOnly`, date/number/string utils, Zod error map, `focusFirstInvalid` / `focusField` (focus an invalid field, see [forms](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/guides/forms.md#focusing-the-first-invalid-field)), Pinia store factories, `getCspNonce` / `setCspNonce` ([helpers](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/guides/helpers.md)) |
@@ -402,6 +404,7 @@ React-only for now: `StepperIndicator` ([roadmap](https://cdn.jsdelivr.net/npm/@
402
404
  | Preview | Component | What it does | @nxgt/material |
403
405
  | --- | --- | --- | --- |
404
406
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/form-fields-field.webp" width="120" alt="Field"> | [`Field`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/form-fields.md#field) | Renders the field matching a config `type` (text, select, date, upload, otp…). | `Field`, `FormField` |
407
+ | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/form-fields-formsection.webp" width="120" alt="FormSection"> | [`FormSection`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/form-fields.md#formsection) | A titled section of a form (an `h2` by default) with an optional description and actions, its fields in the form grid's columns, one column on a phone. | `FormSection` |
405
408
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/form-fields-textfield.webp" width="120" alt="TextField"> | [`TextField`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/form-fields.md#textfield) · `TextFormField` | Labelled input with leading / trailing adornments and helper text. | `TextField`, `TextFormField` |
406
409
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/form-fields-textareafield.webp" width="120" alt="TextareaField"> | [`TextareaField`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/form-fields.md#textareafield) · `TextareaFormField` | Labelled textarea with row sizing and a `maxLength` counter. | `TextareaField`, `TextareaFormField` |
407
410
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/form-fields-emailfield.webp" width="120" alt="EmailField"> | [`EmailField`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/form-fields.md#emailfield) · `EmailFormField` | Validates on blur; shows a `mailto:` button once the address is valid. | `EmailField`, `EmailFormField` |
@@ -485,6 +488,8 @@ React-only for now: `StepperIndicator` ([roadmap](https://cdn.jsdelivr.net/npm/@
485
488
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/data-display-paramtable.webp" width="120" alt="ParamTable"> | [`ParamTable`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/data-display.md#paramtable) | Name / type / default / description table; stacked cards below `sm`. | `ParamTable` |
486
489
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/data-display-qrcode.webp" width="120" alt="QRCode"> | [`QRCode`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/data-display.md#qrcode) | QR code on a padded tile, with an optional centred logo in its `#logo` slot. | `QRCode` |
487
490
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/data-display-barecode.webp" width="120" alt="Barecode"> | [`Barecode`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/data-display.md#barecode) | 1D barcode. | `Barecode` |
491
+ | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/data-display-enrolmentsecret.webp" width="120" alt="EnrolmentSecret"> | [`EnrolmentSecret`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/data-display.md#enrolmentsecret), `groupSecret` | A TOTP enrolment: the `otpauth://` QR code, the URI as a link to the authenticator app, and the key grouped by four, copyable, wrapping on a phone. | `EnrolmentSecret` |
492
+ | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/data-display-recoverycodes.webp" width="120" alt="RecoveryCodes"> | [`RecoveryCodes`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/data-display.md#recoverycodes), `recoveryCodesText`, `downloadText` | One-time recovery codes: a list, copy (announced), download, print of the card alone, and an "I have saved these codes" confirmation before Done. | `RecoveryCodes` |
488
493
 
489
494
  ### Data table, filter & lists
490
495
 
@@ -502,6 +507,7 @@ React-only for now: `StepperIndicator` ([roadmap](https://cdn.jsdelivr.net/npm/@
502
507
  | Preview | Component | What it does | @nxgt/material |
503
508
  | --- | --- | --- | --- |
504
509
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/navigation-layout-appshell.webp" width="120" alt="ActivityLayout"> | [`ActivityLayout`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/navigation-and-layout.md#activitylayout), `ActivityContent`, `AppSidebar`, `AppHeader`, `AppBreadcrumb` | App shell: sidebar built from `items`, a header with a mobile sheet, route breadcrumbs and a titled page; entries are real links, and `link-component` swaps the link. See the [app shell guide](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/guides/app-shell.md). | `ActivityLayout`, `ActivityContent`, `AppSidebar`, `AppHeader`, `AppBreadcrumb` |
510
+ | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/navigation-layout-authcard.webp" width="120" alt="AuthCard"> | [`AuthCard`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/navigation-and-layout.md#authcard) | The frame of a signed-out page: one `main`, a centred card whose title is the `h1` (focusable on an end state), a status or alert notice, a brand and toolbar row, safe-area padding. | `AuthCard` |
505
511
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/navigation-layout-sidebar.webp" width="120" alt="Sidebar"> | [`Sidebar`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/navigation-and-layout.md#sidebar), `SidebarHeader`, `SidebarContent`, `SidebarFooter`, `SidebarMenuItem`, `SidebarMenuLabel` | Collapsible navigation sidebar with icons, tooltips and active items. | `Sidebar` (same parts) |
506
512
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/navigation-layout-topappbar.webp" width="120" alt="TopAppBar"> | [`TopAppBar`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/navigation-and-layout.md#topappbar), `BottomAppBar` | Top bar surface, and a bottom bar of icon actions with an active state. | `TopAppBar`, `BottomAppBar` |
507
513
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/previews/navigation-layout-breadcrumb.webp" width="120" alt="Breadcrumb"> | [`Breadcrumb`](https://cdn.jsdelivr.net/npm/@nxgt/material-vue@0/docs/components/navigation-and-layout.md#breadcrumb), `BreadcrumbList`, `BreadcrumbItem`, `BreadcrumbLink`, `BreadcrumbPage` + parts | Breadcrumb primitives. | `Breadcrumb` (same parts) |
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./utils-CykWQ0iJ.js";
2
- import { t } from "./use-material-translation-CaHS6oZz.js";
2
+ import { t } from "./use-material-translation-DRB6oPdF.js";
3
3
  import { Comment as n, Fragment as r, Text as i, computed as a, createBlock as o, createElementBlock as s, createElementVNode as c, createTextVNode as l, createVNode as u, defineComponent as d, guardReactiveProps as f, h as p, inject as ee, isVNode as m, mergeProps as h, normalizeClass as g, normalizeProps as _, onBeforeUnmount as v, openBlock as y, provide as b, ref as x, renderSlot as S, shallowRef as C, unref as w, useAttrs as te, useSlots as ne, watch as T, withCtx as E } from "vue";
4
4
  import { Primitive as D, TooltipArrow as O, TooltipContent as k, TooltipPortal as A, TooltipProvider as re, TooltipRoot as j, TooltipTrigger as M, useForwardPropsEmits as N } from "reka-ui";
5
5
  import { cva as P } from "class-variance-authority";
@@ -1,6 +1,6 @@
1
1
  import { t as e } from "./utils-CykWQ0iJ.js";
2
- import { t } from "./use-material-translation-CaHS6oZz.js";
3
- import { t as n } from "./Button-DEA5W6O3.js";
2
+ import { t } from "./use-material-translation-DRB6oPdF.js";
3
+ import { t as n } from "./Button-CurFF4Zt.js";
4
4
  import { t as r } from "./use-inert-others-CtGqZKR8.js";
5
5
  import { t as i } from "./field-name-attribute-Bl7LSVK0.js";
6
6
  import { computed as a, createBlock as o, createCommentVNode as s, createElementBlock as c, createElementVNode as l, createTextVNode as u, createVNode as d, defineComponent as f, getCurrentInstance as p, guardReactiveProps as m, isRef as h, mergeProps as g, normalizeClass as _, normalizeProps as v, onMounted as ee, onUpdated as y, openBlock as b, renderSlot as x, toDisplayString as S, unref as C, useAttrs as w, useId as T, useTemplateRef as E, vModelText as D, withCtx as O, withDirectives as k } from "vue";
@@ -1,8 +1,8 @@
1
1
  import { t as e } from "./utils-CykWQ0iJ.js";
2
- import { _r as t, hr as n, mr as r } from "./components-DFEmacXJ.js";
3
- import { t as i } from "./use-material-translation-CaHS6oZz.js";
4
- import { t as a } from "./Button-DEA5W6O3.js";
5
- import { t as o } from "./icon-button-CWcOcNHr.js";
2
+ import { _r as t, hr as n, mr as r } from "./components-D56FEfTa.js";
3
+ import { t as i } from "./use-material-translation-DRB6oPdF.js";
4
+ import { t as a } from "./Button-CurFF4Zt.js";
5
+ import { t as o } from "./icon-button-CIUc1bEp.js";
6
6
  import { createBlock as s, createCommentVNode as c, createElementBlock as l, createElementVNode as u, createTextVNode as d, createVNode as f, defineComponent as p, normalizeClass as m, openBlock as h, ref as g, renderSlot as _, shallowRef as v, toDisplayString as y, unref as b, withCtx as x } from "vue";
7
7
  import { Pause as S, Play as C } from "@lucide/vue";
8
8
  //#region lib/components/ui/media/camera/camera-content.vue?vue&type=script&setup=true&lang.ts
@@ -21,6 +21,7 @@
21
21
  @import "./ui/actions/button-group/button-group.css";
22
22
  @import "./ui/primitives/label/label.css";
23
23
  @import "./ui/feedback/toast/toast.css";
24
+ @import "./print-only.css";
24
25
  @import "./ui/fields/contacts/contact-item.css";
25
26
  @import "./ui/fields/opening-hours/opening-hours-item.css";
26
27
  @import "./ui/fields/attributes/partials/attribute-form.css";
@@ -0,0 +1,44 @@
1
+ /* Printing one element of the page (`printOnly`, from `/lib` or
2
+ * @nxgt/material-core/print-only; RecoveryCodes' Print button): while
3
+ * <html data-nxgt-print> is set, print media shows the element marked
4
+ * data-nxgt-print-target and nothing else. No inline style: only these rules,
5
+ * the same in @nxgt/material and @nxgt/material-vue.
6
+ *
7
+ * Everything that neither is, holds nor sits inside the target is taken out
8
+ * of the flow, so the page prints no blank sheets after it; where :has() is
9
+ * not supported, that rule is dropped and `visibility` alone hides the rest.
10
+ * The target's ancestors stop positioning it, so it starts at the top left of
11
+ * the first page. Unlayered, these rules beat the components' Tailwind
12
+ * utilities (layered) with no `!important`. */
13
+ @media print {
14
+ html[data-nxgt-print]
15
+ body
16
+ *:not(
17
+ [data-nxgt-print-target],
18
+ [data-nxgt-print-target] *,
19
+ :has([data-nxgt-print-target])
20
+ ) {
21
+ display: none;
22
+ }
23
+
24
+ html[data-nxgt-print] body * {
25
+ visibility: hidden;
26
+ }
27
+
28
+ html[data-nxgt-print] :has([data-nxgt-print-target]) {
29
+ position: static;
30
+ transform: none;
31
+ }
32
+
33
+ html[data-nxgt-print] [data-nxgt-print-target],
34
+ html[data-nxgt-print] [data-nxgt-print-target] * {
35
+ visibility: visible;
36
+ }
37
+
38
+ html[data-nxgt-print] [data-nxgt-print-target] {
39
+ position: absolute;
40
+ inset: 0 0 auto 0;
41
+ margin: 0;
42
+ box-shadow: none;
43
+ }
44
+ }