@nxgt/material-vue 0.23.4 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -28
- package/dist/{Button-CVIR6uLK.js → Button-C1aaI0Gw.js} +95 -72
- package/dist/{HoverCardTrigger-iAL5ALrL.js → HoverCardTrigger-JtHn0IFQ.js} +2 -2
- package/dist/{camera-Gvg5N956.js → camera-BacVyXl0.js} +6 -6
- package/dist/{components-AScwCcds.js → components-DRBKkOqk.js} +15764 -13833
- package/dist/components.js +8 -8
- package/dist/composables.js +2 -2
- package/dist/dnd.js +1 -1
- package/dist/form-scope-VxlJuvFe.js +43 -0
- package/dist/{i18n-provider-BqWxpaKu.js → i18n-provider-D0oYv0XS.js} +1 -1
- package/dist/i18n.js +4 -4
- package/dist/{icon-button-DbEME76t.js → icon-button-B2FQtIHS.js} +34 -37
- package/dist/lib/components/ui/actions/button/has-text-content.d.ts +10 -0
- package/dist/lib/components/ui/actions/copy-button/copy-value.vue.d.ts +21 -0
- package/dist/lib/components/ui/actions/copy-button/index.d.ts +2 -0
- package/dist/lib/components/ui/collections/data-table/data-table-context.d.ts +6 -0
- package/dist/lib/components/ui/collections/data-table/data-table-pagination.vue.d.ts +2 -0
- package/dist/lib/components/ui/collections/data-table/data-table.vue.d.ts +17 -27
- package/dist/lib/components/ui/collections/data-table/index.d.ts +1 -1
- package/dist/lib/components/ui/collections/data-table/partials/data-table-body.vue.d.ts +10 -1
- package/dist/lib/components/ui/collections/data-table/partials/data-table-empty.vue.d.ts +13 -1
- package/dist/lib/components/ui/collections/data-table/partials/data-table-head.vue.d.ts +22 -0
- package/dist/lib/components/ui/collections/data-table/partials/data-table-skeleton-rows.vue.d.ts +10 -0
- package/dist/lib/components/ui/collections/data-table/use-data-table.d.ts +17 -0
- package/dist/lib/components/ui/collections/filter/partials/filter-field-slider-range.vue.d.ts +1 -4
- package/dist/lib/components/ui/collections/pagination/index.d.ts +5 -0
- package/dist/lib/components/ui/collections/pagination/pagination-bar.vue.d.ts +21 -0
- package/dist/lib/components/ui/collections/pagination/pagination-items.d.ts +2 -0
- package/dist/lib/components/ui/collections/pagination/pagination-link.vue.d.ts +18 -0
- package/dist/lib/components/ui/collections/tree/use-tree.d.ts +2 -0
- package/dist/lib/components/ui/dates/date-field/date-field.vue.d.ts +10 -1
- package/dist/lib/components/ui/dates/date-field/date-form-field.vue.d.ts +3 -1
- package/dist/lib/components/ui/dates/date-field/day-matcher.d.ts +26 -0
- package/dist/lib/components/ui/dates/date-field/index.d.ts +1 -0
- package/dist/lib/components/ui/dates/date-field/partials/date-field-content.vue.d.ts +2 -0
- package/dist/lib/components/ui/dates/date-range-field/date-range-field.utils.d.ts +11 -0
- package/dist/lib/components/ui/dates/date-range-field/date-range-field.vue.d.ts +26 -1
- package/dist/lib/components/ui/dates/date-range-field/date-range-form-field.vue.d.ts +3 -1
- package/dist/lib/components/ui/dates/date-range-field/index.d.ts +1 -0
- package/dist/lib/components/ui/dates/date-range-field/partials/date-range-calendar.vue.d.ts +5 -0
- package/dist/lib/components/ui/dates/date-range-field/partials/date-range-field-trigger.vue.d.ts +2 -0
- package/dist/lib/components/ui/dates/date-range-field/partials/date-range-presets.vue.d.ts +12 -0
- package/dist/lib/components/ui/dates/date-range-field/partials/date-range-times.vue.d.ts +13 -0
- package/dist/lib/components/ui/dates/date-range-field/use-date-range-presets.d.ts +23 -0
- package/dist/lib/components/ui/dates/time-picker/time-picker-utils.d.ts +7 -0
- package/dist/lib/components/ui/display/accordion-card/accordion-card.vue.d.ts +29 -1
- package/dist/lib/components/ui/display/avatar/Avatar.vue.d.ts +14 -3
- package/dist/lib/components/ui/display/avatar/index.d.ts +1 -0
- package/dist/lib/components/ui/display/cards/cards.gallery.d.ts +5 -9
- package/dist/lib/components/ui/display/markdown/index.d.ts +18 -0
- package/dist/lib/components/ui/display/qrcode/qrcode.vue.d.ts +5 -3
- package/dist/lib/components/ui/display/status-indicator/status-tone.d.ts +3 -0
- package/dist/lib/components/ui/feedback/confirmation-dialog/async-form-scope.d.ts +15 -0
- package/dist/lib/components/ui/feedback/confirmation-dialog/confirmation-dialog.vue.d.ts +37 -24
- package/dist/lib/components/ui/feedback/confirmation-dialog/index.d.ts +1 -1
- package/dist/lib/components/ui/feedback/confirmation-dialog/partials/confirmation-dialog-form-error.vue.d.ts +3 -0
- package/dist/lib/components/ui/feedback/skeleton/skeleton-text.vue.d.ts +1 -1
- package/dist/lib/components/ui/feedback/spinner/spinner.compound-variants.d.ts +4 -0
- package/dist/lib/components/ui/fields/attributes/form-schema.d.ts +24 -22
- package/dist/lib/components/ui/fields/contacts/consts.d.ts +1 -1
- package/dist/lib/components/ui/fields/inline-edit/index.d.ts +1 -0
- package/dist/lib/components/ui/fields/inline-edit/inline-edit-form-field.vue.d.ts +7 -0
- package/dist/lib/components/ui/fields/number-field/number-field.vue.d.ts +2 -0
- package/dist/lib/components/ui/fields/slider/partials/slider-field-row.vue.d.ts +32 -0
- package/dist/lib/components/ui/fields/slider/slider-field.vue.d.ts +22 -1
- package/dist/lib/components/ui/fields/slider/slider-form-field.vue.d.ts +13 -1
- package/dist/lib/components/ui/forms/form-scope-schema.d.ts +43 -0
- package/dist/lib/components/ui/forms/form-scope.vue.d.ts +33 -0
- package/dist/lib/components/ui/layout/doc/doc.vue.d.ts +5 -5
- package/dist/lib/components/ui/layout/doc/index.d.ts +8 -1
- package/dist/lib/components/ui/layout/doc/partials/default-doc-link.vue.d.ts +14 -0
- package/dist/lib/components/ui/layout/doc/partials/doc-copy-page.vue.d.ts +6 -0
- package/dist/lib/components/ui/layout/doc/partials/doc-link.vue.d.ts +3 -7
- package/dist/lib/components/ui/layout/doc/types.d.ts +6 -1
- package/dist/lib/components/ui/media/file-preview/file-preview-pdf.lazy.d.ts +8 -0
- package/dist/lib/components/ui/media/file-preview/file-preview.vue.d.ts +9 -0
- package/dist/lib/components/ui/media/file-preview/index.d.ts +3 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-body.vue.d.ts +21 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-card.vue.d.ts +15 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-download.vue.d.ts +11 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-media.vue.d.ts +17 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-pdf.vue.d.ts +21 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-status.vue.d.ts +22 -0
- package/dist/lib/components/ui/media/file-preview/partials/file-preview-text.vue.d.ts +16 -0
- package/dist/lib/components/ui/media/file-preview/types.d.ts +19 -0
- package/dist/lib/components/ui/media/file-preview/use-file-preview.d.ts +21 -0
- package/dist/lib/components/ui/media/file-preview/use-text-preview.d.ts +17 -0
- package/dist/lib/components/ui/media/files-form-field/files-form-field.vue.d.ts +29 -0
- package/dist/lib/components/ui/media/files-form-field/index.d.ts +2 -0
- package/dist/lib/components/ui/media/image-cropper/partials/image-cropper-canvas.vue.d.ts +1 -1
- package/dist/lib/components/ui/media/index.d.ts +2 -0
- package/dist/lib/components/ui/media/pdf-viewer/index.d.ts +6 -6
- package/dist/lib/components/ui/media/pdf-viewer/partials/pdf-page.vue.d.ts +1 -1
- package/dist/lib/components/ui/media/pdf-viewer/partials/pdf-reader-body.vue.d.ts +2 -2
- package/dist/lib/components/ui/media/pdf-viewer/pdf-reader.vue.d.ts +2 -2
- package/dist/lib/components/ui/media/upload/network-upload-field/use-image-preview.d.ts +9 -1
- package/dist/lib/components/ui/primitives/icon/icon-context.d.ts +1 -1
- package/dist/lib/components/ui/primitives/tabs/Tabs.vue.d.ts +3 -0
- package/dist/lib/components/ui/primitives/tabs/index.d.ts +1 -0
- package/dist/lib/components/ui/primitives/tabs/tabs-variant.d.ts +9 -0
- package/dist/lib/components/ui/selection/autocomplete/autocomplete-form-field.vue.d.ts +31 -5
- package/dist/lib/components/ui/selection/autocomplete/autocomplete-items.d.ts +23 -0
- package/dist/lib/components/ui/selection/autocomplete/autocomplete.vue.d.ts +48 -13
- package/dist/lib/components/ui/selection/autocomplete/filter-options.d.ts +2 -1
- package/dist/lib/components/ui/selection/autocomplete/partials/autocomplete-box.vue.d.ts +13 -1
- package/dist/lib/components/ui/selection/autocomplete/partials/autocomplete-list.vue.d.ts +17 -3
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-items.d.ts +15 -0
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-open.d.ts +15 -0
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-texts.d.ts +14 -0
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete.d.ts +34 -0
- package/dist/lib/components/ui/selection/checkbox/Checkbox.vue.d.ts +21 -5
- package/dist/lib/components/ui/selection/checkbox/checkbox-form-field.vue.d.ts +17 -0
- package/dist/lib/components/ui/selection/checkbox/index.d.ts +2 -0
- package/dist/lib/components/ui/selection/index.d.ts +1 -0
- package/dist/lib/components/ui/selection/select-field/select-field.vue.d.ts +16 -1
- package/dist/lib/components/ui/selection/select-field/select-form-field.vue.d.ts +16 -2
- package/dist/lib/components/ui/selection/tree-select-field/index.d.ts +3 -0
- package/dist/lib/components/ui/selection/tree-select-field/partials/tree-select-panel.vue.d.ts +27 -0
- package/dist/lib/components/ui/selection/tree-select-field/partials/tree-select-trigger.vue.d.ts +28 -0
- package/dist/lib/components/ui/selection/tree-select-field/tree-select-field.vue.d.ts +8 -0
- package/dist/lib/components/ui/selection/tree-select-field/tree-select-form-field.vue.d.ts +8 -0
- package/dist/lib/components/ui/selection/tree-select-field/tree-select.utils.d.ts +29 -0
- package/dist/lib/components/ui/selection/tree-select-field/types.d.ts +28 -0
- package/dist/lib/components/ui/selection/tree-select-field/use-tree-select-field.d.ts +19 -0
- package/dist/lib/components/ui/widgets/charts/chart-container.vue.d.ts +1 -1
- package/dist/lib/components/ui/widgets/code-editor/code-editor-form-field.vue.d.ts +13 -0
- package/dist/lib/components/ui/widgets/code-editor/code-editor-options.d.ts +4 -1
- package/dist/lib/components/ui/widgets/code-editor/code-editor.vue.d.ts +7 -0
- package/dist/lib/components/ui/widgets/code-editor/index.d.ts +2 -0
- package/dist/lib/components/ui/widgets/code-editor/monaco-editor.vue.d.ts +3 -0
- package/dist/lib/i18n/resources/en/en.d.ts +40 -0
- package/dist/lib/i18n/resources/en/material.json.d.ts +43 -3
- package/dist/lib/i18n/resources/fr/fr.d.ts +40 -0
- package/dist/lib/i18n/resources/fr/material.json.d.ts +43 -3
- package/dist/lib/i18n/resources/resources.d.ts +80 -0
- package/dist/lib/i18n/translator.d.ts +1 -1
- package/dist/lib/nuxt/component-names.d.ts +1 -1
- package/dist/lib.js +2 -2
- package/dist/main.js +17 -17
- package/dist/map.js +4 -4
- package/dist/material-vue.css +1 -1
- package/dist/{pdf-outline-sidebar-oz9wdBhB.js → pdf-outline-sidebar-jJfhNjnN.js} +2 -2
- package/dist/{pdf-page-0rlq1Lo6.js → pdf-page-BW1hXzPu.js} +1 -1
- package/dist/{pdf-page-list-DfhjNHoI.js → pdf-page-list-D277RtWS.js} +2 -2
- package/dist/{pdf-reader-Dr8RVcs4.js → pdf-reader-BReUTsn_.js} +73 -71
- package/dist/{pdf-sidebar-VXPQbC_R.js → pdf-sidebar-Bk6PowY1.js} +3 -3
- package/dist/{pdf-thumbnail-sidebar-BpgXrVBj.js → pdf-thumbnail-sidebar-BcNDFsks.js} +3 -3
- package/dist/{pdf-toolbar-B6gRRcsv.js → pdf-toolbar-CHjaMhH9.js} +4 -4
- package/dist/pdf.js +2 -2
- package/dist/{sortable-provider-oEVjQiCl.js → sortable-provider-C83VBfGl.js} +2 -2
- package/dist/{stored-language-rjOMJkyX.js → stored-language-CC_vdcCN.js} +90 -6
- package/dist/{stx-player-DNADkQ31.js → stx-player-BMQ1D2Li.js} +20 -20
- package/dist/{translator-BCSJSO1-.js → translator-B-X_1taI.js} +1 -1
- package/dist/{use-heading-spy-d50_nxgR.js → use-heading-spy-C_ySuvTl.js} +1 -1
- package/dist/{use-material-translation-C5zPFhbk.js → use-material-translation-B6sIk0mF.js} +3 -3
- package/docs/components/README.md +2 -1
- package/docs/components/buttons-and-actions.md +19 -3
- package/docs/components/data-display.md +65 -11
- package/docs/components/data-table-filter-and-lists.md +94 -8
- package/docs/components/date-and-time.md +116 -9
- package/docs/components/feedback-and-status.md +57 -5
- package/docs/components/form-fields.md +21 -9
- package/docs/components/media-and-files.md +120 -6
- package/docs/components/navigation-and-layout.md +68 -7
- package/docs/components/primitives.md +25 -6
- package/docs/components/rich-widgets.md +21 -3
- package/docs/components/selection-and-choice.md +151 -22
- package/docs/guides/forms.md +16 -8
- package/docs/guides/i18n.md +50 -6
- package/docs/guides/ssr.md +2 -0
- package/docs/previews/buttons-actions-copybutton.webp +0 -0
- package/docs/previews/data-table-filter-lists-pagination.webp +0 -0
- package/docs/previews/date-time-daterangefield.webp +0 -0
- package/docs/previews/form-fields-slider.webp +0 -0
- package/docs/previews/media-files-filepreview.webp +0 -0
- package/docs/previews/navigation-layout-stepper.webp +0 -0
- package/docs/previews/selection-choice-checkbox.webp +0 -0
- package/docs/previews/selection-choice-treeselectfield.webp +0 -0
- package/docs/roadmap.md +47 -1
- package/docs/troubleshooting.md +213 -0
- package/lib/nuxt/component-names.ts +16 -0
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as e } from "./utils-CykWQ0iJ.js";
|
|
2
|
-
import {
|
|
3
|
-
import { t as l } from "./use-material-translation-
|
|
2
|
+
import { $t as t, Jt as n, Qt as r, Yt as i, Zt as a, en as o, jp as s, qt as c } from "./components-DRBKkOqk.js";
|
|
3
|
+
import { t as l } from "./use-material-translation-B6sIk0mF.js";
|
|
4
4
|
import { createBlock as u, createCommentVNode as d, createElementBlock as f, createElementVNode as p, createTextVNode as m, createVNode as h, defineComponent as g, normalizeClass as _, openBlock as v, toDisplayString as y, unref as b, withCtx as x } from "vue";
|
|
5
5
|
//#region lib/components/ui/media/stx-player/partials/stx-player-frame.vue?vue&type=script&setup=true&lang.ts
|
|
6
6
|
var S = ["data-layout", "aria-label"], C = {
|
|
@@ -19,21 +19,21 @@ var S = ["data-layout", "aria-label"], C = {
|
|
|
19
19
|
Array
|
|
20
20
|
] }
|
|
21
21
|
},
|
|
22
|
-
setup(
|
|
23
|
-
let { containerRef: g, state: w } =
|
|
22
|
+
setup(i) {
|
|
23
|
+
let { containerRef: g, state: w } = o();
|
|
24
24
|
function T(e) {
|
|
25
25
|
g.value = e instanceof HTMLElement ? e : null;
|
|
26
26
|
}
|
|
27
27
|
let { t: E } = l();
|
|
28
|
-
return (
|
|
28
|
+
return (o, l) => (v(), f("section", {
|
|
29
29
|
ref: T,
|
|
30
30
|
"data-slot": "stx-player",
|
|
31
|
-
"data-layout":
|
|
31
|
+
"data-layout": i.layout,
|
|
32
32
|
"aria-label": b(w).current?.title ?? b(E)("material.stx-player.label", "Media player"),
|
|
33
|
-
class: _(b(e)("@container rounded outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
34
|
-
}, [
|
|
33
|
+
class: _(b(e)("@container rounded outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50", o.$props.class))
|
|
34
|
+
}, [i.layout === "mini" ? (v(), u(a, { key: 0 })) : (v(), f("div", {
|
|
35
35
|
key: 1,
|
|
36
|
-
class: _(b(e)("grid gap-3",
|
|
36
|
+
class: _(b(e)("grid gap-3", i.showQueue && "@min-[768px]:grid-cols-[minmax(0,1fr)_18rem] @min-[768px]:items-stretch"))
|
|
37
37
|
}, [p("div", { class: _(b(e)("bg-card overflow-hidden rounded border", b(w).current?.kind === "audio" && "flex flex-col gap-4 p-6")) }, [
|
|
38
38
|
b(w).current?.kind === "audio" ? (v(), f("div", C, [h(s, { variant: "title-medium" }, {
|
|
39
39
|
default: x(() => [m(y(b(w).current.title), 1)]),
|
|
@@ -45,24 +45,24 @@ var S = ["data-layout", "aria-label"], C = {
|
|
|
45
45
|
default: x(() => [m(y(b(w).current.artist) + " " + y(b(w).current.album ? ` · ${b(w).current.album}` : ""), 1)]),
|
|
46
46
|
_: 1
|
|
47
47
|
})) : d("", !0)])) : d("", !0),
|
|
48
|
-
h(
|
|
49
|
-
default: x(() => [b(w).current?.kind === "audio" ? d("", !0) : (v(), u(
|
|
48
|
+
h(c, null, {
|
|
49
|
+
default: x(() => [b(w).current?.kind === "audio" ? d("", !0) : (v(), u(t, {
|
|
50
50
|
key: 0,
|
|
51
51
|
tone: "overlay"
|
|
52
52
|
}, {
|
|
53
|
-
trailing: x(() => [h(
|
|
53
|
+
trailing: x(() => [h(r, { tone: "overlay" })]),
|
|
54
54
|
_: 1
|
|
55
55
|
}))]),
|
|
56
56
|
_: 1
|
|
57
57
|
}),
|
|
58
|
-
b(w).current?.kind === "audio" ? (v(), u(
|
|
58
|
+
b(w).current?.kind === "audio" ? (v(), u(t, {
|
|
59
59
|
key: 1,
|
|
60
60
|
tone: "surface"
|
|
61
61
|
}, {
|
|
62
|
-
trailing: x(() => [h(
|
|
62
|
+
trailing: x(() => [h(r, { tone: "surface" })]),
|
|
63
63
|
_: 1
|
|
64
64
|
})) : d("", !0)
|
|
65
|
-
], 2),
|
|
65
|
+
], 2), i.showQueue ? (v(), u(n, {
|
|
66
66
|
key: 0,
|
|
67
67
|
class: "min-h-72"
|
|
68
68
|
})) : d("", !0)], 2))], 10, S));
|
|
@@ -97,12 +97,12 @@ var S = ["data-layout", "aria-label"], C = {
|
|
|
97
97
|
] }
|
|
98
98
|
},
|
|
99
99
|
emits: ["trackChange"],
|
|
100
|
-
setup(e, { emit:
|
|
101
|
-
let
|
|
100
|
+
setup(e, { emit: t }) {
|
|
101
|
+
let n = e, r = t;
|
|
102
102
|
function a(e, t) {
|
|
103
|
-
|
|
103
|
+
n.onTrackChange?.(e, t), r("trackChange", e, t);
|
|
104
104
|
}
|
|
105
|
-
return (
|
|
105
|
+
return (t, r) => (v(), u(i, {
|
|
106
106
|
tracks: e.tracks,
|
|
107
107
|
"current-index": e.currentIndex,
|
|
108
108
|
"default-index": e.defaultIndex,
|
|
@@ -113,7 +113,7 @@ var S = ["data-layout", "aria-label"], C = {
|
|
|
113
113
|
default: x(() => [h(w, {
|
|
114
114
|
layout: e.layout,
|
|
115
115
|
"show-queue": e.showQueue,
|
|
116
|
-
class: _(
|
|
116
|
+
class: _(n.class)
|
|
117
117
|
}, null, 8, [
|
|
118
118
|
"layout",
|
|
119
119
|
"show-queue",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as e, i as t, r as n, t as r } from "./stored-language-
|
|
1
|
+
import { a as e, i as t, r as n, t as r } from "./stored-language-CC_vdcCN.js";
|
|
2
2
|
import { t as i } from "./get-CTzJAwfc.js";
|
|
3
3
|
//#region ../../node_modules/@formatjs/fast-memoize/index.js
|
|
4
4
|
function a(e, t) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as e } from "./i18n-provider-
|
|
1
|
+
import { a as e } from "./i18n-provider-D0oYv0XS.js";
|
|
2
2
|
import { c as t, d as n, f as r, l as i, n as a, u as o } from "./number.utils-Cy1z6qI7.js";
|
|
3
3
|
import { computed as s, getCurrentInstance as c, onMounted as l, ref as u, toValue as d } from "vue";
|
|
4
4
|
import { useIntersectionObserver as f, useMediaQuery as p, useSSRWidth as m, useStorage as h } from "@vueuse/core";
|
|
@@ -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-CC_vdcCN.js";
|
|
2
|
+
import { a as e } from "./i18n-provider-D0oYv0XS.js";
|
|
3
|
+
import { i as t, r as n } from "./translator-B-X_1taI.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]])) {
|
|
@@ -98,10 +98,11 @@ Telling the user what happened: alert, banner, confirm dialogs, empty state, pro
|
|
|
98
98
|
|
|
99
99
|
## [Media & files](media-and-files.md)
|
|
100
100
|
|
|
101
|
-
Uploads, file lists, images and cropping, galleries, carousel, PDF, audio/video player, camera, maps, print documents.
|
|
101
|
+
Uploads, file lists, file previews, images and cropping, galleries, carousel, PDF, audio/video player, camera, maps, print documents. 15 entries.
|
|
102
102
|
|
|
103
103
|
[<img src="../previews/media-files-uploadfield.webp" height="72" alt="UploadField">](media-and-files.md#uploadfield)
|
|
104
104
|
[<img src="../previews/media-files-filelist.webp" height="72" alt="FileList">](media-and-files.md#filelist)
|
|
105
|
+
[<img src="../previews/media-files-filepreview.webp" height="72" alt="FilePreview">](media-and-files.md#filepreview)
|
|
105
106
|
[<img src="../previews/media-files-imagecropper.webp" height="72" alt="ImageCropper">](media-and-files.md#imagecropper)
|
|
106
107
|
[<img src="../previews/media-files-pdfreader.webp" height="72" alt="PdfReader">](media-and-files.md#pdfreader)
|
|
107
108
|
|
|
@@ -319,9 +319,25 @@ import { CopyButton } from '@nxgt/material-vue/components';
|
|
|
319
319
|
| `#icon` slot | — | a copy icon | replaces the idle icon |
|
|
320
320
|
| `variant`, `color` | as `IconButton` | `'ghost'`, `'default'` | the button style |
|
|
321
321
|
|
|
322
|
-
The check mark stays for 1.5 s.
|
|
323
|
-
|
|
324
|
-
|
|
322
|
+
The check mark stays for 1.5 s. `copyToClipboard(text)` is the same copy
|
|
323
|
+
without a button.
|
|
324
|
+
|
|
325
|
+
`CopyValue` shows the value in a monospace chip with the button beside it:
|
|
326
|
+
|
|
327
|
+
```vue
|
|
328
|
+
<script setup lang="ts">
|
|
329
|
+
import { CopyValue } from '@nxgt/material-vue/components';
|
|
330
|
+
</script>
|
|
331
|
+
|
|
332
|
+
<template>
|
|
333
|
+
<CopyValue value="https://app.example.com/orders/SO-1842" display="SO-1842" />
|
|
334
|
+
</template>
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
| `CopyValue` prop | Type | Default | Effect |
|
|
338
|
+
| --- | --- | --- | --- |
|
|
339
|
+
| `value` | `string` | — (required) | what is copied, and shown when there is no `display` |
|
|
340
|
+
| `display` / default slot | `string` | `value` | what is shown instead (React's `display` node) |
|
|
325
341
|
|
|
326
342
|
**Storybook:** `Buttons & actions/CopyButton` · **React:** `CopyButton`, `CopyValue`
|
|
327
343
|
|
|
@@ -35,7 +35,7 @@ from `@nxgt/material-vue/components`.
|
|
|
35
35
|
|
|
36
36
|

|
|
37
37
|
|
|
38
|
-
Round image with a fallback that shows while it loads or when it fails.
|
|
38
|
+
Round image with a fallback that shows while it loads or when it fails, and an optional presence dot.
|
|
39
39
|
|
|
40
40
|
```vue
|
|
41
41
|
<script setup lang="ts">
|
|
@@ -53,10 +53,23 @@ import { Avatar, AvatarFallback, AvatarImage } from '@nxgt/material-vue/componen
|
|
|
53
53
|
Parts: `Avatar` (the round frame), `AvatarImage` (`src`, `alt`),
|
|
54
54
|
`AvatarFallback` (initials or an icon in its slot). Size and shape come from
|
|
55
55
|
`class` (`size-12 rounded-md`). Unlike the React `Avatar`, there is no
|
|
56
|
-
`src` / `fallback`
|
|
57
|
-
[`StatusIndicator`](#statusindicator) beside it for an online dot.
|
|
56
|
+
`src` / `fallback` shorthand: compose the parts.
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
`status` adds a presence dot at the bottom right, named for a screen reader
|
|
59
|
+
(`role="img"`): `success` "Online", `neutral` "Offline", `warning` "Away",
|
|
60
|
+
`error` "Busy", any other tone "Active" (`material.avatar.*`, translated).
|
|
61
|
+
`status-pulse` animates it. Attributes still land on the avatar itself.
|
|
62
|
+
|
|
63
|
+
```vue
|
|
64
|
+
<template>
|
|
65
|
+
<Avatar status="success" class="size-10">
|
|
66
|
+
<AvatarImage src="/people/ada.png" alt="Ada Lovelace" />
|
|
67
|
+
<AvatarFallback>AL</AvatarFallback>
|
|
68
|
+
</Avatar>
|
|
69
|
+
</template>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Storybook:** `Data display/Avatar` (story `Status`) · **React:** `Avatar`, `AvatarImage`, `AvatarFallback`
|
|
60
73
|
|
|
61
74
|
---
|
|
62
75
|
|
|
@@ -463,7 +476,7 @@ import { Icon, ListTile } from '@nxgt/material-vue/components';
|
|
|
463
476
|
|
|
464
477
|

|
|
465
478
|
|
|
466
|
-
Renders `items` (title, content) as a styled accordion.
|
|
479
|
+
Renders `items` (title, content) as a styled accordion, with `#header`, `#title` and `#content` slots.
|
|
467
480
|
|
|
468
481
|
```vue
|
|
469
482
|
<script setup lang="ts">
|
|
@@ -492,11 +505,37 @@ const open = ref('shipping');
|
|
|
492
505
|
| `showIcon` | `boolean` | `true` | decorative chevron on each header, inside the trigger `<button>` |
|
|
493
506
|
| `v-model` | `string \| string[]` | — | open item(s); omit for an uncontrolled accordion |
|
|
494
507
|
|
|
495
|
-
Titles and content are strings;
|
|
496
|
-
|
|
508
|
+
Titles and content are strings; the slots take markup instead (React's
|
|
509
|
+
`title` / `content` nodes and `renderHeader`). Each receives `{ item, index }`:
|
|
510
|
+
|
|
511
|
+
| Slot | Replaces |
|
|
512
|
+
| --- | --- |
|
|
513
|
+
| `#title` | the header's text, beside the chevron |
|
|
514
|
+
| `#content` | the panel's content |
|
|
515
|
+
| `#header` (also `title`) | the whole header: one element, which becomes the trigger — a `<button>`, as React's `renderHeader` returns |
|
|
516
|
+
|
|
517
|
+
```vue
|
|
518
|
+
<script setup lang="ts">
|
|
519
|
+
import { ref } from 'vue';
|
|
520
|
+
import { AccordionCard } from '@nxgt/material-vue/components';
|
|
521
|
+
|
|
522
|
+
const open = ref('shipping');
|
|
523
|
+
const items = [
|
|
524
|
+
{ key: 'shipping', title: 'Shipping', content: 'Ships within two working days.' },
|
|
525
|
+
{ key: 'returns', title: 'Returns', content: 'Free returns for 30 days.' },
|
|
526
|
+
];
|
|
527
|
+
</script>
|
|
528
|
+
|
|
529
|
+
<template>
|
|
530
|
+
<AccordionCard v-model="open" :items="items">
|
|
531
|
+
<template #title="{ item, index }">{{ index + 1 }}. {{ item.title }}</template>
|
|
532
|
+
<template #content="{ item }"><p><strong>{{ item.title }}:</strong> {{ item.content }}</p></template>
|
|
533
|
+
</AccordionCard>
|
|
534
|
+
</template>
|
|
535
|
+
```
|
|
497
536
|
|
|
498
537
|
**Emits:** `update:modelValue` with `string | string[]`.
|
|
499
|
-
**Storybook:** `Data display/AccordionCard` · **React:** `AccordionCard`
|
|
538
|
+
**Storybook:** `Data display/AccordionCard` (story `Slots`) · **React:** `AccordionCard`
|
|
500
539
|
|
|
501
540
|
---
|
|
502
541
|
|
|
@@ -656,7 +695,20 @@ left alone. Mermaid diagrams
|
|
|
656
695
|
render in the browser only, after mount; on the server the fence is left
|
|
657
696
|
empty.
|
|
658
697
|
|
|
659
|
-
|
|
698
|
+
`MermaidDiagram` renders one chart outside markdown, the same way: client-only,
|
|
699
|
+
with `mermaid` imported on mount.
|
|
700
|
+
|
|
701
|
+
```vue
|
|
702
|
+
<script setup lang="ts">
|
|
703
|
+
import { MermaidDiagram } from '@nxgt/material-vue/components';
|
|
704
|
+
</script>
|
|
705
|
+
|
|
706
|
+
<template>
|
|
707
|
+
<MermaidDiagram chart="graph LR Draft --> Review --> Published" />
|
|
708
|
+
</template>
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
**Storybook:** `Data display/Markdown` · **React:** `Markdown`, `MermaidDiagram`
|
|
660
712
|
|
|
661
713
|
---
|
|
662
714
|
|
|
@@ -803,7 +855,9 @@ import { QRCode } from '@nxgt/material-vue/components';
|
|
|
803
855
|
|
|
804
856
|
<template>
|
|
805
857
|
<QRCode value="https://example.com/tickets/DS-184" :size="160" level="H">
|
|
806
|
-
<
|
|
858
|
+
<template #logo>
|
|
859
|
+
<img src="/logo.svg" alt="" width="32" />
|
|
860
|
+
</template>
|
|
807
861
|
</QRCode>
|
|
808
862
|
</template>
|
|
809
863
|
```
|
|
@@ -816,7 +870,7 @@ import { QRCode } from '@nxgt/material-vue/components';
|
|
|
816
870
|
| `fgColor`, `bgColor` | `string` | `'#000000'`, `'#FFFFFF'` | colours |
|
|
817
871
|
| `title` | `string` | — | accessible label of the SVG |
|
|
818
872
|
| `aria-label` | `string` | — | the SVG's name too, and wins over `title` |
|
|
819
|
-
|
|
|
873
|
+
| `#logo` | slot | — | the logo, centred over the code on a white pad (React's `logo`); the default slot still works |
|
|
820
874
|
|
|
821
875
|
The code is an `<svg role="img">` named by `aria-label`, else `title`, else
|
|
822
876
|
"QR code" (`material.qrcode.label`, translated):
|
|
@@ -23,7 +23,7 @@ each other, so either can be used alone.
|
|
|
23
23
|
|
|
24
24
|

|
|
25
25
|
|
|
26
|
-
TanStack Table v9 with sorting, filtering, selection, expandable rows, pagination or load-more, and
|
|
26
|
+
TanStack Table v9 with sorting, filtering, selection, expandable rows, pagination or load-more, column visibility, skeleton rows while loading and your own empty state.
|
|
27
27
|
|
|
28
28
|
```vue
|
|
29
29
|
<script setup lang="ts">
|
|
@@ -59,7 +59,8 @@ const columns = columnHelper.columns([
|
|
|
59
59
|
|
|
60
60
|
Parts: `DataTable`; `DataTableColumnHeader` (a sortable header with a hide
|
|
61
61
|
action); `DataTablePagination` and `DataTableViewOptions` (used by the table,
|
|
62
|
-
exported for a table of your own
|
|
62
|
+
exported for a table of your own; `DataTablePagination` takes `disabled`);
|
|
63
|
+
`useColumnHelpers<T>()` returns a
|
|
63
64
|
`columnHelper` bound to the table's features and `predefinedColumns()` —
|
|
64
65
|
`select` (checkboxes) and `expand` (a toggle for the expanded row, named
|
|
65
66
|
"Toggle row details" (`material.table.labels.toggle-row`) with `aria-expanded`);
|
|
@@ -78,6 +79,58 @@ table enables, for typing your own column defs.
|
|
|
78
79
|
| `onLoadMore` / `isLoadingMore` | `() => void` / `boolean` | — | adds a "load more" button under the rows |
|
|
79
80
|
| `options` | `{ showPage?: boolean; showSelected?: boolean }` | both shown | parts of the footer |
|
|
80
81
|
| `showHeader` | `boolean` | hidden on mobile | header row |
|
|
82
|
+
| `loading` | `boolean` | `false` | skeleton rows, or the current rows dimmed; `aria-busy`; controls disabled |
|
|
83
|
+
| `loadingRows` | `number` | the page size | how many skeleton rows |
|
|
84
|
+
| `#empty="{ filtered }"` | slot | icon and "No data available" | content of the empty row, spanning every visible column |
|
|
85
|
+
|
|
86
|
+
### Loading and empty states
|
|
87
|
+
|
|
88
|
+
```vue
|
|
89
|
+
<script setup lang="ts">
|
|
90
|
+
import { DataTable, useColumnHelpers } from '@nxgt/material-vue/components';
|
|
91
|
+
|
|
92
|
+
type Person = { id: string; name: string; email: string };
|
|
93
|
+
|
|
94
|
+
defineProps<{ people: Person[]; isFetching: boolean }>();
|
|
95
|
+
|
|
96
|
+
const { columnHelper } = useColumnHelpers<Person>();
|
|
97
|
+
const columns = columnHelper.columns([
|
|
98
|
+
columnHelper.accessor('name', { header: 'Name' }),
|
|
99
|
+
columnHelper.accessor('email', { header: 'Email' }),
|
|
100
|
+
]);
|
|
101
|
+
</script>
|
|
102
|
+
|
|
103
|
+
<template>
|
|
104
|
+
<DataTable
|
|
105
|
+
:data="people"
|
|
106
|
+
:columns="columns"
|
|
107
|
+
:loading="isFetching"
|
|
108
|
+
:loading-rows="5"
|
|
109
|
+
>
|
|
110
|
+
<template #empty="{ filtered }">
|
|
111
|
+
{{ filtered ? 'No person matches these filters.' : 'No people yet.' }}
|
|
112
|
+
</template>
|
|
113
|
+
</DataTable>
|
|
114
|
+
</template>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
While `loading` is `true`, the table is `aria-busy` and a visually
|
|
118
|
+
hidden status says "Loading data…" (`material.table.loading`). With no row to
|
|
119
|
+
show, the body is `loadingRows` skeleton rows (default: the page size), one
|
|
120
|
+
cell per visible column. With rows already shown — a refresh — the rows stay
|
|
121
|
+
where they are, dimmed and `inert`, rather than being swapped for
|
|
122
|
+
skeletons: the table keeps its height, so nothing below it jumps when the data
|
|
123
|
+
arrives. Sorting (`DataTableColumnHeader`), the `select` column's "Select
|
|
124
|
+
all", the toolbar's native controls (it
|
|
125
|
+
is a disabled `<fieldset>`, so every input or button you render there, a
|
|
126
|
+
filter or an export, is disabled
|
|
127
|
+
too) and pagination are disabled meanwhile.
|
|
128
|
+
|
|
129
|
+
When no row is left after filtering, the empty state is one `TableEmpty`
|
|
130
|
+
cell spanning every visible column: today's icon and "No data available" by
|
|
131
|
+
default, or the `#empty` slot, told whether rows exist but none matches the
|
|
132
|
+
filters (`filtered`); content that renders nothing gets the default.
|
|
133
|
+
`DataTableEmptyState` types the slot props.
|
|
81
134
|
|
|
82
135
|
For the TanStack API itself (column helpers, features, row models), see
|
|
83
136
|
[TanStack Table v9](https://tanstack.com/table/latest).
|
|
@@ -132,7 +185,10 @@ A field's `type` is one of `text`, `number`, `select`, `multi-select`, `date`,
|
|
|
132
185
|
`chips-multiple`, `chips-single`, `slider`, `slider-range`, `switch` or
|
|
133
186
|
`custom` (`render` returns a VNode); `schema.groups` puts fields in
|
|
134
187
|
collapsible sections. The filter state lives in a Pinia store, so the app
|
|
135
|
-
needs `app.use(createPinia())`.
|
|
188
|
+
needs `app.use(createPinia())`. A `number-range` or `slider-range` is a
|
|
189
|
+
`role="group"` named by its `label`, with its inputs named by their part
|
|
190
|
+
("Min" / "Max", or the slider's "<label> Minimum" / "<label> Maximum"):
|
|
191
|
+
`getByRole('group', { name: 'Price' })`.
|
|
136
192
|
|
|
137
193
|
Parts: `Filter` (one component, `variant` picks the layout);
|
|
138
194
|
`FilterProvider` + `FilterContent` + `FilterActions` to lay the panel out
|
|
@@ -203,7 +259,34 @@ above shows `FilterPopover` open; every variant has its own story.
|
|
|
203
259
|
|
|
204
260
|

|
|
205
261
|
|
|
206
|
-
Pagination primitives on Reka UI's `Pagination`, with first / last buttons and ellipses.
|
|
262
|
+
Pagination primitives on Reka UI's `Pagination`, with first / last buttons and ellipses. `PaginationBar` adds a sibling window with ellipses.
|
|
263
|
+
|
|
264
|
+
```vue
|
|
265
|
+
<script setup lang="ts">
|
|
266
|
+
import { ref } from 'vue';
|
|
267
|
+
import { PaginationBar } from '@nxgt/material-vue/components';
|
|
268
|
+
|
|
269
|
+
const page = ref(1);
|
|
270
|
+
</script>
|
|
271
|
+
|
|
272
|
+
<template>
|
|
273
|
+
<PaginationBar v-model:page="page" :page-count="12" />
|
|
274
|
+
</template>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
| `PaginationBar` prop / event | Type | Default | Effect |
|
|
278
|
+
| --- | --- | --- | --- |
|
|
279
|
+
| `page` / `v-model:page` | `number` | — (required) | current page, from 1; controlled |
|
|
280
|
+
| `page-count` | `number` | — (required) | number of pages |
|
|
281
|
+
| `sibling-count` | `number` | `1` | pages on each side of the current one before an ellipsis |
|
|
282
|
+
| `disabled` | `boolean` | `false` | disables every button |
|
|
283
|
+
| `@update:page`, `@page-change` | `(page: number) => void` | — | a page was chosen (React's `onPageChange`) |
|
|
284
|
+
|
|
285
|
+
`paginationItems(page, pageCount, siblingCount?)` is the window it renders, as
|
|
286
|
+
`(number | 'ellipsis')[]` (`PaginationItemToken`). `PaginationLink` is a page
|
|
287
|
+
as an anchor (`href`, `is-active`), for server-rendered lists.
|
|
288
|
+
|
|
289
|
+
The parts, composed by hand:
|
|
207
290
|
|
|
208
291
|
```vue
|
|
209
292
|
<script setup lang="ts">
|
|
@@ -243,9 +326,8 @@ const page = ref(1);
|
|
|
243
326
|
Parts: `Pagination` (the root), `PaginationContent` (its slot gives the
|
|
244
327
|
`items` window), `PaginationItem` (`value`, `is-active`),
|
|
245
328
|
`PaginationPrevious`, `PaginationNext`, `PaginationFirst`, `PaginationLast`,
|
|
246
|
-
`PaginationEllipsis`.
|
|
247
|
-
|
|
248
|
-
already wired.
|
|
329
|
+
`PaginationEllipsis`. Composed by hand, the root computes the window itself.
|
|
330
|
+
For a table, `DataTablePagination` is already wired.
|
|
249
331
|
|
|
250
332
|
| Prop | Type | Default | Effect |
|
|
251
333
|
| --- | --- | --- | --- |
|
|
@@ -258,7 +340,7 @@ already wired.
|
|
|
258
340
|
| `aria-label` | `string` | `'pagination'` (translated) | the `nav`'s name; the buttons are named "First", "Previous", "Next", "Last" and "Page {n}" (`material.pagination.*`). An `aria-label` on a part wins |
|
|
259
341
|
|
|
260
342
|
**Emits:** `update:page` with `number`.
|
|
261
|
-
**Storybook:** `Data table, filter & lists/Pagination` · **React:** `Pagination` (parts), `PaginationBar`
|
|
343
|
+
**Storybook:** `Data table, filter & lists/Pagination` · **React:** `Pagination` (parts), `PaginationFirst`, `PaginationLast`, `PaginationLink`, `PaginationBar`, `paginationItems`
|
|
262
344
|
|
|
263
345
|
---
|
|
264
346
|
|
|
@@ -310,6 +392,10 @@ own) and `TreeItem` (one row); `findTreeNode` and `flattenVisibleTree`.
|
|
|
310
392
|
Arrow keys move and expand / collapse, Home / End jump, Enter and Space
|
|
311
393
|
select.
|
|
312
394
|
|
|
395
|
+
Tab lands on the focused row, or on the first visible row when that one is
|
|
396
|
+
filtered or folded away. `useTree` returns that row as `tabbableId`: give it
|
|
397
|
+
`tabindex="0"` in a tree you build yourself.
|
|
398
|
+
|
|
313
399
|
**Emits:** `update:selectedIds` and `update:expandedIds` with `string[]`, `select`.
|
|
314
400
|
**Storybook:** `Data table, filter & lists/Tree` · **React:** `Tree`, `TreeItem`, `useTree`
|
|
315
401
|
|
|
@@ -70,7 +70,7 @@ No form wrapper — use `DateFormField`.
|
|
|
70
70
|
|
|
71
71
|

|
|
72
72
|
|
|
73
|
-
Labelled trigger that opens a calendar popover, with an optional time picker
|
|
73
|
+
Labelled trigger that opens a calendar popover, with an optional time picker and `disabled-days`.
|
|
74
74
|
|
|
75
75
|
```vue
|
|
76
76
|
<script setup lang="ts">
|
|
@@ -81,7 +81,12 @@ const delivery = ref<Date | undefined>();
|
|
|
81
81
|
</script>
|
|
82
82
|
|
|
83
83
|
<template>
|
|
84
|
-
<DateField
|
|
84
|
+
<DateField
|
|
85
|
+
v-model="delivery"
|
|
86
|
+
label="Delivery date"
|
|
87
|
+
placeholder="Pick a day"
|
|
88
|
+
:disabled-days="[{ dayOfWeek: [0] }, { before: new Date() }]"
|
|
89
|
+
/>
|
|
85
90
|
</template>
|
|
86
91
|
```
|
|
87
92
|
|
|
@@ -89,10 +94,12 @@ const delivery = ref<Date | undefined>();
|
|
|
89
94
|
| --- | --- | --- | --- |
|
|
90
95
|
| `v-model` | `Date \| undefined` | — | the selected day, shown in the short `P` format |
|
|
91
96
|
| `show-time-picker` | `boolean` | — | adds a `TimePicker` and an OK button; the popover stays open |
|
|
97
|
+
| `disabled-days` | `DisabledDays` | — | days that cannot be picked: a `Date`, a `Date[]`, `{ from, to }` (ends included), `{ before }`, `{ after }`, `{ before, after }`, `{ dayOfWeek }` (`0` is Sunday), a `(date) => boolean`, or a list of those (any that matches) — React's `disabledDays` |
|
|
92
98
|
| `placeholder`, `label`, `helper-text`, `error`, `required`, `disabled` | | — | `placeholder` is the trigger's text; `label` and `helper-text` sit beside it; `error`, `required` and `disabled` its state |
|
|
93
99
|
|
|
94
|
-
Unlike React, the calendar's
|
|
95
|
-
through
|
|
100
|
+
Unlike React, the calendar's other props (bounds, the first month) are not
|
|
101
|
+
passed through: use `disabled-days` for both bounds and days. A disabled day
|
|
102
|
+
is greyed out and cannot be picked. The popover closes on the first pick unless `show-time-picker` is
|
|
96
103
|
set, and picking a day keeps the time of the current value.
|
|
97
104
|
|
|
98
105
|
Attributes you put on the field (`id`, `aria-describedby`, `data-*`,
|
|
@@ -113,7 +120,7 @@ before your `aria-describedby` ids.
|
|
|
113
120
|
**Emits:** `update:modelValue` with `Date | undefined`.
|
|
114
121
|
**Form wrapper:** `DateFormField` — `name` inside a vee-validate form, see
|
|
115
122
|
[forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
|
|
116
|
-
**Storybook:** `Date & time/DateField` · **React:** `DateField`, `DateFormField`
|
|
123
|
+
**Storybook:** `Date & time/DateField` (story `DisabledDays`) · **React:** `DateField`, `DateFormField`
|
|
117
124
|
|
|
118
125
|
---
|
|
119
126
|
|
|
@@ -121,7 +128,7 @@ before your `aria-describedby` ids.
|
|
|
121
128
|
|
|
122
129
|

|
|
123
130
|
|
|
124
|
-
From / to range picked in a popover calendar.
|
|
131
|
+
From / to range picked in a popover calendar, with `disabled-days`, presets and times.
|
|
125
132
|
|
|
126
133
|
```vue
|
|
127
134
|
<script setup lang="ts">
|
|
@@ -132,17 +139,26 @@ const stay = ref<DateRange | undefined>();
|
|
|
132
139
|
</script>
|
|
133
140
|
|
|
134
141
|
<template>
|
|
135
|
-
<DateRangeField
|
|
142
|
+
<DateRangeField
|
|
143
|
+
v-model="stay"
|
|
144
|
+
label="Stay"
|
|
145
|
+
placeholder="Check-in – check-out"
|
|
146
|
+
:disabled-days="{ dayOfWeek: [0] }"
|
|
147
|
+
/>
|
|
136
148
|
</template>
|
|
137
149
|
```
|
|
138
150
|
|
|
139
151
|
| Prop | Type | Default | Effect |
|
|
140
152
|
| --- | --- | --- | --- |
|
|
141
153
|
| `v-model` | `DateRange \| undefined` | — | `{ from?: Date; to?: Date }` |
|
|
154
|
+
| `disabled-days` | `DisabledDays` | — | days that cannot be picked: a `Date`, a `Date[]`, `{ from, to }` (ends included), `{ before }`, `{ after }`, `{ before, after }`, `{ dayOfWeek }` (`0` is Sunday), a `(date) => boolean`, or a list of those (any that matches) — as on `DateField` |
|
|
142
155
|
| `placeholder`, `label`, `helper-text`, `error`, `required`, `disabled` | | — | `placeholder` is the trigger's text; `label` and `helper-text` sit beside it; `error`, `required` and `disabled` its state |
|
|
156
|
+
| `presets` | `readonly DateRangePresetOption[]` | — (no list) | one-click ranges beside the calendar: built-in ids (`DATE_RANGE_PRESET_IDS`) and `{ label, range }` of your own |
|
|
157
|
+
| `with-time` | `boolean` | `false` | a time of day on each end, under the calendar, and on the trigger; the popover stays open until OK |
|
|
158
|
+
| `min-date`, `max-date` | `Date` | — | the first and last day that can be picked (Reka's `minValue` / `maxValue`) |
|
|
143
159
|
|
|
144
160
|
It emits on each click (`to` is unset after the first) and closes the popover
|
|
145
|
-
once both ends are picked.
|
|
161
|
+
once both ends are picked (with `with-time`, OK closes it).
|
|
146
162
|
|
|
147
163
|
Attributes you put on the field (`id`, `aria-describedby`, `data-*`,
|
|
148
164
|
listeners) go on the trigger, the element that has focus, not on the field's
|
|
@@ -159,11 +175,97 @@ the helper text sit beside the trigger in the field's root `div`
|
|
|
159
175
|
(`data-slot="date-range-field"`), not in it; the helper text describes the trigger
|
|
160
176
|
before your `aria-describedby` ids.
|
|
161
177
|
|
|
178
|
+
### Presets
|
|
179
|
+
|
|
180
|
+
`presets` lists one-click ranges beside the calendar (above it on a narrow
|
|
181
|
+
screen), in the order you give them. A built-in id is translated
|
|
182
|
+
(`material.date-range-field.preset.<id>`); a preset of your own is
|
|
183
|
+
`{ label, range }`, where `range` is `{ from, to }` or `(now) => ({ from, to })`.
|
|
184
|
+
|
|
185
|
+
```vue
|
|
186
|
+
<script setup lang="ts">
|
|
187
|
+
import { ref } from 'vue';
|
|
188
|
+
import {
|
|
189
|
+
type DateRange,
|
|
190
|
+
DateRangeField,
|
|
191
|
+
type DateRangePreset,
|
|
192
|
+
} from '@nxgt/material-vue/components';
|
|
193
|
+
|
|
194
|
+
const lastQuarter: DateRangePreset = {
|
|
195
|
+
label: 'Last quarter',
|
|
196
|
+
range: (now) => {
|
|
197
|
+
const start = new Date(now.getFullYear(), Math.floor(now.getMonth() / 3) * 3 - 3, 1);
|
|
198
|
+
return { from: start, to: new Date(start.getFullYear(), start.getMonth() + 3, 0) };
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
const period = ref<DateRange | undefined>();
|
|
202
|
+
const today = new Date();
|
|
203
|
+
</script>
|
|
204
|
+
|
|
205
|
+
<template>
|
|
206
|
+
<DateRangeField
|
|
207
|
+
v-model="period"
|
|
208
|
+
label="Period"
|
|
209
|
+
:max-date="today"
|
|
210
|
+
:presets="['today', 'last-7-days', 'this-month', 'last-month', lastQuarter]"
|
|
211
|
+
/>
|
|
212
|
+
</template>
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
| Built-in id | Range |
|
|
216
|
+
| --- | --- |
|
|
217
|
+
| `today`, `yesterday` | that day |
|
|
218
|
+
| `last-7-days`, `last-30-days` | ends today and counts it |
|
|
219
|
+
| `this-month`, `this-year` | from the first day to today |
|
|
220
|
+
| `last-month` | the whole previous month |
|
|
221
|
+
|
|
222
|
+
A built-in range starts at 00:00 (and with `with-time` ends at 23:59); your
|
|
223
|
+
own ranges keep the times you gave them. Picking a preset sets the value and
|
|
224
|
+
closes the popover (with `with-time` it stays open); open again, the calendar
|
|
225
|
+
is on that range's month. The list is a group named "Presets"
|
|
226
|
+
(`material.date-range-field.presets`) of buttons in the tab order, and the
|
|
227
|
+
one whose days are the value's has `aria-pressed="true"`. A preset is
|
|
228
|
+
disabled when its range starts before `min-date`, ends after `max-date`, or
|
|
229
|
+
either end is one of `disabled-days`; the days between are not checked, as the
|
|
230
|
+
calendar lets a range span a disabled day.
|
|
231
|
+
The built-in presets use the current date when the popover opens; there is
|
|
232
|
+
no `now` prop, and none is planned. A preset of your own whose end comes
|
|
233
|
+
before its start is disabled.
|
|
234
|
+
|
|
235
|
+
### Times
|
|
236
|
+
|
|
237
|
+
`with-time` adds two `TimePicker`s under the calendar, in groups named
|
|
238
|
+
"Start time" and "End time" (`material.date-range-field.start-time`,
|
|
239
|
+
`.end-time`), each disabled until its end has a day, and an OK button
|
|
240
|
+
(`material.buttons.ok`) that closes the popover. The trigger shows each end
|
|
241
|
+
with its time (date-fns `Pp`).
|
|
242
|
+
|
|
243
|
+
```vue
|
|
244
|
+
<script setup lang="ts">
|
|
245
|
+
import { ref } from 'vue';
|
|
246
|
+
import { type DateRange, DateRangeField } from '@nxgt/material-vue/components';
|
|
247
|
+
|
|
248
|
+
const slot = ref<DateRange | undefined>();
|
|
249
|
+
</script>
|
|
250
|
+
|
|
251
|
+
<template>
|
|
252
|
+
<DateRangeField v-model="slot" label="Booking" with-time :presets="['today']" />
|
|
253
|
+
</template>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
A day picked on the calendar keeps the time that end had; a new start is
|
|
257
|
+
00:00 and a new end 23:59, as a built-in preset ends, so a filter on
|
|
258
|
+
`<= to` keeps the last day. On the same day, an end time set before the
|
|
259
|
+
start time becomes the start time.
|
|
260
|
+
|
|
261
|
+
Without `with-time`, a picked day carries the current time of day.
|
|
262
|
+
(`@nxgt/material` gives it 00:00.)
|
|
263
|
+
|
|
162
264
|
**Emits:** `update:modelValue` with `DateRange | undefined` — `{ from, to }`,
|
|
163
265
|
where `to` stays `undefined` until the second day is picked.
|
|
164
266
|
**Form wrapper:** `DateRangeFormField` — `name` inside a vee-validate form, see
|
|
165
267
|
[forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
|
|
166
|
-
**Storybook:** `Date & time/DateRangeField` · **React:** `DateRangeField`, `DateRangeFormField`
|
|
268
|
+
**Storybook:** `Date & time/DateRangeField` (stories `DisabledDays`, `MinMaxDates`, `Presets`, `DisabledPresets`, `WithTime`) · **React:** `DateRangeField`, `DateRangeFormField` (`withTime`, `minDate` / `maxDate`; without time, a picked day is at 00:00 there, the current time of day here)
|
|
167
269
|
|
|
168
270
|
---
|
|
169
271
|
|
|
@@ -245,6 +347,11 @@ const time = ref<Date | undefined>(new Date());
|
|
|
245
347
|
| `label` | `string` | — | header text |
|
|
246
348
|
| `#footer` | slot | — | under the inputs (the OK button in `TimeField`) |
|
|
247
349
|
|
|
350
|
+
The hours and minutes inputs are named "Hours" and "Minutes"
|
|
351
|
+
(`material.time-picker.hours`, `.minutes`). AM / PM shows the half of the day
|
|
352
|
+
`date` is in, so a date changed from outside shows its own; switching it moves
|
|
353
|
+
the time 12 hours, and a click on the pressed half changes nothing.
|
|
354
|
+
|
|
248
355
|
**Emits:** `change` with `Date | undefined` (no `v-model`). No form wrapper —
|
|
249
356
|
use `TimeFormField`.
|
|
250
357
|
**Storybook:** `Date & time/TimePicker` · **React:** `TimePicker`
|