nuxt-ui-tools 1.23.0 → 1.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.
Files changed (226) hide show
  1. package/dist/module.d.mts +3 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +8 -0
  4. package/dist/runtime/display/components/blocks/display-accordion.d.vue.ts +4 -0
  5. package/dist/runtime/display/components/blocks/display-accordion.vue +93 -0
  6. package/dist/runtime/display/components/blocks/display-accordion.vue.d.ts +4 -0
  7. package/dist/runtime/display/components/blocks/display-alert.d.vue.ts +4 -0
  8. package/dist/runtime/display/components/blocks/display-alert.vue +133 -0
  9. package/dist/runtime/display/components/blocks/display-alert.vue.d.ts +4 -0
  10. package/dist/runtime/display/components/blocks/display-breakdown.d.vue.ts +4 -0
  11. package/dist/runtime/display/components/blocks/display-breakdown.vue +178 -0
  12. package/dist/runtime/display/components/blocks/display-breakdown.vue.d.ts +4 -0
  13. package/dist/runtime/display/components/blocks/display-chart.d.vue.ts +4 -0
  14. package/dist/runtime/display/components/blocks/display-chart.vue +237 -0
  15. package/dist/runtime/display/components/blocks/display-chart.vue.d.ts +4 -0
  16. package/dist/runtime/display/components/blocks/display-code.d.vue.ts +4 -0
  17. package/dist/runtime/display/components/blocks/display-code.vue +143 -0
  18. package/dist/runtime/display/components/blocks/display-code.vue.d.ts +4 -0
  19. package/dist/runtime/display/components/blocks/display-date.d.vue.ts +4 -0
  20. package/dist/runtime/display/components/blocks/display-date.vue +174 -0
  21. package/dist/runtime/display/components/blocks/display-date.vue.d.ts +4 -0
  22. package/dist/runtime/display/components/blocks/display-diff.d.vue.ts +4 -0
  23. package/dist/runtime/display/components/blocks/display-diff.vue +142 -0
  24. package/dist/runtime/display/components/blocks/display-diff.vue.d.ts +4 -0
  25. package/dist/runtime/display/components/blocks/display-empty.d.vue.ts +4 -0
  26. package/dist/runtime/display/components/blocks/display-empty.vue +74 -0
  27. package/dist/runtime/display/components/blocks/display-empty.vue.d.ts +4 -0
  28. package/dist/runtime/display/components/blocks/display-facts.d.vue.ts +4 -0
  29. package/dist/runtime/display/components/blocks/display-facts.vue +180 -0
  30. package/dist/runtime/display/components/blocks/display-facts.vue.d.ts +4 -0
  31. package/dist/runtime/display/components/blocks/display-heading.d.vue.ts +4 -0
  32. package/dist/runtime/display/components/blocks/display-heading.vue +96 -0
  33. package/dist/runtime/display/components/blocks/display-heading.vue.d.ts +4 -0
  34. package/dist/runtime/display/components/blocks/display-list.d.vue.ts +4 -0
  35. package/dist/runtime/display/components/blocks/display-list.vue +295 -0
  36. package/dist/runtime/display/components/blocks/display-list.vue.d.ts +4 -0
  37. package/dist/runtime/display/components/blocks/display-media.d.vue.ts +4 -0
  38. package/dist/runtime/display/components/blocks/display-media.vue +326 -0
  39. package/dist/runtime/display/components/blocks/display-media.vue.d.ts +4 -0
  40. package/dist/runtime/display/components/blocks/display-meter.d.vue.ts +4 -0
  41. package/dist/runtime/display/components/blocks/display-meter.vue +301 -0
  42. package/dist/runtime/display/components/blocks/display-meter.vue.d.ts +4 -0
  43. package/dist/runtime/display/components/blocks/display-person.d.vue.ts +4 -0
  44. package/dist/runtime/display/components/blocks/display-person.vue +146 -0
  45. package/dist/runtime/display/components/blocks/display-person.vue.d.ts +4 -0
  46. package/dist/runtime/display/components/blocks/display-record.d.vue.ts +4 -0
  47. package/dist/runtime/display/components/blocks/display-record.vue +208 -0
  48. package/dist/runtime/display/components/blocks/display-record.vue.d.ts +4 -0
  49. package/dist/runtime/display/components/blocks/display-stat.d.vue.ts +4 -0
  50. package/dist/runtime/display/components/blocks/display-stat.vue +178 -0
  51. package/dist/runtime/display/components/blocks/display-stat.vue.d.ts +4 -0
  52. package/dist/runtime/display/components/blocks/display-table.d.vue.ts +4 -0
  53. package/dist/runtime/display/components/blocks/display-table.vue +132 -0
  54. package/dist/runtime/display/components/blocks/display-table.vue.d.ts +4 -0
  55. package/dist/runtime/display/components/blocks/display-text.d.vue.ts +4 -0
  56. package/dist/runtime/display/components/blocks/display-text.vue +135 -0
  57. package/dist/runtime/display/components/blocks/display-text.vue.d.ts +4 -0
  58. package/dist/runtime/display/components/blocks/display-timeline.d.vue.ts +4 -0
  59. package/dist/runtime/display/components/blocks/display-timeline.vue +232 -0
  60. package/dist/runtime/display/components/blocks/display-timeline.vue.d.ts +4 -0
  61. package/dist/runtime/display/components/display.d.vue.ts +24 -0
  62. package/dist/runtime/display/components/display.vue +21 -0
  63. package/dist/runtime/display/components/display.vue.d.ts +24 -0
  64. package/dist/runtime/display/components/parts/display-actions.d.vue.ts +9 -0
  65. package/dist/runtime/display/components/parts/display-actions.vue +24 -0
  66. package/dist/runtime/display/components/parts/display-actions.vue.d.ts +9 -0
  67. package/dist/runtime/display/components/parts/display-chip.d.vue.ts +11 -0
  68. package/dist/runtime/display/components/parts/display-chip.vue +45 -0
  69. package/dist/runtime/display/components/parts/display-chip.vue.d.ts +11 -0
  70. package/dist/runtime/display/components/parts/display-copy.d.vue.ts +6 -0
  71. package/dist/runtime/display/components/parts/display-copy.vue +27 -0
  72. package/dist/runtime/display/components/parts/display-copy.vue.d.ts +6 -0
  73. package/dist/runtime/display/components/parts/display-empty-line.d.vue.ts +7 -0
  74. package/dist/runtime/display/components/parts/display-empty-line.vue +21 -0
  75. package/dist/runtime/display/components/parts/display-empty-line.vue.d.ts +7 -0
  76. package/dist/runtime/display/components/parts/display-fact-value.d.vue.ts +7 -0
  77. package/dist/runtime/display/components/parts/display-fact-value.vue +35 -0
  78. package/dist/runtime/display/components/parts/display-fact-value.vue.d.ts +7 -0
  79. package/dist/runtime/display/components/parts/display-load-error.d.vue.ts +7 -0
  80. package/dist/runtime/display/components/parts/display-load-error.vue +29 -0
  81. package/dist/runtime/display/components/parts/display-load-error.vue.d.ts +7 -0
  82. package/dist/runtime/display/components/parts/display-more.d.vue.ts +10 -0
  83. package/dist/runtime/display/components/parts/display-more.vue +23 -0
  84. package/dist/runtime/display/components/parts/display-more.vue.d.ts +10 -0
  85. package/dist/runtime/display/components/parts/display-record-media.d.vue.ts +9 -0
  86. package/dist/runtime/display/components/parts/display-record-media.vue +59 -0
  87. package/dist/runtime/display/components/parts/display-record-media.vue.d.ts +9 -0
  88. package/dist/runtime/display/components/parts/display-render.d.ts +10 -0
  89. package/dist/runtime/display/components/parts/display-render.js +5 -0
  90. package/dist/runtime/display/components/parts/display-skeleton.d.vue.ts +7 -0
  91. package/dist/runtime/display/components/parts/display-skeleton.vue +67 -0
  92. package/dist/runtime/display/components/parts/display-skeleton.vue.d.ts +7 -0
  93. package/dist/runtime/display/composables/use-display-config.d.ts +6 -0
  94. package/dist/runtime/display/composables/use-display-config.js +11 -0
  95. package/dist/runtime/display/composables/use-display-file-preview.d.ts +9 -0
  96. package/dist/runtime/display/composables/use-display-file-preview.js +11 -0
  97. package/dist/runtime/display/composables/use-display-icons.d.ts +8 -0
  98. package/dist/runtime/display/composables/use-display-icons.js +62 -0
  99. package/dist/runtime/display/composables/use-display-locale.d.ts +5 -0
  100. package/dist/runtime/display/composables/use-display-locale.js +5 -0
  101. package/dist/runtime/display/composables/use-display-number.d.ts +2 -0
  102. package/dist/runtime/display/composables/use-display-number.js +7 -0
  103. package/dist/runtime/display/composables/use-display-reveal.d.ts +14 -0
  104. package/dist/runtime/display/composables/use-display-reveal.js +15 -0
  105. package/dist/runtime/display/composables/use-display-url.d.ts +26 -0
  106. package/dist/runtime/display/composables/use-display-url.js +46 -0
  107. package/dist/runtime/display/index.d.ts +4 -0
  108. package/dist/runtime/display/index.js +3 -0
  109. package/dist/runtime/display/plugins/display-tones.d.ts +3 -0
  110. package/dist/runtime/display/plugins/display-tones.js +17 -0
  111. package/dist/runtime/display/types/blocks/accordion.d.ts +18 -0
  112. package/dist/runtime/display/types/blocks/accordion.js +0 -0
  113. package/dist/runtime/display/types/blocks/alert.d.ts +31 -0
  114. package/dist/runtime/display/types/blocks/alert.js +0 -0
  115. package/dist/runtime/display/types/blocks/breakdown.d.ts +36 -0
  116. package/dist/runtime/display/types/blocks/breakdown.js +0 -0
  117. package/dist/runtime/display/types/blocks/chart.d.ts +23 -0
  118. package/dist/runtime/display/types/blocks/chart.js +0 -0
  119. package/dist/runtime/display/types/blocks/code.d.ts +21 -0
  120. package/dist/runtime/display/types/blocks/code.js +0 -0
  121. package/dist/runtime/display/types/blocks/date.d.ts +27 -0
  122. package/dist/runtime/display/types/blocks/date.js +0 -0
  123. package/dist/runtime/display/types/blocks/diff.d.ts +20 -0
  124. package/dist/runtime/display/types/blocks/diff.js +0 -0
  125. package/dist/runtime/display/types/blocks/empty.d.ts +13 -0
  126. package/dist/runtime/display/types/blocks/empty.js +0 -0
  127. package/dist/runtime/display/types/blocks/facts.d.ts +50 -0
  128. package/dist/runtime/display/types/blocks/facts.js +0 -0
  129. package/dist/runtime/display/types/blocks/heading.d.ts +19 -0
  130. package/dist/runtime/display/types/blocks/heading.js +0 -0
  131. package/dist/runtime/display/types/blocks/list.d.ts +36 -0
  132. package/dist/runtime/display/types/blocks/list.js +0 -0
  133. package/dist/runtime/display/types/blocks/media.d.ts +42 -0
  134. package/dist/runtime/display/types/blocks/media.js +0 -0
  135. package/dist/runtime/display/types/blocks/meter.d.ts +48 -0
  136. package/dist/runtime/display/types/blocks/meter.js +0 -0
  137. package/dist/runtime/display/types/blocks/person.d.ts +32 -0
  138. package/dist/runtime/display/types/blocks/person.js +0 -0
  139. package/dist/runtime/display/types/blocks/record.d.ts +42 -0
  140. package/dist/runtime/display/types/blocks/record.js +0 -0
  141. package/dist/runtime/display/types/blocks/stat.d.ts +44 -0
  142. package/dist/runtime/display/types/blocks/stat.js +0 -0
  143. package/dist/runtime/display/types/blocks/table.d.ts +28 -0
  144. package/dist/runtime/display/types/blocks/table.js +0 -0
  145. package/dist/runtime/display/types/blocks/text.d.ts +22 -0
  146. package/dist/runtime/display/types/blocks/text.js +0 -0
  147. package/dist/runtime/display/types/blocks/timeline.d.ts +37 -0
  148. package/dist/runtime/display/types/blocks/timeline.js +0 -0
  149. package/dist/runtime/display/types/config.d.ts +53 -0
  150. package/dist/runtime/display/types/config.js +0 -0
  151. package/dist/runtime/display/types/index.d.ts +22 -0
  152. package/dist/runtime/display/types/index.js +0 -0
  153. package/dist/runtime/display/types/registry.d.ts +57 -0
  154. package/dist/runtime/display/types/registry.js +0 -0
  155. package/dist/runtime/display/types/shared.d.ts +71 -0
  156. package/dist/runtime/display/types/shared.js +0 -0
  157. package/dist/runtime/display/utils/classes.d.ts +3 -0
  158. package/dist/runtime/display/utils/classes.js +7 -0
  159. package/dist/runtime/display/utils/config.d.ts +6 -0
  160. package/dist/runtime/display/utils/config.js +7 -0
  161. package/dist/runtime/display/utils/content.d.ts +7 -0
  162. package/dist/runtime/display/utils/content.js +13 -0
  163. package/dist/runtime/display/utils/dates.d.ts +16 -0
  164. package/dist/runtime/display/utils/dates.js +34 -0
  165. package/dist/runtime/display/utils/json.d.ts +7 -0
  166. package/dist/runtime/display/utils/json.js +15 -0
  167. package/dist/runtime/display/utils/meter.d.ts +7 -0
  168. package/dist/runtime/display/utils/meter.js +13 -0
  169. package/dist/runtime/display/utils/registry.d.ts +47 -0
  170. package/dist/runtime/display/utils/registry.js +64 -0
  171. package/dist/runtime/display/utils/tone-css.d.ts +7 -0
  172. package/dist/runtime/display/utils/tone-css.js +38 -0
  173. package/dist/runtime/display/utils/tone.d.ts +26 -0
  174. package/dist/runtime/display/utils/tone.js +38 -0
  175. package/dist/runtime/display/utils/urls.d.ts +10 -0
  176. package/dist/runtime/display/utils/urls.js +33 -0
  177. package/dist/runtime/file-preview/components/shell/file-preview-stage.vue +5 -3
  178. package/dist/runtime/file-preview/composables/use-file-preview-source.d.ts +7 -0
  179. package/dist/runtime/file-preview/composables/use-file-preview-source.js +7 -1
  180. package/dist/runtime/file-preview/index.d.ts +1 -0
  181. package/dist/runtime/file-preview/index.js +1 -0
  182. package/dist/runtime/file-preview/types/file.d.ts +9 -0
  183. package/dist/runtime/file-preview/utils/errors.d.ts +30 -0
  184. package/dist/runtime/file-preview/utils/errors.js +26 -0
  185. package/dist/runtime/form/components/utils/form-file-preview.vue +7 -2
  186. package/dist/runtime/form/composables/use-form-root.js +2 -0
  187. package/dist/runtime/form/composables/use-form-runtime.js +7 -2
  188. package/dist/runtime/form/fields/index.d.ts +5 -0
  189. package/dist/runtime/form/fields/info/component.vue +51 -19
  190. package/dist/runtime/form/fields/info/config.d.ts +5 -0
  191. package/dist/runtime/form/fields/info/config.js +2 -1
  192. package/dist/runtime/form/fields/info/types.d.ts +78 -4
  193. package/dist/runtime/form/fields/info/use-info-display.d.ts +20 -0
  194. package/dist/runtime/form/fields/info/use-info-display.js +82 -0
  195. package/dist/runtime/form/fields/upload/upload-item.vue +10 -2
  196. package/dist/runtime/form/types/api.d.ts +6 -0
  197. package/dist/runtime/form/types/runtime.d.ts +2 -0
  198. package/dist/runtime/form/utils/dynamic.d.ts +6 -0
  199. package/dist/runtime/form/utils/dynamic.js +7 -0
  200. package/dist/runtime/i18n/locales/en.js +32 -0
  201. package/dist/runtime/i18n/locales/fr.js +32 -0
  202. package/dist/runtime/i18n/types.d.ts +40 -0
  203. package/dist/runtime/shared/styles/tokens.css +1 -1
  204. package/dist/runtime/shared/utils/file.d.ts +1 -1
  205. package/dist/runtime/table/components/data-list/data-list-root.vue +2 -0
  206. package/dist/runtime/table/components/data-list/data-list-selection-actions.d.vue.ts +1 -1
  207. package/dist/runtime/table/components/data-list/data-list-selection-actions.vue +32 -5
  208. package/dist/runtime/table/components/data-list/data-list-selection-actions.vue.d.ts +1 -1
  209. package/dist/runtime/table/components/data-list/data-list-selection-sheet.d.vue.ts +10 -0
  210. package/dist/runtime/table/components/data-list/data-list-selection-sheet.vue +238 -0
  211. package/dist/runtime/table/components/data-list/data-list-selection-sheet.vue.d.ts +10 -0
  212. package/dist/runtime/table/components/grid/grid-renderer.vue +2 -0
  213. package/dist/runtime/table/components/summary/summary-renderer.vue +2 -0
  214. package/dist/runtime/table/components/table/table-renderer.vue +2 -0
  215. package/dist/runtime/table/components/utils/overlay-inset-spacer.d.vue.ts +3 -0
  216. package/dist/runtime/table/components/utils/overlay-inset-spacer.vue +13 -0
  217. package/dist/runtime/table/components/utils/overlay-inset-spacer.vue.d.ts +3 -0
  218. package/dist/runtime/table/composables/use-data-list-overlay-inset.d.ts +10 -0
  219. package/dist/runtime/table/composables/use-data-list-overlay-inset.js +11 -0
  220. package/dist/runtime/table/composables/use-table-actions.js +11 -2
  221. package/dist/runtime/table/constants/mobile.d.ts +0 -7
  222. package/dist/runtime/table/constants/mobile.js +0 -1
  223. package/dist/runtime/table/types/actions.d.ts +7 -0
  224. package/dist/runtime/table/types/data-list.d.ts +8 -1
  225. package/dist/runtime/table/utils/data-list-ui.d.ts +1 -1
  226. package/package.json +16 -1
