nuxt-ui-tools 1.1.0 → 1.3.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 (213) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +10 -1
  3. package/dist/runtime/dashboard/components/block/dashboard-block-state.d.vue.ts +2 -0
  4. package/dist/runtime/dashboard/components/block/dashboard-block-state.vue +4 -1
  5. package/dist/runtime/dashboard/components/block/dashboard-block-state.vue.d.ts +2 -0
  6. package/dist/runtime/dashboard/components/block/dashboard-chips.d.vue.ts +20 -0
  7. package/dist/runtime/dashboard/components/block/dashboard-chips.vue +42 -0
  8. package/dist/runtime/dashboard/components/block/dashboard-chips.vue.d.ts +20 -0
  9. package/dist/runtime/dashboard/components/block/dashboard-series-picker.d.vue.ts +8 -0
  10. package/dist/runtime/dashboard/components/block/dashboard-series-picker.vue +29 -0
  11. package/dist/runtime/dashboard/components/block/dashboard-series-picker.vue.d.ts +8 -0
  12. package/dist/runtime/dashboard/components/block/dashboard-skeleton.d.vue.ts +1 -1
  13. package/dist/runtime/dashboard/components/block/dashboard-skeleton.vue +6 -3
  14. package/dist/runtime/dashboard/components/block/dashboard-skeleton.vue.d.ts +1 -1
  15. package/dist/runtime/dashboard/components/block/dashboard-view-scope.d.vue.ts +21 -0
  16. package/dist/runtime/dashboard/components/block/dashboard-view-scope.vue +12 -0
  17. package/dist/runtime/dashboard/components/block/dashboard-view-scope.vue.d.ts +21 -0
  18. package/dist/runtime/dashboard/components/dashboard-alerts.vue +3 -3
  19. package/dist/runtime/dashboard/components/dashboard-bar-chart.d.vue.ts +14 -3
  20. package/dist/runtime/dashboard/components/dashboard-bar-chart.vue +30 -9
  21. package/dist/runtime/dashboard/components/dashboard-bar-chart.vue.d.ts +14 -3
  22. package/dist/runtime/dashboard/components/dashboard-bars.vue +4 -4
  23. package/dist/runtime/dashboard/components/dashboard-card.vue +28 -6
  24. package/dist/runtime/dashboard/components/dashboard-combo-chart.d.vue.ts +6 -1
  25. package/dist/runtime/dashboard/components/dashboard-combo-chart.vue +13 -3
  26. package/dist/runtime/dashboard/components/dashboard-combo-chart.vue.d.ts +6 -1
  27. package/dist/runtime/dashboard/components/dashboard-donut-chart.vue +5 -5
  28. package/dist/runtime/dashboard/components/dashboard-feed.vue +8 -7
  29. package/dist/runtime/dashboard/components/dashboard-filter.d.vue.ts +67 -0
  30. package/dist/runtime/dashboard/components/dashboard-filter.vue +134 -0
  31. package/dist/runtime/dashboard/components/dashboard-filter.vue.d.ts +67 -0
  32. package/dist/runtime/dashboard/components/dashboard-filters.d.vue.ts +49 -0
  33. package/dist/runtime/dashboard/components/dashboard-filters.vue +96 -0
  34. package/dist/runtime/dashboard/components/dashboard-filters.vue.d.ts +49 -0
  35. package/dist/runtime/dashboard/components/dashboard-funnel.vue +5 -5
  36. package/dist/runtime/dashboard/components/dashboard-gauge.vue +3 -3
  37. package/dist/runtime/dashboard/components/dashboard-grid.d.vue.ts +10 -3
  38. package/dist/runtime/dashboard/components/dashboard-grid.vue +24 -9
  39. package/dist/runtime/dashboard/components/dashboard-grid.vue.d.ts +10 -3
  40. package/dist/runtime/dashboard/components/dashboard-line-chart.d.vue.ts +14 -3
  41. package/dist/runtime/dashboard/components/dashboard-line-chart.vue +30 -9
  42. package/dist/runtime/dashboard/components/dashboard-line-chart.vue.d.ts +14 -3
  43. package/dist/runtime/dashboard/components/dashboard-list.d.vue.ts +3 -0
  44. package/dist/runtime/dashboard/components/dashboard-list.vue +18 -6
  45. package/dist/runtime/dashboard/components/dashboard-list.vue.d.ts +3 -0
  46. package/dist/runtime/dashboard/components/dashboard-page.d.vue.ts +53 -0
  47. package/dist/runtime/dashboard/components/dashboard-page.vue +156 -0
  48. package/dist/runtime/dashboard/components/dashboard-page.vue.d.ts +53 -0
  49. package/dist/runtime/dashboard/components/dashboard-paired-bars.vue +4 -4
  50. package/dist/runtime/dashboard/components/dashboard-refresh.d.vue.ts +1 -1
  51. package/dist/runtime/dashboard/components/dashboard-refresh.vue +1 -0
  52. package/dist/runtime/dashboard/components/dashboard-refresh.vue.d.ts +1 -1
  53. package/dist/runtime/dashboard/components/dashboard-stack-bar.vue +4 -4
  54. package/dist/runtime/dashboard/components/dashboard-stat.d.vue.ts +14 -2
  55. package/dist/runtime/dashboard/components/dashboard-stat.vue +28 -10
  56. package/dist/runtime/dashboard/components/dashboard-stat.vue.d.ts +14 -2
  57. package/dist/runtime/dashboard/components/dashboard-stats.vue +3 -3
  58. package/dist/runtime/dashboard/components/dashboard-table.d.vue.ts +1 -1
  59. package/dist/runtime/dashboard/components/dashboard-table.vue +3 -3
  60. package/dist/runtime/dashboard/components/dashboard-table.vue.d.ts +1 -1
  61. package/dist/runtime/dashboard/components/dashboard-tabs.d.vue.ts +1 -1
  62. package/dist/runtime/dashboard/components/dashboard-tabs.vue.d.ts +1 -1
  63. package/dist/runtime/dashboard/components/dashboard-total.d.vue.ts +7 -2
  64. package/dist/runtime/dashboard/components/dashboard-total.vue +10 -2
  65. package/dist/runtime/dashboard/components/dashboard-total.vue.d.ts +7 -2
  66. package/dist/runtime/dashboard/components/dashboard-view-tabs.d.vue.ts +33 -0
  67. package/dist/runtime/dashboard/components/dashboard-view-tabs.vue +66 -0
  68. package/dist/runtime/dashboard/components/dashboard-view-tabs.vue.d.ts +33 -0
  69. package/dist/runtime/dashboard/components/dashboard-widget.vue +1 -1
  70. package/dist/runtime/dashboard/components/filter/dashboard-filter-menu.d.vue.ts +44 -0
  71. package/dist/runtime/dashboard/components/filter/dashboard-filter-menu.vue +220 -0
  72. package/dist/runtime/dashboard/components/filter/dashboard-filter-menu.vue.d.ts +44 -0
  73. package/dist/runtime/dashboard/composables/use-dashboard-api.d.ts +6 -1
  74. package/dist/runtime/dashboard/composables/use-dashboard-api.js +29 -6
  75. package/dist/runtime/dashboard/composables/use-dashboard-block.d.ts +5 -4
  76. package/dist/runtime/dashboard/composables/use-dashboard-block.js +32 -15
  77. package/dist/runtime/dashboard/composables/use-dashboard-chart.d.ts +8 -1
  78. package/dist/runtime/dashboard/composables/use-dashboard-chart.js +16 -4
  79. package/dist/runtime/dashboard/composables/use-dashboard-context.d.ts +50 -0
  80. package/dist/runtime/dashboard/composables/use-dashboard-context.js +56 -0
  81. package/dist/runtime/dashboard/composables/use-dashboard-derived.js +6 -1
  82. package/dist/runtime/dashboard/composables/use-dashboard-filter-control.d.ts +16 -0
  83. package/dist/runtime/dashboard/composables/use-dashboard-filter-control.js +161 -0
  84. package/dist/runtime/dashboard/composables/use-dashboard-filter-scope.d.ts +37 -0
  85. package/dist/runtime/dashboard/composables/use-dashboard-filter-scope.js +107 -0
  86. package/dist/runtime/dashboard/composables/use-dashboard-format.d.ts +46 -6
  87. package/dist/runtime/dashboard/composables/use-dashboard-format.js +51 -8
  88. package/dist/runtime/dashboard/composables/use-dashboard-options.d.ts +11 -4
  89. package/dist/runtime/dashboard/composables/use-dashboard-options.js +33 -47
  90. package/dist/runtime/dashboard/composables/use-dashboard-remote-options.d.ts +8 -5
  91. package/dist/runtime/dashboard/composables/use-dashboard-remote-options.js +66 -77
  92. package/dist/runtime/dashboard/composables/use-dashboard-resource.d.ts +15 -4
  93. package/dist/runtime/dashboard/composables/use-dashboard-resource.js +52 -17
  94. package/dist/runtime/dashboard/composables/use-dashboard-scope.d.ts +10 -7
  95. package/dist/runtime/dashboard/composables/use-dashboard-scope.js +26 -16
  96. package/dist/runtime/dashboard/composables/use-dashboard-series-picker.d.ts +20 -0
  97. package/dist/runtime/dashboard/composables/use-dashboard-series-picker.js +30 -0
  98. package/dist/runtime/dashboard/composables/use-dashboard-time.d.ts +2 -0
  99. package/dist/runtime/dashboard/composables/use-dashboard-time.js +4 -1
  100. package/dist/runtime/dashboard/composables/use-dashboard-ui.d.ts +12 -2
  101. package/dist/runtime/dashboard/composables/use-dashboard-ui.js +3 -0
  102. package/dist/runtime/dashboard/composables/use-dashboard-views.d.ts +15 -3
  103. package/dist/runtime/dashboard/composables/use-dashboard-views.js +33 -10
  104. package/dist/runtime/dashboard/composables/use-dashboard.d.ts +18 -12
  105. package/dist/runtime/dashboard/composables/use-dashboard.js +98 -9
  106. package/dist/runtime/dashboard/index.d.ts +3 -1
  107. package/dist/runtime/dashboard/index.js +3 -1
  108. package/dist/runtime/dashboard/schema/index.d.ts +62 -30
  109. package/dist/runtime/dashboard/schema/index.js +3 -0
  110. package/dist/runtime/dashboard/types/blocks.d.ts +30 -4
  111. package/dist/runtime/dashboard/types/charts.d.ts +2 -2
  112. package/dist/runtime/dashboard/types/controls.d.ts +123 -0
  113. package/dist/runtime/dashboard/types/filters.d.ts +236 -0
  114. package/dist/runtime/dashboard/types/index.d.ts +3 -2
  115. package/dist/runtime/dashboard/types/page.d.ts +17 -0
  116. package/dist/runtime/dashboard/types/page.js +0 -0
  117. package/dist/runtime/dashboard/types/resource.d.ts +66 -28
  118. package/dist/runtime/dashboard/types/runtime.d.ts +39 -8
  119. package/dist/runtime/dashboard/types/schema.d.ts +94 -54
  120. package/dist/runtime/dashboard/types/ui.d.ts +78 -0
  121. package/dist/runtime/dashboard/utils/builders/dashboard-filters.d.ts +142 -0
  122. package/dist/runtime/dashboard/utils/builders/dashboard-filters.js +135 -0
  123. package/dist/runtime/dashboard/utils/charts.d.ts +4 -15
  124. package/dist/runtime/dashboard/utils/charts.js +26 -28
  125. package/dist/runtime/dashboard/utils/{params/codecs.d.ts → codecs.d.ts} +2 -2
  126. package/dist/runtime/dashboard/utils/{params/codecs.js → codecs.js} +1 -1
  127. package/dist/runtime/dashboard/utils/environment.d.ts +36 -0
  128. package/dist/runtime/dashboard/utils/environment.js +30 -0
  129. package/dist/runtime/dashboard/utils/filters.d.ts +44 -0
  130. package/dist/runtime/dashboard/utils/filters.js +62 -0
  131. package/dist/runtime/dashboard/utils/format.d.ts +25 -0
  132. package/dist/runtime/dashboard/utils/format.js +66 -0
  133. package/dist/runtime/dashboard/utils/grid.d.ts +17 -0
  134. package/dist/runtime/dashboard/utils/grid.js +14 -0
  135. package/dist/runtime/dashboard/utils/options.d.ts +3 -8
  136. package/dist/runtime/dashboard/utils/options.js +6 -5
  137. package/dist/runtime/dashboard/utils/remote.d.ts +7 -0
  138. package/dist/runtime/dashboard/utils/remote.js +14 -0
  139. package/dist/runtime/dashboard/utils/resource.d.ts +16 -7
  140. package/dist/runtime/dashboard/utils/resource.js +15 -9
  141. package/dist/runtime/dashboard/utils/schema.d.ts +8 -3
  142. package/dist/runtime/dashboard/utils/schema.js +9 -4
  143. package/dist/runtime/dashboard/utils/state.d.ts +11 -6
  144. package/dist/runtime/dashboard/utils/state.js +10 -5
  145. package/dist/runtime/dashboard/utils/time.d.ts +2 -0
  146. package/dist/runtime/dashboard/utils/time.js +11 -1
  147. package/dist/runtime/dashboard/utils/ui.d.ts +1 -1
  148. package/dist/runtime/dashboard/utils/ui.js +1 -1
  149. package/dist/runtime/form/components/root/form.vue +1 -1
  150. package/dist/runtime/form/fields/card-selection.d.ts +1 -0
  151. package/dist/runtime/form/fields/card-selection.js +1 -0
  152. package/dist/runtime/form/fields/checkbox-card/component.vue +3 -1
  153. package/dist/runtime/form/fields/checkbox-group/component.vue +5 -0
  154. package/dist/runtime/form/fields/radio/component.vue +10 -0
  155. package/dist/runtime/form/fields/radio-card/component.vue +3 -1
  156. package/dist/runtime/form/types/options.d.ts +1 -11
  157. package/dist/runtime/form/utils/focus.js +1 -1
  158. package/dist/runtime/i18n/locales/en.js +32 -1
  159. package/dist/runtime/i18n/locales/fr.js +32 -1
  160. package/dist/runtime/i18n/types.d.ts +44 -0
  161. package/dist/runtime/shared/styles/scrollbars.css +1 -1
  162. package/dist/runtime/shared/styles/tokens.css +1 -1
  163. package/dist/runtime/shared/types/query.d.ts +8 -0
  164. package/dist/runtime/shared/utils/remote-options.d.ts +10 -0
  165. package/dist/runtime/shared/utils/remote-options.js +6 -0
  166. package/dist/runtime/table/components/filters/shared/filter-option-list-end.d.vue.ts +11 -0
  167. package/dist/runtime/table/components/filters/shared/filter-option-list-end.vue +76 -0
  168. package/dist/runtime/table/components/filters/shared/filter-option-list-end.vue.d.ts +11 -0
  169. package/dist/runtime/table/components/filters/shared/filter-option-loading-list.d.vue.ts +3 -0
  170. package/dist/runtime/table/components/filters/shared/filter-option-loading-list.vue +2 -1
  171. package/dist/runtime/table/components/filters/shared/filter-option-loading-list.vue.d.ts +3 -0
  172. package/dist/runtime/table/components/filters/shared/filter-option-multiple-list.vue +1 -1
  173. package/dist/runtime/table/components/filters/shared/filter-option-picker-content.vue +13 -0
  174. package/dist/runtime/table/components/filters/shared/filter-option-single-list.d.vue.ts +2 -0
  175. package/dist/runtime/table/components/filters/shared/filter-option-single-list.vue +1 -1
  176. package/dist/runtime/table/components/filters/shared/filter-option-single-list.vue.d.ts +2 -0
  177. package/dist/runtime/table/components/filters/shared/filter-option-tree-content.d.vue.ts +3 -0
  178. package/dist/runtime/table/components/filters/shared/filter-option-tree-content.vue +2 -2
  179. package/dist/runtime/table/components/filters/shared/filter-option-tree-content.vue.d.ts +3 -0
  180. package/dist/runtime/table/components/filters/shared/filter-searchable-panel.vue +1 -0
  181. package/dist/runtime/table/composables/use-option-filter-editor-state.d.ts +13 -1
  182. package/dist/runtime/table/composables/use-option-filter-editor-state.js +6 -2
  183. package/dist/runtime/table/composables/use-table-filter-options.d.ts +11 -1
  184. package/dist/runtime/table/composables/use-table-filter-options.js +128 -17
  185. package/dist/runtime/table/composables/use-table-filter-selected-options.d.ts +20 -0
  186. package/dist/runtime/table/composables/use-table-filter-selected-options.js +99 -0
  187. package/dist/runtime/table/composables/use-table-filters.d.ts +5 -0
  188. package/dist/runtime/table/composables/use-table-filters.js +20 -1
  189. package/dist/runtime/table/composables/use-table-internals.d.ts +15 -0
  190. package/dist/runtime/table/composables/use-table-remote-filter-options.d.ts +42 -0
  191. package/dist/runtime/table/composables/use-table-remote-filter-options.js +102 -0
  192. package/dist/runtime/table/types/filters.d.ts +42 -0
  193. package/dist/runtime/table/types/index.d.ts +1 -0
  194. package/dist/runtime/table/types/remote-options.d.ts +64 -0
  195. package/dist/runtime/table/types/remote-options.js +0 -0
  196. package/dist/runtime/table/types/source.d.ts +15 -1
  197. package/dist/runtime/table/utils/builders/table-source.d.ts +2 -6
  198. package/dist/runtime/table/utils/filters/options.d.ts +2 -0
  199. package/dist/runtime/table/utils/filters/options.js +1 -1
  200. package/dist/runtime/table/utils/index.d.ts +1 -0
  201. package/dist/runtime/table/utils/index.js +1 -0
  202. package/dist/runtime/table/utils/prefetch.js +21 -1
  203. package/dist/runtime/table/utils/remote-table-options.d.ts +26 -0
  204. package/dist/runtime/table/utils/remote-table-options.js +88 -0
  205. package/package.json +4 -1
  206. package/dist/runtime/dashboard/composables/use-dashboard-param-scope.d.ts +0 -30
  207. package/dist/runtime/dashboard/composables/use-dashboard-param-scope.js +0 -71
  208. package/dist/runtime/dashboard/types/options.d.ts +0 -46
  209. package/dist/runtime/dashboard/types/params.d.ts +0 -115
  210. package/dist/runtime/dashboard/utils/builders/dashboard-params.d.ts +0 -85
  211. package/dist/runtime/dashboard/utils/builders/dashboard-params.js +0 -87
  212. /package/dist/runtime/dashboard/types/{options.js → controls.js} +0 -0
  213. /package/dist/runtime/dashboard/types/{params.js → filters.js} +0 -0
