@nxgt/material-vue 0.37.1 → 0.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/README.md +1 -0
  3. package/dist/{Button-CurFF4Zt.js → Button-DVeAQorb.js} +1 -1
  4. package/dist/{DropdownMenuTrigger-BsuyNVzV.js → DropdownMenuTrigger-C7uYPf_9.js} +36 -36
  5. package/dist/{HoverCardTrigger-jCXl6TrX.js → HoverCardTrigger-VvXPswRz.js} +122 -120
  6. package/dist/{camera-CYwiFuGE.js → camera-CG6WfZNc.js} +4 -4
  7. package/dist/components/base-content.css +64 -4
  8. package/dist/components/base.css +3 -1
  9. package/dist/{components--v_k8diD.js → components-B2kSyBK0.js} +13277 -12751
  10. package/dist/components.js +8 -8
  11. package/dist/composables.js +2 -2
  12. package/dist/dnd.js +1 -1
  13. package/dist/{form-scope-B2oJ5fHr.js → form-scope-XhlaF5na.js} +1 -1
  14. package/dist/{i18n-provider-B2q6vp6H.js → i18n-provider-BBnUUGqM.js} +1 -1
  15. package/dist/i18n.js +4 -4
  16. package/dist/{icon-button-CIUc1bEp.js → icon-button-CSPfP615.js} +1 -1
  17. package/dist/in-dialog-Blhwwbyb.js +31 -0
  18. package/dist/lib/components/ui/collections/data-table/data-table-density.d.ts +15 -0
  19. package/dist/lib/components/ui/collections/data-table/data-table.stories.columns.d.ts +47 -0
  20. package/dist/lib/components/ui/collections/data-table/data-table.stories.template.d.ts +1 -0
  21. package/dist/lib/components/ui/collections/data-table/index.d.ts +1 -1
  22. package/dist/lib/components/ui/collections/data-table/types.d.ts +7 -0
  23. package/dist/lib/components/ui/feedback/banner/banner.vue.d.ts +1 -1
  24. package/dist/lib/components/ui/fields/contacts/consts.d.ts +1 -1
  25. package/dist/lib/components/ui/fields/index.d.ts +1 -0
  26. package/dist/lib/components/ui/fields/repeatable-group/index.d.ts +4 -0
  27. package/dist/lib/components/ui/fields/repeatable-group/partials/repeatable-group-footer.vue.d.ts +14 -0
  28. package/dist/lib/components/ui/fields/repeatable-group/partials/repeatable-group-row.vue.d.ts +33 -0
  29. package/dist/lib/components/ui/fields/repeatable-group/repeatable-group-classes.d.ts +33 -0
  30. package/dist/lib/components/ui/fields/repeatable-group/repeatable-group-form-field.vue.d.ts +44 -0
  31. package/dist/lib/components/ui/fields/repeatable-group/repeatable-group-names.d.ts +16 -0
  32. package/dist/lib/components/ui/fields/repeatable-group/repeatable-group.vue.d.ts +69 -0
  33. package/dist/lib/components/ui/fields/repeatable-group/use-repeatable-group.d.ts +39 -0
  34. package/dist/lib/components/ui/fields/search-field/search-field.vue.d.ts +10 -1
  35. package/dist/lib/components/ui/media/stx-player/stx-player-extras.vue.d.ts +1 -1
  36. package/dist/lib/components/ui/overlays/command/CommandItem.vue.d.ts +10 -3
  37. package/dist/lib/components/ui/overlays/command/CommandList.vue.d.ts +4 -2
  38. package/dist/lib/components/ui/overlays/dialog/in-dialog.d.ts +12 -0
  39. package/dist/lib/components/ui/primitives/typography/typography.variants.d.ts +1 -0
  40. package/dist/lib/components/ui/primitives/typography/typography.vue.d.ts +2 -0
  41. package/dist/lib/components/ui/selection/checkbox-group/checkbox-group.vue.d.ts +2 -0
  42. package/dist/lib/components/ui/selection/option-count/option-count.vue.d.ts +25 -0
  43. package/dist/lib/components/ui/selection/option-count/use-option-count-text.d.ts +10 -0
  44. package/dist/lib/components/ui/selection/radio-group/radio-group-field.vue.d.ts +2 -0
  45. package/dist/lib/components/ui/selection/select-chip-field/select-chip-field.vue.d.ts +11 -0
  46. package/dist/lib/components/ui/selection/sortable-list/sortable-list.vue.d.ts +1 -1
  47. package/dist/lib/components/ui/selection/transfer-list/transfer-list.vue.d.ts +1 -1
  48. package/dist/lib/i18n/resources/en/en.d.ts +15 -0
  49. package/dist/lib/i18n/resources/en/material.json.d.ts +15 -0
  50. package/dist/lib/i18n/resources/fr/fr.d.ts +15 -0
  51. package/dist/lib/i18n/resources/fr/material.json.d.ts +15 -0
  52. package/dist/lib/i18n/resources/resources.d.ts +30 -0
  53. package/dist/lib/i18n/translator.d.ts +1 -1
  54. package/dist/lib/nuxt/component-names.d.ts +1 -1
  55. package/dist/lib.js +1 -1
  56. package/dist/main.js +17 -17
  57. package/dist/map.js +4 -4
  58. package/dist/material-vue.css +1 -1
  59. package/dist/{pdf-outline-sidebar-DJJ-ARco.js → pdf-outline-sidebar-aQ5Lhbss.js} +2 -2
  60. package/dist/{pdf-page-CRt6KXdJ.js → pdf-page-NCmScgMW.js} +1 -1
  61. package/dist/{pdf-page-list-BgCp5Asx.js → pdf-page-list-BnvE130d.js} +2 -2
  62. package/dist/{pdf-reader-BGxqEx8O.js → pdf-reader-CMt9dKZ-.js} +8 -8
  63. package/dist/{pdf-sidebar-Cvtuomgp.js → pdf-sidebar-BWzX3e0f.js} +3 -3
  64. package/dist/{pdf-thumbnail-sidebar-CeWPs7o7.js → pdf-thumbnail-sidebar-8nbYsI3d.js} +3 -3
  65. package/dist/{pdf-toolbar-BtXcyEpd.js → pdf-toolbar-DpQMG5rv.js} +5 -5
  66. package/dist/pdf.js +2 -2
  67. package/dist/{print-format.utils-keJqahvw.js → print-format.utils-oj5kle2P.js} +2 -2
  68. package/dist/{sortable-provider-DMu8DL2z.js → sortable-provider-2czx1jSW.js} +2 -2
  69. package/dist/{stored-language-dtksFoGO.js → stored-language-CKZMMJcz.js} +26 -0
  70. package/dist/{stx-player-nDsDyvc-.js → stx-player-CS1FYHVS.js} +5 -5
  71. package/dist/{translator-DqiGrSH_.js → translator-uh5FWiMq.js} +1 -1
  72. package/dist/{use-heading-spy-BZ7ctGZ5.js → use-heading-spy-CcJfoBA1.js} +1 -1
  73. package/dist/{use-material-translation-DRB6oPdF.js → use-material-translation-C6xccbic.js} +3 -3
  74. package/docs/components/README.md +1 -1
  75. package/docs/components/data-table-filter-and-lists.md +3 -1
  76. package/docs/components/form-fields.md +146 -0
  77. package/docs/components/overlays-and-menus.md +2 -0
  78. package/docs/components/primitives.md +3 -1
  79. package/docs/components/selection-and-choice.md +28 -4
  80. package/docs/guides/forms.md +89 -4
  81. package/docs/guides/i18n.md +2 -1
  82. package/docs/previews/form-fields-repeatablegroup.webp +0 -0
  83. package/docs/roadmap.md +7 -0
  84. package/docs/troubleshooting.md +70 -0
  85. package/lib/components/base-content.css +64 -4
  86. package/lib/components/base.css +3 -1
  87. package/lib/nuxt/component-names.ts +2 -0
  88. package/package.json +2 -2
  89. package/dist/use-inert-others-CtGqZKR8.js +0 -22