@@ -2,7 +2,7 @@
2
2
  import UButton from "@nuxt/ui/components/Button.vue";
3
3
  import UIcon from "@nuxt/ui/components/Icon.vue";
4
4
  import UProgress from "@nuxt/ui/components/Progress.vue";
5
- import { computed } from "vue";
5
+ import { computed, ref, watch } from "vue";
6
6
  import { useUiToolsLocale } from "../../../i18n/use-locale";
7
7
  import { fileExtensionLabel, fileIconName, formatFileSize } from "../../../shared/utils/file";
8
8
  const props = defineProps({
@@ -14,6 +14,13 @@ const props = defineProps({
14
14
  const emit = defineEmits(["open", "start", "cancel", "retry", "remove", "replace"]);
15
15
  const { code, t } = useUiToolsLocale();
16
16
  const icon = computed(() => fileIconName(props.item.type));
17
+ const thumbnailFailed = ref(false);
18
+ watch(
19
+ () => props.item.thumbnail,
20
+ () => {
21
+ thumbnailFailed.value = false;
22
+ }
23
+ );
17
24
  const meta = computed(() => {
18
25
  if (props.item.description) return props.item.description;
19
26
  const extension = fileExtensionLabel({ name: props.item.name, type: props.item.type });
@@ -37,9 +44,10 @@ const status = computed(() => {
37
44
  :data-form-upload-item="item.status"
38
45
  >
39
46
  <img
40
- v-if="item.thumbnail"
47
+ v-if="item.thumbnail && !thumbnailFailed"
41
48
  :src="item.thumbnail"
42
49
  :alt="item.name"
50
+ @error="thumbnailFailed = true"
43
51
  class="shrink-0 rounded-md border border-default bg-white object-contain p-0.5"
44
52
  :class="compact ? 'size-7' : 'size-10'"
45
53
  />
@@ -59,6 +59,12 @@ export interface FormFieldFormApi {
59
59
  reset: () => Promise<void>;
60
60
  /** Submits the form through the configured submit lifecycle. */
61
61
  submit: () => Promise<boolean>;
62
+ /**
63
+ * Closes the form the way its Cancel action does: asks to discard unsaved changes when the
64
+ * schema asks for it, then cancels (an overlay closes). Does nothing for a form rendered without
65
+ * a cancel handler.
66
+ */
67
+ close: () => Promise<void>;
62
68
  /** Advances to the next step on stepped forms. */
63
69
  nextStep: () => Promise<boolean>;
64
70
  /** Returns to the previous step on stepped forms. */
@@ -92,4 +92,6 @@ export interface FormRuntime {
92
92
  nextStep: () => Promise<boolean>;
93
93
  previousStep: () => Promise<boolean>;
94
94
  goToStep: (index: number) => Promise<boolean>;
95
+ /** Cancels the rendered form, as its Cancel action does. Set by the form root that renders it. */
96
+ bindCancel: (cancel: (() => Promise<void>) | null) => void;
95
97
  }
@@ -0,0 +1,6 @@
1
+ import type { FormDynamic } from '../types/index.js';
2
+ /**
3
+ * Value of a static-or-callback option: the callback's result for `params`, else the value.
4
+ * Any function counts as the callback, the same convention as every field callback.
5
+ */
6
+ export declare function resolveFormDynamic<TValue, TParams>(value: FormDynamic<TValue, TParams>, params: TParams): TValue;
@@ -0,0 +1,7 @@
1
+ import { isFunction } from "../../shared/utils/predicate.js";
2
+ export function resolveFormDynamic(value, params) {
3
+ return isDynamicCallback(value) ? value(params) : value;
4
+ }
5
+ function isDynamicCallback(value) {
6
+ return isFunction(value);
7
+ }
@@ -97,6 +97,33 @@ export default defineUiToolsLocale({
97
97
  retry: "Retry"
98
98
  }
99
99
  },
100
+ display: {
101
+ after: "After",
102
+ before: "Before",
103
+ conceal: "Hide",
104
+ copied: "Copied",
105
+ copy: "Copy",
106
+ details: "Details",
107
+ download: "Download",
108
+ dueOn: "Due {date}",
109
+ empty: "Nothing to show",
110
+ field: "Field",
111
+ from: "From",
112
+ hideDetails: "Hide details",
113
+ loadError: "This content could not be loaded.",
114
+ open: "Open",
115
+ overdue: "{duration} overdue",
116
+ pages: "{count} pages",
117
+ play: "Play the video",
118
+ readLess: "Show less",
119
+ readMore: "Read more",
120
+ retry: "Retry",
121
+ reveal: "Show",
122
+ showDetails: "Show details",
123
+ showMore: "Show more \xB7 {count}",
124
+ to: "To",
125
+ today: "Today"
126
+ },
100
127
  filePreview: {
101
128
  close: "Close",
102
129
  converted: {
@@ -718,8 +745,13 @@ export default defineUiToolsLocale({
718
745
  selectRowAt: "Select row {position}"
719
746
  },
720
747
  selectionBar: {
748
+ actions: "Actions",
749
+ actionsTitle: "Actions on the selection",
721
750
  allResults: "All results",
722
751
  clear: "Clear selection",
752
+ countAll: "All {count} results",
753
+ countSelectedOne: "{count} selected",
754
+ countSelectedOther: "{count} selected",
723
755
  more: "More actions",
724
756
  selection: "Selection"
725
757
  },
@@ -97,6 +97,33 @@ export default defineUiToolsLocale({
97
97
  retry: "R\xE9essayer"
98
98
  }
99
99
  },
100
+ display: {
101
+ after: "Apr\xE8s",
102
+ before: "Avant",
103
+ conceal: "Masquer",
104
+ copied: "Copi\xE9",
105
+ copy: "Copier",
106
+ details: "D\xE9tail",
107
+ download: "T\xE9l\xE9charger",
108
+ dueOn: "\xC9ch\xE9ance {date}",
109
+ empty: "Rien \xE0 afficher",
110
+ field: "Champ",
111
+ from: "Du",
112
+ hideDetails: "Masquer le d\xE9tail",
113
+ loadError: "Ce contenu n\u2019a pas pu \xEAtre charg\xE9.",
114
+ open: "Ouvrir",
115
+ overdue: "En retard de {duration}",
116
+ pages: "{count} pages",
117
+ play: "Lire la vid\xE9o",
118
+ readLess: "R\xE9duire",
119
+ readMore: "Lire la suite",
120
+ retry: "R\xE9essayer",
121
+ reveal: "Afficher",
122
+ showDetails: "Voir le d\xE9tail",
123
+ showMore: "Voir plus \xB7 {count}",
124
+ to: "Au",
125
+ today: "Aujourd'hui"
126
+ },
100
127
  filePreview: {
101
128
  close: "Fermer",
102
129
  converted: {
@@ -718,8 +745,13 @@ export default defineUiToolsLocale({
718
745
  selectRowAt: "S\xE9lectionner la ligne {position}"
719
746
  },
720
747
  selectionBar: {
748
+ actions: "Actions",
749
+ actionsTitle: "Actions sur la s\xE9lection",
721
750
  allResults: "Tous les r\xE9sultats",
722
751
  clear: "Effacer la s\xE9lection",
752
+ countAll: "Tous les {count} r\xE9sultats",
753
+ countSelectedOne: "{count} s\xE9lectionn\xE9",
754
+ countSelectedOther: "{count} s\xE9lectionn\xE9s",
723
755
  more: "Plus d\u2019actions",
724
756
  selection: "S\xE9lection"
725
757
  },
@@ -60,6 +60,11 @@ export interface UiToolsTableMessages {
60
60
  allResults: string;
61
61
  more: string;
62
62
  clear: string;
63
+ actions: string;
64
+ actionsTitle: string;
65
+ countSelectedOne: string;
66
+ countSelectedOther: string;
67
+ countAll: string;
63
68
  };
64
69
  summaries: {
65
70
  total: string;
@@ -718,6 +723,40 @@ export interface UiToolsDashboardMessages {
718
723
  };
719
724
  };
720
725
  }
726
+ export interface UiToolsDisplayMessages {
727
+ /** Shown by a block with nothing to list. */
728
+ empty: string;
729
+ /** "Show more · {count}" */
730
+ showMore: string;
731
+ readMore: string;
732
+ readLess: string;
733
+ showDetails: string;
734
+ hideDetails: string;
735
+ /** Toggle of a collapsible breakdown. */
736
+ details: string;
737
+ copy: string;
738
+ copied: string;
739
+ reveal: string;
740
+ conceal: string;
741
+ open: string;
742
+ download: string;
743
+ play: string;
744
+ today: string;
745
+ from: string;
746
+ to: string;
747
+ /** "{duration} overdue" */
748
+ overdue: string;
749
+ /** "Due {date}" */
750
+ dueOn: string;
751
+ /** "{count} pages" */
752
+ pages: string;
753
+ /** Shown when a block's props failed to load. */
754
+ loadError: string;
755
+ retry: string;
756
+ field: string;
757
+ before: string;
758
+ after: string;
759
+ }
721
760
  export interface UiToolsFilePreviewMessages {
722
761
  /** Name shown for a file that has none, such as a pasted image. */
723
762
  untitled: string;
@@ -826,6 +865,7 @@ export interface UiToolsFilePreviewMessages {
826
865
  }
827
866
  export interface Messages {
828
867
  dashboard: UiToolsDashboardMessages;
868
+ display: UiToolsDisplayMessages;
829
869
  filePreview: UiToolsFilePreviewMessages;
830
870
  form: UiToolsFormMessages;
831
871
  table: UiToolsTableMessages;
@@ -1 +1 @@
1
- @layer theme, base, components, utilities;@layer base{:root{--nut-form-veil:rgba(31,29,26,.18)}.dark{--nut-form-veil:rgba(0,0,0,.45)}:where(:root){--nut-dash-s1:var(--ui-primary);--nut-dash-s2:var(--ui-color-neutral-400);--nut-dash-s3:var(--ui-secondary);--nut-dash-s4:color-mix(in oklab,var(--ui-primary) 20%,var(--ui-bg));--nut-dash-s5:var(--ui-warning);--nut-dash-s6:color-mix(in oklab,var(--ui-secondary) 35%,var(--ui-bg));--nut-dash-up:var(--ui-success);--nut-dash-up-mark:var(--nut-dash-up);--nut-dash-down:var(--ui-error);--nut-dash-muted:var(--ui-border-accented);--nut-dash-track:var(--ui-bg-elevated);--nut-dash-grid:var(--ui-border-muted);--nut-dash-axis:var(--ui-text-dimmed);--nut-dash-ref:var(--ui-text-dimmed);--nut-dash-ref-label:var(--ui-text-muted);--nut-dash-ghost:var(--ui-bg-accented);--nut-dash-ghost-shine:color-mix(in oklab,var(--ui-bg) 70%,transparent);--nut-dash-filter-active:color-mix(in oklab,var(--ui-primary) 9%,var(--ui-bg));--nut-dash-filter-active-line:color-mix(in oklab,var(--ui-primary) 35%,var(--ui-border));--nut-dash-filter-ink:var(--nut-dl-accent-ink,var(--ui-primary));--nut-dash-row-hover:var(--ui-bg-elevated)}:where(.dark){--nut-dash-s2:var(--ui-color-neutral-500);--nut-dash-s4:color-mix(in oklab,var(--ui-primary) 30%,var(--ui-bg));--nut-dash-s6:color-mix(in oklab,var(--ui-secondary) 40%,var(--ui-bg))}@supports (color:oklch(from red l c h)){:where(:root){--nut-dash-s4:oklch(from var(--ui-primary) 0.88 calc(c * 0.45) h);--nut-dash-s6:oklch(from var(--ui-secondary) 0.8 calc(c * 0.55) h)}:where(.dark){--nut-dash-s4:oklch(from var(--ui-primary) 0.42 calc(c * 0.6) h);--nut-dash-s6:oklch(from var(--ui-secondary) 0.45 calc(c * 0.65) h)}}:where(:root){--nut-fp-veil:rgba(31,29,26,.4);--nut-fp-stage:var(--ui-bg-muted);--nut-fp-document:#525659;--nut-fp-checker-a:#fff;--nut-fp-checker-b:#ebe7e2;--nut-fp-token-key:var(--ui-primary);--nut-fp-token-string:var(--ui-success);--nut-fp-token-number:var(--ui-info);--nut-fp-token-literal:var(--ui-error)}:where(.dark){--nut-fp-veil:rgba(0,0,0,.62);--nut-fp-stage:var(--ui-bg);--nut-fp-checker-a:#e9e4dd;--nut-fp-checker-b:#d8d1c7}}@layer components{.nut-dash-chart{--vis-font-family:inherit;--vis-axis-tick-label-color:var(--nut-dash-axis);--vis-axis-tick-label-font-size:10px;--vis-axis-grid-color:var(--nut-dash-grid);--vis-axis-domain-color:var(--nut-dash-grid);--vis-crosshair-line-stroke-color:var(--ui-border-accented);--vis-crosshair-circle-stroke-color:var(--ui-bg);--vis-tooltip-background-color:var(--ui-bg);--vis-tooltip-border-color:var(--ui-border);--vis-tooltip-text-color:var(--ui-text);--vis-tooltip-padding:8px 10px;--vis-tooltip-border-radius:calc(var(--ui-radius)*1.5);--vis-tooltip-shadow-color:rgb(0 0 0/8%);--vis-plotline-label-font-size:10px}.nut-dash-chart--bars [data-vis-component] rect:hover{opacity:.8}.nut-dash-tip{display:flex;flex-direction:column;font-size:12px;gap:4px;min-width:9rem}.nut-dash-tip-title{color:var(--ui-text-muted);font-weight:500}.nut-dash-tip-row{align-items:center;display:flex;gap:6px}.nut-dash-tip-row i{border-radius:2px;height:8px;width:8px}.nut-dash-tip-row span{color:var(--ui-text-muted);flex:1}.nut-dash-tip-row b{font-variant-numeric:tabular-nums;font-weight:600}.nut-dash-ghost{background:var(--nut-dash-ghost)}.nut-dash-shimmer{overflow:hidden;position:relative}.nut-dash-shimmer:after{animation:nut-dash-shimmer 1.6s ease-in-out infinite;background:linear-gradient(100deg,transparent 25%,var(--nut-dash-ghost-shine) 50%,transparent 75%);content:"";inset:0;pointer-events:none;position:absolute;transform:translateX(-100%);will-change:transform}@keyframes nut-dash-shimmer{to{transform:translateX(100%)}}.nut-dash-enter{animation:nut-dash-enter .28s ease-out}@keyframes nut-dash-enter{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:none}}.nut-dash-progress{animation:nut-dash-progress 1.1s ease-in-out infinite}@keyframes nut-dash-progress{0%{transform:translateX(-100%)}to{transform:translateX(300%)}}@media (prefers-reduced-motion:reduce){.nut-dash-shimmer:after{display:none}.nut-dash-enter{animation:none}.nut-dash-progress{animation-duration:3s}}.nut-fp-checker{background-color:var(--nut-fp-checker-a);background-image:conic-gradient(var(--nut-fp-checker-b) 25%,transparent 0 50%,var(--nut-fp-checker-b) 0 75%,transparent 0);background-size:18px 18px}.nut-fp-code [data-token=key]{color:var(--nut-fp-token-key)}.nut-fp-code [data-token=string]{color:var(--nut-fp-token-string)}.nut-fp-code [data-token=number]{color:var(--nut-fp-token-number)}.nut-fp-code [data-token=literal]{color:var(--nut-fp-token-literal)}[data-file-preview-bottom][data-single]:has([data-file-preview-tools]:empty){display:none}@keyframes nut-fp-progress{0%{transform:translateX(-100%)}to{transform:translateX(300%)}}.nut-fp-progress{animation:nut-fp-progress 1s ease-in-out infinite}@keyframes nut-fp-equalizer{to{transform:scaleY(.45)}}.nut-fp-equalizer{animation:nut-fp-equalizer .9s ease-in-out infinite alternate}@media (prefers-reduced-motion:reduce){.nut-fp-progress{animation-duration:2.4s}.nut-fp-equalizer{animation:none}}.nut-fp-prose{color:var(--ui-text);font-size:.925rem;line-height:1.7}.nut-fp-prose>:first-child{margin-top:0}.nut-fp-prose :where(h1,h2,h3,h4){color:var(--ui-text-highlighted);font-weight:650;letter-spacing:-.01em;line-height:1.25;margin:1.75em 0 .6em}.nut-fp-prose h1{font-size:1.6em}.nut-fp-prose h2{font-size:1.25em}.nut-fp-prose h3{font-size:1.05em}.nut-fp-prose :where(p,ul,ol,pre,table,blockquote){margin:0 0 1em}.nut-fp-prose :where(ul,ol){padding-inline-start:1.4em}.nut-fp-prose ul{list-style:disc}.nut-fp-prose ol{list-style:decimal}.nut-fp-prose a{color:var(--ui-primary);text-decoration:underline;text-underline-offset:2px}.nut-fp-prose :not(pre)>code{background:var(--ui-bg-elevated);border:1px solid var(--ui-border-muted);border-radius:4px;font-size:.86em;padding:.1em .35em}.nut-fp-prose pre{background:var(--ui-bg-elevated);border:1px solid var(--ui-border);border-radius:8px;font-size:.85em;overflow-x:auto;padding:.9em 1.1em}.nut-fp-prose table{border-collapse:collapse;display:block;font-size:.9em;overflow-x:auto}.nut-fp-prose :where(th,td){border:1px solid var(--ui-border);padding:.4em .75em;text-align:start}.nut-fp-prose th{background:var(--ui-bg-elevated);font-weight:600}.nut-fp-prose blockquote{border-inline-start:3px solid var(--ui-primary);color:var(--ui-text-toned);padding-inline-start:1em}.nut-fp-prose img{border-radius:6px;max-width:100%}}
1
+ @layer theme, base, components, utilities;@layer base{:root{--nut-form-veil:rgba(31,29,26,.18)}.dark{--nut-form-veil:rgba(0,0,0,.45)}:where(:root){--nut-dash-s1:var(--ui-primary);--nut-dash-s2:var(--ui-color-neutral-400);--nut-dash-s3:var(--ui-secondary);--nut-dash-s4:color-mix(in oklab,var(--ui-primary) 20%,var(--ui-bg));--nut-dash-s5:var(--ui-warning);--nut-dash-s6:color-mix(in oklab,var(--ui-secondary) 35%,var(--ui-bg));--nut-dash-up:var(--ui-success);--nut-dash-up-mark:var(--nut-dash-up);--nut-dash-down:var(--ui-error);--nut-dash-muted:var(--ui-border-accented);--nut-dash-track:var(--ui-bg-elevated);--nut-dash-grid:var(--ui-border-muted);--nut-dash-axis:var(--ui-text-dimmed);--nut-dash-ref:var(--ui-text-dimmed);--nut-dash-ref-label:var(--ui-text-muted);--nut-dash-ghost:var(--ui-bg-accented);--nut-dash-ghost-shine:color-mix(in oklab,var(--ui-bg) 70%,transparent);--nut-dash-filter-active:color-mix(in oklab,var(--ui-primary) 9%,var(--ui-bg));--nut-dash-filter-active-line:color-mix(in oklab,var(--ui-primary) 35%,var(--ui-border));--nut-dash-filter-ink:var(--nut-dl-accent-ink,var(--ui-primary));--nut-dash-row-hover:var(--ui-bg-elevated)}:where(.dark){--nut-dash-s2:var(--ui-color-neutral-500);--nut-dash-s4:color-mix(in oklab,var(--ui-primary) 30%,var(--ui-bg));--nut-dash-s6:color-mix(in oklab,var(--ui-secondary) 40%,var(--ui-bg))}@supports (color:oklch(from red l c h)){:where(:root){--nut-dash-s4:oklch(from var(--ui-primary) 0.88 calc(c * 0.45) h);--nut-dash-s6:oklch(from var(--ui-secondary) 0.8 calc(c * 0.55) h)}:where(.dark){--nut-dash-s4:oklch(from var(--ui-primary) 0.42 calc(c * 0.6) h);--nut-dash-s6:oklch(from var(--ui-secondary) 0.45 calc(c * 0.65) h)}}:where(:root){--nut-fp-veil:rgba(31,29,26,.4);--nut-fp-stage:var(--ui-bg-muted);--nut-fp-document:#525659;--nut-fp-checker-a:#fff;--nut-fp-checker-b:#ebe7e2;--nut-fp-token-key:var(--ui-primary);--nut-fp-token-string:var(--ui-success);--nut-fp-token-number:var(--ui-info);--nut-fp-token-literal:var(--ui-error)}:where(.dark){--nut-fp-veil:rgba(0,0,0,.62);--nut-fp-stage:var(--ui-bg);--nut-fp-checker-a:#e9e4dd;--nut-fp-checker-b:#d8d1c7}:where(:root){--nut-display-radius:calc(var(--ui-radius)*2);--nut-display-track:var(--ui-bg-accented);--nut-display-code-bg:var(--ui-color-neutral-900);--nut-display-code-ink:var(--ui-color-neutral-100);--nut-display-code-muted:var(--ui-color-neutral-400);--nut-display-code-line:var(--ui-color-neutral-800);--nut-display-code-key:var(--ui-color-primary-300);--nut-display-code-string:var(--ui-color-success-300);--nut-display-code-number:var(--ui-color-info-300);--nut-display-code-literal:var(--ui-color-error-300);--nut-display-primary:var(--ui-primary);--nut-display-primary-ink:var(--ui-primary);--nut-display-primary-soft:color-mix(in oklab,var(--ui-primary) 10%,var(--ui-bg));--nut-display-primary-line:color-mix(in oklab,var(--ui-primary) 40%,var(--ui-bg));--nut-display-primary-contrast:var(--ui-text-inverted);--nut-display-secondary:var(--ui-secondary);--nut-display-secondary-ink:var(--ui-secondary);--nut-display-secondary-soft:color-mix(in oklab,var(--ui-secondary) 10%,var(--ui-bg));--nut-display-secondary-line:color-mix(in oklab,var(--ui-secondary) 40%,var(--ui-bg));--nut-display-secondary-contrast:var(--ui-text-inverted);--nut-display-success:var(--ui-success);--nut-display-success-ink:var(--ui-success);--nut-display-success-soft:color-mix(in oklab,var(--ui-success) 10%,var(--ui-bg));--nut-display-success-line:color-mix(in oklab,var(--ui-success) 40%,var(--ui-bg));--nut-display-success-contrast:var(--ui-text-inverted);--nut-display-info:var(--ui-info);--nut-display-info-ink:var(--ui-info);--nut-display-info-soft:color-mix(in oklab,var(--ui-info) 10%,var(--ui-bg));--nut-display-info-line:color-mix(in oklab,var(--ui-info) 40%,var(--ui-bg));--nut-display-info-contrast:var(--ui-text-inverted);--nut-display-warning:var(--ui-warning);--nut-display-warning-ink:var(--ui-warning);--nut-display-warning-soft:color-mix(in oklab,var(--ui-warning) 10%,var(--ui-bg));--nut-display-warning-line:color-mix(in oklab,var(--ui-warning) 40%,var(--ui-bg));--nut-display-warning-contrast:var(--ui-text-inverted);--nut-display-error:var(--ui-error);--nut-display-error-ink:var(--ui-error);--nut-display-error-soft:color-mix(in oklab,var(--ui-error) 10%,var(--ui-bg));--nut-display-error-line:color-mix(in oklab,var(--ui-error) 40%,var(--ui-bg));--nut-display-error-contrast:var(--ui-text-inverted);--nut-display-neutral:var(--ui-bg-inverted);--nut-display-neutral-ink:var(--ui-text-toned);--nut-display-neutral-soft:var(--ui-bg-elevated);--nut-display-neutral-line:var(--ui-border-accented);--nut-display-neutral-contrast:var(--ui-text-inverted)}:where(.dark){--nut-display-code-bg:var(--ui-color-neutral-950);--nut-display-code-line:var(--ui-color-neutral-800)}:where(.nut-display-tone-primary){--nut-tone:var(--nut-display-primary);--nut-tone-ink:var(--nut-display-primary-ink);--nut-tone-soft:var(--nut-display-primary-soft);--nut-tone-line:var(--nut-display-primary-line);--nut-tone-contrast:var(--nut-display-primary-contrast)}:where(.nut-display-tone-secondary){--nut-tone:var(--nut-display-secondary);--nut-tone-ink:var(--nut-display-secondary-ink);--nut-tone-soft:var(--nut-display-secondary-soft);--nut-tone-line:var(--nut-display-secondary-line);--nut-tone-contrast:var(--nut-display-secondary-contrast)}:where(.nut-display-tone-success){--nut-tone:var(--nut-display-success);--nut-tone-ink:var(--nut-display-success-ink);--nut-tone-soft:var(--nut-display-success-soft);--nut-tone-line:var(--nut-display-success-line);--nut-tone-contrast:var(--nut-display-success-contrast)}:where(.nut-display-tone-info){--nut-tone:var(--nut-display-info);--nut-tone-ink:var(--nut-display-info-ink);--nut-tone-soft:var(--nut-display-info-soft);--nut-tone-line:var(--nut-display-info-line);--nut-tone-contrast:var(--nut-display-info-contrast)}:where(.nut-display-tone-warning){--nut-tone:var(--nut-display-warning);--nut-tone-ink:var(--nut-display-warning-ink);--nut-tone-soft:var(--nut-display-warning-soft);--nut-tone-line:var(--nut-display-warning-line);--nut-tone-contrast:var(--nut-display-warning-contrast)}:where(.nut-display-tone-error){--nut-tone:var(--nut-display-error);--nut-tone-ink:var(--nut-display-error-ink);--nut-tone-soft:var(--nut-display-error-soft);--nut-tone-line:var(--nut-display-error-line);--nut-tone-contrast:var(--nut-display-error-contrast)}:where(.nut-display-tone-neutral){--nut-tone:var(--nut-display-neutral);--nut-tone-ink:var(--nut-display-neutral-ink);--nut-tone-soft:var(--nut-display-neutral-soft);--nut-tone-line:var(--nut-display-neutral-line);--nut-tone-contrast:var(--nut-display-neutral-contrast)}}@layer components{.nut-dash-chart{--vis-font-family:inherit;--vis-axis-tick-label-color:var(--nut-dash-axis);--vis-axis-tick-label-font-size:10px;--vis-axis-grid-color:var(--nut-dash-grid);--vis-axis-domain-color:var(--nut-dash-grid);--vis-crosshair-line-stroke-color:var(--ui-border-accented);--vis-crosshair-circle-stroke-color:var(--ui-bg);--vis-tooltip-background-color:var(--ui-bg);--vis-tooltip-border-color:var(--ui-border);--vis-tooltip-text-color:var(--ui-text);--vis-tooltip-padding:8px 10px;--vis-tooltip-border-radius:calc(var(--ui-radius)*1.5);--vis-tooltip-shadow-color:rgb(0 0 0/8%);--vis-plotline-label-font-size:10px}.nut-dash-chart--bars [data-vis-component] rect:hover{opacity:.8}.nut-dash-tip{display:flex;flex-direction:column;font-size:12px;gap:4px;min-width:9rem}.nut-dash-tip-title{color:var(--ui-text-muted);font-weight:500}.nut-dash-tip-row{align-items:center;display:flex;gap:6px}.nut-dash-tip-row i{border-radius:2px;height:8px;width:8px}.nut-dash-tip-row span{color:var(--ui-text-muted);flex:1}.nut-dash-tip-row b{font-variant-numeric:tabular-nums;font-weight:600}.nut-dash-ghost{background:var(--nut-dash-ghost)}.nut-dash-shimmer{overflow:hidden;position:relative}.nut-dash-shimmer:after{animation:nut-dash-shimmer 1.6s ease-in-out infinite;background:linear-gradient(100deg,transparent 25%,var(--nut-dash-ghost-shine) 50%,transparent 75%);content:"";inset:0;pointer-events:none;position:absolute;transform:translateX(-100%);will-change:transform}@keyframes nut-dash-shimmer{to{transform:translateX(100%)}}.nut-dash-enter{animation:nut-dash-enter .28s ease-out}@keyframes nut-dash-enter{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:none}}.nut-dash-progress{animation:nut-dash-progress 1.1s ease-in-out infinite}@keyframes nut-dash-progress{0%{transform:translateX(-100%)}to{transform:translateX(300%)}}@media (prefers-reduced-motion:reduce){.nut-dash-shimmer:after{display:none}.nut-dash-enter{animation:none}.nut-dash-progress{animation-duration:3s}}.nut-fp-checker{background-color:var(--nut-fp-checker-a);background-image:conic-gradient(var(--nut-fp-checker-b) 25%,transparent 0 50%,var(--nut-fp-checker-b) 0 75%,transparent 0);background-size:18px 18px}.nut-fp-code [data-token=key]{color:var(--nut-fp-token-key)}.nut-fp-code [data-token=string]{color:var(--nut-fp-token-string)}.nut-fp-code [data-token=number]{color:var(--nut-fp-token-number)}.nut-fp-code [data-token=literal]{color:var(--nut-fp-token-literal)}[data-file-preview-bottom][data-single]:has([data-file-preview-tools]:empty){display:none}@keyframes nut-fp-progress{0%{transform:translateX(-100%)}to{transform:translateX(300%)}}.nut-fp-progress{animation:nut-fp-progress 1s ease-in-out infinite}@keyframes nut-fp-equalizer{to{transform:scaleY(.45)}}.nut-fp-equalizer{animation:nut-fp-equalizer .9s ease-in-out infinite alternate}@media (prefers-reduced-motion:reduce){.nut-fp-progress{animation-duration:2.4s}.nut-fp-equalizer{animation:none}}.nut-fp-prose{color:var(--ui-text);font-size:.925rem;line-height:1.7}.nut-fp-prose>:first-child{margin-top:0}.nut-fp-prose :where(h1,h2,h3,h4){color:var(--ui-text-highlighted);font-weight:650;letter-spacing:-.01em;line-height:1.25;margin:1.75em 0 .6em}.nut-fp-prose h1{font-size:1.6em}.nut-fp-prose h2{font-size:1.25em}.nut-fp-prose h3{font-size:1.05em}.nut-fp-prose :where(p,ul,ol,pre,table,blockquote){margin:0 0 1em}.nut-fp-prose :where(ul,ol){padding-inline-start:1.4em}.nut-fp-prose ul{list-style:disc}.nut-fp-prose ol{list-style:decimal}.nut-fp-prose a{color:var(--ui-primary);text-decoration:underline;text-underline-offset:2px}.nut-fp-prose :not(pre)>code{background:var(--ui-bg-elevated);border:1px solid var(--ui-border-muted);border-radius:4px;font-size:.86em;padding:.1em .35em}.nut-fp-prose pre{background:var(--ui-bg-elevated);border:1px solid var(--ui-border);border-radius:8px;font-size:.85em;overflow-x:auto;padding:.9em 1.1em}.nut-fp-prose table{border-collapse:collapse;display:block;font-size:.9em;overflow-x:auto}.nut-fp-prose :where(th,td){border:1px solid var(--ui-border);padding:.4em .75em;text-align:start}.nut-fp-prose th{background:var(--ui-bg-elevated);font-weight:600}.nut-fp-prose blockquote{border-inline-start:3px solid var(--ui-primary);color:var(--ui-text-toned);padding-inline-start:1em}.nut-fp-prose img{border-radius:6px;max-width:100%}}
@@ -1,4 +1,4 @@
1
- export declare function fileIconName(type: string | null | undefined): "i-lucide-file-text" | "i-lucide-file-image" | "i-lucide-file-video" | "i-lucide-file-audio" | "i-lucide-file-spreadsheet" | "i-lucide-file-type" | "i-lucide-file-archive" | "i-lucide-file";
1
+ export declare function fileIconName(type: string | null | undefined): "i-lucide-file" | "i-lucide-file-text" | "i-lucide-file-image" | "i-lucide-file-video" | "i-lucide-file-audio" | "i-lucide-file-spreadsheet" | "i-lucide-file-type" | "i-lucide-file-archive";
2
2
  /** Lowercase extension of a file name without the dot, or `null` when it has none. */
3
3
  export declare function fileExtension(name: string): string | null;
4
4
  export declare function fileExtensionLabel(file: {
@@ -4,6 +4,7 @@ import { computed, onBeforeUnmount, onMounted } from "vue";
4
4
  import { provideUiToolsLocale, useUiToolsLocaleRef } from "#ui-tools/i18n";
5
5
  import { isObject } from "../../../shared/utils/predicate";
6
6
  import { useDataListBreakpoint } from "../../composables/use-data-list-breakpoint";
7
+ import { provideDataListOverlayInset } from "../../composables/use-data-list-overlay-inset";
7
8
  import { provideDataListUi } from "../../composables/use-data-list-ui";
8
9
  import { provideTableInternals } from "../../composables/use-table-internals";
9
10
  import { mergeDataListUiConfig } from "../../utils";
@@ -18,6 +19,7 @@ const props = defineProps({
18
19
  const appConfig = useAppConfig();
19
20
  provideTableInternals(props.table["__internals"]);
20
21
  provideUiToolsLocale(useUiToolsLocaleRef(computed(() => props.locale)));
22
+ provideDataListOverlayInset();
21
23
  const { isMobile } = useDataListBreakpoint();
22
24
  provideDataListUi(
23
25
  computed(() => {
@@ -4,7 +4,7 @@ type __VLS_Props = {
4
4
  size?: DataListControlSize;
5
5
  /** `absolute` docks the bar inside the nearest positioned ancestor; `fixed` pins it to the viewport. */
6
6
  position?: 'absolute' | 'fixed';
7
- /** Number of actions rendered inline before the overflow menu. */
7
+ /** Number of actions the desktop bar renders inline before the overflow menu. Below `md` every action opens from a sheet. */
8
8
  maxVisible?: number;
9
9
  /** Shows the selection / all-results scope switch when the schema allows an `all` scope. */
10
10
  scope?: boolean;
@@ -1,15 +1,17 @@
1
1
  <script setup>
2
2
  import UButton from "@nuxt/ui/components/Button.vue";
3
3
  import UDropdownMenu from "@nuxt/ui/components/DropdownMenu.vue";
4
- import { useResizeObserver } from "@vueuse/core";
5
- import { computed, nextTick, ref, useTemplateRef, watch } from "vue";
4
+ import { useElementSize, useResizeObserver } from "@vueuse/core";
5
+ import { computed, nextTick, onBeforeUnmount, ref, useTemplateRef, watch, watchEffect } from "vue";
6
6
  import { useUiToolsLocale } from "#ui-tools/i18n";
7
7
  import { isString, isNullish } from "../../../shared/utils/predicate";
8
8
  import { useDataListBreakpoint } from "../../composables/use-data-list-breakpoint";
9
+ import { useDataListOverlayInset } from "../../composables/use-data-list-overlay-inset";
9
10
  import { useDataListUi } from "../../composables/use-data-list-ui";
10
11
  import { useTableInternals } from "../../composables/use-table-internals";
11
12
  import { mergeDataListProps, mergeDataListUiClass } from "../../utils";
12
13
  import { resolveTableActionLabel } from "../../utils/actions";
14
+ import DataListSelectionSheet from "./data-list-selection-sheet.vue";
13
15
  const props = defineProps({
14
16
  size: { type: String, required: false },
15
17
  position: { type: String, required: false, default: "absolute" },
@@ -59,7 +61,12 @@ const scopeEnabled = computed(
59
61
  () => props.scope && internals.schema.value.selection?.scope !== "page" && !isNullish(matchingCount.value) && matchingCount.value > 0
60
62
  );
61
63
  const bulkScope = computed(() => internals.selection.bulkScope.value);
62
- const maxVisible = computed(() => props.maxVisible ?? (isMobile.value ? 1 : 3));
64
+ const maxVisible = computed(() => props.maxVisible ?? 3);
65
+ const placement = computed(() => {
66
+ if (props.position === "fixed")
67
+ return isMobile.value ? "fixed inset-x-0 bottom-[calc(12px+env(safe-area-inset-bottom))]" : "fixed inset-x-0 bottom-4";
68
+ return isMobile.value ? "absolute inset-x-0 bottom-3" : "absolute inset-x-0 bottom-[22px]";
69
+ });
63
70
  const fitted = ref(Number.POSITIVE_INFINITY);
64
71
  const visibleCount = computed(() => Math.min(maxVisible.value, fitted.value));
65
72
  const visibleActions = computed(() => actions.value.slice(0, visibleCount.value));
@@ -99,6 +106,7 @@ async function fit() {
99
106
  watch(
100
107
  () => [
101
108
  selectedCount.value > 0,
109
+ isMobile.value,
102
110
  maxVisible.value,
103
111
  actions.value.map((action) => resolveTableActionLabel(action.definition.label)).join("\n")
104
112
  ],
@@ -106,6 +114,15 @@ watch(
106
114
  { flush: "post" }
107
115
  );
108
116
  useResizeObserver(rootElement, () => void fit());
117
+ const overlayInset = useDataListOverlayInset();
118
+ const { height: rootHeight } = useElementSize(rootElement);
119
+ watchEffect(() => {
120
+ if (overlayInset)
121
+ overlayInset.bottom.value = isMobile.value && rootHeight.value ? rootHeight.value + 24 : 0;
122
+ });
123
+ onBeforeUnmount(() => {
124
+ if (overlayInset) overlayInset.bottom.value = 0;
125
+ });
109
126
  </script>
110
127
 
111
128
  <template>
@@ -115,20 +132,30 @@ useResizeObserver(rootElement, () => void fit());
115
132
  ref="rootElement"
116
133
  :class="
117
134
  mergeDataListUiClass(
118
- `nut-dl-selbar pointer-events-none z-40 flex justify-center px-4 ${position === 'fixed' ? 'fixed inset-x-0 bottom-4' : 'absolute inset-x-0 bottom-[22px]'}`,
135
+ `nut-dl-selbar pointer-events-none z-40 flex justify-center px-4 ${placement}`,
119
136
  void 0,
120
137
  ui.root
121
138
  )
122
139
  "
123
140
  >
124
- <div class="pointer-events-auto flex max-w-full justify-center">
141
+ <div
142
+ class="pointer-events-auto flex max-w-full justify-center"
143
+ :class="{ 'w-full': isMobile }"
144
+ >
125
145
  <slot
126
146
  :actions="actions"
127
147
  :selected-count="selectedCount"
128
148
  :selection="selection"
129
149
  :clear-selection="clearSelection"
130
150
  >
151
+ <DataListSelectionSheet
152
+ v-if="isMobile"
153
+ :scope="scopeEnabled"
154
+ :ui="ui"
155
+ :controls="controlProps"
156
+ />
131
157
  <div
158
+ v-else
132
159
  :class="
133
160
  mergeDataListUiClass(
134
161
  'nut-dl-selbar__bar flex h-11 max-w-[min(840px,100%)] items-center gap-2.5 rounded-[10px] bg-inverted px-1.5 text-[13px] text-inverted shadow-[0_20px_50px_-18px_rgb(31_29_26/0.6)]',
@@ -4,7 +4,7 @@ type __VLS_Props = {
4
4
  size?: DataListControlSize;
5
5
  /** `absolute` docks the bar inside the nearest positioned ancestor; `fixed` pins it to the viewport. */
6
6
  position?: 'absolute' | 'fixed';
7
- /** Number of actions rendered inline before the overflow menu. */
7
+ /** Number of actions the desktop bar renders inline before the overflow menu. Below `md` every action opens from a sheet. */
8
8
  maxVisible?: number;
9
9
  /** Shows the selection / all-results scope switch when the schema allows an `all` scope. */
10
10
  scope?: boolean;
@@ -0,0 +1,10 @@
1
+ import type { DataListSelectionActionsProps, DataListSelectionActionsUi } from '../../types/index.js';
2
+ type __VLS_Props = {
3
+ /** Shows the selection / all-results scope switch at the top of the sheet. */
4
+ scope: boolean;
5
+ ui: DataListSelectionActionsUi;
6
+ controls: DataListSelectionActionsProps;
7
+ };
8
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ declare const _default: typeof __VLS_export;
10
+ export default _default;
@@ -0,0 +1,238 @@
1
+ <script setup>
2
+ import UButton from "@nuxt/ui/components/Button.vue";
3
+ import UDrawer from "@nuxt/ui/components/Drawer.vue";
4
+ import UIcon from "@nuxt/ui/components/Icon.vue";
5
+ import { computed, nextTick, ref, useId, useTemplateRef, watch } from "vue";
6
+ import { useUiToolsLocale } from "#ui-tools/i18n";
7
+ import { isString } from "../../../shared/utils/predicate";
8
+ import { useTableInternals } from "../../composables/use-table-internals";
9
+ import { mergeDataListProps, mergeDataListUiClass } from "../../utils";
10
+ import { resolveTableActionLabel } from "../../utils/actions";
11
+ const props = defineProps({
12
+ scope: { type: Boolean, required: true },
13
+ ui: { type: Object, required: true },
14
+ controls: { type: Object, required: true }
15
+ });
16
+ const internals = useTableInternals();
17
+ const { locale, t } = useUiToolsLocale();
18
+ const id = useId();
19
+ const open = ref(false);
20
+ const sheetBody = useTemplateRef("sheetBody");
21
+ const selectedCount = computed(() => internals.selection.selectedCount.value);
22
+ const matchingCount = computed(() => internals.pagination.rowCount.value ?? 0);
23
+ const bulkScope = computed(() => internals.selection.bulkScope.value);
24
+ const targetsAll = computed(() => props.scope && bulkScope.value === "all");
25
+ const count = computed(() => {
26
+ const template = targetsAll.value ? t("table.selectionBar.countAll") : selectedCount.value === 1 ? t("table.selectionBar.countSelectedOne") : t("table.selectionBar.countSelectedOther");
27
+ const [before = "", after = ""] = template.split("{count}");
28
+ const value = formatCount(targetsAll.value ? matchingCount.value : selectedCount.value);
29
+ return { after, before, text: `${before}${value}${after}`, value };
30
+ });
31
+ const scopeOptions = computed(() => [
32
+ {
33
+ count: selectedCount.value,
34
+ label: t("table.selectionBar.selection"),
35
+ value: "selection"
36
+ },
37
+ { count: matchingCount.value, label: t("table.selectionBar.allResults"), value: "all" }
38
+ ]);
39
+ const rows = computed(() => internals.actions.bulkActions.value.map(toRow));
40
+ const groups = computed(
41
+ () => [
42
+ rows.value.filter((row) => !row.destructive),
43
+ rows.value.filter((row) => row.destructive)
44
+ ].filter((group) => group.length)
45
+ );
46
+ const busy = computed(() => rows.value.some((row) => row.pending));
47
+ const triggerProps = computed(
48
+ () => mergeDataListProps(
49
+ {
50
+ color: "primary",
51
+ label: t("table.selectionBar.actions"),
52
+ size: "lg",
53
+ trailingIcon: "i-lucide-chevron-up",
54
+ variant: "solid"
55
+ },
56
+ props.controls.trigger
57
+ )
58
+ );
59
+ const dismissProps = computed(
60
+ () => mergeDataListProps(
61
+ { color: "neutral", icon: "i-lucide-x", size: "lg", square: true, variant: "ghost" },
62
+ props.controls.dismiss
63
+ )
64
+ );
65
+ function formatCount(value) {
66
+ return new Intl.NumberFormat(locale.value.code).format(value);
67
+ }
68
+ function toRow(action) {
69
+ const pending = action.running || action.state.loading;
70
+ const icon = isString(action.definition.icon) ? action.definition.icon : void 0;
71
+ return {
72
+ action,
73
+ destructive: action.definition.color === "error",
74
+ detail: action.state.disabled && action.state.disabledReason || action.definition.description,
75
+ detailId: `${id}-${action.definition.key}`,
76
+ icon: pending ? "i-lucide-loader-circle" : icon,
77
+ label: resolveTableActionLabel(action.definition.label) ?? action.definition.key,
78
+ pending,
79
+ unavailable: action.state.disabled || pending
80
+ };
81
+ }
82
+ watch(open, async (value) => {
83
+ if (!value) return;
84
+ await nextTick();
85
+ sheetBody.value?.querySelector(
86
+ '[role="radio"][aria-checked="true"], .nut-dl-selsheet__action:not([aria-disabled])'
87
+ )?.focus({ preventScroll: true });
88
+ });
89
+ function run(row) {
90
+ if (row.unavailable) return;
91
+ open.value = false;
92
+ void row.action.execute();
93
+ }
94
+ </script>
95
+
96
+ <template>
97
+ <div
98
+ :class="
99
+ mergeDataListUiClass(
100
+ 'nut-dl-selbar__bar nut-dl-selbar__bar--compact flex h-[60px] w-full items-center gap-1 rounded-[calc(var(--ui-radius)*2+0.5rem)] bg-inverted p-2 text-inverted shadow-[0_20px_50px_-18px_rgb(31_29_26/0.6)]',
101
+ void 0,
102
+ ui.bar
103
+ )
104
+ "
105
+ role="region"
106
+ :aria-label="t('table.selectionBar.selection')"
107
+ >
108
+ <UButton
109
+ v-bind="dismissProps"
110
+ :aria-label="t('table.selectionBar.clear')"
111
+ :title="t('table.selectionBar.clear')"
112
+ :ui="{
113
+ base: mergeDataListUiClass(
114
+ 'nut-dl-selbar__dismiss size-11 shrink-0 justify-center text-inverted/80 hover:bg-white/12 hover:text-inverted focus-visible:outline-2 focus-visible:outline-[var(--ui-text-inverted)] active:bg-white/16 active:text-inverted',
115
+ void 0,
116
+ ui.dismiss
117
+ )
118
+ }"
119
+ @click="internals.selection.clearSelection()"
120
+ />
121
+
122
+ <span
123
+ :class="
124
+ mergeDataListUiClass(
125
+ 'nut-dl-selbar__count min-w-0 flex-1 text-[15px] leading-tight font-semibold',
126
+ void 0,
127
+ ui.count
128
+ )
129
+ "
130
+ role="status"
131
+ >
132
+ {{ count.before }}<span class="text-primary tabular-nums">{{ count.value }}</span
133
+ >{{ count.after }}
134
+ </span>
135
+
136
+ <UDrawer
137
+ v-model:open="open"
138
+ direction="bottom"
139
+ :handle="true"
140
+ :title="t('table.selectionBar.actionsTitle')"
141
+ :ui="{
142
+ header: 'sr-only',
143
+ content: mergeDataListUiClass(
144
+ 'nut-dl-sheet nut-dl-selsheet max-h-[85vh] rounded-t-[16px]',
145
+ void 0,
146
+ ui.sheet
147
+ ),
148
+ container: 'gap-0 p-0',
149
+ body: 'min-h-0 overflow-y-auto p-0 pb-[max(12px,env(safe-area-inset-bottom))]'
150
+ }"
151
+ >
152
+ <UButton
153
+ v-bind="triggerProps"
154
+ :aria-label="t('table.selectionBar.actionsTitle')"
155
+ :loading="busy"
156
+ :ui="{
157
+ base: mergeDataListUiClass(
158
+ 'nut-dl-selbar__trigger h-11 shrink-0 rounded-lg px-4 text-[15px] font-semibold focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--ui-text-inverted)]',
159
+ void 0,
160
+ ui.trigger
161
+ ),
162
+ trailingIcon: 'size-4'
163
+ }"
164
+ />
165
+
166
+ <template #body>
167
+ <div ref="sheetBody">
168
+ <div
169
+ v-if="scope"
170
+ class="nut-dl-selsheet__scope mx-[10px] mt-2 mb-1 grid grid-cols-[repeat(2,minmax(0,1fr))] gap-0.5 rounded-md bg-elevated p-0.5"
171
+ role="radiogroup"
172
+ :aria-label="t('table.selectionBar.selection')"
173
+ >
174
+ <button
175
+ v-for="option in scopeOptions"
176
+ :key="option.value"
177
+ type="button"
178
+ role="radio"
179
+ class="nut-dl-selsheet__scope-btn flex min-h-11 min-w-0 flex-wrap items-center justify-center gap-x-1.5 rounded-[5px] px-1 py-1 text-center text-[13px] leading-tight font-medium outline-none transition-colors focus-visible:ring-2 focus-visible:ring-primary/40"
180
+ :class="
181
+ bulkScope === option.value ? 'bg-default text-highlighted shadow-[0_0_0_1px_var(--ui-border)]' : 'text-muted hover:text-default'
182
+ "
183
+ :aria-checked="bulkScope === option.value"
184
+ @click="internals.selection.setBulkScope(option.value)"
185
+ >
186
+ <span>{{ option.label }}</span>
187
+ <b class="font-semibold text-primary tabular-nums">{{ formatCount(option.count) }}</b>
188
+ </button>
189
+ </div>
190
+ <div
191
+ v-else
192
+ class="nut-dl-sheet__title px-5 pt-3 pb-1.5 text-[13px] font-semibold text-muted"
193
+ >
194
+ {{ count.text }}
195
+ </div>
196
+
197
+ <div class="px-[10px] pt-1">
198
+ <template v-for="(group, groupIndex) in groups" :key="groupIndex">
199
+ <div v-if="groupIndex" class="my-1 border-t border-default" />
200
+ <button
201
+ v-for="row in group"
202
+ :key="row.action.definition.key"
203
+ type="button"
204
+ class="nut-dl-sheet__row nut-dl-selsheet__action flex min-h-[46px] w-full items-center gap-[10px] rounded-lg px-[10px] py-2 text-left text-[15px] outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-inset"
205
+ :class="
206
+ row.unavailable ? 'cursor-not-allowed text-dimmed' : row.destructive ? 'text-error active:bg-error/10' : 'text-highlighted active:bg-elevated'
207
+ "
208
+ :aria-disabled="row.unavailable || void 0"
209
+ :aria-describedby="row.detail ? row.detailId : void 0"
210
+ @click="run(row)"
211
+ >
212
+ <UIcon
213
+ v-if="row.icon"
214
+ :name="row.icon"
215
+ class="size-4 shrink-0"
216
+ :class="[
217
+ row.pending ? 'animate-spin motion-reduce:animate-none' : '',
218
+ row.destructive && !row.unavailable ? 'text-error' : 'text-muted'
219
+ ]"
220
+ />
221
+ <span class="flex min-w-0 flex-1 flex-col gap-0.5">
222
+ <span class="nut-dl-selsheet__label">{{ row.label }}</span>
223
+ <span
224
+ v-if="row.detail"
225
+ :id="row.detailId"
226
+ class="nut-dl-selsheet__detail text-[12.5px] leading-snug text-muted"
227
+ >
228
+ {{ row.detail }}
229
+ </span>
230
+ </span>
231
+ </button>
232
+ </template>
233
+ </div>
234
+ </div>
235
+ </template>
236
+ </UDrawer>
237
+ </div>
238
+ </template>