@@ -1,3 +1,4 @@
1
+ import type { RouteLocationRaw } from 'vue-router';
1
2
  import type { LazyTextValue } from '#ui-tools/shared/types/utils';
2
3
  import type { DashboardBlockBaseProps, DashboardBlockUi, DashboardListUi, DashboardRowActions, DashboardSelected, DashboardSelectEvent, DashboardSeriesColor, DashboardSourceLike, DashboardValueFormat } from '../types/index.js';
3
4
  declare const __VLS_export: <TRow>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
@@ -27,6 +28,8 @@ declare const __VLS_export: <TRow>(__VLS_props: NonNullable<Awaited<typeof __VLS
27
28
  rowKey?: (row: TRow, index: number) => PropertyKey;
28
29
  /** Rows shown as selected (the value a `select` handler stored). */
29
30
  selected?: DashboardSelected<TRow>;
31
+ /** Makes each row a link to what this returns (rows returning `undefined` stay plain). */
32
+ to?: (row: TRow, index: number) => RouteLocationRaw | undefined;
30
33
  /** Actions of each row: inline icon buttons and a `⋮` menu at the end of the row. */
31
34
  rowActions?: DashboardRowActions<TRow>;
32
35
  /** Makes each row a button. */
@@ -0,0 +1,53 @@
1
+ import type { ButtonProps } from '@nuxt/ui/components/Button.vue';
2
+ import type { LazyTextValue } from '#ui-tools/shared/types/utils';
3
+ import type { DashboardPageTarget, DashboardPageUi, DashboardViewKeysOf } from '../types/index.js';
4
+ declare const __VLS_export: <TDashboard extends DashboardPageTarget>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
5
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<{
6
+ dashboard: TDashboard;
7
+ title?: LazyTextValue;
8
+ /**
9
+ * Line under the title. Defaults to today's date and when the data on screen was fetched;
10
+ * `false` removes it.
11
+ */
12
+ description?: LazyTextValue | false;
13
+ /** Buttons before the refresh control. A button with an icon shows only the icon on phones. */
14
+ actions?: readonly ButtonProps[];
15
+ /** The refresh control and its auto-refresh menu. Defaults to `true`. */
16
+ refresh?: boolean;
17
+ /** The view tabs, while two views or more are enabled. Defaults to `true`. */
18
+ tabs?: boolean;
19
+ /** The filter bar. Defaults to `true`. */
20
+ filters?: boolean;
21
+ /** Keeps the tabs and the filter bar pinned while the page scrolls. Defaults to `true`. */
22
+ sticky?: boolean;
23
+ ui?: DashboardPageUi;
24
+ }> & (typeof globalThis extends {
25
+ __VLS_PROPS_FALLBACK: infer P;
26
+ } ? P : {});
27
+ expose: (exposed: {}) => void;
28
+ attrs: any;
29
+ slots: { [TKey in DashboardViewKeysOf<TDashboard>]?: (() => unknown) | undefined; } & {
30
+ /** Content of a dashboard without views, or of a view without its own slot. */
31
+ default?: (props: {
32
+ view: DashboardViewKeysOf<TDashboard> | undefined;
33
+ }) => unknown;
34
+ title?: () => unknown;
35
+ description?: () => unknown;
36
+ /** Replaces the page actions and the refresh control. */
37
+ actions?: () => unknown;
38
+ /** Replaces the view tabs. */
39
+ tabs?: () => unknown;
40
+ /** Replaces the filter bar, e.g. with a `UiDashboardFilters` that customizes some filters. */
41
+ filters?: () => unknown;
42
+ };
43
+ emit: {};
44
+ }>) => import("vue").VNode & {
45
+ __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
46
+ };
47
+ declare const _default: typeof __VLS_export;
48
+ export default _default;
49
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
50
+ [K in keyof T]: T[K];
51
+ } : {
52
+ [K in keyof T as K]: T[K];
53
+ }) & {};
@@ -0,0 +1,156 @@
1
+ <script setup>
2
+ import UButton from "@nuxt/ui/components/Button.vue";
3
+ import { twMerge } from "tailwind-merge";
4
+ import { computed, onBeforeUnmount, shallowRef, useTemplateRef, watch } from "vue";
5
+ import { useUiToolsLocale } from "#ui-tools/i18n";
6
+ import { isObject, isString } from "#ui-tools/shared/utils/predicate";
7
+ import { resolveTextValue } from "#ui-tools/shared/utils/render";
8
+ import { useDashboardTime } from "../composables/use-dashboard-time";
9
+ import { useDashboardUi } from "../composables/use-dashboard-ui";
10
+ import { resolveDashboardClasses } from "../utils/ui";
11
+ import DashboardViewScope from "./block/dashboard-view-scope.vue";
12
+ import DashboardFilters from "./dashboard-filters.vue";
13
+ import DashboardRefresh from "./dashboard-refresh.vue";
14
+ import DashboardRelativeTime from "./dashboard-relative-time.vue";
15
+ import DashboardViewTabs from "./dashboard-view-tabs.vue";
16
+ const {
17
+ dashboard,
18
+ title = void 0,
19
+ description = void 0,
20
+ actions = [],
21
+ refresh = true,
22
+ tabs = true,
23
+ filters = true,
24
+ sticky = true,
25
+ ui
26
+ } = defineProps({
27
+ dashboard: { type: null, required: true },
28
+ title: { type: [String, Number, Function], required: false },
29
+ description: { type: [String, Number, Function, Boolean], required: false },
30
+ actions: { type: Array, required: false },
31
+ refresh: { type: Boolean, required: false },
32
+ tabs: { type: Boolean, required: false },
33
+ filters: { type: Boolean, required: false },
34
+ sticky: { type: Boolean, required: false },
35
+ ui: { type: Object, required: false }
36
+ });
37
+ defineSlots();
38
+ const { t } = useUiToolsLocale();
39
+ const time = useDashboardTime();
40
+ const appUi = useDashboardUi();
41
+ const classes = computed(
42
+ () => resolveDashboardClasses(
43
+ {
44
+ actions: "flex min-h-[34px] items-center gap-2",
45
+ body: "flex flex-col gap-4 px-4 pt-1 pb-12 lg:gap-6 lg:px-7 lg:pb-15",
46
+ description: "col-span-full mt-1 text-[12.5px] font-light text-muted md:text-[13.5px]",
47
+ filters: "px-4 py-3 lg:px-7 lg:py-4",
48
+ header: "grid grid-cols-[minmax(0,1fr)_auto] items-center gap-x-4 bg-default px-4 pt-4 pb-3.5 lg:px-7 lg:pt-[22px] lg:pb-[18px]",
49
+ root: "h-full overflow-auto bg-muted",
50
+ tabs: "bg-default px-2 lg:px-7",
51
+ title: "m-0 min-w-0 truncate text-2xl leading-[1.1] font-light tracking-[-0.04em] text-highlighted md:text-[30px]",
52
+ toolbar: [
53
+ "z-20 bg-muted transition-shadow duration-200 data-[stuck]:shadow-[0_10px_24px_-18px_rgb(0_0_0/0.35)]",
54
+ sticky && "sticky top-0"
55
+ ].filter(Boolean).join(" ")
56
+ },
57
+ appUi.value.page,
58
+ ui
59
+ )
60
+ );
61
+ const views = computed(() => hasViews(dashboard) ? dashboard : void 0);
62
+ const current = computed(() => views.value?.view.current);
63
+ const marker = useTemplateRef("marker");
64
+ const stuck = shallowRef(false);
65
+ let observer;
66
+ watch(
67
+ () => sticky ? marker.value : null,
68
+ (element) => {
69
+ observer?.disconnect();
70
+ observer = void 0;
71
+ stuck.value = false;
72
+ if (!element || typeof IntersectionObserver === "undefined") return;
73
+ observer = new IntersectionObserver(
74
+ ([entry]) => {
75
+ stuck.value = Boolean(
76
+ entry && !entry.isIntersecting && entry.boundingClientRect.top < (entry.rootBounds?.top ?? 0)
77
+ );
78
+ },
79
+ { root: scrollContainer(element) }
80
+ );
81
+ observer.observe(element);
82
+ },
83
+ { flush: "post", immediate: true }
84
+ );
85
+ onBeforeUnmount(() => observer?.disconnect());
86
+ function hasViews(target) {
87
+ return isObject(target.view) && "items" in target.view;
88
+ }
89
+ function scrollContainer(element) {
90
+ for (let node = element.parentElement; node; node = node.parentElement) {
91
+ if (/auto|scroll/u.test(getComputedStyle(node).overflowY)) return node;
92
+ }
93
+ return null;
94
+ }
95
+ function actionUi(action) {
96
+ const label = action.ui?.label;
97
+ if (!action.icon || label !== void 0 && !isString(label)) return action.ui;
98
+ return { ...action.ui, label: twMerge(label, "max-sm:sr-only") };
99
+ }
100
+ </script>
101
+
102
+ <template>
103
+ <!-- Without a dashboard (its schema threw during setup), render nothing: that error stays the one reported. -->
104
+ <div v-if="dashboard" :class="classes.root" data-dashboard-page>
105
+ <header :class="classes.header">
106
+ <h1 :class="classes.title">
107
+ <slot name="title">{{ title === void 0 ? "" : resolveTextValue(title) }}</slot>
108
+ </h1>
109
+ <div :class="classes.actions">
110
+ <slot name="actions">
111
+ <UButton
112
+ v-for="(action, index) in actions"
113
+ :key="index"
114
+ color="neutral"
115
+ variant="outline"
116
+ size="md"
117
+ v-bind="action"
118
+ :ui="actionUi(action)"
119
+ />
120
+ <DashboardRefresh v-if="refresh" :dashboard :updated="false" size="md" />
121
+ </slot>
122
+ </div>
123
+ <p v-if="description !== false" :class="classes.description" data-allow-mismatch="text">
124
+ <slot name="description">
125
+ <template v-if="description !== void 0">{{ resolveTextValue(description) }}</template>
126
+ <template v-else>
127
+ {{ time.today() }} ·
128
+ <template v-if="dashboard.updatedAt !== void 0">
129
+ {{ t("dashboard.page.updated") }}
130
+ <DashboardRelativeTime :value="dashboard.updatedAt" />
131
+ </template>
132
+ <template v-else>{{ t("dashboard.page.loading") }}</template>
133
+ </template>
134
+ </slot>
135
+ </p>
136
+ </header>
137
+
138
+ <div ref="marker" aria-hidden="true" />
139
+ <div :class="classes.toolbar" :data-stuck="stuck || void 0">
140
+ <slot name="tabs">
141
+ <DashboardViewTabs v-if="tabs && views" :dashboard="views" :class="classes.tabs" />
142
+ </slot>
143
+ <slot name="filters">
144
+ <DashboardFilters v-if="filters" :dashboard :class="classes.filters" />
145
+ </slot>
146
+ </div>
147
+
148
+ <div :class="classes.body">
149
+ <DashboardViewScope v-if="current" :key="current" :dashboard :view="current">
150
+ <slot v-if="$slots[current]" :name="current" />
151
+ <slot v-else :view="current" />
152
+ </DashboardViewScope>
153
+ <slot v-else :view="current" />
154
+ </div>
155
+ </div>
156
+ </template>
@@ -0,0 +1,53 @@
1
+ import type { ButtonProps } from '@nuxt/ui/components/Button.vue';
2
+ import type { LazyTextValue } from '#ui-tools/shared/types/utils';
3
+ import type { DashboardPageTarget, DashboardPageUi, DashboardViewKeysOf } from '../types/index.js';
4
+ declare const __VLS_export: <TDashboard extends DashboardPageTarget>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
5
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<{
6
+ dashboard: TDashboard;
7
+ title?: LazyTextValue;
8
+ /**
9
+ * Line under the title. Defaults to today's date and when the data on screen was fetched;
10
+ * `false` removes it.
11
+ */
12
+ description?: LazyTextValue | false;
13
+ /** Buttons before the refresh control. A button with an icon shows only the icon on phones. */
14
+ actions?: readonly ButtonProps[];
15
+ /** The refresh control and its auto-refresh menu. Defaults to `true`. */
16
+ refresh?: boolean;
17
+ /** The view tabs, while two views or more are enabled. Defaults to `true`. */
18
+ tabs?: boolean;
19
+ /** The filter bar. Defaults to `true`. */
20
+ filters?: boolean;
21
+ /** Keeps the tabs and the filter bar pinned while the page scrolls. Defaults to `true`. */
22
+ sticky?: boolean;
23
+ ui?: DashboardPageUi;
24
+ }> & (typeof globalThis extends {
25
+ __VLS_PROPS_FALLBACK: infer P;
26
+ } ? P : {});
27
+ expose: (exposed: {}) => void;
28
+ attrs: any;
29
+ slots: { [TKey in DashboardViewKeysOf<TDashboard>]?: (() => unknown) | undefined; } & {
30
+ /** Content of a dashboard without views, or of a view without its own slot. */
31
+ default?: (props: {
32
+ view: DashboardViewKeysOf<TDashboard> | undefined;
33
+ }) => unknown;
34
+ title?: () => unknown;
35
+ description?: () => unknown;
36
+ /** Replaces the page actions and the refresh control. */
37
+ actions?: () => unknown;
38
+ /** Replaces the view tabs. */
39
+ tabs?: () => unknown;
40
+ /** Replaces the filter bar, e.g. with a `UiDashboardFilters` that customizes some filters. */
41
+ filters?: () => unknown;
42
+ };
43
+ emit: {};
44
+ }>) => import("vue").VNode & {
45
+ __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
46
+ };
47
+ declare const _default: typeof __VLS_export;
48
+ export default _default;
49
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
50
+ [K in keyof T]: T[K];
51
+ } : {
52
+ [K in keyof T as K]: T[K];
53
+ }) & {};
@@ -34,12 +34,12 @@ const {
34
34
  title: { type: [String, Number, Function], required: false },
35
35
  subtitle: { type: [String, Number, Function], required: false },
36
36
  size: { type: String, required: false },
37
- rows: { type: String, required: false },
38
37
  card: { type: Boolean, required: false },
39
38
  activation: { type: String, required: false },
40
39
  empty: { type: Object, required: false },
41
40
  menu: { type: [Boolean, Array, Function], required: false },
42
41
  actions: { type: Array, required: false },
42
+ filters: { type: Array, required: false },
43
43
  freshness: { type: Boolean, required: false },
44
44
  source: { type: Object, required: true },
45
45
  label: { type: Function, required: true },
@@ -47,7 +47,7 @@ const {
47
47
  value: { type: Function, required: true },
48
48
  totalLabel: { type: [String, Number, Function], required: false },
49
49
  valueLabel: { type: [String, Number, Function], required: false },
50
- format: { type: Function, required: false },
50
+ format: { type: [String, Function], required: false, skipCheck: true },
51
51
  colors: { type: Array, required: false },
52
52
  limit: { type: Number, required: false },
53
53
  rowKey: { type: Function, required: false },
@@ -78,7 +78,7 @@ const legend = computed(
78
78
  { color: valueColor.value, key: "value", label: resolveTextValue(valueLabel) }
79
79
  ] : void 0
80
80
  );
81
- const formatValue = computed(() => format ?? formats.number.value);
81
+ const formatValue = computed(() => formats.resolve(format));
82
82
  const entries = computed(
83
83
  () => (source.data ?? []).map((row, index) => {
84
84
  const outer = total(row);
@@ -90,7 +90,7 @@ const entries = computed(
90
90
  key: rowKey?.(row, index) ?? index,
91
91
  label: resolveTextValue(label(row)),
92
92
  outer,
93
- ratio: outer > 0 ? formats.percent.value(Math.round(inner / outer * 100)) : "",
93
+ ratio: outer > 0 ? formats.percent(Math.round(inner / outer * 100)) : "",
94
94
  row
95
95
  };
96
96
  })
@@ -20,7 +20,7 @@ type __VLS_Props = {
20
20
  intervals?: readonly number[];
21
21
  /** Shows when the data on screen was last fetched. */
22
22
  updated?: boolean;
23
- /** Shows the "Refresh" label next to the icon. */
23
+ /** Shows the "Refresh" label next to the icon, from the `sm` breakpoint up (phones get the icon). */
24
24
  label?: boolean;
25
25
  size?: 'xs' | 'sm' | 'md';
26
26
  };
@@ -64,6 +64,7 @@ function refresh() {
64
64
  icon="i-lucide-refresh-cw"
65
65
  :label="label ? t('dashboard.refresh.label') : void 0"
66
66
  :aria-label="label ? void 0 : t('dashboard.refresh.label')"
67
+ :ui="{ label: 'max-sm:sr-only' }"
67
68
  :loading="dashboard.refreshing"
68
69
  @click="refresh"
69
70
  />
@@ -20,7 +20,7 @@ type __VLS_Props = {
20
20
  intervals?: readonly number[];
21
21
  /** Shows when the data on screen was last fetched. */
22
22
  updated?: boolean;
23
- /** Shows the "Refresh" label next to the icon. */
23
+ /** Shows the "Refresh" label next to the icon, from the `sm` breakpoint up (phones get the icon). */
24
24
  label?: boolean;
25
25
  size?: 'xs' | 'sm' | 'md';
26
26
  };
@@ -30,12 +30,12 @@ const {
30
30
  title: { type: [String, Number, Function], required: false },
31
31
  subtitle: { type: [String, Number, Function], required: false },
32
32
  size: { type: String, required: false },
33
- rows: { type: String, required: false },
34
33
  card: { type: Boolean, required: false },
35
34
  activation: { type: String, required: false },
36
35
  empty: { type: Object, required: false },
37
36
  menu: { type: [Boolean, Array, Function], required: false },
38
37
  actions: { type: Array, required: false },
38
+ filters: { type: Array, required: false },
39
39
  freshness: { type: Boolean, required: false },
40
40
  source: { type: Object, required: true },
41
41
  label: { type: Function, required: true },
@@ -78,7 +78,7 @@ const parts = computed(() => {
78
78
  label: resolveTextValue(label(row)),
79
79
  row,
80
80
  share,
81
- text: text ? resolveTextValue(text(row, share)) : formats.percent.value(share),
81
+ text: text ? resolveTextValue(text(row, share)) : formats.percent(share),
82
82
  width: `${share}%`
83
83
  };
84
84
  });
@@ -92,8 +92,8 @@ function tabulate() {
92
92
  ],
93
93
  rows: parts.value.map((part) => [
94
94
  toDashboardCell(part.label),
95
- toDashboardCell(part.amount, formats.number.value(part.amount)),
96
- toDashboardCell(Math.round(part.share * 10) / 10, formats.percent.value(part.share))
95
+ toDashboardCell(part.amount, formats.number(part.amount)),
96
+ toDashboardCell(Math.round(part.share * 10) / 10, formats.percent(part.share))
97
97
  ])
98
98
  };
99
99
  }
@@ -5,14 +5,21 @@ declare const __VLS_export: <TData>(__VLS_props: NonNullable<Awaited<typeof __VL
5
5
  source: DashboardSourceLike<TData>;
6
6
  /** KPI label, shown above the value. */
7
7
  label: LazyTextValue;
8
- /** Main value. Numbers go through `format` (locale number format by default). */
9
- value: (data: TData & ({} | null)) => LazyTextValue;
8
+ /**
9
+ * Main value. Numbers go through `format` (locale number format by default); `null` /
10
+ * `undefined` (an average without units, a rate without a base) show "—".
11
+ */
12
+ value: (data: TData & ({} | null)) => LazyTextValue | null | undefined;
10
13
  format?: DashboardValueFormat;
11
14
  /**
12
15
  * Change indicator, in percent by default. `null` hides it. Defaults to the change from
13
16
  * `compare` when that is set.
14
17
  */
15
18
  delta?: (data: TData & ({} | null)) => number | null | undefined;
19
+ /**
20
+ * Format of the delta. Defaults to a signed percent (`delta`), or with `compare-mode="difference"`
21
+ * to `points` for `percent` / `ratio` values and a signed number otherwise.
22
+ */
16
23
  deltaFormat?: DashboardValueFormat;
17
24
  /** A decrease is good news (e.g. a failure rate): colors the delta accordingly. */
18
25
  invertDelta?: boolean;
@@ -29,6 +36,11 @@ declare const __VLS_export: <TData>(__VLS_props: NonNullable<Awaited<typeof __VL
29
36
  * default `delta`, and the default caption ("vs 1,204 previous period").
30
37
  */
31
38
  compare?: (data: TData & ({} | null)) => number | null | undefined;
39
+ /**
40
+ * How the default delta compares `value` with `compare`: the relative change in percent
41
+ * (`change`, default), or the difference (`difference`: `+12` accounts, `+2.1 pts` of margin).
42
+ */
43
+ compareMode?: "change" | "difference";
32
44
  /**
33
45
  * Caption shown with `compare`, as text or built from the formatted previous value. Defaults to
34
46
  * "vs <value> previous period".
@@ -5,7 +5,7 @@ import { computed } from "vue";
5
5
  import { useUiToolsLocale } from "#ui-tools/i18n";
6
6
  import { isNumber, isString } from "#ui-tools/shared/utils/predicate";
7
7
  import { resolveTextValue } from "#ui-tools/shared/utils/render";
8
- import { useDashboardFormat } from "../composables/use-dashboard-format";
8
+ import { DASHBOARD_MISSING_VALUE, useDashboardFormat } from "../composables/use-dashboard-format";
9
9
  import { useDashboardUi } from "../composables/use-dashboard-ui";
10
10
  import { resolveDashboardColor } from "../utils/charts";
11
11
  import { resolveDashboardSparkBars, resolveDashboardSparkline } from "../utils/sparkline";
@@ -29,6 +29,7 @@ const {
29
29
  trendType = "area",
30
30
  trendColor = "series-1",
31
31
  compare,
32
+ compareMode = "change",
32
33
  compareLabel,
33
34
  goal,
34
35
  status,
@@ -36,19 +37,19 @@ const {
36
37
  ...block
37
38
  } = defineProps({
38
39
  size: { type: String, required: false },
39
- rows: { type: String, required: false },
40
40
  card: { type: Boolean, required: false },
41
41
  activation: { type: String, required: false },
42
42
  empty: { type: Object, required: false },
43
43
  menu: { type: [Boolean, Array, Function], required: false },
44
44
  actions: { type: Array, required: false },
45
+ filters: { type: Array, required: false },
45
46
  freshness: { type: Boolean, required: false },
46
47
  source: { type: Object, required: true },
47
48
  label: { type: [String, Number, Function], required: true },
48
49
  value: { type: Function, required: true },
49
- format: { type: Function, required: false },
50
+ format: { type: [String, Function], required: false, skipCheck: true },
50
51
  delta: { type: Function, required: false },
51
- deltaFormat: { type: Function, required: false },
52
+ deltaFormat: { type: [String, Function], required: false, skipCheck: true },
52
53
  invertDelta: { type: Boolean, required: false },
53
54
  caption: { type: [String, Function], required: false },
54
55
  icon: { type: String, required: false },
@@ -56,6 +57,7 @@ const {
56
57
  trendType: { type: String, required: false },
57
58
  trendColor: { type: String, required: false },
58
59
  compare: { type: Function, required: false },
60
+ compareMode: { type: String, required: false },
59
61
  compareLabel: { type: [String, Number, Function], required: false },
60
62
  goal: { type: Function, required: false },
61
63
  status: { type: Function, required: false },
@@ -70,22 +72,38 @@ const ready = computed(() => {
70
72
  return data === void 0 ? null : { data };
71
73
  });
72
74
  const resolved = computed(() => ready.value ? value(ready.value.data) : void 0);
73
- const formatValue = computed(() => format ?? formats.number.value);
75
+ const formatValue = computed(() => formats.resolve(format));
74
76
  const display = computed(() => {
75
- if (resolved.value === void 0) return "";
76
- return isNumber(resolved.value) ? formatValue.value(resolved.value) : resolveTextValue(resolved.value);
77
+ if (!ready.value) return "";
78
+ const shown = resolved.value;
79
+ if (shown === null || shown === void 0) return DASHBOARD_MISSING_VALUE;
80
+ return isNumber(shown) ? formatValue.value(shown) : resolveTextValue(shown);
77
81
  });
78
82
  const previous = computed(() => {
79
83
  if (!ready.value || !compare) return null;
80
84
  const amount = compare(ready.value.data);
81
85
  return isNumber(amount) && Number.isFinite(amount) ? amount : null;
82
86
  });
87
+ const scale = computed(() => compareMode === "difference" && format === "ratio" ? 100 : 1);
88
+ const deltaFallback = computed(() => {
89
+ if (compareMode !== "difference") return "delta";
90
+ return format === "percent" || format === "ratio" ? "points" : "signed";
91
+ });
83
92
  const change = computed(() => {
84
93
  if (!ready.value) return null;
85
- const amount = delta ? delta(ready.value.data) : previous.value !== null && previous.value !== 0 && isNumber(resolved.value) ? (resolved.value - previous.value) / Math.abs(previous.value) * 100 : null;
94
+ const current = resolved.value;
95
+ const before = previous.value;
96
+ let amount = null;
97
+ if (delta) amount = delta(ready.value.data);
98
+ else if (before !== null && isNumber(current))
99
+ amount = compareMode === "difference" ? (current - before) * scale.value : before === 0 ? null : (current - before) / Math.abs(before) * 100;
86
100
  if (amount === null || amount === void 0 || !Number.isFinite(amount)) return null;
87
101
  const good = invertDelta ? amount <= 0 : amount >= 0;
88
- return { good, label: (deltaFormat ?? formats.delta.value)(amount), up: amount >= 0 };
102
+ return {
103
+ good,
104
+ label: formats.resolve(deltaFormat, deltaFallback.value)(amount),
105
+ up: amount >= 0
106
+ };
89
107
  });
90
108
  const captionText = computed(() => {
91
109
  if (!ready.value) return "";
@@ -113,7 +131,7 @@ const progress = computed(() => {
113
131
  const completion = resolved.value / target * 100;
114
132
  const filled = Math.round(Math.max(0, Math.min(100, completion)));
115
133
  return {
116
- completion: formats.percent.value(completion),
134
+ completion: formats.percent(completion),
117
135
  filled,
118
136
  goal: t("dashboard.stat.goal", { value: formatValue.value(target) }),
119
137
  reached: completion >= 100
@@ -5,14 +5,21 @@ declare const __VLS_export: <TData>(__VLS_props: NonNullable<Awaited<typeof __VL
5
5
  source: DashboardSourceLike<TData>;
6
6
  /** KPI label, shown above the value. */
7
7
  label: LazyTextValue;
8
- /** Main value. Numbers go through `format` (locale number format by default). */
9
- value: (data: TData & ({} | null)) => LazyTextValue;
8
+ /**
9
+ * Main value. Numbers go through `format` (locale number format by default); `null` /
10
+ * `undefined` (an average without units, a rate without a base) show "—".
11
+ */
12
+ value: (data: TData & ({} | null)) => LazyTextValue | null | undefined;
10
13
  format?: DashboardValueFormat;
11
14
  /**
12
15
  * Change indicator, in percent by default. `null` hides it. Defaults to the change from
13
16
  * `compare` when that is set.
14
17
  */
15
18
  delta?: (data: TData & ({} | null)) => number | null | undefined;
19
+ /**
20
+ * Format of the delta. Defaults to a signed percent (`delta`), or with `compare-mode="difference"`
21
+ * to `points` for `percent` / `ratio` values and a signed number otherwise.
22
+ */
16
23
  deltaFormat?: DashboardValueFormat;
17
24
  /** A decrease is good news (e.g. a failure rate): colors the delta accordingly. */
18
25
  invertDelta?: boolean;
@@ -29,6 +36,11 @@ declare const __VLS_export: <TData>(__VLS_props: NonNullable<Awaited<typeof __VL
29
36
  * default `delta`, and the default caption ("vs 1,204 previous period").
30
37
  */
31
38
  compare?: (data: TData & ({} | null)) => number | null | undefined;
39
+ /**
40
+ * How the default delta compares `value` with `compare`: the relative change in percent
41
+ * (`change`, default), or the difference (`difference`: `+12` accounts, `+2.1 pts` of margin).
42
+ */
43
+ compareMode?: "change" | "difference";
32
44
  /**
33
45
  * Caption shown with `compare`, as text or built from the formatted previous value. Defaults to
34
46
  * "vs <value> previous period".
@@ -26,12 +26,12 @@ const {
26
26
  title: { type: [String, Number, Function], required: false },
27
27
  subtitle: { type: [String, Number, Function], required: false },
28
28
  size: { type: String, required: false },
29
- rows: { type: String, required: false },
30
29
  card: { type: Boolean, required: false },
31
30
  activation: { type: String, required: false },
32
31
  empty: { type: Object, required: false },
33
32
  menu: { type: [Boolean, Array, Function], required: false },
34
33
  actions: { type: Array, required: false },
34
+ filters: { type: Array, required: false },
35
35
  freshness: { type: Boolean, required: false },
36
36
  source: { type: Object, required: true },
37
37
  items: { type: Array, required: true },
@@ -89,14 +89,14 @@ const entries = computed(() => {
89
89
  caption: resolveTextValue(caption),
90
90
  change: isNumber(amount) && Number.isFinite(amount) ? amount : null,
91
91
  color: resolveDashboardColor(item.color, index),
92
- delta: isNumber(amount) && Number.isFinite(amount) ? { good, label: formats.delta.value(amount), up: amount >= 0 } : null,
92
+ delta: isNumber(amount) && Number.isFinite(amount) ? { good, label: formats.delta(amount), up: amount >= 0 } : null,
93
93
  icon: item.icon,
94
94
  key: item.key,
95
95
  label: resolveTextValue(item.label),
96
96
  progress: isNumber(done) ? Math.round(Math.max(0, Math.min(100, done))) : null,
97
97
  raw,
98
98
  status: status ? { color: resolveDashboardColor(status.color, 0), label: resolveTextValue(status.label) } : null,
99
- value: raw === null || raw === void 0 ? "\u2013" : isNumber(raw) ? (item.format ?? formats.number.value)(raw) : resolveTextValue(raw)
99
+ value: raw === null || raw === void 0 ? "\u2013" : isNumber(raw) ? formats.resolve(item.format)(raw) : resolveTextValue(raw)
100
100
  };
101
101
  });
102
102
  });
@@ -18,7 +18,7 @@ declare const __VLS_export: <TRow>(__VLS_props: NonNullable<Awaited<typeof __VLS
18
18
  } & {
19
19
  /**
20
20
  * Sort state. Header clicks cycle a column through its natural direction (numbers descending, text
21
- * ascending), the opposite one, then source order. Bind it to keep the sort in a param.
21
+ * ascending), the opposite one, then source order. Bind it to keep the sort in a filter.
22
22
  */
23
23
  sort?: DashboardTableSort | null | undefined;
24
24
  }) & {
@@ -34,12 +34,12 @@ const {
34
34
  title: { type: [String, Number, Function], required: false },
35
35
  subtitle: { type: [String, Number, Function], required: false },
36
36
  size: { type: String, required: false },
37
- rows: { type: String, required: false },
38
37
  card: { type: Boolean, required: false },
39
38
  activation: { type: String, required: false },
40
39
  empty: { type: Object, required: false },
41
40
  menu: { type: [Boolean, Array, Function], required: false },
42
41
  actions: { type: Array, required: false },
42
+ filters: { type: Array, required: false },
43
43
  freshness: { type: Boolean, required: false },
44
44
  source: { type: Object, required: true },
45
45
  columns: { type: Array, required: true },
@@ -93,9 +93,9 @@ const entries = computed(() => {
93
93
  const { column, type } = resolved;
94
94
  if (type === "delta") {
95
95
  const good = column.invert ? value <= 0 : value >= 0;
96
- return { good, text: (column.format ?? formats.delta.value)(value), value };
96
+ return { good, text: formats.resolve(column.format, "delta")(value), value };
97
97
  }
98
- const format = column.format ?? (type === "percent" ? formats.percent.value : formats.number.value);
98
+ const format = formats.resolve(column.format, type === "percent" ? "percent" : "number");
99
99
  const max = maxima[position] ?? 0;
100
100
  const width = type === "bar" && max > 0 ? `${Math.max(0, Math.min(100, value / max * 100))}%` : void 0;
101
101
  return { text: format(value), value, width };
@@ -18,7 +18,7 @@ declare const __VLS_export: <TRow>(__VLS_props: NonNullable<Awaited<typeof __VLS
18
18
  } & {
19
19
  /**
20
20
  * Sort state. Header clicks cycle a column through its natural direction (numbers descending, text
21
- * ascending), the opposite one, then source order. Bind it to keep the sort in a param.
21
+ * ascending), the opposite one, then source order. Bind it to keep the sort in a filter.
22
22
  */
23
23
  sort?: DashboardTableSort | null | undefined;
24
24
  }) & {
@@ -9,7 +9,7 @@ declare const __VLS_export: <TValue extends string | number>(__VLS_props: NonNul
9
9
  full?: boolean;
10
10
  } & {
11
11
  /**
12
- * Tab strip for dashboard cards, bound with `v-model`. Bind it to a widget param to switch what a
12
+ * Tab strip for dashboard cards, bound with `v-model`. Bind it to a query filter to switch what a
13
13
  * block fetches (the tab lands in the URL, and the block refreshes in place), or to a local ref to
14
14
  * switch between blocks: render only the active one, so the others' deferred queries stay idle.
15
15
  */