@nxgt/material-vue 0.31.0 → 0.33.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 (104) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +20 -7
  3. package/dist/{Button-CNbJT5qV.js → Button-DEA5W6O3.js} +1 -1
  4. package/dist/{HoverCardTrigger-BTAHE6wK.js → HoverCardTrigger-CjSteFgk.js} +2 -2
  5. package/dist/{camera-rJmgxIEn.js → camera-B063QUeM.js} +4 -4
  6. package/dist/components/components.css +3 -1
  7. package/dist/components/ui/fields/otp-field/input-otp.css +48 -0
  8. package/dist/{components-Dxy9DvEe.js → components-CmIOfRO4.js} +13547 -17345
  9. package/dist/components.js +8 -8
  10. package/dist/composables.js +25 -25
  11. package/dist/dnd.js +1 -1
  12. package/dist/fonts/katex/KaTeX_AMS-Regular.woff2 +0 -0
  13. package/dist/fonts/katex/KaTeX_Caligraphic-Bold.woff2 +0 -0
  14. package/dist/fonts/katex/KaTeX_Caligraphic-Regular.woff2 +0 -0
  15. package/dist/fonts/katex/KaTeX_Fraktur-Bold.woff2 +0 -0
  16. package/dist/fonts/katex/KaTeX_Fraktur-Regular.woff2 +0 -0
  17. package/dist/fonts/katex/KaTeX_Main-Bold.woff2 +0 -0
  18. package/dist/fonts/katex/KaTeX_Main-BoldItalic.woff2 +0 -0
  19. package/dist/fonts/katex/KaTeX_Main-Italic.woff2 +0 -0
  20. package/dist/fonts/katex/KaTeX_Main-Regular.woff2 +0 -0
  21. package/dist/fonts/katex/KaTeX_Math-BoldItalic.woff2 +0 -0
  22. package/dist/fonts/katex/KaTeX_Math-Italic.woff2 +0 -0
  23. package/dist/fonts/katex/KaTeX_SansSerif-Bold.woff2 +0 -0
  24. package/dist/fonts/katex/KaTeX_SansSerif-Italic.woff2 +0 -0
  25. package/dist/fonts/katex/KaTeX_SansSerif-Regular.woff2 +0 -0
  26. package/dist/fonts/katex/KaTeX_Script-Regular.woff2 +0 -0
  27. package/dist/fonts/katex/KaTeX_Size1-Regular.woff2 +0 -0
  28. package/dist/fonts/katex/KaTeX_Size2-Regular.woff2 +0 -0
  29. package/dist/fonts/katex/KaTeX_Size3-Regular.woff2 +0 -0
  30. package/dist/fonts/katex/KaTeX_Size4-Regular.woff2 +0 -0
  31. package/dist/fonts/katex/KaTeX_Typewriter-Regular.woff2 +0 -0
  32. package/dist/{form-scope-BhNw4Mm6.js → form-scope-DuDx5Jyx.js} +1 -1
  33. package/dist/{i18n-provider-BPK68eqM.js → i18n-provider-CiVi05fs.js} +1 -1
  34. package/dist/i18n.js +4 -4
  35. package/dist/{icon-button-DXXjxBgr.js → icon-button-CWcOcNHr.js} +1 -1
  36. package/dist/lib/components/ui/fields/attributes/form-schema.d.ts +11 -2
  37. package/dist/lib/components/ui/fields/contacts/consts.d.ts +1 -1
  38. package/dist/lib/components/ui/fields/opening-hours/consts.d.ts +12 -1
  39. package/dist/lib/components/ui/fields/search-field/index.d.ts +2 -1
  40. package/dist/lib/components/ui/primitives/index.d.ts +1 -0
  41. package/dist/lib/components/ui/primitives/nonce-provider/index.d.ts +2 -0
  42. package/dist/lib/components/ui/primitives/nonce-provider/nonce-provider.vue.d.ts +20 -0
  43. package/dist/lib/components/ui/selection/autocomplete/autocomplete-items.d.ts +5 -0
  44. package/dist/lib/components/ui/selection/autocomplete/autocomplete.vue.d.ts +6 -3
  45. package/dist/lib/components/ui/selection/autocomplete/filter-options.d.ts +9 -2
  46. package/dist/lib/components/ui/selection/autocomplete/index.d.ts +1 -0
  47. package/dist/lib/components/ui/selection/autocomplete/partials/autocomplete-list.vue.d.ts +8 -1
  48. package/dist/lib/components/ui/selection/autocomplete/search-types.d.ts +34 -0
  49. package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-items.d.ts +20 -3
  50. package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-list.d.ts +28 -0
  51. package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-search.d.ts +11 -0
  52. package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-status.d.ts +32 -0
  53. package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-texts.d.ts +1 -3
  54. package/dist/lib/components/ui/selection/autocomplete/use-autocomplete.d.ts +10 -5
  55. package/dist/lib/components/ui/selection/radio-group/radio-group-field.vue.d.ts +2 -0
  56. package/dist/lib/composables/index.d.ts +1 -0
  57. package/dist/lib/composables/use-csp-nonce.d.ts +18 -0
  58. package/dist/lib/i18n/resources/en/en.d.ts +4 -0
  59. package/dist/lib/i18n/resources/en/material.json.d.ts +5 -1
  60. package/dist/lib/i18n/resources/fr/fr.d.ts +4 -0
  61. package/dist/lib/i18n/resources/fr/material.json.d.ts +5 -1
  62. package/dist/lib/i18n/resources/resources.d.ts +8 -0
  63. package/dist/lib/i18n/translator.d.ts +1 -1
  64. package/dist/lib/lib/index.d.ts +1 -0
  65. package/dist/lib/nuxt/auto-imports.d.ts +1 -1
  66. package/dist/lib/nuxt/component-names.d.ts +1 -1
  67. package/dist/lib/vite/index.d.ts +3 -2
  68. package/dist/lib.js +50 -49
  69. package/dist/main.js +17 -17
  70. package/dist/map.js +4 -4
  71. package/dist/material-vue.css +1 -1
  72. package/dist/{pdf-outline-sidebar-6pIxLP_o.js → pdf-outline-sidebar-CzY59j_Y.js} +2 -2
  73. package/dist/{pdf-page-list-ojy2YSTr.js → pdf-page-list-BMxNOnPk.js} +2 -2
  74. package/dist/{pdf-page--zE3j8bc.js → pdf-page-nM_fvTHh.js} +1 -1
  75. package/dist/{pdf-reader-CcSJaFFp.js → pdf-reader-Dpv3oWe1.js} +52 -49
  76. package/dist/{pdf-sidebar-8DC9VdCG.js → pdf-sidebar-DkefUgWg.js} +3 -3
  77. package/dist/{pdf-thumbnail-sidebar-BbPcfCYm.js → pdf-thumbnail-sidebar-I6i1lv5J.js} +3 -3
  78. package/dist/{pdf-toolbar-B_MDicKL.js → pdf-toolbar-Da6UMt1O.js} +4 -4
  79. package/dist/pdf.js +2 -2
  80. package/dist/{sortable-provider-Cb3tm9Cy.js → sortable-provider-Cvpqk8tp.js} +2 -2
  81. package/dist/{stored-language-UnInBB6T.js → stored-language-GDRdeYD8.js} +10 -2
  82. package/dist/{stx-player-CjGKQF6K.js → stx-player-CN7Ic8tP.js} +14 -14
  83. package/dist/{translator-J3_vaV_A.js → translator-BDFEmlcL.js} +1 -1
  84. package/dist/{use-heading-spy-_dk8kGwL.js → use-heading-spy-DimKb49j.js} +54 -46
  85. package/dist/{use-material-translation-Do6ztdtV.js → use-material-translation-CaHS6oZz.js} +3 -3
  86. package/dist/vite.js +2 -2
  87. package/docs/README.md +1 -0
  88. package/docs/components/data-display.md +5 -0
  89. package/docs/components/form-fields.md +23 -0
  90. package/docs/components/primitives.md +41 -0
  91. package/docs/components/selection-and-choice.md +75 -4
  92. package/docs/getting-started.md +5 -1
  93. package/docs/guides/csp.md +420 -0
  94. package/docs/guides/helpers.md +3 -1
  95. package/docs/guides/theming.md +27 -0
  96. package/docs/roadmap.md +21 -0
  97. package/docs/troubleshooting.md +217 -0
  98. package/lib/components/components.css +3 -1
  99. package/lib/components/ui/fields/otp-field/input-otp.css +48 -0
  100. package/lib/nuxt/auto-imports.ts +1 -0
  101. package/lib/nuxt/component-names.ts +1 -0
  102. package/lib/vite/index.ts +6 -2
  103. package/package.json +9 -4
  104. package/dist/lib/components/ui/fields/search-field/debounce.d.ts +0 -5