@@ -1,7 +1,7 @@
1
1
  import { n as e } from "./rolldown-runtime-CWhphoD1.js";
2
2
  import { t } from "./utils-CykWQ0iJ.js";
3
- import { Bf as n } from "./components--v_k8diD.js";
4
- import { t as r } from "./use-material-translation-DRB6oPdF.js";
3
+ import { Hf as n } from "./components-B2kSyBK0.js";
4
+ import { t as r } from "./use-material-translation-C6xccbic.js";
5
5
  import { Fragment as i, computed as a, createBlock as o, createCommentVNode as s, createElementBlock as c, createElementVNode as l, defineComponent as u, normalizeClass as d, normalizeStyle as f, openBlock as p, ref as m, renderList as h, toDisplayString as g, unref as _, withCtx as v } from "vue";
6
6
  //#region lib/components/ui/media/pdf-viewer/partials/pdf-outline-row.vue?vue&type=script&setup=true&lang.ts
7
7
  var y = {
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./utils-CykWQ0iJ.js";
2
- import { Up as t } from "./components--v_k8diD.js";
2
+ import { Gp as t } from "./components-B2kSyBK0.js";
3
3
  import { computed as n, createBlock as r, createCommentVNode as i, createElementBlock as a, createElementVNode as o, defineComponent as s, nextTick as c, normalizeClass as l, normalizeStyle as u, onBeforeUnmount as d, openBlock as f, ref as p, shallowRef as m, unref as h, watch as g } from "vue";
4
4
  import { DEFAULT_PAGE_SIZE as _, escapeHtml as v, findTextMatches as y, highlightItemHtml as b, placeholderSize as x, rotatedSize as S } from "@nxgt/material-core/pdf-viewer";
5
5
  //#region lib/components/ui/media/pdf-viewer/pdf-note-icons.ts
@@ -1,6 +1,6 @@
1
1
  import { n as e } from "./rolldown-runtime-CWhphoD1.js";
2
- import { Bf as t } from "./components--v_k8diD.js";
3
- import { t as n } from "./pdf-page-CRt6KXdJ.js";
2
+ import { Hf as t } from "./components-B2kSyBK0.js";
3
+ import { t as n } from "./pdf-page-NCmScgMW.js";
4
4
  import { Fragment as r, createBlock as i, createElementBlock as a, createElementVNode as o, defineComponent as s, openBlock as c, renderList as l, withCtx as u } from "vue";
5
5
  //#region lib/components/ui/media/pdf-viewer/partials/pdf-page-list.vue?vue&type=script&setup=true&lang.ts
6
6
  var d = { class: "flex flex-col items-center gap-4 px-4 py-4" }, f = /*@__PURE__*/ s({
@@ -1,12 +1,12 @@
1
1
  import { t as e } from "./utils-CykWQ0iJ.js";
2
- import { kn as t } from "./components--v_k8diD.js";
3
- import { t as n } from "./use-material-translation-DRB6oPdF.js";
4
- import { t as r } from "./Button-CurFF4Zt.js";
5
- import { o as i } from "./HoverCardTrigger-jCXl6TrX.js";
6
- import { n as a } from "./pdf-page-CRt6KXdJ.js";
7
- import { t as o } from "./pdf-page-list-BgCp5Asx.js";
8
- import { t as s } from "./pdf-sidebar-Cvtuomgp.js";
9
- import { t as c } from "./pdf-toolbar-BtXcyEpd.js";
2
+ import { kn as t } from "./components-B2kSyBK0.js";
3
+ import { t as n } from "./use-material-translation-C6xccbic.js";
4
+ import { t as r } from "./Button-DVeAQorb.js";
5
+ import { o as i } from "./HoverCardTrigger-VvXPswRz.js";
6
+ import { n as a } from "./pdf-page-NCmScgMW.js";
7
+ import { t as o } from "./pdf-page-list-BnvE130d.js";
8
+ import { t as s } from "./pdf-sidebar-BWzX3e0f.js";
9
+ import { t as c } from "./pdf-toolbar-DpQMG5rv.js";
10
10
  import { computed as l, createBlock as u, createCommentVNode as d, createElementBlock as f, createElementVNode as p, createTextVNode as m, createVNode as h, defineComponent as g, nextTick as _, normalizeClass as v, onBeforeUnmount as y, onMounted as b, openBlock as x, reactive as S, ref as C, shallowRef as w, toDisplayString as T, toRef as E, unref as D, useId as O, watch as k, withCtx as A } from "vue";
11
11
  import { AlertCircle as j, FileX2 as M, KeyRound as N, Loader2 as P } from "@lucide/vue";
12
12
  import { pdfSourceKey as F, toPdfjsParams as I } from "@nxgt/material-core/pdf-source";
@@ -1,8 +1,8 @@
1
1
  import { n as e } from "./rolldown-runtime-CWhphoD1.js";
2
2
  import { t } from "./utils-CykWQ0iJ.js";
3
- import { t as n } from "./use-material-translation-DRB6oPdF.js";
4
- import { t as r } from "./pdf-outline-sidebar-DJJ-ARco.js";
5
- import { t as i } from "./pdf-thumbnail-sidebar-CeWPs7o7.js";
3
+ import { t as n } from "./use-material-translation-C6xccbic.js";
4
+ import { t as r } from "./pdf-outline-sidebar-aQ5Lhbss.js";
5
+ import { t as i } from "./pdf-thumbnail-sidebar-8nbYsI3d.js";
6
6
  import { createElementBlock as a, createElementVNode as o, createVNode as s, defineComponent as c, normalizeClass as l, openBlock as u, toDisplayString as d, unref as f, useId as p, useTemplateRef as m } from "vue";
7
7
  //#region lib/components/ui/media/pdf-viewer/partials/pdf-sidebar.vue?vue&type=script&setup=true&lang.ts
8
8
  var h = ["aria-label"], g = ["aria-label"], _ = [
@@ -1,8 +1,8 @@
1
1
  import { n as e } from "./rolldown-runtime-CWhphoD1.js";
2
2
  import { t } from "./utils-CykWQ0iJ.js";
3
- import { Bf as n } from "./components--v_k8diD.js";
4
- import { t as r } from "./use-material-translation-DRB6oPdF.js";
5
- import { t as i } from "./pdf-page-CRt6KXdJ.js";
3
+ import { Hf as n } from "./components-B2kSyBK0.js";
4
+ import { t as r } from "./use-material-translation-C6xccbic.js";
5
+ import { t as i } from "./pdf-page-NCmScgMW.js";
6
6
  import { Fragment as a, createCommentVNode as o, createElementBlock as s, createElementVNode as c, createVNode as l, defineComponent as u, normalizeClass as d, openBlock as f, renderList as p, toDisplayString as m, unref as h, withCtx as g } from "vue";
7
7
  //#region lib/components/ui/media/pdf-viewer/partials/pdf-thumbnail-sidebar.vue?vue&type=script&setup=true&lang.ts
8
8
  var _ = ["aria-label"], v = {
@@ -1,10 +1,10 @@
1
1
  import { n as e } from "./rolldown-runtime-CWhphoD1.js";
2
2
  import { t } from "./utils-CykWQ0iJ.js";
3
- import { t as n } from "./use-material-translation-DRB6oPdF.js";
4
- import { d as r } from "./Button-CurFF4Zt.js";
5
- import { t as i } from "./icon-button-CIUc1bEp.js";
6
- import { a, i as o, n as s, o as c, r as l, t as u } from "./DropdownMenuTrigger-BsuyNVzV.js";
7
- import { o as d } from "./HoverCardTrigger-jCXl6TrX.js";
3
+ import { t as n } from "./use-material-translation-C6xccbic.js";
4
+ import { d as r } from "./Button-DVeAQorb.js";
5
+ import { t as i } from "./icon-button-CSPfP615.js";
6
+ import { a, i as o, n as s, o as c, r as l, t as u } from "./DropdownMenuTrigger-C7uYPf_9.js";
7
+ import { o as d } from "./HoverCardTrigger-VvXPswRz.js";
8
8
  import { Fragment as f, computed as p, createBlock as m, createCommentVNode as h, createElementBlock as g, createElementVNode as _, createTextVNode as v, createVNode as y, defineComponent as b, nextTick as x, normalizeClass as S, openBlock as C, ref as w, renderList as T, toDisplayString as E, unref as D, useTemplateRef as O, watch as k, withCtx as A } from "vue";
9
9
  import { ChevronDown as j, ChevronLeft as M, ChevronRight as N, ChevronUp as P, Download as F, Maximize2 as I, Minimize2 as L, Moon as R, Printer as z, RotateCw as B, Search as V, Sidebar as H, ZoomIn as U, ZoomOut as W } from "@lucide/vue";
10
10
  //#region lib/components/ui/media/pdf-viewer/partials/pdf-toolbar-search.vue?vue&type=script&setup=true&lang.ts
package/dist/pdf.js CHANGED
@@ -1,5 +1,5 @@
1
- import { n as e, t } from "./use-material-translation-DRB6oPdF.js";
2
- import { t as n } from "./Button-CurFF4Zt.js";
1
+ import { n as e, t } from "./use-material-translation-C6xccbic.js";
2
+ import { t as n } from "./Button-DVeAQorb.js";
3
3
  import { computed as r, createBlock as i, createTextVNode as a, defineComponent as o, getCurrentInstance as s, nextTick as c, onMounted as l, onScopeDispose as u, openBlock as d, ref as f, renderSlot as p, shallowRef as m, toDisplayString as ee, toValue as h, unref as g, watch as te, withCtx as ne } from "vue";
4
4
  import { contentDisposition as re, pdfBytesResponse as ie, toWebStream as ae } from "@nxgt/material-core/pdf/http";
5
5
  import { badge as oe, dataTable as se, defaultPdfTheme as ce, definePdfDocument as _, divider as v, header as y, heading as b, image as x, keyValue as S, keyValueOf as C, link as w, metric as T, page as E, pageBreak as D, pageNumber as O, pdfDocument as k, resolvePdfColor as A, resolvePdfTheme as j, row as M, section as N, spacer as P, stack as F, table as I, text as L, totals as R } from "@nxgt/material-core/pdf/model";
@@ -1,5 +1,5 @@
1
- import { i as e, r as t, t as n } from "./stored-language-dtksFoGO.js";
2
- import { r } from "./translator-DqiGrSH_.js";
1
+ import { i as e, r as t, t as n } from "./stored-language-CKZMMJcz.js";
2
+ import { r } from "./translator-uh5FWiMq.js";
3
3
  import { t as i } from "./_baseIsEqual-BUD8VQJE.js";
4
4
  import { n as a } from "./number.utils-Bpo9tUaJ.js";
5
5
  import { defineComponent as o, getCurrentInstance as s, h as c, inject as l, provide as u, useId as d } from "vue";
@@ -1,6 +1,6 @@
1
1
  import { t as e } from "./utils-CykWQ0iJ.js";
2
- import { t } from "./use-material-translation-DRB6oPdF.js";
3
- import { t as n } from "./icon-button-CIUc1bEp.js";
2
+ import { t } from "./use-material-translation-C6xccbic.js";
3
+ import { t as n } from "./icon-button-CSPfP615.js";
4
4
  import { Teleport as r, computed as i, createBlock as a, createCommentVNode as o, createElementBlock as s, createVNode as c, defineComponent as l, inject as u, mergeProps as d, normalizeStyle as f, onUnmounted as p, openBlock as m, provide as h, reactive as g, ref as _, renderSlot as v, toValue as y, unref as b, useAttrs as x, watch as S, watchEffect as C, withCtx as w, withModifiers as T } from "vue";
5
5
  import { GripVertical as E } from "@lucide/vue";
6
6
  import { Primitive as D } from "reka-ui";
@@ -345,6 +345,7 @@ var e = {
345
345
  "select-all": "Select all",
346
346
  "select-row": "Select row",
347
347
  "toggle-row": "Toggle row details",
348
+ expand: "Expand",
348
349
  "scroll-region": "Scrollable table"
349
350
  },
350
351
  pagination: {
@@ -752,6 +753,7 @@ var e = {
752
753
  placeholder: "Search…",
753
754
  empty: "No results"
754
755
  },
756
+ "option-count": { label: "{count, plural, one {result} other {results}}" },
755
757
  autocomplete: {
756
758
  empty: "No option found.",
757
759
  add: "Add \"{query}\"",
@@ -1223,6 +1225,17 @@ var e = {
1223
1225
  saved: "I have saved these codes",
1224
1226
  "saved-required": "Tick the box once your codes are safe",
1225
1227
  done: "Done"
1228
+ },
1229
+ "repeatable-group": {
1230
+ row: "row",
1231
+ add: "Add {label}",
1232
+ remove: "Remove {label} {index}",
1233
+ "move-up": "Move {label} {index} up",
1234
+ "move-down": "Move {label} {index} down",
1235
+ added: "Added {label} {index}",
1236
+ removed: "Removed {label} {index}",
1237
+ moved: "Moved {label} {from} to position {to}",
1238
+ "max-reached": "Maximum reached ({max})"
1226
1239
  }
1227
1240
  } },
1228
1241
  fr: { material: {
@@ -1569,6 +1582,7 @@ var e = {
1569
1582
  "select-all": "Tout sélectionner",
1570
1583
  "select-row": "Sélectionner la ligne",
1571
1584
  "toggle-row": "Afficher ou masquer les détails de la ligne",
1585
+ expand: "Déplier",
1572
1586
  "scroll-region": "Tableau défilant"
1573
1587
  },
1574
1588
  pagination: {
@@ -1976,6 +1990,7 @@ var e = {
1976
1990
  placeholder: "Rechercher…",
1977
1991
  empty: "Aucun résultat"
1978
1992
  },
1993
+ "option-count": { label: "{count, plural, one {résultat} other {résultats}}" },
1979
1994
  autocomplete: {
1980
1995
  empty: "Aucune option.",
1981
1996
  add: "Ajouter « {query} »",
@@ -2447,6 +2462,17 @@ var e = {
2447
2462
  saved: "J'ai enregistré ces codes",
2448
2463
  "saved-required": "Cochez la case une fois vos codes en lieu sûr",
2449
2464
  done: "Terminé"
2465
+ },
2466
+ "repeatable-group": {
2467
+ row: "ligne",
2468
+ add: "Ajouter une {label}",
2469
+ remove: "Retirer la {label} {index}",
2470
+ "move-up": "Monter la {label} {index}",
2471
+ "move-down": "Descendre la {label} {index}",
2472
+ added: "Ajout : {label} {index}",
2473
+ removed: "Suppression : {label} {index}",
2474
+ moved: "Déplacement : {label} {from} en position {to}",
2475
+ "max-reached": "Maximum atteint ({max})"
2450
2476
  }
2451
2477
  } }
2452
2478
  }, t = "language", n = "en", r = Object.keys(e);
@@ -1,6 +1,6 @@
1
1
  import { t as e } from "./utils-CykWQ0iJ.js";
2
- import { $t as t, Jt as n, Kp as r, Qt as i, Xt as a, Yt as o, en as s, tn as c } from "./components--v_k8diD.js";
3
- import { t as l } from "./use-material-translation-DRB6oPdF.js";
2
+ import { $t as t, Jp as n, Jt as r, Qt as i, Xt as a, Yt as o, en as s, tn as c } from "./components-B2kSyBK0.js";
3
+ import { t as l } from "./use-material-translation-C6xccbic.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 = {
@@ -35,17 +35,17 @@ var S = ["data-layout", "aria-label"], C = {
35
35
  key: 1,
36
36
  class: _(b(e)("grid gap-3", a.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
- b(w).current?.kind === "audio" ? (v(), f("div", C, [h(r, { variant: "title-medium" }, {
38
+ b(w).current?.kind === "audio" ? (v(), f("div", C, [h(n, { variant: "title-medium" }, {
39
39
  default: x(() => [m(y(b(w).current.title), 1)]),
40
40
  _: 1
41
- }), b(w).current.artist ? (v(), u(r, {
41
+ }), b(w).current.artist ? (v(), u(n, {
42
42
  key: 0,
43
43
  class: "text-muted-foreground"
44
44
  }, {
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(n, null, {
48
+ h(r, null, {
49
49
  default: x(() => [b(w).current?.kind === "audio" ? d("", !0) : (v(), u(s, {
50
50
  key: 0,
51
51
  tone: "overlay"
@@ -1,4 +1,4 @@
1
- import { a as e, i as t, r as n, t as r } from "./stored-language-dtksFoGO.js";
1
+ import { a as e, i as t, r as n, t as r } from "./stored-language-CKZMMJcz.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-B2q6vp6H.js";
1
+ import { a as e } from "./i18n-provider-BBnUUGqM.js";
2
2
  import { c as t, d as n, f as r, l as i, r as a, u as o } from "./number.utils-Bpo9tUaJ.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";
@@ -1,6 +1,6 @@
1
- import "./stored-language-dtksFoGO.js";
2
- import { a as e } from "./i18n-provider-B2q6vp6H.js";
3
- import { i as t, r as n } from "./translator-DqiGrSH_.js";
1
+ import "./stored-language-CKZMMJcz.js";
2
+ import { a as e } from "./i18n-provider-BBnUUGqM.js";
3
+ import { i as t, r as n } from "./translator-uh5FWiMq.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]])) {
@@ -26,7 +26,7 @@ Anything you press that is not a field: buttons, link buttons, copy, load more,
26
26
 
27
27
  ## [Form fields](form-fields.md)
28
28
 
29
- Labelled inputs with a value, each with its form-library wrapper, and the composite values (attributes, contacts, address, opening hours), and the titled sections a long form is laid out in. 25 entries.
29
+ Labelled inputs with a value, each with its form-library wrapper, and the composite values (attributes, contacts, address, opening hours), the titled sections a long form is laid out in, and the rows a user adds and removes. 26 entries.
30
30
 
31
31
  [<img src="../previews/form-fields-textfield.webp" height="72" alt="TextField">](form-fields.md#textfield)
32
32
  [<img src="../previews/form-fields-phonefield.webp" height="72" alt="PhoneField">](form-fields.md#phonefield)
@@ -64,7 +64,8 @@ of your own; both footers take `disabled`);
64
64
  `useColumnHelpers<T>()` returns a
65
65
  `columnHelper` bound to the table's features and `predefinedColumns()` —
66
66
  `select` (checkboxes) and `expand` (a toggle for the expanded row, named
67
- "Toggle row details" (`material.table.labels.toggle-row`) with `aria-expanded`);
67
+ "Toggle row details" (`material.table.labels.toggle-row`) with `aria-expanded`, under a
68
+ visually hidden header "Expand", `material.table.labels.expand`);
68
69
  `useDeleteRowsHandler(onDelete)` for a delete-selected action behind a
69
70
  confirm dialog.
70
71
  `dataTableFeatures` / `DataTableFeatures` are the TanStack v9 features the
@@ -84,6 +85,7 @@ table enables, for typing your own column defs.
84
85
  | `scrollLabel` | `string` | "Scrollable table" | the name of the scroll region the table becomes while it overflows |
85
86
  | `loading` | `boolean` | `false` | skeleton rows, or the current rows dimmed; `aria-busy`; controls disabled |
86
87
  | `loadingRows` | `number` | the page size | how many skeleton rows |
88
+ | `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 |
87
89
  | `#empty="{ filtered }"` | slot | icon and "No data available" | content of the empty row, spanning every visible column |
88
90
  | `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)) |
89
91
  | `v-model:sorting` | `SortingState` | held inside | controlled sorting; `update:sorting` gets the new state |
@@ -12,6 +12,7 @@ value type each one writes. Everything is imported from
12
12
  | --- | --- | --- |
13
13
  | <img src="../previews/form-fields-field.webp" width="96" alt=""> | [Field](#field) | Renders the field matching a config `type` |
14
14
  | <img src="../previews/form-fields-formsection.webp" width="96" alt=""> | [FormSection](#formsection) | Titled section of a form, one column on a phone |
15
+ | <img src="../previews/form-fields-repeatablegroup.webp" width="96" alt=""> | [RepeatableGroup](#repeatablegroup) | Rows a user adds, removes and reorders |
15
16
  | <img src="../previews/form-fields-textfield.webp" width="96" alt=""> | [TextField](#textfield) | Labelled input with adornments and helper text |
16
17
  | <img src="../previews/form-fields-textareafield.webp" width="96" alt=""> | [TextareaField](#textareafield) | Labelled textarea with row sizing and a counter |
17
18
  | <img src="../previews/form-fields-emailfield.webp" width="96" alt=""> | [EmailField](#emailfield) | Validates on blur, `mailto:` button |
@@ -171,6 +172,125 @@ semibold, uppercase and muted, set apart from the fields' labels, and reads
171
172
 
172
173
  ---
173
174
 
175
+ ## RepeatableGroup
176
+
177
+ ![RepeatableGroup](../previews/form-fields-repeatablegroup.webp)
178
+
179
+ Rows of fields a user adds, removes and, optionally, reorders — a school
180
+ year's periods, a list of contacts. `RepeatableGroupFormField` wires it to
181
+ vee-validate's `useFieldArray`; each row's fields are your own form wrappers,
182
+ rendered by its `row` slot.
183
+
184
+ ```vue
185
+ <script setup lang="ts">
186
+ import { useForm } from 'vee-validate';
187
+ import {
188
+ Button,
189
+ DateFormField,
190
+ RepeatableGroupFormField,
191
+ TextFormField,
192
+ } from '@nxgt/material-vue/components';
193
+
194
+ type Period = { name: string; start?: Date; end?: Date };
195
+
196
+ const { handleSubmit } = useForm<{ periods: Period[] }>({
197
+ initialValues: { periods: [{ name: 'Term 1' }] },
198
+ });
199
+ const onSubmit = handleSubmit((values) => console.log(values));
200
+ const newRow = (): Period => ({ name: '' });
201
+ </script>
202
+
203
+ <template>
204
+ <form class="form-grid-layout" @submit="onSubmit">
205
+ <div data-slot="form-fields">
206
+ <RepeatableGroupFormField
207
+ name="periods"
208
+ label="Periods"
209
+ row-label="period"
210
+ add-label="Add period"
211
+ :max="6"
212
+ reorderable
213
+ empty-title="No periods yet"
214
+ :new-row="newRow"
215
+ >
216
+ <template #row="{ path }">
217
+ <TextFormField :name="`${path}.name`" label="Name" />
218
+ <DateFormField :name="`${path}.start`" label="Start date" />
219
+ <DateFormField :name="`${path}.end`" label="End date" />
220
+ </template>
221
+ </RepeatableGroupFormField>
222
+ </div>
223
+ <div data-slot="form-actions">
224
+ <Button type="submit">Save</Button>
225
+ </div>
226
+ </form>
227
+ </template>
228
+ ```
229
+
230
+ | Prop / slot | Type | Default | Effect |
231
+ | --- | --- | --- | --- |
232
+ | `name` | `string` | — | the array's path in the form (`RepeatableGroupFormField`) |
233
+ | `new-row` | `() => TRow` | — | the value Add pushes |
234
+ | `#row` | slot | — | one row's fields; its props are `{ field, index, position, path }` (`index` 0-based, `position` 1-based, `path` `${name}[${index}]`) |
235
+ | `label` / `#label` | `string` / slot | — | names the group (the list inside it is not named again) |
236
+ | `row-label` | `string` | `'row'` (translated) | names each row's buttons ("Remove period 2") and the announcements |
237
+ | `add-label` | `string` | `'Add {rowLabel}'` | the Add button's text |
238
+ | `reorderable` | `boolean` | `false` | move up / move down buttons on each row |
239
+ | `max` | `number` | — | at this many rows, Add is disabled and says why |
240
+ | `min` | `number` | — | at this many rows, Remove is disabled |
241
+ | `empty-title`, `empty-description` / `#empty` | `string` / slot | — | an `EmptyState` when there is no row; the slot replaces it |
242
+ | `disabled` | `boolean` | `false` | disables every button |
243
+
244
+ Without a form library, `RepeatableGroup` takes the rows and listens to the
245
+ actions; the move buttons show only with a `@move` listener:
246
+
247
+ ```vue
248
+ <script setup lang="ts">
249
+ import { ref } from 'vue';
250
+ import { RepeatableGroup, TextField } from '@nxgt/material-vue/components';
251
+
252
+ type Guest = { id: string; name: string };
253
+ const guests = ref<Guest[]>([]);
254
+ const add = () => guests.value.push({ id: crypto.randomUUID(), name: '' });
255
+ const remove = (index: number) => guests.value.splice(index, 1);
256
+ </script>
257
+
258
+ <template>
259
+ <RepeatableGroup label="Guests" row-label="guest" :items="guests" @add="add" @remove="remove">
260
+ <template #row="{ item }">
261
+ <TextField v-model="item.name" label="Name" />
262
+ </template>
263
+ </RepeatableGroup>
264
+ </template>
265
+ ```
266
+
267
+ `get-key` defaults to the item's `key`, then its `id`, then the index.
268
+ vee-validate's `useFieldArray` gives each entry a `key`, so
269
+ `RepeatableGroupFormField` needs none; a plain list keyed by `id` needs none
270
+ either. `error` shows an error under the rows.
271
+
272
+ `row-label` is a lower-case noun. The French templates carry the feminine
273
+ article ("Ajouter une ligne", "Retirer la ligne 2"), so a French app passes a
274
+ feminine noun (`row-label="période"`), or overrides `add-label` and the
275
+ `material.repeatable-group.*` keys in its own bundle (`mergeResources`) for a
276
+ masculine one.
277
+
278
+ - **Semantics:** a `role="group"` named by `label`, its rows a list
279
+ (`getAllByRole('listitem')`), each row's icon buttons named after it
280
+ ("Remove period 2", "Move period 2 up").
281
+ - **Focus and announcements:** see
282
+ [Rows a user adds and removes](../guides/forms.md#rows-a-user-adds-and-removes);
283
+ at `max`, Add stays focusable (`aria-disabled`) and is described by
284
+ "Maximum reached (6)".
285
+ - **Errors:** the array's own error (the error at `name`) describes the group;
286
+ each row's fields show their own.
287
+ - **Layout:** one column on a phone, columns of at least 11rem from a container
288
+ width of `@xl`; no inline style.
289
+
290
+ **Storybook:** `Form fields/RepeatableGroup` · **React:** `RepeatableGroup`, `RepeatableGroupFormField`
291
+
292
+ ---
293
+
174
294
  ## TextField
175
295
 
176
296
  ![TextField](../previews/form-fields-textfield.webp)
@@ -513,8 +633,34 @@ const query = ref('');
513
633
  | `@value-change` | `(value: string) => void` | — | the text, debounced when `debounce-ms` is set |
514
634
  | `debounce-ms` | `number` | `0` | delay before `value-change`; `0` emits it on every key |
515
635
  | `loading` | `boolean` | `false` | spinner in the input |
636
+ | `shortcut` | `string` | — | a hint for the key that focuses the field, e.g. `"/"`: a `Kbd` at the end while the field is empty, not loading and not disabled (`aria-hidden`) and `aria-keyshortcuts` on the input. It binds no key; your page listens and calls `focus()` on the component ref (exposed) |
516
637
  | `v-model` | `string` | — | still updated on every key, undebounced |
517
638
 
639
+ The `shortcut` hint binds no key; the page does, and calls the exposed
640
+ `focus()`:
641
+
642
+ ```vue
643
+ <script setup lang="ts">
644
+ import { onMounted, onUnmounted, ref } from 'vue';
645
+ import { SearchField } from '@nxgt/material-vue/components';
646
+
647
+ const searchRef = ref<InstanceType<typeof SearchField> | null>(null);
648
+ const onKey = (event: KeyboardEvent) => {
649
+ const target = event.target as HTMLElement;
650
+ if (event.key === '/' && !target.closest('input, textarea, [contenteditable]')) {
651
+ event.preventDefault();
652
+ searchRef.value?.focus();
653
+ }
654
+ };
655
+ onMounted(() => document.addEventListener('keydown', onKey));
656
+ onUnmounted(() => document.removeEventListener('keydown', onKey));
657
+ </script>
658
+
659
+ <template>
660
+ <SearchField ref="searchRef" shortcut="/" />
661
+ </template>
662
+ ```
663
+
518
664
  **Emits:** `update:modelValue` and `value-change`, both `string`;
519
665
  `SearchFormField` stores `string`.
520
666
  **Form wrapper:** `SearchFormField` — `name` inside a vee-validate form, see
@@ -637,6 +637,8 @@ Parts: `Command`, `CommandDialog`, `CommandInput`, `CommandList`,
637
637
  | Prop | Type | Default | Effect |
638
638
  | --- | --- | --- | --- |
639
639
  | `value` (`CommandItem`) | `string` | — (required) | the item's value, emitted by `@select` and by `Command`'s `v-model` |
640
+ | `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) |
641
+ | `multiselectable` (`CommandList`) | `boolean` | — | sets `aria-multiselectable` on the list |
640
642
  | `@select` (`CommandItem`) | `(event) => void` | — | Enter or click on the item; `event.detail.value` is its `value` |
641
643
  | `heading` (`CommandGroup`) | `string` | — | the group's label |
642
644
  | `title` / `description` (`CommandDialog`) | `string` | `"Command Palette"` / `"Search for a command to run..."` (translated) | the dialog's title and description, visually hidden |
@@ -193,14 +193,16 @@ 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`, `error` is `text-error-text`; `default` inherits (a `class` colour still wins) |
196
197
  | `as` | a tag name or a component | `'div'` | the element to render, keeping the variant, e.g. `as="h2"` or `as="span"` |
197
198
  | `asChild` | `boolean` | `false` | merge the classes onto the single child instead of rendering an element |
198
199
 
199
- It renders a `<div>` unless `as` or `asChild` says otherwise:
200
+ It renders a `<div>` unless `as` or `asChild` says otherwise. Use `as="span"` inside a `<button>` or a link, where a `<div>` is invalid HTML. It sets no `overflow`, so it is never a scroll region: text with break points wraps, while an unbreakable string can overflow its box (add `wrap-anywhere` or `min-w-0`; put your own wrapper with `overflow-auto` and `tabindex="0"` around it to scroll):
200
201
 
201
202
  ```vue
202
203
  <Typography as="span" variant="title-small">Inline</Typography>
203
204
  <Typography as-child variant="body-medium"><a href="/docs">Docs</a></Typography>
205
+ <Typography tone="muted" variant="body-medium">Jan 3 to Jan 9</Typography>
204
206
  ```
205
207
 
206
208
  The variants are also exported as `typographyVariants` for use on your own elements. Vue has one more step than React, `huge-larger`.
@@ -463,7 +463,7 @@ const picked = ref<string[]>(['astro']);
463
463
 
464
464
  | Prop | Type | Default | Effect |
465
465
  | --- | --- | --- | --- |
466
- | `options` | `{ value: string; label: string }[]` | — | required; the boxes |
466
+ | `options` | `{ value: string; label: string; count?: number }[]` | — | required; the boxes; `count`: see [option counts](#option-counts). |
467
467
  | `v-model` | `string[]` | `[]` | the checked values; the new list on each toggle |
468
468
  | `orientation` | `'vertical' \| 'horizontal'` | `'horizontal'` | layout |
469
469
  | `label`, `helper-text` | `string` | — | the question and its help or error text, above the boxes |
@@ -487,6 +487,10 @@ stops matching.
487
487
  The `#helper-text` slot replaces the helper text's content (shown only while
488
488
  `helper-text` is set) and stays part of the group's description.
489
489
 
490
+ #### Option counts
491
+
492
+ `count` on an option of `CheckboxGroup`, `RadioGroupField` or `SelectChipField` shows a number after the label, in muted `tabular-nums` text, and joins the accessible name: the number as plain text plus a visually hidden unit word, so the option is named "CE1 24 results" (it starts with the visible label). The unit is the ICU plural `material.option-count.label` (`result` / `results`; `résultat` / `résultats` in French), so override it in your resources for another noun. `0` is a valid count.
493
+
490
494
  **Emits:** `update:modelValue` with `string[]`.
491
495
  **Form wrapper:** `CheckboxGroupFormField` — `name` inside a vee-validate form, see
492
496
  [forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
@@ -524,7 +528,7 @@ React the labelled one is called `RadioGroup`.
524
528
 
525
529
  | Prop | Type | Default | Effect |
526
530
  | --- | --- | --- | --- |
527
- | `options` | `{ value: string; label: string; disabled?: boolean }[]` | — | required; the radios; `disabled` on an option disables only it |
531
+ | `options` | `{ value: string; label: string; disabled?: boolean; count?: number }[]` | — | required; the radios; `disabled` on an option disables only it; `count`: see [option counts](#option-counts). |
528
532
  | `v-model` | `string` | — | the selected `value` |
529
533
  | `orientation` | `'vertical' \| 'horizontal'` | `'horizontal'` | layout |
530
534
  | `label`, `helper-text`, `error`, `disabled` | | — | the field's text and state |
@@ -652,11 +656,31 @@ const picked = ref<string[]>([]);
652
656
  </template>
653
657
  ```
654
658
 
659
+ With icons, counts, and a single choice that stays chosen when pressed again:
660
+
661
+ ```vue
662
+ <script setup lang="ts">
663
+ import { AtomIcon } from '@lucide/vue';
664
+ import { markRaw, ref } from 'vue';
665
+
666
+ const level = ref<string[]>([]);
667
+ const levels = [
668
+ { value: 'ce1', label: 'CE1', count: 24, icon: markRaw(AtomIcon) },
669
+ { value: 'ce2', label: 'CE2', count: 1 },
670
+ ];
671
+ </script>
672
+
673
+ <template>
674
+ <SelectChipField v-model="level" label="Level" :options="levels" :deselectable="false" />
675
+ </template>
676
+ ```
677
+
655
678
  | Prop | Type | Default | Effect |
656
679
  | --- | --- | --- | --- |
657
- | `mode` | `'single' \| 'multiple'` | `'single'` | clicking the selected chip in `single` mode clears it |
680
+ | `mode` | `'single' \| 'multiple'` | `'single'` | clicking the selected chip in `single` mode clears it, unless `deselectable` is `false` |
681
+ | `deselectable` | `boolean` | `true` | `false`: in `single` mode a second press keeps the chosen chip chosen, as a radio group does; another chip still replaces it |
658
682
  | `v-model` | `string[]` | `[]` | the selected values, even in `single` mode |
659
- | `options` | `{ value: string; label: string }[]` | — | required; the chips |
683
+ | `options` | `{ value: string; label: string; icon?: Component; count?: number }[]` | — | required; the chips (`icon`: a component, such as a `@lucide/vue` icon, shown before the label); `count`: see [option counts](#option-counts). |
660
684
  | `label`, `helper-text`, `error`, `disabled` | | — | the field's text and state |
661
685
 
662
686
  **Accessibility:** the chips are toggle buttons in a `role="group"` named by