@nxgt/material-vue 0.42.0 → 0.43.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +117 -0
- package/README.md +18 -5
- package/dist/{Button-CWmzvv9p.js → Button-CEvi_i4g.js} +4 -4
- package/dist/{HoverCardTrigger-C5AbAyHE.js → HoverCardTrigger-B7m5Zvj1.js} +69 -62
- package/dist/backgrounds/backgrounds.css +8 -0
- package/dist/backgrounds/css/base.css +169 -0
- package/dist/backgrounds/css/gradient.css +53 -0
- package/dist/backgrounds/css/grain.css +19 -0
- package/dist/backgrounds/css/motion.css +30 -0
- package/dist/backgrounds.js +111 -0
- package/dist/{camera-C-9slBUV.js → camera-DP3Qfhhc.js} +4 -4
- package/dist/{chunk-7M6MHVWA-wgE1MsQ9.js → chunk-7M6MHVWA-DzYWbKT9.js} +1 -1
- package/dist/{chunk-GNY47TPC-BByCj-tp.js → chunk-GNY47TPC-D4sl5ZSh.js} +1 -1
- package/dist/{classDiagram-v2-NBCMYWYE-LDc3yyTu.js → classDiagram-v2-NBCMYWYE-BtmPeDVI.js} +1 -1
- package/dist/components/base.css +5 -2
- package/dist/components/components.css +5 -0
- package/dist/components/theme-tokens.css +21 -0
- package/dist/{components-DX4EycMi.js → components-zm5JC2dA.js} +14077 -13577
- package/dist/components.js +8 -8
- package/dist/composables.js +3 -3
- package/dist/{dagre-6A5THRUB-CCigPI-W.js → dagre-6A5THRUB-CmmqjQ01.js} +1 -1
- package/dist/{diagram-22UHCM2B-vav-BOss.js → diagram-22UHCM2B-BYL1soMk.js} +1 -1
- package/dist/dnd.js +1 -1
- package/dist/{erDiagram-OPXOYQCR-BV3UGLoQ.js → erDiagram-OPXOYQCR-DhNOupcl.js} +1 -1
- package/dist/{flowDiagram-KWPJA3E3-B3AfwLQk.js → flowDiagram-KWPJA3E3-_S6NO9vf.js} +2 -2
- package/dist/{form-scope-CN68PTXc.js → form-scope-XQGlh8m3.js} +1 -1
- package/dist/{i18n-provider-DmZSTBnp.js → i18n-provider-tL27-a8y.js} +1 -1
- package/dist/i18n.js +26 -9
- package/dist/{icon-button-DErh1aJS.js → icon-button-BNA3fXM2.js} +4 -4
- package/dist/lib/backgrounds/background/background.vue.d.ts +22 -0
- package/dist/lib/backgrounds/background/index.d.ts +2 -0
- package/dist/lib/backgrounds/background/partials/background-layers.vue.d.ts +9 -0
- package/dist/lib/backgrounds/background/partials/scene-svg.d.ts +10 -0
- package/dist/lib/backgrounds/background/types.d.ts +24 -0
- package/dist/lib/backgrounds/index.d.ts +13 -0
- package/dist/lib/components/ui/actions/button/button-tones.d.ts +3 -3
- package/dist/lib/components/ui/actions/responsive-button/responsive-button.vue.d.ts +3 -3
- package/dist/lib/components/ui/collections/data-table/data-table-context.d.ts +4 -0
- package/dist/lib/components/ui/collections/data-table/data-table.vue.d.ts +8 -0
- package/dist/lib/components/ui/collections/data-table/partials/data-table-body.vue.d.ts +8 -0
- package/dist/lib/components/ui/collections/data-table/partials/data-table-empty.vue.d.ts +5 -1
- package/dist/lib/components/ui/collections/data-table/partials/data-table-toolbar.d.ts +16 -3
- package/dist/lib/components/ui/collections/data-table/select-checkbox.d.ts +36 -0
- package/dist/lib/components/ui/collections/data-table/types.d.ts +15 -0
- package/dist/lib/components/ui/collections/data-table/use-data-table.d.ts +2 -0
- package/dist/lib/components/ui/feedback/circular-progress/circular-progress.vue.d.ts +1 -1
- package/dist/lib/components/ui/feedback/empty-state/empty-state.vue.d.ts +21 -8
- package/dist/lib/components/ui/feedback/empty-state/index.d.ts +1 -1
- package/dist/lib/components/ui/feedback/error-state/error-state.vue.d.ts +54 -0
- package/dist/lib/components/ui/feedback/error-state/index.d.ts +3 -0
- package/dist/lib/components/ui/feedback/error-state/partials/error-state-details.vue.d.ts +7 -0
- package/dist/lib/components/ui/feedback/index.d.ts +1 -0
- package/dist/lib/components/ui/feedback/state-frame/state-frame.vue.d.ts +36 -0
- package/dist/lib/components/ui/feedback/state-frame/state-icon.vue.d.ts +7 -0
- package/dist/lib/components/ui/feedback/state-frame/state-illustration.vue.d.ts +8 -0
- package/dist/lib/components/ui/feedback/state-frame/state-tones.d.ts +11 -0
- package/dist/lib/components/ui/fields/contacts/consts.d.ts +1 -1
- package/dist/lib/components/ui/layout/app-shell/use-truncated-title.d.ts +10 -0
- package/dist/lib/components/ui/layout/background/background.vue.d.ts +18 -3
- package/dist/lib/components/ui/layout/doc/partials/doc-empty.vue.d.ts +7 -4
- package/dist/lib/components/ui/media/stx-player/stx-player-viewport.vue.d.ts +2 -2
- package/dist/lib/components/ui/overlays/command/CommandSeparator.vue.d.ts +3 -1
- package/dist/lib/components/ui/overlays/dialog/in-dialog.d.ts +1 -1
- package/dist/lib/components/ui/overlays/dialog/use-escape-forward.d.ts +13 -0
- package/dist/lib/components/ui/overlays/dialog/use-modal-content.d.ts +2 -0
- package/dist/lib/components/ui/primitives/nonce-provider/nonce-provider.vue.d.ts +4 -1
- package/dist/lib/components/ui/selection/autocomplete/autocomplete-keyboard.d.ts +22 -4
- package/dist/lib/components/ui/selection/autocomplete/partials/autocomplete-box.vue.d.ts +6 -2
- package/dist/lib/components/ui/selection/autocomplete/partials/autocomplete-list.vue.d.ts +7 -0
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-active.d.ts +17 -0
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-keydown.d.ts +21 -0
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-open.d.ts +3 -3
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete.d.ts +2 -1
- package/dist/lib/components/ui/selection/autocomplete/use-drawer-room.d.ts +11 -0
- package/dist/lib/components/ui/selection/autocomplete/use-query-change.d.ts +8 -0
- package/dist/lib/components/ui/widgets/charts/chart-container.vue.d.ts +2 -2
- package/dist/lib/components/ui/widgets/kanban/partials/kanban-empty.vue.d.ts +1 -0
- package/dist/lib/composables/use-background-activity.d.ts +8 -0
- package/dist/lib/i18n/resources/en/en.d.ts +24 -0
- package/dist/lib/i18n/resources/en/material.json.d.ts +25 -1
- package/dist/lib/i18n/resources/fr/fr.d.ts +24 -0
- package/dist/lib/i18n/resources/fr/material.json.d.ts +25 -1
- package/dist/lib/i18n/resources/resources.d.ts +48 -0
- package/dist/lib/i18n/translator.d.ts +1 -1
- package/dist/lib/lib/index.d.ts +1 -0
- package/dist/lib/lib/is-production.d.ts +11 -0
- package/dist/lib/nuxt/component-names.d.ts +1 -1
- package/dist/lib/nuxt/module.d.ts +2 -11
- package/dist/lib/nuxt/pdf-fonts.d.ts +1 -1
- package/dist/lib/nuxt/plugin-options.d.ts +58 -0
- package/dist/lib/vite/index.d.ts +4 -8
- package/dist/lib.js +52 -51
- package/dist/main.js +17 -17
- package/dist/map.js +4 -4
- package/dist/material-vue.css +1 -1
- package/dist/{merge-BzRhCAF6.js → merge-CUkhQBjf.js} +1 -1
- package/dist/{mermaid.core-B2ydTQ4X.js → mermaid.core-B70hvAGW.js} +11 -11
- package/dist/{mindmap-definition-NLK3R4M7-DCb99I7s.js → mindmap-definition-NLK3R4M7-B59LL3gV.js} +1 -1
- package/dist/{pdf-outline-sidebar-BU4o_hBI.js → pdf-outline-sidebar-ChDcGkbS.js} +2 -2
- package/dist/{pdf-page-anNe78Lc.js → pdf-page-DFvf3lsq.js} +1 -1
- package/dist/{pdf-page-list-CSY76HH6.js → pdf-page-list-K-ncOHkY.js} +2 -2
- package/dist/{pdf-reader-BhZNrW7R.js → pdf-reader-BPq6yCdy.js} +15 -15
- package/dist/{pdf-sidebar-DcIpG7eh.js → pdf-sidebar-divDHLe7.js} +3 -3
- package/dist/{pdf-thumbnail-sidebar-CUC0V4if.js → pdf-thumbnail-sidebar-C8XMXCq0.js} +4 -4
- package/dist/{pdf-toolbar-C373S-ul.js → pdf-toolbar-DQdedyLO.js} +4 -4
- package/dist/pdf.js +2 -2
- package/dist/{print-format.utils-C81c0weJ.js → print-format.utils-DutRk52h.js} +2 -2
- package/dist/{requirementDiagram-PLB6GJNP-DnkvMOW6.js → requirementDiagram-PLB6GJNP-BvzdTtRf.js} +1 -1
- package/dist/{sortable-provider-CL2UGGn8.js → sortable-provider-CwnKfRFb.js} +2 -2
- package/dist/{stateDiagram-v2-GCMORJYK-BCh7NZQn.js → stateDiagram-v2-GCMORJYK-VPagBr-W.js} +1 -1
- package/dist/{stored-language-Wtcj2HsU.js → stored-language-DVP9KzRu.js} +50 -2
- package/dist/{stx-player-CMmM3F5Z.js → stx-player-NiBlUGm4.js} +12 -12
- package/dist/styles.css +4 -0
- package/dist/{swimlanesDiagram-TC7HE7FX-D4-k5-iq.js → swimlanesDiagram-TC7HE7FX-BA-757S-.js} +2 -2
- package/dist/{translator-D5Dp-dob.js → translator-Dpfm1mAC.js} +171 -159
- package/dist/use-background-activity-DdTBbNpX.js +17 -0
- package/dist/{use-heading-spy-BIBHtUXN.js → use-heading-spy-jn8f2ioE.js} +13 -13
- package/dist/{use-material-translation-COoBTGpB.js → use-material-translation-CHacJbhU.js} +3 -3
- package/dist/{usecaseDiagram-POWQR4AR-Bi5we59l.js → usecaseDiagram-POWQR4AR-1f4iixDN.js} +1 -1
- package/dist/vite.js +7 -2
- package/docs/README.md +3 -0
- package/docs/components/buttons-and-actions.md +2 -0
- package/docs/components/data-table-filter-and-lists.md +59 -8
- package/docs/components/feedback-and-status.md +79 -8
- package/docs/components/media-and-files.md +2 -0
- package/docs/components/navigation-and-layout.md +13 -5
- package/docs/components/overlays-and-menus.md +20 -3
- package/docs/components/primitives.md +5 -3
- package/docs/components/rich-widgets.md +1 -1
- package/docs/components/selection-and-choice.md +14 -4
- package/docs/getting-started.md +22 -3
- package/docs/guides/app-shell.md +1 -1
- package/docs/guides/backgrounds.md +143 -0
- package/docs/guides/csp.md +48 -6
- package/docs/guides/helpers.md +1 -0
- package/docs/guides/i18n.md +51 -1
- package/docs/guides/migrate-to-vite-plugin.md +259 -0
- package/docs/guides/pdf.md +11 -4
- package/docs/guides/ssr.md +1 -1
- package/docs/guides/theming.md +52 -4
- package/docs/guides/vite-plugin.md +194 -0
- package/docs/previews/backgrounds-matrix.webp +0 -0
- package/docs/previews/feedback-status-emptystate.webp +0 -0
- package/docs/previews/feedback-status-errorstate.webp +0 -0
- package/docs/roadmap.md +60 -32
- package/docs/troubleshooting.md +251 -7
- package/lib/backgrounds/backgrounds.css +8 -0
- package/lib/backgrounds/css/base.css +169 -0
- package/lib/backgrounds/css/gradient.css +53 -0
- package/lib/backgrounds/css/grain.css +19 -0
- package/lib/backgrounds/css/motion.css +30 -0
- package/lib/components/base.css +5 -2
- package/lib/components/components.css +5 -0
- package/lib/components/theme-tokens.css +21 -0
- package/lib/nuxt/component-names.ts +1 -0
- package/lib/nuxt/module.ts +29 -15
- package/lib/nuxt/pdf-fonts.ts +1 -1
- package/lib/nuxt/plugin-options.ts +92 -0
- package/lib/nuxt/runtime/inter.css +6 -0
- package/lib/styles.css +4 -0
- package/lib/vite/index.ts +19 -2
- package/package.json +24 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { onBeforeUnmount as e, onMounted as t, ref as n, watch as r } from "vue";
|
|
2
|
+
import { observeBackgroundActivity as i } from "@nxgt/material-core/backgrounds";
|
|
3
|
+
//#region lib/composables/use-background-activity.ts
|
|
4
|
+
function a(a, o) {
|
|
5
|
+
let s = n(!1), c, l = () => {
|
|
6
|
+
c?.(), c = void 0, s.value = !1;
|
|
7
|
+
}, u = () => {
|
|
8
|
+
l(), o() && a.value && (c = i(a.value, (e) => {
|
|
9
|
+
s.value = e;
|
|
10
|
+
}));
|
|
11
|
+
};
|
|
12
|
+
return t(() => {
|
|
13
|
+
u(), r(o, u);
|
|
14
|
+
}), e(l), s;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { a as t };
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { a as e } from "./i18n-provider-
|
|
1
|
+
import { a as e } from "./i18n-provider-tL27-a8y.js";
|
|
2
2
|
import { c as t, d as n, l as r, n as i, s as a, u as o } from "./number.utils-C1eB3GDr.js";
|
|
3
3
|
import { computed as s, getCurrentInstance as c, inject as l, onMounted as u, ref as d, shallowRef as f, toValue as p, watch as m } from "vue";
|
|
4
4
|
import { injectConfigProviderContext as h } from "reka-ui";
|
|
5
5
|
import { useIntersectionObserver as g, useMediaQuery as _, useSSRWidth as v, useStorage as y } from "@vueuse/core";
|
|
6
|
+
//#region lib/composables/use-ssr-media-query.ts
|
|
7
|
+
var b = 1024;
|
|
8
|
+
function x(e) {
|
|
9
|
+
return c() ? _(e, { ssrWidth: v() ?? b }) : _(e);
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
6
12
|
//#region lib/composables/resolve-theme.ts
|
|
7
|
-
function
|
|
13
|
+
function S(e, t) {
|
|
8
14
|
let n = e === "light" || e === "dark" ? e : "system";
|
|
9
15
|
return {
|
|
10
16
|
theme: n === "system" ? t ? "dark" : "light" : n,
|
|
11
17
|
preference: n
|
|
12
18
|
};
|
|
13
19
|
}
|
|
14
|
-
function x(e) {
|
|
15
|
-
typeof document > "u" || (document.documentElement.classList.toggle("dark", e === "dark"), document.documentElement.style.colorScheme = e);
|
|
16
|
-
}
|
|
17
|
-
//#endregion
|
|
18
|
-
//#region lib/composables/use-ssr-media-query.ts
|
|
19
|
-
var S = 1024;
|
|
20
20
|
function C(e) {
|
|
21
|
-
|
|
21
|
+
typeof document > "u" || (document.documentElement.classList.toggle("dark", e === "dark"), document.documentElement.style.colorScheme = e);
|
|
22
22
|
}
|
|
23
23
|
//#endregion
|
|
24
24
|
//#region lib/composables/use-theme.ts
|
|
25
25
|
function w() {
|
|
26
|
-
let e =
|
|
26
|
+
let e = x("(prefers-color-scheme: dark)"), t = y("theme", null, void 0, { initOnMounted: !0 }), n = s(() => S(t.value, !!e.value));
|
|
27
27
|
return {
|
|
28
28
|
get theme() {
|
|
29
29
|
return n.value.theme;
|
|
@@ -32,7 +32,7 @@ function w() {
|
|
|
32
32
|
return n.value.preference;
|
|
33
33
|
},
|
|
34
34
|
updateTheme: (n) => {
|
|
35
|
-
n === "system" ? t.value = null : t.value = n,
|
|
35
|
+
n === "system" ? t.value = null : t.value = n, C(S(n === "system" ? void 0 : n, !!e.value).theme);
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
38
|
}
|
|
@@ -40,7 +40,7 @@ function w() {
|
|
|
40
40
|
//#region lib/composables/use-mobile.ts
|
|
41
41
|
var T = 768;
|
|
42
42
|
function E() {
|
|
43
|
-
return
|
|
43
|
+
return x(`(max-width: ${T - 1}px)`);
|
|
44
44
|
}
|
|
45
45
|
//#endregion
|
|
46
46
|
//#region ../../node_modules/date-fns/locale/fr/_lib/formatDistance.js
|
|
@@ -495,4 +495,4 @@ function q(e, t, n) {
|
|
|
495
495
|
});
|
|
496
496
|
}
|
|
497
497
|
//#endregion
|
|
498
|
-
export { V as a, w as c,
|
|
498
|
+
export { V as a, w as c, x as d, W as i, C as l, U as n, B as o, H as r, E as s, q as t, S as u };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "./stored-language-
|
|
2
|
-
import { a as e } from "./i18n-provider-
|
|
3
|
-
import { i as t, r as n } from "./translator-
|
|
1
|
+
import "./stored-language-DVP9KzRu.js";
|
|
2
|
+
import { a as e } from "./i18n-provider-tL27-a8y.js";
|
|
3
|
+
import { i as t, r as n } from "./translator-Dpfm1mAC.js";
|
|
4
4
|
//#region lib/i18n/translate-material.ts
|
|
5
5
|
function r(e, r, i, a) {
|
|
6
6
|
if (e) for (let t of /* @__PURE__ */ new Set([e, e.split("-")[0]])) {
|
|
@@ -12,7 +12,7 @@ import "./chunk-Z7XXMR3K-DdnrI6vA.js";
|
|
|
12
12
|
import { t as ee } from "./chunk-XXDRQBXY-B9ckANit.js";
|
|
13
13
|
import { t as te } from "./chunk-WEXAMYUT-DufdZ2tS.js";
|
|
14
14
|
import "./chunk-UA2S7LBM-DN55-gzN.js";
|
|
15
|
-
import { r as ne, t as re } from "./chunk-GNY47TPC-
|
|
15
|
+
import { r as ne, t as re } from "./chunk-GNY47TPC-D4sl5ZSh.js";
|
|
16
16
|
//#region ../../node_modules/chevrotain/node_modules/lodash-es/_freeGlobal.js
|
|
17
17
|
var ie = typeof global == "object" && global && global.Object === Object && global, ae = typeof self == "object" && self && self.Object === Object && self, b = ie || ae || Function("return this")(), oe = b.Symbol, se = Object.prototype, ce = se.hasOwnProperty, le = se.toString, ue = oe ? oe.toStringTag : void 0;
|
|
18
18
|
function de(e) {
|
package/dist/vite.js
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { CSP_NONCE_PLACEHOLDER as e, ZOD_JITLESS_SCRIPT as t, cspAssetsInlineLimit as n, nxgtMaterial as r, pdfkitStandardFonts as i } from "@nxgt/material-core/vite";
|
|
2
|
+
//#region lib/vite/index.ts
|
|
3
|
+
function a(e) {
|
|
4
|
+
return r(e, "@nxgt/material-vue");
|
|
5
|
+
}
|
|
6
|
+
//#endregion
|
|
7
|
+
export { e as CSP_NONCE_PLACEHOLDER, t as ZOD_JITLESS_SCRIPT, n as cspAssetsInlineLimit, a as nxgtMaterial, i as pdfkitStandardFonts };
|
package/docs/README.md
CHANGED
|
@@ -14,8 +14,11 @@ detail: every option, the second example, and the traps.
|
|
|
14
14
|
| [Printing](guides/printing.md) | You lay out a printable document (invoice, report) with the `Print*` components |
|
|
15
15
|
| [PDF documents](guides/pdf.md) | You produce a PDF file from data with `@nxgt/material-vue/pdf`: in the browser (`usePdf`, `PdfDownloadButton`) or from a Nuxt server route (`pdfResponse`), fonts on an inlined server |
|
|
16
16
|
| [Maps](guides/maps.md) | You render Leaflet maps or a location field with `@nxgt/material-vue/map` |
|
|
17
|
+
| [Backgrounds](guides/backgrounds.md) | You want a gradient or patterned backdrop: tones, intensity, the opt-in `backgrounds.css`, custom colours, motion and CSP |
|
|
17
18
|
| [SSR](guides/ssr.md) | Your app renders on a server — Nuxt or a Vite SSR server — and bundles this package |
|
|
18
19
|
| [Content Security Policy](guides/csp.md) | Your app sends a strict CSP: the directives to use, the components that still inject a `<style>`, the zod and KaTeX settings, self-hosting a font, the per-request nonce |
|
|
20
|
+
| [The Vite plugin](guides/vite-plugin.md) | You are adding `nxgtMaterial()` to `vite.config.ts`: the CSP by hash or nonce, fonts, the styles check, PDFs on a bundled server and the Nuxt module, and each option's opt-out |
|
|
21
|
+
| [Migrating to the Vite plugin](guides/migrate-to-vite-plugin.md) | Your app has its own CSP header, nonce, `zod-config`, Inter import or PDF bundling, and you move it to `nxgtMaterial()`: search → replace pairs, each with how to verify |
|
|
19
22
|
| [Helpers](guides/helpers.md) | You need a utility, composable, Pinia store factory or type from `/lib`, `/composables`, `/i18n`, `/models`, `/types` or `/dnd` |
|
|
20
23
|
| [Troubleshooting](troubleshooting.md) | Something failed and you have an error message or a symptom |
|
|
21
24
|
| [Roadmap](roadmap.md) | You want to know what is planned, what shipped, and what will not be done |
|
|
@@ -298,6 +298,8 @@ replace that name, so pass one only when it should differ from the label.
|
|
|
298
298
|
own, so it is not announced as "collapsed". Used as a popover, drawer or menu
|
|
299
299
|
trigger (`as-child`), it carries that trigger's `aria-expanded`.
|
|
300
300
|
|
|
301
|
+
A `tooltip` always opens below 768 px or with `expanded={false}`. On a desktop width, or with `expanded`, one that repeats the visible label is not opened, and one that adds to it ("Create order (Ctrl+N)") still opens.
|
|
302
|
+
|
|
301
303
|
**Storybook:** `Buttons & actions/ResponsiveButton` · **React:** `ResponsiveButton`
|
|
302
304
|
|
|
303
305
|
---
|
|
@@ -80,7 +80,8 @@ table enables, for typing your own column defs.
|
|
|
80
80
|
| `data` | `T[]` | — | rows; sorting, filtering and pagination run client-side |
|
|
81
81
|
| `#expanded="{ row }"` / `renderExpandedRow` | slot / `(row) => VNode` | — | makes rows expandable; pair with the `expand` column |
|
|
82
82
|
| `showViewOptions` | `boolean` | — | column visibility menu above the table |
|
|
83
|
-
| `#actions="{ table }"` / `actions` | slot / `(table) => VNode` | — | toolbar content with access to the table (selected rows…) |
|
|
83
|
+
| `#actions="{ table }"` / `actions` | slot / `(table) => VNode` | — | toolbar content with access to the table (selected rows…); disabled while `loading` |
|
|
84
|
+
| `#filters="{ table }"` / `filters` | slot / `(table) => VNode` | — | a search or filter controls, on the toolbar's start side; unlike `actions` they stay enabled while `loading`, so a search typed during a reload keeps its focus and text |
|
|
84
85
|
| `onLoadMore` / `isLoadingMore` | `() => void` / `boolean` | — | adds a "load more" button under the rows |
|
|
85
86
|
| `options` | `{ showPage?: boolean; showSelected?: boolean }` | both shown | parts of the footer |
|
|
86
87
|
| `showHeader` | `boolean` | shown | header row (column names, sorting, "Select all") at every width; `false` hides it |
|
|
@@ -89,10 +90,13 @@ table enables, for typing your own column defs.
|
|
|
89
90
|
| `loading` | `boolean` | `false` | skeleton rows, or the current rows dimmed; `aria-busy`; controls disabled |
|
|
90
91
|
| `loadingRows` | `number` | the page size | how many skeleton rows |
|
|
91
92
|
| `density` | `'comfortable' \| 'compact'` | `'comfortable'` | `compact` tightens the cell padding, the row and header heights and the gap between rows, the selection column included; it is the table's `data-density` attribute, styled with classes (no inline style). The toolbar band and the empty state keep their size; the print variant is unchanged |
|
|
92
|
-
| `#empty="{ filtered }"` | slot |
|
|
93
|
+
| `#empty="{ filtered }"` | slot | a compact `EmptyState`: "No data available", or "No results" when filtered | content of the empty row, spanning every visible column |
|
|
94
|
+
| `#empty-filtered` | slot | none (falls back to `#empty`, then the default) | content of the empty row when rows exist but the filters hide every one; wins over `#empty` then |
|
|
93
95
|
| `manual` | `boolean` | `false` | `data` is one server page: no client filtering, sorting or paging; the footer is the server footer ([server-side data](#server-side-data)) |
|
|
94
96
|
| `v-model:sorting` | `SortingState` | held inside | controlled sorting; `update:sorting` gets the new state |
|
|
95
97
|
| `getRowId` | `(row, index) => string` | the index | the row's id, the key of the row selection |
|
|
98
|
+
| `enableRowSelection` | `boolean \| (row) => boolean` | `true` | which rows can be selected (`row` is the data). A row that cannot has a disabled checkbox; "Select all" skips it and its checked and indeterminate states count only selectable rows. A locked row already in the selection can be cleared by its own box (and only cleared) |
|
|
99
|
+
| `rowSelectionDisabledReason` | `(row) => string \| undefined` | — | why a row cannot be selected: its checkbox is `aria-disabled` but stays focusable, shows the reason in a tooltip on hover and focus, and has it as its `aria-describedby`; without a reason it is a plain `disabled` box |
|
|
96
100
|
| `v-model:row-selection` | `RowSelectionState` | held inside | controlled selection, by id; may hold rows of other pages |
|
|
97
101
|
| `pagination` | `{ totalCount?, offset?, previous?, next? }` | — | the server footer's range ("41–60 of 133") and Previous / Next: an href (a link) or a callback (a button) |
|
|
98
102
|
| `#footer="{ table }"` / `footer` | slot / `false \| (table) => VNode` | the pagination | replaces the footer; `false` removes it |
|
|
@@ -141,13 +145,60 @@ arrives. Sorting (`DataTableColumnHeader`), the `select` column's "Select
|
|
|
141
145
|
all", the toolbar's native controls (it
|
|
142
146
|
is a disabled `<fieldset>`, so every input or button you render there, a
|
|
143
147
|
filter or an export, is disabled
|
|
144
|
-
too) and pagination are disabled meanwhile.
|
|
145
|
-
|
|
146
|
-
When no row is left
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
too) and pagination are disabled meanwhile. The toolbar's `actions` are in that fieldset; a search or filter you want to keep typing in while the list reloads goes in `#filters` (or `filters`) instead, which sits beside it and stays enabled (its focus and text survive a reload).
|
|
149
|
+
|
|
150
|
+
When no row is left, the empty state is one `TableEmpty` cell spanning every
|
|
151
|
+
visible column. What it holds, first match wins:
|
|
152
|
+
|
|
153
|
+
1. the `#empty-filtered` slot, when rows exist but the filters hide every one
|
|
154
|
+
(`filtered`);
|
|
155
|
+
2. the `#empty` slot, told `{ filtered }`;
|
|
156
|
+
3. the default, a compact `EmptyState`: "No data available"
|
|
157
|
+
(`material.table.labels.no-data`) for a table with no data, or, when
|
|
158
|
+
filtered, "No results" and "Try a different search or clear the filters."
|
|
159
|
+
(`material.table.labels.no-results`, `no-results-description`) announced by the table's
|
|
160
|
+
status.
|
|
161
|
+
|
|
162
|
+
A slot that renders nothing falls through to the next step; there is no blank
|
|
163
|
+
option, the default shows. When the filters hide every row, the table's hidden
|
|
164
|
+
status announces "No results. Try a different search or clear the filters."
|
|
165
|
+
whatever the visible content is. `#empty-filtered`
|
|
166
|
+
is not used for a table with no data at all, nor with `manual` (server-side
|
|
167
|
+
data): the table cannot tell a filtered page from an empty one there, so it
|
|
168
|
+
reads `filtered` as `false`; branch on your own filter state in `#empty`.
|
|
150
169
|
`DataTableEmptyState` types the slot props.
|
|
170
|
+
`filtered` is computed from the core row model (`getCoreRowModel().rows.length > 0`), as in React.
|
|
171
|
+
|
|
172
|
+
```vue
|
|
173
|
+
<DataTable :data="people" :columns="columns">
|
|
174
|
+
<template #empty>No people yet.</template>
|
|
175
|
+
<template #empty-filtered>No person matches these filters.</template>
|
|
176
|
+
</DataTable>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Locked rows and a search that stays usable
|
|
180
|
+
|
|
181
|
+
`enableRowSelection` leaves rows out of the selection, `rowSelectionDisabledReason` says why, and `#filters` keeps a search enabled while the list reloads (`#actions` is disabled meanwhile):
|
|
182
|
+
|
|
183
|
+
```vue
|
|
184
|
+
<DataTable
|
|
185
|
+
v-model:row-selection="selection"
|
|
186
|
+
:columns="columns"
|
|
187
|
+
:data="proposals"
|
|
188
|
+
:loading="isFetching"
|
|
189
|
+
:enable-row-selection="(proposal) => proposal.status !== 'applied'"
|
|
190
|
+
:row-selection-disabled-reason="() => 'Already applied'"
|
|
191
|
+
>
|
|
192
|
+
<template #filters>
|
|
193
|
+
<SearchField v-model="q" label="Search" />
|
|
194
|
+
</template>
|
|
195
|
+
<template #actions="{ table }">
|
|
196
|
+
<Button>Apply to {{ table.getSelectedRowModel().rows.length }}</Button>
|
|
197
|
+
</template>
|
|
198
|
+
</DataTable>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
A locked row's checkbox is `aria-disabled` but focusable, so Tab reaches it and the tooltip says why; "Select all" skips it.
|
|
151
202
|
|
|
152
203
|
### Phones and narrow screens
|
|
153
204
|
|
|
@@ -11,7 +11,8 @@ centre. Everything is imported from `@nxgt/material-vue/components`.
|
|
|
11
11
|
| <img src="../previews/feedback-status-alertdialog.webp" width="96" alt=""> | [AlertDialog](#alertdialog) | Parts for a blocking confirmation dialog |
|
|
12
12
|
| <img src="../previews/feedback-status-confirmdialog.webp" width="96" alt=""> | [ConfirmDialog](#confirmdialog) | Confirm / cancel dialog, `ConfirmationDialog`, `CustomAlertDialog` |
|
|
13
13
|
| <img src="../previews/feedback-status-customdialog.webp" width="96" alt=""> | [CustomDialog](#customdialog) | Ready-made dialog with trigger, icon, title, body and footer |
|
|
14
|
-
| <img src="../previews/feedback-status-emptystate.webp" width="96" alt=""> | [EmptyState](#emptystate) |
|
|
14
|
+
| <img src="../previews/feedback-status-emptystate.webp" width="96" alt=""> | [EmptyState](#emptystate) | Illustration, title, description and action, by kind (empty, search, not-found, unauthorized) |
|
|
15
|
+
| <img src="../previews/feedback-status-errorstate.webp" width="96" alt=""> | [ErrorState](#errorstate) | Failure block with Retry and technical details |
|
|
15
16
|
| <img src="../previews/feedback-status-progress.webp" width="96" alt=""> | [Progress](#progress) | Linear bar, circular ring and labelled progress field |
|
|
16
17
|
| <img src="../previews/feedback-status-scrollprogress.webp" width="96" alt=""> | [ScrollProgress](#scrollprogress) | Hairline tracking the window or a scrollable element |
|
|
17
18
|
| <img src="../previews/feedback-status-spinner.webp" width="96" alt=""> | [Spinner](#spinner) | Loading spinner in several styles and colours |
|
|
@@ -412,8 +413,7 @@ icon for that reason now needs an element such as a `Button` or `IconButton`.
|
|
|
412
413
|
|
|
413
414
|

|
|
414
415
|
|
|
415
|
-
|
|
416
|
-
unauthorized, generic, empty, offline, search and maintenance presets.
|
|
416
|
+
A calm absence: an illustration (an icon when `size="compact"`), title, description and action, for the `empty`, `search`, `not-found` and `unauthorized` kinds. Text is `text-foreground` and reads at 7:1. For something that failed, use an error state instead.
|
|
417
417
|
|
|
418
418
|
```vue
|
|
419
419
|
<script setup lang="ts">
|
|
@@ -423,7 +423,7 @@ function clearFilters() {}
|
|
|
423
423
|
</script>
|
|
424
424
|
|
|
425
425
|
<template>
|
|
426
|
-
<EmptyState
|
|
426
|
+
<EmptyState kind="search">
|
|
427
427
|
<template #action>
|
|
428
428
|
<Button variant="outlined" @click="clearFilters">Clear filters</Button>
|
|
429
429
|
</template>
|
|
@@ -433,17 +433,88 @@ function clearFilters() {}
|
|
|
433
433
|
|
|
434
434
|
| Prop | Type | Default | Effect |
|
|
435
435
|
| --- | --- | --- | --- |
|
|
436
|
-
| `
|
|
437
|
-
|
|
|
438
|
-
| `
|
|
436
|
+
| `kind` | `'empty' \| 'search' \| 'not-found' \| 'unauthorized'` | `'generic'` (legacy, until 1.0) | illustration, icon, title and description |
|
|
437
|
+
| `size` | `'default' \| 'compact'` | `'default'` | `compact` swaps the illustration for a small icon and tightens the spacing |
|
|
438
|
+
| `variant` | the four kinds, plus `'generic' \| 'offline' \| 'maintenance'` | — | **deprecated**, removed in 1.0: use `kind`; the error values render without `role="alert"` |
|
|
439
|
+
| `#illustration` slot | — | the kind's | replaces the illustration |
|
|
440
|
+
| `#icon` slot | — | the kind's | replaces the icon |
|
|
441
|
+
| `title` / `description` | `string` (or `#title` / `#description`) | the kind's (translated) | replace the kind's text; see below |
|
|
439
442
|
| `#action` slot | — | — | shown under the text |
|
|
440
443
|
|
|
441
|
-
The
|
|
444
|
+
The default description is the companion of its title: with your own `title` and no `description`, no description is rendered. Pass `description` to keep a line under your own title. A `#title` slot counts as your own title; a `#description` slot always renders.
|
|
445
|
+
|
|
446
|
+
`EmptyState` cannot hide its media yet, unlike React's `illustration={false}` ([#711](https://github.com/softistx/nxgt-material/issues/711)); `ErrorState` can, with `:illustration="false"`.
|
|
447
|
+
|
|
448
|
+
`<EmptyState />` with no `kind` or `variant` still renders the `generic` (error) copy until 1.0; pass `kind`.
|
|
449
|
+
|
|
450
|
+
### Migrating from `variant`
|
|
451
|
+
|
|
452
|
+
`variant` still works and is removed in 1.0. Until then:
|
|
453
|
+
|
|
454
|
+
| Before | After |
|
|
455
|
+
| --- | --- |
|
|
456
|
+
| `variant="empty"`, `"search"`, `"not-found"`, `"unauthorized"` | `kind="…"` with the same value |
|
|
457
|
+
| `variant="generic"`, `"offline"`, `"maintenance"` | `<ErrorState kind="…">`: it is a `role="alert"` block with Retry and technical details; an `EmptyState` error `variant` has no `role` |
|
|
458
|
+
| no `variant` | pass `kind`: the default stays `generic` until 1.0, then becomes `empty` |
|
|
459
|
+
| class overrides to shrink it (`min-h-0`, smaller padding) | `size="compact"`: a small icon, no minimum height |
|
|
460
|
+
| `material.empty-state.generic\|offline\|maintenance.*` overrides | the same text under `material.error-state.<kind>.*` |
|
|
461
|
+
|
|
462
|
+
```vue
|
|
463
|
+
<!-- before -->
|
|
464
|
+
<EmptyState variant="offline" />
|
|
465
|
+
<EmptyState variant="search" class="min-h-0 py-6" />
|
|
466
|
+
|
|
467
|
+
<!-- after -->
|
|
468
|
+
<ErrorState kind="offline" @retry="refetch" />
|
|
469
|
+
<EmptyState kind="search" size="compact" />
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
In 1.0, `variant` goes, the error kinds leave `EmptyState`, and `kind` defaults to `empty`. The DOM keeps `data-slot="empty-state"` and `data-variant`, and adds `data-kind` and `data-size`.
|
|
442
473
|
|
|
443
474
|
**Storybook:** `Feedback & status/EmptyState` · **React:** `EmptyState`
|
|
444
475
|
|
|
445
476
|
---
|
|
446
477
|
|
|
478
|
+
## ErrorState
|
|
479
|
+
|
|
480
|
+

|
|
481
|
+
|
|
482
|
+
Failure block with `role="alert"`, an illustration, an optional outlined Retry
|
|
483
|
+
and collapsed technical details (name, message and causes, never the stack).
|
|
484
|
+
Text reads at 7:1 in both themes.
|
|
485
|
+
|
|
486
|
+
```vue
|
|
487
|
+
<script setup lang="ts">
|
|
488
|
+
import { ErrorState } from '@nxgt/material-vue/components';
|
|
489
|
+
</script>
|
|
490
|
+
|
|
491
|
+
<template>
|
|
492
|
+
<ErrorState kind="offline" :error="error" @retry="refetch" />
|
|
493
|
+
</template>
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
| Prop | Type | Default | Effect |
|
|
497
|
+
| --- | --- | --- | --- |
|
|
498
|
+
| `kind` | `'generic' \| 'offline' \| 'maintenance'` | `'generic'` | illustration, title and description (`material.error-state.<kind>.*`) |
|
|
499
|
+
| `size` | `'default' \| 'compact'` | `'default'` | compact swaps the illustration for an icon |
|
|
500
|
+
| `title` / `description` | `string` | the kind's (translated) | replace the text; a custom `title` drops the default description |
|
|
501
|
+
| `illustration` | `boolean` | `true` | `:illustration="false"` hides the media |
|
|
502
|
+
| `#illustration` / `#icon` slots | — | the built-in illustration | replace the media |
|
|
503
|
+
| `#details` slot | — | the collapsed technical details | replaces them; React has no equivalent yet ([#712](https://github.com/softistx/nxgt-material/issues/712)) |
|
|
504
|
+
| `error` | `unknown` | none | the thrown value; its name, message and `cause` chain go in the details |
|
|
505
|
+
| `showDetails` | `boolean` | `true` when `error` is set | `false` hides the details |
|
|
506
|
+
| `@retry` | `() => unknown` | none | shows an outlined **Retry** button; a returned promise keeps it loading until it settles |
|
|
507
|
+
| `retrying` / `retryLabel` | `boolean` / `string` | derived / `Retry` | force the loading state; rename the button |
|
|
508
|
+
| `action` | the `#action` slot | none | extra actions after Retry |
|
|
509
|
+
|
|
510
|
+
The details are a native `<details>`: keyboard and server-render friendly.
|
|
511
|
+
Copy keys: `material.error-state.{generic,offline,maintenance}.{title,description}`,
|
|
512
|
+
`error-state.retry`, `error-state.details` and `error-state.details-name|message|cause`.
|
|
513
|
+
|
|
514
|
+
**Storybook:** `Feedback & status/ErrorState` · **React:** `ErrorState`
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
447
518
|
## Progress
|
|
448
519
|
|
|
449
520
|

|
|
@@ -624,6 +624,8 @@ Parts: `PdfReader` (`PdfViewer` is a deprecated alias), `PdfToolbar`, `PdfSideba
|
|
|
624
624
|
`PdfThumbnailSidebar`, `PdfOutlineSidebar`, `PdfPageList`, and the
|
|
625
625
|
`usePdfReader` composable for building your own layout.
|
|
626
626
|
|
|
627
|
+
A failed load shows the reader's own error; the React reader adds a Retry button to it, which is React-only for now ([#702](https://github.com/softistx/nxgt-material/issues/702)).
|
|
628
|
+
|
|
627
629
|
| Prop | Type | Default | Effect |
|
|
628
630
|
| --- | --- | --- | --- |
|
|
629
631
|
| `file` | `PdfSource \| null` | — (required) | a URL (`string` or `URL`), a `File` or `Blob`, an `ArrayBuffer` or `Uint8Array`, or `{ url, httpHeaders?, withCredentials? }`; `null` shows the empty state |
|
|
@@ -78,7 +78,7 @@ which work alone; `findActiveMenuItem`, `isMenuItemActive` and
|
|
|
78
78
|
| `avatarSrc` | `string` | — | avatar image in the header |
|
|
79
79
|
| `logo` (or `#logo`), `name` | `AppLogo` (`string \| AppLogoImage`, `AppLogoImage` = `{ src, alt? }`), `string` | — | the app's logo alone in the collapsed rail, named by `name` (also its tooltip); logo and name side by side in the phone's menu sheet; `#logo` wins over `logo` |
|
|
80
80
|
| `#brand` | slot | — | replaces the sidebar header, in the rail and the menu sheet; wins over `logo` and `name` |
|
|
81
|
-
| `#header-title` | slot | — | the header's leading title (the context: an organisation's name), after the phone's menu button, truncated when long |
|
|
81
|
+
| `#header-title` | slot | — | the header's leading title (the context: an organisation's name), after the phone's menu button, truncated when long; when it is cut off, its full text is the `title` tooltip (#629) |
|
|
82
82
|
| `#header-actions`, `#avatar` | slots | — | header, before the avatar; `#avatar` replaces it |
|
|
83
83
|
| `title`, `subtitle`, `#actions` | `string`, `string`, slot | — | `ActivityContent`'s header card |
|
|
84
84
|
| `#header` / `hideHeader` | slot / `boolean` | — / `false` | `ActivityContent`: replace or drop the header card |
|
|
@@ -780,7 +780,7 @@ Parts: `Doc` (the shell), `DocPage` (header, content, see also and pager);
|
|
|
780
780
|
the pieces it composes — `DocTopbar`, `DocSidebar`, `DocNav`, `DocArticle`,
|
|
781
781
|
`DocToc`, `DocPager`, `DocSearch`, `DocSeeAlso`, `DocChildCards`,
|
|
782
782
|
`DocProgress`, `DocSkipLink`, `DocHeader`, `DocCopyPage`, `DocCopyMarkdown`,
|
|
783
|
-
`DocLink` — and `DocEmpty` for a 404.
|
|
783
|
+
`DocLink` — and `DocEmpty` for a 404. `DocEmpty` is an `EmptyState` (`kind` defaults to `not-found`; `size` is `default` or `compact`): see [EmptyState](./feedback-and-status.md#emptystate).
|
|
784
784
|
`useDoc` / `provideDoc` / `useDocContext` expose the state for a shell of
|
|
785
785
|
your own, built from those parts:
|
|
786
786
|
|
|
@@ -878,9 +878,17 @@ import { Background, Card } from '@nxgt/material-vue/components';
|
|
|
878
878
|
</template>
|
|
879
879
|
```
|
|
880
880
|
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
881
|
+
| Prop | Values | Default |
|
|
882
|
+
| --- | --- | --- |
|
|
883
|
+
| `preset` | `gradient` (the only preset on `/components`) | `gradient` |
|
|
884
|
+
| `tone` | `primary`, `secondary`, `tertiary`, `neutral`, `success`, `warning`, `error`, `info`, `mixed` (primary, secondary and tertiary), `custom` (reads `--nxgt-bg-custom-1..3`) | `primary` |
|
|
885
|
+
| `intensity` | `subtle`, `default`, `vivid` | `default` |
|
|
886
|
+
| `animated` | drifts the blobs; paused while the page is hidden or the background is off screen, and never under reduced motion | `false` |
|
|
887
|
+
|
|
888
|
+
It fills the viewport; pass a `class` such as `h-96 w-full` to use it as a band.
|
|
889
|
+
It is plain CSS from `styles.css`, with no inline `style`, and its colours lift
|
|
890
|
+
in dark. `ActivityLayout` and `ThreadLayout` sit on it. The superset with `grain`,
|
|
891
|
+
`seed`, `fill` and the other presets is `Background` from `/backgrounds`; see the [backgrounds guide](../guides/backgrounds.md).
|
|
884
892
|
|
|
885
893
|
**Storybook:** `Navigation & layout/Background` · **React:** `Background`
|
|
886
894
|
|
|
@@ -39,7 +39,16 @@ default) leave the page as it is.
|
|
|
39
39
|
|
|
40
40
|

|
|
41
41
|
|
|
42
|
-
Modal dialog parts with a close button.
|
|
42
|
+
Modal dialog parts with a close button. An open `SelectField` list inside it has always taken the first Escape, as a layer of its own. So does an open `ComboboxField` or `Autocomplete` list: the second Escape closes the dialog. The same holds in a `Sheet`, a `Drawer`, an `AlertDialog` and a `Popover`.
|
|
43
|
+
|
|
44
|
+
Your own `@escape-key-down` on the content receives the Escape that only closes an open list with `event.defaultPrevented === true`; a handler that asks "close without saving?" returns early on it:
|
|
45
|
+
|
|
46
|
+
```vue
|
|
47
|
+
<DialogContent @escape-key-down="(event) => {
|
|
48
|
+
if (event.defaultPrevented) return; // only an open list is closing
|
|
49
|
+
if (dirty) event.preventDefault(); // ask "close without saving?"
|
|
50
|
+
}">
|
|
51
|
+
```
|
|
43
52
|
|
|
44
53
|
```vue
|
|
45
54
|
<script setup lang="ts">
|
|
@@ -198,6 +207,8 @@ Vue.
|
|
|
198
207
|
|
|
199
208
|
Swipeable bottom or side drawer (Reka UI's drawer).
|
|
200
209
|
|
|
210
|
+
An `Autocomplete` inside a Drawer keeps its list floating, stopped above the Drawer's footer, and a drag that starts on the list scrolls it instead of dragging the Drawer.
|
|
211
|
+
|
|
201
212
|
```vue
|
|
202
213
|
<script setup lang="ts">
|
|
203
214
|
import {
|
|
@@ -638,20 +649,26 @@ Parts: `Command`, `CommandDialog`, `CommandInput`, `CommandList`,
|
|
|
638
649
|
`CommandEmpty`, `CommandGroup`, `CommandItem`, `CommandShortcut`,
|
|
639
650
|
`CommandSeparator`.
|
|
640
651
|
|
|
652
|
+
`CommandEmpty` shows when the search matches nothing. With no children it
|
|
653
|
+
renders a compact `EmptyState` ("No results", `material.command.empty`); give it
|
|
654
|
+
children and they replace that, as before.
|
|
655
|
+
|
|
641
656
|
| Prop | Type | Default | Effect |
|
|
642
657
|
| --- | --- | --- | --- |
|
|
643
658
|
| `value` (`CommandItem`) | `string` | — (required) | the item's value, emitted by `@select` and by `Command`'s `v-model` |
|
|
644
659
|
| `checked` (`CommandItem`) | `boolean` | — | sets `aria-checked` and shows a checkbox indicator, for a multi-choice list; reka's `aria-selected` keeps meaning "selected value" (`multiple` is not used) |
|
|
645
660
|
| `multiselectable` (`CommandList`) | `boolean` | — | sets `aria-multiselectable` on the list |
|
|
646
661
|
| `@select` (`CommandItem`) | `(event) => void` | — | Enter or click on the item; `event.detail.value` is its `value` |
|
|
662
|
+
| `aria-label` (`CommandList`) | `string` | `"Suggestions"` (translated, `material.command.list`) | the list's accessible name; your own `aria-label` replaces the default |
|
|
663
|
+
| `decorative` (`CommandSeparator`) | `boolean` | `true` | the separator is purely visual (`role="none"`): a `role="separator"` is not allowed inside the listbox |
|
|
647
664
|
| `heading` (`CommandGroup`) | `string` | — | the group's label |
|
|
648
665
|
| `title` / `description` (`CommandDialog`) | `string` | `"Command Palette"` / `"Search for a command to run..."` (translated) | the dialog's title and description, visually hidden |
|
|
649
666
|
| `v-model:open` (`CommandDialog`) | `boolean` | — | `CommandDialog` takes every `Dialog` prop |
|
|
650
667
|
|
|
651
668
|
The filter matches the item's text, case- and accent-insensitive; there is no
|
|
652
669
|
`shouldFilter` or `keywords` in Vue. `CommandDialog`'s default title and
|
|
653
|
-
description
|
|
654
|
-
keyboard shortcut: listen for ⌘K yourself (`useMagicKeys` from VueUse) and set
|
|
670
|
+
description follow `I18nProvider` (`material.command.title` / `description`).
|
|
671
|
+
It does not bind a keyboard shortcut: listen for ⌘K yourself (`useMagicKeys` from VueUse) and set
|
|
655
672
|
`open`.
|
|
656
673
|
|
|
657
674
|
**Storybook:** `Overlays & menus/Command` · **React:** `Command`, `CommandDialog` (same parts)
|
|
@@ -193,7 +193,7 @@ import { Typography } from '@nxgt/material-vue/components';
|
|
|
193
193
|
| Prop | Type | Default | Effect |
|
|
194
194
|
| --- | --- | --- | --- |
|
|
195
195
|
| `variant` | `'huge-larger' \| 'huge-large' \| 'huge-medium' \| 'huge-small' \| 'headline-larger' \| 'headline-large' \| 'headline-medium' \| 'headline-small' \| 'title-large' \| 'title-medium' \| 'title-small' \| 'body-medium' \| 'body-small' \| 'caption' \| 'normal'` | `'normal'` | size and weight; `caption` is also muted |
|
|
196
|
-
| `tone` | `'default' \| 'muted' \| 'primary' \| 'error'` | `'default'` | text colour: `muted` is `text-muted-foreground`, `primary` is `text-primary
|
|
196
|
+
| `tone` | `'default' \| 'muted' \| 'primary' \| 'error'` | `'default'` | text colour: `muted` is `text-muted-foreground`, `primary` is `text-primary-text` (primary lightened in dark), `error` is `text-error-text`; `default` inherits (a `class` colour still wins) |
|
|
197
197
|
| `as` | a tag name or a component | `'div'` | the element to render, keeping the variant, e.g. `as="h2"` or `as="span"` |
|
|
198
198
|
| `asChild` | `boolean` | `false` | merge the classes onto the single child instead of rendering an element |
|
|
199
199
|
|
|
@@ -364,6 +364,8 @@ Takes every `<input>` attribute. `v-model` carries `string | number`;
|
|
|
364
364
|
the error outline. For a labelled field with helper text and a form wrapper,
|
|
365
365
|
use `TextField` on the [Form fields](form-fields.md) page.
|
|
366
366
|
|
|
367
|
+
In an input group (`InputGroupInput`, `InputGroupField`) the fill tint follows the value: an empty field is not tinted, with or without a `placeholder` (one without renders a blank `placeholder=" "` so that CSS can tell). The bare `Input` and `Textarea` have no tint and get no placeholder.
|
|
368
|
+
|
|
367
369
|
**Emits:** `update:modelValue` — `string | number`.
|
|
368
370
|
**Storybook:** `Primitives/Input` · **React:** `Input`
|
|
369
371
|
|
|
@@ -461,7 +463,7 @@ import { Icon } from '@nxgt/material-vue/components';
|
|
|
461
463
|
|
|
462
464
|
<template>
|
|
463
465
|
<Icon name="bell" />
|
|
464
|
-
<Icon name="bell" type="solid" class="size-6 text-primary" aria-hidden="true" />
|
|
466
|
+
<Icon name="bell" type="solid" class="size-6 text-primary-text" aria-hidden="true" />
|
|
465
467
|
</template>
|
|
466
468
|
```
|
|
467
469
|
|
|
@@ -901,7 +903,7 @@ defineProps<{ nonce?: string }>();
|
|
|
901
903
|
|
|
902
904
|
| Prop | Type | Default | Effect |
|
|
903
905
|
| --- | --- | --- | --- |
|
|
904
|
-
| `nonce` | `string` | `undefined` | the nonce of the page's `style-src-elem 'nonce-…'`; `undefined` or `''` inherits the nearest outer `NonceProvider`'s (or `ConfigProvider`'s) nonce (
|
|
906
|
+
| `nonce` | `string` | `undefined` | the nonce of the page's `style-src-elem 'nonce-…'`; `undefined` or `''` inherits the nearest outer `NonceProvider`'s (or `ConfigProvider`'s) nonce, else, on the client from the first render (read in `setup`), the page's own (`csp-nonce` meta tag, …); a server has no page, so it passes the prop |
|
|
905
907
|
|
|
906
908
|
`useCspNonce()` (`@nxgt/material-vue/composables`) reads it in a component of
|
|
907
909
|
your own; `getCspNonce()` and `setCspNonce()` (`@nxgt/material-vue/lib`) read
|
|
@@ -238,7 +238,7 @@ props below, and `option` for anything else.
|
|
|
238
238
|
| `height` | `string \| number` | `320` | the container's height; the chart fills it |
|
|
239
239
|
| `loading` | `boolean` | `false` | a skeleton instead of the chart |
|
|
240
240
|
| `empty` | `boolean` | when `data` is empty | force the empty state on or off |
|
|
241
|
-
| `#emptyState` | slot | built-in
|
|
241
|
+
| `#emptyState` | slot | the built-in compact `EmptyState` | what an empty chart shows; a custom slot keeps its centring wrapper |
|
|
242
242
|
| `colors` | `string[]` | from the `--chart-*` tokens | override the palette; any CSS colour, `oklch()` included (converted to `rgb()` for ECharts) |
|
|
243
243
|
| `margin` | `ChartMargin` | — | plot padding |
|
|
244
244
|
| `option` | `EChartsOption` | — | merged into the generated ECharts option |
|
|
@@ -234,6 +234,8 @@ options by label. Picking the selected option again clears it.
|
|
|
234
234
|
|
|
235
235
|
Single or multiple (chips) autocomplete typed by its options, with free-solo values, accent-insensitive matching, a debounced server search and option slots.
|
|
236
236
|
|
|
237
|
+
The input is a `combobox` (`aria-expanded`, `aria-controls`, `aria-activedescendant`) and the list a `listbox` of `option`s, as in `@nxgt/material`; the list opens on a click or on typing, not on focus alone. In tests, use `getByRole('combobox', { name })` and `getByRole('option', { name })`.
|
|
238
|
+
|
|
237
239
|
```vue
|
|
238
240
|
<script setup lang="ts">
|
|
239
241
|
import { ref } from 'vue';
|
|
@@ -336,15 +338,23 @@ update them on `@query-change`, and pass `filter="none"` when the server
|
|
|
336
338
|
already filtered.
|
|
337
339
|
|
|
338
340
|
A disabled option (`disabled: true` on it, in `options` or in what `on-search`
|
|
339
|
-
returns) is greyed out, carries `aria-disabled` and a native `disabled`, so
|
|
340
|
-
|
|
341
|
-
enabled option), in `single` and `multiple` mode.
|
|
341
|
+
returns) is greyed out, carries `aria-disabled` and a native `disabled`, so the arrow keys skip it, and is never picked, by click or by Enter (which picks the
|
|
342
|
+
highlighted option, the first enabled one until the arrows move it), in `single` and `multiple` mode.
|
|
342
343
|
|
|
343
344
|
**Accessibility.** A polite live region (`role="status"`) says "Loading…",
|
|
344
345
|
then "3 results" or "No results" (or the failure) once the search answers or
|
|
345
346
|
typing pauses — never on every keystroke. The list is `aria-busy` while
|
|
346
347
|
loading. The strings are `material.autocomplete.loading`, `.results`,
|
|
347
|
-
`.search-error` and `.min-query`.
|
|
348
|
+
`.search-error` and `.min-query`.
|
|
349
|
+
|
|
350
|
+
**Keyboard.** The input keeps the focus and points at the highlighted option
|
|
351
|
+
with `aria-activedescendant`. `ArrowDown` and `ArrowUp` open a closed list
|
|
352
|
+
and move the highlight over the enabled options (wrapping at the ends); with
|
|
353
|
+
an empty query `Home` and `End` jump to the first and last one. `Enter`
|
|
354
|
+
picks the highlighted option (or adds the free-solo value when "Add …" stands
|
|
355
|
+
for it) and, with the list closed, submits the form; hovering an option moves
|
|
356
|
+
the highlight. `Escape` closes the list, and `Backspace` on an empty query removes
|
|
357
|
+
the last chip. The options are not tab stops: Tab leaves the field.
|
|
348
358
|
|
|
349
359
|
It is a generic component: `T` is inferred from `options`, and the slots —
|
|
350
360
|
React's render props — receive it whole:
|
package/docs/getting-started.md
CHANGED
|
@@ -35,7 +35,7 @@ does not import that entry never has them in its tree.
|
|
|
35
35
|
The tarball contains the built `dist/` (with KaTeX's fonts in
|
|
36
36
|
`dist/fonts/katex/`, which the compiled stylesheet loads),
|
|
37
37
|
`lib/styles.css`, the component
|
|
38
|
-
stylesheets it imports (`lib/components/**/*.css`), `lib/map/map.css`, the
|
|
38
|
+
stylesheets it imports (`lib/components/**/*.css`), `lib/map/map.css`, `lib/backgrounds/backgrounds.css`, `lib/backgrounds/css/*.css`, the
|
|
39
39
|
Nuxt module (`lib/nuxt`, with the
|
|
40
40
|
`lib/vite/index.ts` it imports), these docs and `CHANGELOG.md` (from the
|
|
41
41
|
release after 0.25.1). There is no `postinstall` build step.
|
|
@@ -112,6 +112,18 @@ Your own components can use the same per-instance store factory
|
|
|
112
112
|
(`defineLocalStore` and the status, filter and step-form stores) from
|
|
113
113
|
`@nxgt/material-vue/lib`; see [helpers](guides/helpers.md#pinia-store-factories).
|
|
114
114
|
|
|
115
|
+
## The Vite plugin
|
|
116
|
+
|
|
117
|
+
In `vite.config.ts`, add the plugin after `tailwindcss()`:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import { nxgtMaterial } from '@nxgt/material-vue/vite';
|
|
121
|
+
|
|
122
|
+
export default defineConfig({ plugins: [/* …, */ tailwindcss(), ...nxgtMaterial()] });
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
It sets up a strict Content Security Policy (the header is written to `dist/.vite/nxgt-csp.json`), keeps fonts out of `data:` URIs, loads Inter when `@fontsource-variable/inter` is installed and fails the build when the stylesheet above is not imported. Each part has an opt-out: [Vite plugin guide](guides/vite-plugin.md). On Nuxt, see the guide's note.
|
|
126
|
+
|
|
115
127
|
## Icons
|
|
116
128
|
|
|
117
129
|
`Icon` renders a Font Awesome **sprite** referenced by a root-relative URL on
|
|
@@ -174,7 +186,9 @@ export default defineNuxtConfig({
|
|
|
174
186
|
// prefix: 'Nxgt', // <NxgtButton />
|
|
175
187
|
// components: true, // auto-import components
|
|
176
188
|
// imports: true, // auto-import composables and i18n helpers
|
|
177
|
-
// pdf: {
|
|
189
|
+
// pdf: { bundle: true }, // a server with no node_modules that renders /pdf
|
|
190
|
+
// fonts: { sans: 'inter' }, // self-hosted Inter (bun add @fontsource-variable/inter)
|
|
191
|
+
// csp: { zodJitless: true }, // zod's jitless script in every head (needs nuxt-security's nonce or hash)
|
|
178
192
|
},
|
|
179
193
|
});
|
|
180
194
|
```
|
|
@@ -184,7 +198,10 @@ export default defineNuxtConfig({
|
|
|
184
198
|
| `prefix` | `string` | `''` | Prepended to every auto-imported component name |
|
|
185
199
|
| `components` | `boolean` | `true` | Registers the components of `@nxgt/material-vue/components` for use without an import |
|
|
186
200
|
| `imports` | `boolean` | `true` | Auto-imports the composables (`useTheme`, `useIsMobile`, `useIsClient`, `useLocalizedDate`, `useFormatters`, `useNumberFormatter`, `useSearchParam`, …) and `useMaterialTranslation`, `createTypedTranslation`, `useOptionalI18nContext` |
|
|
187
|
-
| `pdf.
|
|
201
|
+
| `pdf.bundle` | `boolean` | `false` | Adds `pdfkitStandardFonts()` to the Nitro build, for a server that renders with `@nxgt/material-vue/pdf` and runs without `node_modules` ([PDF documents](guides/pdf.md#fonts-on-a-fully-inlined-server)). `pdf.bundleStandardFonts` is its deprecated name |
|
|
202
|
+
| `fonts` | `boolean \| { katex?, sans? }` | `{ katex: true, sans: false }` | `katex`: a font is never inlined as a `data:` URI (`font-src 'self'`). `sans: 'inter'`: loads self-hosted Inter and sets `--font-sans` through `css` (a missing `@fontsource-variable/inter` warns once and keeps the system font). `false` turns both off |
|
|
203
|
+
| `csp.zodJitless` | `boolean` | `false` | Puts zod's jitless inline script in every page's `<head>` (`tagPriority: 'critical'`). It is an inline script: a strict CSP needs `nuxt-security` with `nonce: true` (or its script hashes) to allow it. The module sets no CSP itself ([Vite plugin guide](guides/vite-plugin.md#nuxt)) |
|
|
204
|
+
| `styles` | `boolean \| { check? }` | `false` | The `vite build` check that the stylesheet is imported, off by default under Nuxt because the module cannot see how `css` entries are resolved. `true` opts in |
|
|
188
205
|
|
|
189
206
|
The module also:
|
|
190
207
|
|
|
@@ -223,6 +240,7 @@ export default defineConfig({
|
|
|
223
240
|
| `@nxgt/material-vue` | Everything from `/components`, `/composables`, `/i18n`, `/lib`, `/models` and `/types` in one barrel, plus the compiled `style` condition (`dist/material-vue.css`, for apps without Tailwind) |
|
|
224
241
|
| `@nxgt/material-vue/components` | UI components and `*FormField` wrappers ([components](components/README.md)) |
|
|
225
242
|
| `@nxgt/material-vue/map` | Leaflet maps, markers, a location field. **Its own entry, not in the barrel above** ([maps](guides/maps.md)) |
|
|
243
|
+
| `@nxgt/material-vue/backgrounds` | Background presets: `Background` (a superset of the `/components` one: `preset` `gradient` or `grain`, `tone`, `intensity`, `animated`, `grain`, `seed`, `fill`), and the types and tables re-exported from `@nxgt/material-core/backgrounds`; more presets are coming. **Its own entry**, with an opt-in stylesheet ([backgrounds](guides/backgrounds.md)) |
|
|
226
244
|
| `@nxgt/material-vue/pdf` | PDF files from plain data: builders, `usePdf`, `PdfDownloadButton`, `pdfResponse`. **Its own entry, not in the barrel above** ([PDF documents](guides/pdf.md)) |
|
|
227
245
|
| `@nxgt/material-vue/composables` | `useTheme`, `useIsClient`, `useIsMobile`, `useLocalizedDate`, `useSearchParam`, … ([helpers](guides/helpers.md#nxgtmaterial-vuecomposables)) |
|
|
228
246
|
| `@nxgt/material-vue/dnd` | Drag-and-drop primitives ([helpers](guides/helpers.md#nxgtmaterial-vuednd)) |
|
|
@@ -232,6 +250,7 @@ export default defineConfig({
|
|
|
232
250
|
| `@nxgt/material-vue/types` | Shared function types (`PromiseOr`, `FunctionOr`, …) |
|
|
233
251
|
| `@nxgt/material-vue/styles.css` | Source Tailwind v4 tokens. **This** is the stylesheet a Tailwind app imports |
|
|
234
252
|
| `@nxgt/material-vue/map.css` | Leaflet's stylesheet, for apps that use `/map`. Not part of `styles.css` |
|
|
253
|
+
| `@nxgt/material-vue/backgrounds.css` | Every background preset's CSS, for apps that use `/backgrounds`; `@nxgt/material-vue/backgrounds/<preset>.css` loads one. Not part of `styles.css` |
|
|
235
254
|
| `@nxgt/material-vue/nuxt` | The Nuxt module ([above](#nuxt)) |
|
|
236
255
|
| `@nxgt/material-vue/vite` | `pdfkitStandardFonts()`, a Vite plugin for a server that inlines `/pdf` ([PDF documents](guides/pdf.md#fonts-on-a-fully-inlined-server)). Build-time code for `vite.config.ts` |
|
|
237
256
|
|