@@ -17,6 +17,7 @@ words in your error.
17
17
  **Styles & assets**
18
18
 
19
19
  - [Components render unstyled, with no error](#components-render-unstyled-with-no-error)
20
+ - [Math renders in the system fonts](#math-renders-in-the-system-fonts)
20
21
  - [`<Icon>` renders nothing](#icon-renders-nothing)
21
22
  - [An accessibility audit reports low contrast on a badge, a button, a toast or a menu entry](#an-accessibility-audit-reports-low-contrast-on-a-badge-a-button-a-toast-or-a-menu-entry)
22
23
  - [`ARIA hidden element must not be focusable or contain focusable elements`](#aria-hidden-element-must-not-be-focusable-or-contain-focusable-elements)
@@ -36,6 +37,9 @@ words in your error.
36
37
  - [An end-to-end test no longer finds a required field by a name ending in `*`](#an-end-to-end-test-no-longer-finds-a-required-field-by-a-name-ending-in-)
37
38
  - [A test no longer finds `aria-invalid` on an upload field's group or drop zone](#a-test-no-longer-finds-aria-invalid-on-an-upload-fields-group-or-drop-zone)
38
39
  - [A test no longer finds `aria-invalid` on a `Switch` row or an `Autocomplete` box](#a-test-no-longer-finds-aria-invalid-on-a-switch-row-or-an-autocomplete-box)
40
+ - [An `Autocomplete` lists more options than before, or "ecole" finds "École"](#an-autocomplete-lists-more-options-than-before-or-ecole-finds-école)
41
+ - [`@query-change` runs more often after upgrading](#query-change-runs-more-often-after-upgrading)
42
+ - [An older search's results replace the newer ones in an `Autocomplete`](#an-older-searchs-results-replace-the-newer-ones-in-an-autocomplete)
39
43
  - [A test no longer finds `aria-invalid` on an `OtpField` slot](#a-test-no-longer-finds-aria-invalid-on-an-otpfield-slot)
40
44
  - [A test no longer finds the breadcrumb's home button](#a-test-no-longer-finds-the-breadcrumbs-home-button)
41
45
  - [A test no longer finds a sidebar entry by the `button` role](#a-test-no-longer-finds-a-sidebar-entry-by-the-button-role)
@@ -47,6 +51,7 @@ words in your error.
47
51
  - [A test no longer finds a calendar day by its number](#a-test-no-longer-finds-a-calendar-day-by-its-number)
48
52
  - [A `QRCode`'s `aria-label` is no longer on its wrapper](#a-qrcodes-aria-label-is-no-longer-on-its-wrapper)
49
53
  - [A `CheckboxGroup` or `RadioGroupField` option selected by `#<id>-<value>` stops matching](#a-checkboxgroup-or-radiogroupfield-option-selected-by-id-value-stops-matching)
54
+ - [One option of a `RadioGroupField` cannot be disabled](#one-option-of-a-radiogroupfield-cannot-be-disabled)
50
55
  - [A `Table`'s `id`, `aria-*` or `style` is no longer on its scrolling container](#a-tables-id-aria--or-style-is-no-longer-on-its-scrolling-container)
51
56
 
52
57
  **Feedback**
@@ -200,6 +205,14 @@ words in your error.
200
205
  - [`@page-change` reports another page after opening on `initialPage`](#page-change-reports-another-page-after-opening-on-initialpage)
201
206
  - [`FilePreview` shows a file card with a Download link for a PDF](#filepreview-shows-a-file-card-with-a-download-link-for-a-pdf)
202
207
  - [`FilePreview` says "This file could not be previewed."](#filepreview-says-this-file-could-not-be-previewed)
208
+
209
+ **Content Security Policy**
210
+
211
+ - [`Refused to apply inline style because it violates the following Content Security Policy directive`](#refused-to-apply-inline-style-because-it-violates-the-following-content-security-policy-directive)
212
+ - [`Refused to load the font 'data:font/woff2…' because it violates the following Content Security Policy directive: "font-src 'self'"`](#refused-to-load-the-font-datafontwoff2-because-it-violates-the-following-content-security-policy-directive-font-src-self)
213
+ - [`Refused to load the font 'https://fonts.gstatic.com/…' because it violates the following Content Security Policy directive: "font-src 'self'"`](#refused-to-load-the-font-httpsfontsgstaticcom-because-it-violates-the-following-content-security-policy-directive-font-src-self)
214
+ - [`Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script`](#refused-to-evaluate-a-string-as-javascript-because-unsafe-eval-is-not-an-allowed-source-of-script)
215
+
203
216
  - [Reporting a bug](#reporting-a-bug)
204
217
 
205
218
  ---
@@ -364,6 +377,21 @@ to 0.22.0.
364
377
  stylesheet up to 0.21.0: an app without Tailwind adds
365
378
  `@import "vue-advanced-cropper/dist/style.css";` on an older version too.
366
379
 
380
+ ### Math renders in the system fonts
381
+
382
+ **When:** a formula in `Markdown` (or `ChatMarkdown`) shows in a serif or
383
+ sans-serif system font: letters look upright or thin, `\mathbb{R}` is a
384
+ plain R, large brackets and roots are mis-sized, and the network tab shows a
385
+ `404` for `fonts/katex/KaTeX_*.woff2`, or no request at all.
386
+ **Why:** the compiled stylesheet (`dist/material-vue.css`) loads KaTeX's fonts from
387
+ `dist/fonts/katex/`, through a relative `url()`. The stylesheet was served
388
+ without that folder beside it (copied alone to a public folder or a CDN).
389
+ **Fix:** serve `dist/fonts/` next to the stylesheet, at the same relative
390
+ path, or let your bundler import it through the `style` condition
391
+ (`@import "@nxgt/material-vue";`), which emits the fonts as files (Vite inlines the 3.6 KB `KaTeX_Size3` font unless `assetsInlineLimit` is set: see the CSP guide's KaTeX fonts section). On the Tailwind route
392
+ (`@nxgt/material-vue/styles.css`) the fonts come from `katex` itself, and your bundler
393
+ emits them.
394
+
367
395
  ### `<Icon>` renders nothing
368
396
 
369
397
  **When:** every `Icon` (and anything that uses one: the app shell menu, the
@@ -578,6 +606,56 @@ await expect(page.getByRole('switch', { name: 'Notifications' })).toHaveAttribut
578
606
  await expect(page.getByLabel('Country')).toHaveAttribute('aria-invalid', 'true');
579
607
  ```
580
608
 
609
+ ### An `Autocomplete` lists more options than before, or "ecole" finds "École"
610
+
611
+ **When:** after upgrading to 0.31.0, typing in an `Autocomplete` with local
612
+ `options` keeps options it used to drop: `e` keeps "Évry", `orle` keeps
613
+ "Orléans".
614
+ **Why:** local matching is now accent-insensitive by default (`filter`
615
+ defaults to `'accent-insensitive'`): the label or value and the query are
616
+ both lowercased in the provider's language and stripped of their accents
617
+ before they are compared. Before, an accent had to be typed to match.
618
+ **Fix:** nothing, if that is what your users expect. To match as before,
619
+ pass your own `filter`; to show `options` exactly as you give them (they are
620
+ filtered on your server), pass `filter="none"`:
621
+
622
+ ```vue
623
+ <!-- Back to a plain case-insensitive match, accents counted: -->
624
+ <Autocomplete
625
+ v-model="value"
626
+ :options="options"
627
+ :filter="(option, query) => option.label.toLowerCase().includes(query.toLowerCase())"
628
+ />
629
+ ```
630
+
631
+ ### `@query-change` runs more often after upgrading
632
+
633
+ **When:** after upgrading to 0.31.0, `@query-change` is called sooner after the
634
+ user stops typing, so a server you fetch from there gets more requests.
635
+ **Why:** the pause it waits for is now `debounceMs`, 250 ms by default; it
636
+ was a fixed 300 ms.
637
+ **Fix:** set the pause you had, `:debounce-ms="300"`, or move the fetch to `on-search`, which
638
+ also aborts the previous request and drops a stale response.
639
+
640
+ ### An older search's results replace the newer ones in an `Autocomplete`
641
+
642
+ **When:** you fetch `options` yourself from `@query-change`, and a slow response
643
+ for an earlier query lands after a faster one for the latest: the list shows
644
+ the results of what the user typed before.
645
+ **Why:** each of your requests resolves whenever the server answers, and
646
+ the last one to resolve wins.
647
+ **Fix:** use `on-search`. It hands each search an `AbortSignal` (pass it to
648
+ `fetch`), aborts the previous search, and drops any response that lands for
649
+ an older query, even from an API that ignores the signal:
650
+
651
+ ```vue
652
+ <Autocomplete
653
+ v-model="value"
654
+ :on-search="(query, { signal }) =>
655
+ fetch(`/api/people?q=${encodeURIComponent(query)}`, { signal }).then((r) => r.json())"
656
+ />
657
+ ```
658
+
581
659
  ### A test no longer finds `aria-invalid` on an `OtpField` slot
582
660
 
583
661
  **When:** `[data-slot="input-otp-slot"][aria-invalid]` (or
@@ -793,6 +871,30 @@ which a `group` may not carry: assert its description instead,
793
871
  hidden hint sits inside the helper element, so match its text with
794
872
  `getByText('Pick any.', { exact: false })` or the description with a RegExp.
795
873
 
874
+ ### One option of a `RadioGroupField` cannot be disabled
875
+
876
+ **When:** you need one choice greyed out (a person already linked, a plan the
877
+ account cannot take) and `disabled` on the group disables all of them. Before
878
+ this release the options had no `disabled`, so apps listed the unavailable ones
879
+ apart or hand-built the group from `RadioGroupItem`.
880
+ **Why:** an option was only `{ value, label }`; `disabled` was the group's.
881
+ **Fix:** upgrade, and set `disabled` on the option. It is rendered and
882
+ announced as disabled, its label is muted (still 4.5:1) and the arrow keys
883
+ skip it; the group's own `disabled` still disables every option. An option
884
+ that is disabled while it is the current `value` stays checked, as in the
885
+ Radix and Reka primitives:
886
+
887
+ ```vue
888
+ <RadioGroupField
889
+ v-model="person"
890
+ label="Person"
891
+ :options="[
892
+ { value: 'ada', label: 'Ada' },
893
+ { value: 'bob', label: 'Bob (already linked)', disabled: true },
894
+ ]"
895
+ />
896
+ ```
897
+
796
898
  ### A `Table`'s `id`, `aria-*` or `style` is no longer on its scrolling container
797
899
 
798
900
  **When:** after upgrading to 0.24.0, either:
@@ -3635,6 +3737,121 @@ beginning is shown, with "Showing the first … of this file." below.
3635
3737
 
3636
3738
  ---
3637
3739
 
3740
+ ## Content Security Policy
3741
+
3742
+ How to set up the policy is in the [Content Security Policy guide](guides/csp.md).
3743
+
3744
+ ### `Refused to apply inline style because it violates the following Content Security Policy directive`
3745
+
3746
+ **When:** a component mounts, or a modal opens, on a page that sends
3747
+ `style-src-elem` or `style-src` without `'unsafe-inline'`. The message ends
3748
+ with `style-src-elem` for a `<style>` element and `style-src-attr` for a
3749
+ `style="…"` attribute.
3750
+ **Why:** a `<style>` element needs the page's nonce, an attribute cannot carry
3751
+ one. The usual sources are the components listed in
3752
+ [the guide](guides/csp.md#style-elements-the-components-inject). reka's
3753
+ `Select`, `Combobox`, `ScrollArea` and `Splitter`, `InputOTP` and
3754
+ `RichTextEditor` take the nonce from `NonceProvider`, and report this when the
3755
+ app has none (or gives it another nonce than the header's). A `<style>` in
3756
+ mermaid's SVG is a [known gap](guides/csp.md#known-gaps). `Toaster`,
3757
+ `ImageCropper`, `Spinner` and `PdfReader` create none: if one of them looks
3758
+ unstyled, the app does not import `styles.css`.
3759
+ **Fix:** for `style-src-attr`, allow attributes: they cannot be nonced.
3760
+
3761
+ ```http
3762
+ Content-Security-Policy: style-src-elem 'self' 'nonce-X'; style-src-attr 'unsafe-inline'
3763
+ ```
3764
+
3765
+ For `style-src-elem`, hand the nonce over:
3766
+
3767
+ ```vue
3768
+ <NonceProvider :nonce="nonce">
3769
+ <!-- the app -->
3770
+ </NonceProvider>
3771
+ ```
3772
+
3773
+ on the server and on the client, with the nonce of the header
3774
+ ([the guide](guides/csp.md#nonceprovider); with Nuxt, nuxt-security's
3775
+ `useNonce()` on the server). For a mermaid diagram, serve that route with
3776
+ `'unsafe-inline'` in `style-src-elem` instead of the nonce (a nonce in the
3777
+ same directive makes browsers ignore `'unsafe-inline'`).
3778
+
3779
+ Once a page has a header-delivered CSP, browsers blank the `nonce` attribute,
3780
+ so Vue's development build may log `Hydration attribute mismatch` when it
3781
+ hydrates a server-rendered `<style nonce>`. The warning is harmless.
3782
+
3783
+ ### `Refused to load the font 'data:font/woff2…' because it violates the following Content Security Policy directive: "font-src 'self'"`
3784
+
3785
+ **When:** a formula renders in `Markdown`, with `font-src 'self'`.
3786
+ **Why:** a KaTeX font reached the browser as a `data:` URI. Vite inlines any
3787
+ asset under its 4096-byte limit, and `KaTeX_Size3-Regular.woff2` is 3.6 KB:
3788
+ on the Tailwind route (`@nxgt/material-vue/styles.css`), and on the compiled route
3789
+ when your Vite build processes `dist/material-vue.css`. Earlier versions' compiled
3790
+ stylesheet inlined all 60 KaTeX fonts itself; it now ships them as files.
3791
+ **Fix:** upgrade, then stop Vite from inlining fonts:
3792
+
3793
+ ```ts
3794
+ // vite.config.ts
3795
+ import { defineConfig } from 'vite';
3796
+
3797
+ export default defineConfig({
3798
+ build: {
3799
+ assetsInlineLimit: (file) => (/\.(woff2?|ttf)$/.test(file) ? false : undefined),
3800
+ },
3801
+ });
3802
+ ```
3803
+
3804
+ ### `Refused to load the font 'https://fonts.gstatic.com/…' because it violates the following Content Security Policy directive: "font-src 'self'"`
3805
+
3806
+ **When:** the page loads a font from `https://fonts.googleapis.com` or
3807
+ `https://fonts.gstatic.com`, or from `rsms.me`, on a page whose `font-src` is
3808
+ `'self'` (the message names the font's URL). The stylesheet that declares it
3809
+ is refused too, as a `style-src-elem` violation.
3810
+ **Why:** the app's `<link>` or `@import` for Inter asks another origin for CSS
3811
+ and woff2 files, and the policy allows only your own.
3812
+ **Fix:** host the font: install `@fontsource-variable/inter`, import it, and set
3813
+ `--font-sans` to `"Inter Variable"` followed by the system stack in the root
3814
+ `@theme`. The woff2 files then come from your build
3815
+ ([CSP guide](guides/csp.md#inter--the-sans-font)):
3816
+
3817
+ ```css
3818
+ @import "@fontsource-variable/inter";
3819
+
3820
+ @theme {
3821
+ --font-sans: "Inter Variable", ui-sans-serif, system-ui, sans-serif;
3822
+ }
3823
+ ```
3824
+
3825
+ Delete the Google Fonts `<link>`, and the `fonts.googleapis.com` and
3826
+ `fonts.gstatic.com` sources you may have added to the policy.
3827
+
3828
+ ### `Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script`
3829
+
3830
+ **When:** an `EvalError` with this message, or a CSP report with
3831
+ `effectiveDirective: script-src` and `sample: ''`, from a stack that ends in
3832
+ zod (`allowsEval`, in `zod/v4/core/util.js`), on a page whose `script-src`
3833
+ has no `'unsafe-eval'`. Nothing visibly breaks.
3834
+ **Why:** the first `z.object()` built in the page makes zod test whether
3835
+ `new Function` works. The error is caught, but the browser sends the
3836
+ violation report. The library builds no schema at import any more (zod is
3837
+ not bundled, its schemas are factories), so the report comes from a schema
3838
+ built before `z.config({ jitless: true })` ran: one of yours, or the first
3839
+ render of a component that validates. Versions that bundled zod built their
3840
+ own schemas at import, before the app could configure anything.
3841
+ **Fix:** switch zod to its interpreter in a module the app imports before
3842
+ anything else, and build your own schemas inside functions rather than at
3843
+ module scope when that module may load first
3844
+ ([CSP guide](guides/csp.md#zod-and-unsafe-eval)):
3845
+
3846
+ ```ts
3847
+ // zod-config.ts, imported first in the app entry
3848
+ import { z } from 'zod';
3849
+
3850
+ z.config({ jitless: true });
3851
+ ```
3852
+
3853
+ ---
3854
+
3638
3855
  ## Reporting a bug
3639
3856
 
3640
3857
  If an error comes from inside this package and none of the entries above
@@ -6,7 +6,8 @@
6
6
  * The code theme (CodeBlock); PdfReader's text layer, highlights and pdf.js's
7
7
  * annotation layer; KaTeX (Markdown), highlight.js (RichTextEditor code
8
8
  * blocks), vue-sonner (Toaster), vue-advanced-cropper (ImageCropper); and the
9
- * components styled by a stylesheet of their own. */
9
+ * components styled by a stylesheet of their own, input-otp.css among them:
10
+ * the rules vue-input-otp also injects, here for a strict CSP. */
10
11
  @import "./ui/display/code/code-moonlight.css";
11
12
  @import "./ui/media/pdf-viewer/pdf-viewer.css";
12
13
  @import "./ui/media/pdf-viewer/pdf-annotation-layer.css";
@@ -15,6 +16,7 @@
15
16
  @import "vue-sonner/style.css";
16
17
  @import "vue-advanced-cropper/dist/style.css";
17
18
  @import "./ui/feedback/spinner/spinner.css";
19
+ @import "./ui/fields/otp-field/input-otp.css";
18
20
  @import "./ui/media/image-cropper/partials/image-cropper-canvas.css";
19
21
  @import "./ui/actions/button-group/button-group.css";
20
22
  @import "./ui/primitives/label/label.css";
@@ -0,0 +1,48 @@
1
+ /* The rules input-otp (React, 1.4.2) and vue-input-otp (0.4.0) add on mount,
2
+ * through `insertRule` into a `<style id="input-otp-style">`: the hidden
3
+ * input's caret, selection and autofill stay invisible behind the slots.
4
+ * Here so a strict CSP blocks nothing. @nxgt/material strips input-otp's
5
+ * injection at build (build/strip-style-injection.ts); vue-input-otp is
6
+ * external, still injects, and takes the nonce (NonceProvider). The same file
7
+ * in both libraries (scripts/shared-paths.ts). */
8
+ /* biome-ignore-all lint/complexity/noImportantStyles: input-otp's own rules */
9
+ [data-input-otp]::selection {
10
+ background: transparent !important;
11
+ color: transparent !important;
12
+ }
13
+
14
+ /* Two rules: a browser that does not know one pseudo-class drops the list. */
15
+ [data-input-otp]:autofill {
16
+ background: transparent !important;
17
+ color: transparent !important;
18
+ border-color: transparent !important;
19
+ opacity: 0 !important;
20
+ box-shadow: none !important;
21
+ -webkit-box-shadow: none !important;
22
+ -webkit-text-fill-color: transparent !important;
23
+ }
24
+
25
+ [data-input-otp]:-webkit-autofill {
26
+ background: transparent !important;
27
+ color: transparent !important;
28
+ border-color: transparent !important;
29
+ opacity: 0 !important;
30
+ box-shadow: none !important;
31
+ -webkit-box-shadow: none !important;
32
+ -webkit-text-fill-color: transparent !important;
33
+ }
34
+
35
+ @supports (-webkit-touch-callout: none) {
36
+ [data-input-otp] {
37
+ letter-spacing: -0.6em !important;
38
+ font-weight: 100 !important;
39
+ font-stretch: ultra-condensed;
40
+ font-optical-sizing: none !important;
41
+ left: -1px !important;
42
+ right: 1px !important;
43
+ }
44
+ }
45
+
46
+ [data-input-otp] + * {
47
+ pointer-events: all !important;
48
+ }
@@ -11,6 +11,7 @@ export const COMPOSABLE_IMPORTS = [
11
11
  'useOptions',
12
12
  'useSearchParam',
13
13
  'useAllowedTransitions',
14
+ 'useCspNonce',
14
15
  'resolveTheme',
15
16
  'applyResolvedTheme',
16
17
  ] as const;
@@ -349,6 +349,7 @@ export const COMPONENT_NAMES = [
349
349
  'NavigationRail',
350
350
  'NetworkUploadField',
351
351
  'NetworkUploadFormField',
352
+ 'NonceProvider',
352
353
  'NoticeCard',
353
354
  'Notifications',
354
355
  'NumberField',
package/lib/vite/index.ts CHANGED
@@ -2,6 +2,10 @@
2
2
  * Build-time helpers for the apps that consume this library: Node code that
3
3
  * runs inside a consumer's `vite.config.ts`. The one copy lives in
4
4
  * `@nxgt/material-core/vite`, shared with the sister library; this entry keeps
5
- * the subpath consumers already import. See `pdfkitStandardFonts` there.
5
+ * the subpath consumers already import. See `pdfkitStandardFonts` and
6
+ * `cspAssetsInlineLimit` there.
6
7
  */
7
- export { pdfkitStandardFonts } from '@nxgt/material-core/vite';
8
+ export {
9
+ cspAssetsInlineLimit,
10
+ pdfkitStandardFonts,
11
+ } from '@nxgt/material-core/vite';
package/package.json CHANGED
@@ -1,10 +1,15 @@
1
1
  {
2
2
  "name": "@nxgt/material-vue",
3
- "version": "0.31.0",
3
+ "version": "0.33.0",
4
4
  "license": "MIT",
5
5
  "bugs": {
6
6
  "email": "stevegires@gmail.com"
7
7
  },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/softistx/nxgt-material.git",
11
+ "directory": "packages/material-vue"
12
+ },
8
13
  "type": "module",
9
14
  "files": [
10
15
  "dist",
@@ -23,9 +28,9 @@
23
28
  ],
24
29
  "exports": {
25
30
  ".": {
26
- "import": "./dist/main.js",
27
31
  "style": "./dist/material-vue.css",
28
32
  "types": "./dist/lib/main.d.ts",
33
+ "import": "./dist/main.js",
29
34
  "require": "./dist/main.js"
30
35
  },
31
36
  "./components": {
@@ -101,7 +106,7 @@
101
106
  "dev": "bun storybook",
102
107
  "generate:nuxt-names": "bun scripts/generate-nuxt-names.ts",
103
108
  "build": "bun run generate:nuxt-names && vue-tsc -b && vite build",
104
- "postbuild": "bun ../../scripts/copy-styles.ts && bun run verify:ssr && bun run verify:dts",
109
+ "postbuild": "bun ../../scripts/copy-styles.ts && bun ../../scripts/katex-fonts.ts && bun run verify:ssr && bun run verify:dts",
105
110
  "prepack": "bun run verify:dts",
106
111
  "storybook": "storybook dev -p 6006",
107
112
  "build-storybook": "storybook build",
@@ -119,7 +124,7 @@
119
124
  "docs:previews": "vitest run --project previews"
120
125
  },
121
126
  "dependencies": {
122
- "@nxgt/material-core": "^0.7.1",
127
+ "@nxgt/material-core": "^0.9.0",
123
128
  "@floating-ui/dom": "^1.8.0",
124
129
  "@fortawesome/fontawesome-common-types": "7.3.1",
125
130
  "@lucide/vue": "^1.45.0",
@@ -1,5 +0,0 @@
1
- export type Debounced<Args extends unknown[]> = ((...args: Args) => void) & {
2
- cancel: () => void;
3
- flush: () => void;
4
- };
5
- export declare function debounce<Args extends unknown[]>(fn: (...args: Args) => void, ms: number): Debounced<Args>;