nuxt-ui-tools 1.2.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.
- package/dist/module.json +1 -1
- package/dist/module.mjs +10 -1
- package/dist/runtime/dashboard/components/block/dashboard-block-state.d.vue.ts +2 -0
- package/dist/runtime/dashboard/components/block/dashboard-block-state.vue +4 -1
- package/dist/runtime/dashboard/components/block/dashboard-block-state.vue.d.ts +2 -0
- package/dist/runtime/dashboard/components/block/dashboard-chips.d.vue.ts +20 -0
- package/dist/runtime/dashboard/components/block/dashboard-chips.vue +42 -0
- package/dist/runtime/dashboard/components/block/dashboard-chips.vue.d.ts +20 -0
- package/dist/runtime/dashboard/components/block/dashboard-series-picker.d.vue.ts +8 -0
- package/dist/runtime/dashboard/components/block/dashboard-series-picker.vue +29 -0
- package/dist/runtime/dashboard/components/block/dashboard-series-picker.vue.d.ts +8 -0
- package/dist/runtime/dashboard/components/block/dashboard-skeleton.d.vue.ts +1 -1
- package/dist/runtime/dashboard/components/block/dashboard-skeleton.vue.d.ts +1 -1
- package/dist/runtime/dashboard/components/block/dashboard-view-scope.d.vue.ts +21 -0
- package/dist/runtime/dashboard/components/block/dashboard-view-scope.vue +12 -0
- package/dist/runtime/dashboard/components/block/dashboard-view-scope.vue.d.ts +21 -0
- package/dist/runtime/dashboard/components/dashboard-alerts.vue +3 -3
- package/dist/runtime/dashboard/components/dashboard-bar-chart.d.vue.ts +14 -3
- package/dist/runtime/dashboard/components/dashboard-bar-chart.vue +30 -9
- package/dist/runtime/dashboard/components/dashboard-bar-chart.vue.d.ts +14 -3
- package/dist/runtime/dashboard/components/dashboard-bars.vue +4 -4
- package/dist/runtime/dashboard/components/dashboard-card.vue +28 -6
- package/dist/runtime/dashboard/components/dashboard-combo-chart.d.vue.ts +6 -1
- package/dist/runtime/dashboard/components/dashboard-combo-chart.vue +13 -3
- package/dist/runtime/dashboard/components/dashboard-combo-chart.vue.d.ts +6 -1
- package/dist/runtime/dashboard/components/dashboard-donut-chart.vue +5 -5
- package/dist/runtime/dashboard/components/dashboard-feed.vue +1 -1
- package/dist/runtime/dashboard/components/dashboard-filter.d.vue.ts +67 -0
- package/dist/runtime/dashboard/components/dashboard-filter.vue +134 -0
- package/dist/runtime/dashboard/components/dashboard-filter.vue.d.ts +67 -0
- package/dist/runtime/dashboard/components/dashboard-filters.d.vue.ts +49 -0
- package/dist/runtime/dashboard/components/dashboard-filters.vue +96 -0
- package/dist/runtime/dashboard/components/dashboard-filters.vue.d.ts +49 -0
- package/dist/runtime/dashboard/components/dashboard-funnel.vue +5 -5
- package/dist/runtime/dashboard/components/dashboard-gauge.vue +3 -3
- package/dist/runtime/dashboard/components/dashboard-grid.d.vue.ts +10 -3
- package/dist/runtime/dashboard/components/dashboard-grid.vue +24 -9
- package/dist/runtime/dashboard/components/dashboard-grid.vue.d.ts +10 -3
- package/dist/runtime/dashboard/components/dashboard-line-chart.d.vue.ts +14 -3
- package/dist/runtime/dashboard/components/dashboard-line-chart.vue +30 -9
- package/dist/runtime/dashboard/components/dashboard-line-chart.vue.d.ts +14 -3
- package/dist/runtime/dashboard/components/dashboard-list.d.vue.ts +3 -0
- package/dist/runtime/dashboard/components/dashboard-list.vue +18 -6
- package/dist/runtime/dashboard/components/dashboard-list.vue.d.ts +3 -0
- package/dist/runtime/dashboard/components/dashboard-page.d.vue.ts +53 -0
- package/dist/runtime/dashboard/components/dashboard-page.vue +156 -0
- package/dist/runtime/dashboard/components/dashboard-page.vue.d.ts +53 -0
- package/dist/runtime/dashboard/components/dashboard-paired-bars.vue +4 -4
- package/dist/runtime/dashboard/components/dashboard-refresh.d.vue.ts +1 -1
- package/dist/runtime/dashboard/components/dashboard-refresh.vue +1 -0
- package/dist/runtime/dashboard/components/dashboard-refresh.vue.d.ts +1 -1
- package/dist/runtime/dashboard/components/dashboard-stack-bar.vue +4 -4
- package/dist/runtime/dashboard/components/dashboard-stat.d.vue.ts +14 -2
- package/dist/runtime/dashboard/components/dashboard-stat.vue +28 -10
- package/dist/runtime/dashboard/components/dashboard-stat.vue.d.ts +14 -2
- package/dist/runtime/dashboard/components/dashboard-stats.vue +3 -3
- package/dist/runtime/dashboard/components/dashboard-table.d.vue.ts +1 -1
- package/dist/runtime/dashboard/components/dashboard-table.vue +3 -3
- package/dist/runtime/dashboard/components/dashboard-table.vue.d.ts +1 -1
- package/dist/runtime/dashboard/components/dashboard-tabs.d.vue.ts +1 -1
- package/dist/runtime/dashboard/components/dashboard-tabs.vue.d.ts +1 -1
- package/dist/runtime/dashboard/components/dashboard-total.d.vue.ts +7 -2
- package/dist/runtime/dashboard/components/dashboard-total.vue +10 -2
- package/dist/runtime/dashboard/components/dashboard-total.vue.d.ts +7 -2
- package/dist/runtime/dashboard/components/dashboard-view-tabs.d.vue.ts +33 -0
- package/dist/runtime/dashboard/components/dashboard-view-tabs.vue +66 -0
- package/dist/runtime/dashboard/components/dashboard-view-tabs.vue.d.ts +33 -0
- package/dist/runtime/dashboard/components/dashboard-widget.vue +1 -1
- package/dist/runtime/dashboard/components/filter/dashboard-filter-menu.d.vue.ts +44 -0
- package/dist/runtime/dashboard/components/filter/dashboard-filter-menu.vue +220 -0
- package/dist/runtime/dashboard/components/filter/dashboard-filter-menu.vue.d.ts +44 -0
- package/dist/runtime/dashboard/composables/use-dashboard-api.d.ts +6 -1
- package/dist/runtime/dashboard/composables/use-dashboard-api.js +29 -6
- package/dist/runtime/dashboard/composables/use-dashboard-block.d.ts +5 -4
- package/dist/runtime/dashboard/composables/use-dashboard-block.js +32 -15
- package/dist/runtime/dashboard/composables/use-dashboard-chart.d.ts +8 -1
- package/dist/runtime/dashboard/composables/use-dashboard-chart.js +16 -4
- package/dist/runtime/dashboard/composables/use-dashboard-context.d.ts +50 -0
- package/dist/runtime/dashboard/composables/use-dashboard-context.js +56 -0
- package/dist/runtime/dashboard/composables/use-dashboard-derived.js +6 -1
- package/dist/runtime/dashboard/composables/use-dashboard-filter-control.d.ts +16 -0
- package/dist/runtime/dashboard/composables/use-dashboard-filter-control.js +161 -0
- package/dist/runtime/dashboard/composables/use-dashboard-filter-scope.d.ts +37 -0
- package/dist/runtime/dashboard/composables/use-dashboard-filter-scope.js +107 -0
- package/dist/runtime/dashboard/composables/use-dashboard-format.d.ts +46 -6
- package/dist/runtime/dashboard/composables/use-dashboard-format.js +51 -8
- package/dist/runtime/dashboard/composables/use-dashboard-options.d.ts +11 -4
- package/dist/runtime/dashboard/composables/use-dashboard-options.js +33 -47
- package/dist/runtime/dashboard/composables/use-dashboard-remote-options.d.ts +8 -5
- package/dist/runtime/dashboard/composables/use-dashboard-remote-options.js +59 -70
- package/dist/runtime/dashboard/composables/use-dashboard-resource.d.ts +15 -4
- package/dist/runtime/dashboard/composables/use-dashboard-resource.js +52 -17
- package/dist/runtime/dashboard/composables/use-dashboard-scope.d.ts +10 -7
- package/dist/runtime/dashboard/composables/use-dashboard-scope.js +26 -16
- package/dist/runtime/dashboard/composables/use-dashboard-series-picker.d.ts +20 -0
- package/dist/runtime/dashboard/composables/use-dashboard-series-picker.js +30 -0
- package/dist/runtime/dashboard/composables/use-dashboard-time.d.ts +2 -0
- package/dist/runtime/dashboard/composables/use-dashboard-time.js +4 -1
- package/dist/runtime/dashboard/composables/use-dashboard-ui.d.ts +12 -2
- package/dist/runtime/dashboard/composables/use-dashboard-ui.js +3 -0
- package/dist/runtime/dashboard/composables/use-dashboard-views.d.ts +15 -3
- package/dist/runtime/dashboard/composables/use-dashboard-views.js +33 -10
- package/dist/runtime/dashboard/composables/use-dashboard.d.ts +18 -12
- package/dist/runtime/dashboard/composables/use-dashboard.js +98 -9
- package/dist/runtime/dashboard/index.d.ts +3 -1
- package/dist/runtime/dashboard/index.js +3 -1
- package/dist/runtime/dashboard/schema/index.d.ts +62 -30
- package/dist/runtime/dashboard/schema/index.js +3 -0
- package/dist/runtime/dashboard/types/blocks.d.ts +30 -4
- package/dist/runtime/dashboard/types/charts.d.ts +2 -2
- package/dist/runtime/dashboard/types/controls.d.ts +123 -0
- package/dist/runtime/dashboard/types/filters.d.ts +236 -0
- package/dist/runtime/dashboard/types/index.d.ts +3 -2
- package/dist/runtime/dashboard/types/page.d.ts +17 -0
- package/dist/runtime/dashboard/types/page.js +0 -0
- package/dist/runtime/dashboard/types/resource.d.ts +66 -28
- package/dist/runtime/dashboard/types/runtime.d.ts +39 -8
- package/dist/runtime/dashboard/types/schema.d.ts +94 -54
- package/dist/runtime/dashboard/types/ui.d.ts +78 -0
- package/dist/runtime/dashboard/utils/builders/dashboard-filters.d.ts +142 -0
- package/dist/runtime/dashboard/utils/builders/dashboard-filters.js +135 -0
- package/dist/runtime/dashboard/utils/charts.d.ts +4 -15
- package/dist/runtime/dashboard/utils/charts.js +26 -28
- package/dist/runtime/dashboard/utils/{params/codecs.d.ts → codecs.d.ts} +2 -2
- package/dist/runtime/dashboard/utils/{params/codecs.js → codecs.js} +1 -1
- package/dist/runtime/dashboard/utils/environment.d.ts +36 -0
- package/dist/runtime/dashboard/utils/environment.js +30 -0
- package/dist/runtime/dashboard/utils/filters.d.ts +44 -0
- package/dist/runtime/dashboard/utils/filters.js +62 -0
- package/dist/runtime/dashboard/utils/format.d.ts +25 -0
- package/dist/runtime/dashboard/utils/format.js +66 -0
- package/dist/runtime/dashboard/utils/grid.d.ts +17 -0
- package/dist/runtime/dashboard/utils/grid.js +14 -0
- package/dist/runtime/dashboard/utils/options.d.ts +3 -1
- package/dist/runtime/dashboard/utils/options.js +6 -0
- package/dist/runtime/dashboard/utils/remote.d.ts +7 -0
- package/dist/runtime/dashboard/utils/remote.js +14 -0
- package/dist/runtime/dashboard/utils/resource.d.ts +16 -7
- package/dist/runtime/dashboard/utils/resource.js +15 -9
- package/dist/runtime/dashboard/utils/schema.d.ts +8 -3
- package/dist/runtime/dashboard/utils/schema.js +9 -4
- package/dist/runtime/dashboard/utils/state.d.ts +11 -6
- package/dist/runtime/dashboard/utils/state.js +10 -5
- package/dist/runtime/dashboard/utils/time.d.ts +2 -0
- package/dist/runtime/dashboard/utils/time.js +11 -1
- package/dist/runtime/dashboard/utils/ui.d.ts +1 -1
- package/dist/runtime/dashboard/utils/ui.js +1 -1
- package/dist/runtime/form/components/root/form.vue +1 -1
- package/dist/runtime/form/fields/card-selection.d.ts +1 -0
- package/dist/runtime/form/fields/card-selection.js +1 -0
- package/dist/runtime/form/fields/checkbox-card/component.vue +3 -1
- package/dist/runtime/form/fields/checkbox-group/component.vue +5 -0
- package/dist/runtime/form/fields/radio/component.vue +10 -0
- package/dist/runtime/form/fields/radio-card/component.vue +3 -1
- package/dist/runtime/form/types/options.d.ts +1 -11
- package/dist/runtime/form/utils/focus.js +1 -1
- package/dist/runtime/i18n/locales/en.js +29 -0
- package/dist/runtime/i18n/locales/fr.js +29 -0
- package/dist/runtime/i18n/types.d.ts +41 -0
- package/dist/runtime/shared/styles/tokens.css +1 -1
- package/dist/runtime/shared/types/query.d.ts +8 -0
- package/dist/runtime/table/types/index.d.ts +1 -0
- package/dist/runtime/table/types/remote-options.d.ts +64 -0
- package/dist/runtime/table/types/remote-options.js +0 -0
- package/dist/runtime/table/types/source.d.ts +10 -1
- package/dist/runtime/table/utils/builders/table-source.d.ts +2 -6
- package/dist/runtime/table/utils/index.d.ts +1 -0
- package/dist/runtime/table/utils/index.js +1 -0
- package/dist/runtime/table/utils/remote-table-options.d.ts +26 -0
- package/dist/runtime/table/utils/remote-table-options.js +88 -0
- package/package.json +4 -1
- package/dist/runtime/dashboard/composables/use-dashboard-param-scope.d.ts +0 -30
- package/dist/runtime/dashboard/composables/use-dashboard-param-scope.js +0 -71
- package/dist/runtime/dashboard/types/options.d.ts +0 -46
- package/dist/runtime/dashboard/types/params.d.ts +0 -115
- package/dist/runtime/dashboard/utils/builders/dashboard-params.d.ts +0 -85
- package/dist/runtime/dashboard/utils/builders/dashboard-params.js +0 -87
- /package/dist/runtime/dashboard/types/{options.js → controls.js} +0 -0
- /package/dist/runtime/dashboard/types/{params.js → filters.js} +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import UIcon from "@nuxt/ui/components/Icon.vue";
|
|
3
|
+
import { computed } from "vue";
|
|
4
|
+
import { useUiToolsLocale } from "#ui-tools/i18n";
|
|
5
|
+
import { isObject } from "#ui-tools/shared/utils/predicate";
|
|
6
|
+
import { useDashboardUi } from "../composables/use-dashboard-ui";
|
|
7
|
+
import { hasDashboardFilterMenu } from "../utils/filters";
|
|
8
|
+
import { resolveDashboardClasses } from "../utils/ui";
|
|
9
|
+
import DashboardFilter from "./dashboard-filter.vue";
|
|
10
|
+
const {
|
|
11
|
+
dashboard,
|
|
12
|
+
only,
|
|
13
|
+
exclude,
|
|
14
|
+
reset = true,
|
|
15
|
+
ui
|
|
16
|
+
} = defineProps({
|
|
17
|
+
dashboard: { type: null, required: true },
|
|
18
|
+
only: { type: Array, required: false },
|
|
19
|
+
exclude: { type: Array, required: false },
|
|
20
|
+
reset: { type: Boolean, required: false },
|
|
21
|
+
ui: { type: Object, required: false }
|
|
22
|
+
});
|
|
23
|
+
defineSlots();
|
|
24
|
+
const { t } = useUiToolsLocale();
|
|
25
|
+
const appUi = useDashboardUi();
|
|
26
|
+
const classes = computed(
|
|
27
|
+
() => resolveDashboardClasses(
|
|
28
|
+
{
|
|
29
|
+
reset: "inline-flex h-8 flex-none items-center gap-1.5 rounded-[7px] px-2 text-[13px] font-medium whitespace-nowrap text-muted transition-colors outline-none hover:text-default focus-visible:ring-2 focus-visible:ring-primary",
|
|
30
|
+
root: "flex min-w-0 items-center gap-2 overflow-x-auto [scrollbar-width:none] lg:flex-wrap lg:overflow-visible"
|
|
31
|
+
},
|
|
32
|
+
appUi.value.filters,
|
|
33
|
+
ui
|
|
34
|
+
)
|
|
35
|
+
);
|
|
36
|
+
const controls = computed(() => {
|
|
37
|
+
const all = new Map(Object.entries(dashboard.controls));
|
|
38
|
+
const current = dashboard.view?.current;
|
|
39
|
+
const view = current ? Reflect.get(dashboard, current) : void 0;
|
|
40
|
+
if (isFiltersTarget(view)) {
|
|
41
|
+
for (const [key, control] of Object.entries(view.controls))
|
|
42
|
+
if (!all.has(key)) all.set(key, control);
|
|
43
|
+
}
|
|
44
|
+
return all;
|
|
45
|
+
});
|
|
46
|
+
const filters = computed(() => {
|
|
47
|
+
const all = controls.value;
|
|
48
|
+
const keys = only ?? [...all.keys()];
|
|
49
|
+
return keys.flatMap((key) => {
|
|
50
|
+
const filter = all.get(key);
|
|
51
|
+
if (!filter || filter.headless || !filter.enabled || exclude?.includes(key)) return [];
|
|
52
|
+
return hasDashboardFilterMenu(filter) || filter.changed ? [filter] : [];
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
function resetFilters() {
|
|
56
|
+
dashboard.resetFilters();
|
|
57
|
+
}
|
|
58
|
+
function isFiltersTarget(value) {
|
|
59
|
+
return isObject(value) && "controls" in value && "resetFilters" in value;
|
|
60
|
+
}
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<template>
|
|
64
|
+
<div
|
|
65
|
+
:class="classes.root"
|
|
66
|
+
role="toolbar"
|
|
67
|
+
:aria-label="t('dashboard.filters.label')"
|
|
68
|
+
data-dashboard-filters
|
|
69
|
+
>
|
|
70
|
+
<slot name="leading" />
|
|
71
|
+
<template v-for="filter in filters" :key="filter.key">
|
|
72
|
+
<slot :name="filter.key" :filter>
|
|
73
|
+
<slot name="filter" :filter>
|
|
74
|
+
<DashboardFilter :filter>
|
|
75
|
+
<template v-if="$slots.item" #item="slotProps">
|
|
76
|
+
<slot name="item" v-bind="slotProps" />
|
|
77
|
+
</template>
|
|
78
|
+
</DashboardFilter>
|
|
79
|
+
</slot>
|
|
80
|
+
</slot>
|
|
81
|
+
</template>
|
|
82
|
+
<slot name="reset" :filtered="dashboard.filtered" :reset="resetFilters">
|
|
83
|
+
<button
|
|
84
|
+
v-if="reset && dashboard.filtered"
|
|
85
|
+
type="button"
|
|
86
|
+
:class="classes.reset"
|
|
87
|
+
data-dashboard-filters-reset
|
|
88
|
+
@click="resetFilters"
|
|
89
|
+
>
|
|
90
|
+
<UIcon name="i-lucide-rotate-ccw" class="size-3.5" />
|
|
91
|
+
{{ t("dashboard.filters.reset") }}
|
|
92
|
+
</button>
|
|
93
|
+
</slot>
|
|
94
|
+
<slot name="trailing" />
|
|
95
|
+
</div>
|
|
96
|
+
</template>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { DashboardFilterControl, DashboardFilterKeysOf, DashboardFiltersTarget, DashboardFiltersUi, DashboardOption, DashboardOptionValue } from '../types/index.js';
|
|
2
|
+
declare const __VLS_export: <TTarget extends DashboardFiltersTarget>(__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<{
|
|
3
|
+
props: import("vue").PublicProps & __VLS_PrettifyLocal<{
|
|
4
|
+
dashboard: TTarget;
|
|
5
|
+
/** Shows these filters only, in this order. */
|
|
6
|
+
only?: readonly (DashboardFilterKeysOf<TTarget> & string)[];
|
|
7
|
+
/** Hides these filters. */
|
|
8
|
+
exclude?: readonly (DashboardFilterKeysOf<TTarget> & string)[];
|
|
9
|
+
/** Shows "Reset" once a filter differs from its default. Defaults to `true`. */
|
|
10
|
+
reset?: boolean;
|
|
11
|
+
ui?: DashboardFiltersUi;
|
|
12
|
+
}> & (typeof globalThis extends {
|
|
13
|
+
__VLS_PROPS_FALLBACK: infer P;
|
|
14
|
+
} ? P : {});
|
|
15
|
+
expose: (exposed: {}) => void;
|
|
16
|
+
attrs: any;
|
|
17
|
+
slots: { [TKey in DashboardFilterKeysOf<TTarget> & string]?: ((props: {
|
|
18
|
+
filter: DashboardFilterControl;
|
|
19
|
+
}) => unknown) | undefined; } & {
|
|
20
|
+
/** Renders every filter that has no slot of its own. */
|
|
21
|
+
filter?: (props: {
|
|
22
|
+
filter: DashboardFilterControl;
|
|
23
|
+
}) => unknown;
|
|
24
|
+
/** Content of the menu rows of every pill. */
|
|
25
|
+
item?: (props: {
|
|
26
|
+
item: DashboardOption<DashboardOptionValue>;
|
|
27
|
+
selected: boolean;
|
|
28
|
+
disabled: boolean;
|
|
29
|
+
filter: DashboardFilterControl;
|
|
30
|
+
}) => unknown;
|
|
31
|
+
/** Replaces the "Reset" button. */
|
|
32
|
+
reset?: (props: {
|
|
33
|
+
filtered: boolean;
|
|
34
|
+
reset: () => void;
|
|
35
|
+
}) => unknown;
|
|
36
|
+
leading?: () => unknown;
|
|
37
|
+
trailing?: () => unknown;
|
|
38
|
+
};
|
|
39
|
+
emit: {};
|
|
40
|
+
}>) => import("vue").VNode & {
|
|
41
|
+
__ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
|
|
42
|
+
};
|
|
43
|
+
declare const _default: typeof __VLS_export;
|
|
44
|
+
export default _default;
|
|
45
|
+
type __VLS_PrettifyLocal<T> = (T extends any ? {
|
|
46
|
+
[K in keyof T]: T[K];
|
|
47
|
+
} : {
|
|
48
|
+
[K in keyof T as K]: T[K];
|
|
49
|
+
}) & {};
|
|
@@ -29,17 +29,17 @@ const {
|
|
|
29
29
|
title: { type: [String, Number, Function], required: false },
|
|
30
30
|
subtitle: { type: [String, Number, Function], required: false },
|
|
31
31
|
size: { type: String, required: false },
|
|
32
|
-
rows: { type: String, required: false },
|
|
33
32
|
card: { type: Boolean, required: false },
|
|
34
33
|
activation: { type: String, required: false },
|
|
35
34
|
empty: { type: Object, required: false },
|
|
36
35
|
menu: { type: [Boolean, Array, Function], required: false },
|
|
37
36
|
actions: { type: Array, required: false },
|
|
37
|
+
filters: { type: Array, required: false },
|
|
38
38
|
freshness: { type: Boolean, required: false },
|
|
39
39
|
source: { type: Object, required: true },
|
|
40
40
|
label: { type: Function, required: true },
|
|
41
41
|
value: { type: Function, required: true },
|
|
42
|
-
format: { type: Function, required: false },
|
|
42
|
+
format: { type: [String, Function], required: false, skipCheck: true },
|
|
43
43
|
colors: { type: Array, required: false },
|
|
44
44
|
onSelect: { type: Function, required: false },
|
|
45
45
|
ui: { type: Object, required: false }
|
|
@@ -75,11 +75,11 @@ const steps = computed(() => {
|
|
|
75
75
|
index,
|
|
76
76
|
label: resolveTextValue(label(row)),
|
|
77
77
|
note: previous === void 0 ? t("dashboard.funnel.base") : t("dashboard.funnel.fromPrevious", {
|
|
78
|
-
value: ratio === null ? "\u2014" : formats.percent
|
|
78
|
+
value: ratio === null ? "\u2014" : formats.percent(ratio)
|
|
79
79
|
}),
|
|
80
80
|
ratio,
|
|
81
81
|
row,
|
|
82
|
-
value: (format
|
|
82
|
+
value: formats.resolve(format)(amount),
|
|
83
83
|
width: first > 0 ? `${amount / first * 100}%` : "0%"
|
|
84
84
|
};
|
|
85
85
|
});
|
|
@@ -96,7 +96,7 @@ function tabulate() {
|
|
|
96
96
|
toDashboardCell(step.amount, step.value),
|
|
97
97
|
toDashboardCell(
|
|
98
98
|
step.ratio === null ? null : Math.round(step.ratio * 10) / 10,
|
|
99
|
-
step.ratio === null ? "" : formats.percent
|
|
99
|
+
step.ratio === null ? "" : formats.percent(step.ratio)
|
|
100
100
|
)
|
|
101
101
|
])
|
|
102
102
|
};
|
|
@@ -32,19 +32,19 @@ const {
|
|
|
32
32
|
title: { type: [String, Number, Function], required: false },
|
|
33
33
|
subtitle: { type: [String, Number, Function], required: false },
|
|
34
34
|
size: { type: String, required: false },
|
|
35
|
-
rows: { type: String, required: false },
|
|
36
35
|
card: { type: Boolean, required: false },
|
|
37
36
|
activation: { type: String, required: false },
|
|
38
37
|
empty: { type: Object, required: false },
|
|
39
38
|
menu: { type: [Boolean, Array, Function], required: false },
|
|
40
39
|
actions: { type: Array, required: false },
|
|
40
|
+
filters: { type: Array, required: false },
|
|
41
41
|
freshness: { type: Boolean, required: false },
|
|
42
42
|
source: { type: Object, required: true },
|
|
43
43
|
value: { type: Function, required: true },
|
|
44
44
|
min: { type: [Number, Function], required: false },
|
|
45
45
|
max: { type: [Number, Function], required: false },
|
|
46
46
|
target: { type: Function, required: false },
|
|
47
|
-
format: { type: Function, required: false },
|
|
47
|
+
format: { type: [String, Function], required: false, skipCheck: true },
|
|
48
48
|
caption: { type: [String, Number, Function], required: false },
|
|
49
49
|
color: { type: [String, Function], required: false },
|
|
50
50
|
variant: { type: String, required: false },
|
|
@@ -78,7 +78,7 @@ const gauge = computed(() => {
|
|
|
78
78
|
const span = high - low;
|
|
79
79
|
const share = span > 0 ? (amount - low) / span : 0;
|
|
80
80
|
const goal = target?.(data);
|
|
81
|
-
const formatValue =
|
|
81
|
+
const formatValue = formats.resolve(format);
|
|
82
82
|
const text = caption === void 0 || isString(caption) || isNumber(caption) ? caption : caption(data);
|
|
83
83
|
return {
|
|
84
84
|
caption: resolveTextValue(text),
|
|
@@ -4,13 +4,19 @@ type __VLS_Props = {
|
|
|
4
4
|
columns?: string;
|
|
5
5
|
/**
|
|
6
6
|
* `cards`: separate cards with a gap. `panels`: one bordered surface whose cells are separated by
|
|
7
|
-
* 1px rules
|
|
7
|
+
* 1px rules.
|
|
8
8
|
*/
|
|
9
9
|
variant?: 'cards' | 'panels';
|
|
10
10
|
/** Gap between cards, any CSS length. Defaults to `1rem`; ignored by `panels`. */
|
|
11
11
|
gap?: string;
|
|
12
12
|
/** Grid span when this grid is nested in another grid, responsive. */
|
|
13
13
|
size?: string;
|
|
14
|
+
/**
|
|
15
|
+
* A row that is not full (a block hidden because its source is disabled, or a short last row)
|
|
16
|
+
* shares its free width between its cells, in proportion to their span. Defaults to `true`;
|
|
17
|
+
* `false` keeps every cell at its span.
|
|
18
|
+
*/
|
|
19
|
+
fill?: boolean;
|
|
14
20
|
/** Card menu of every block inside that does not set its own `menu`. */
|
|
15
21
|
menu?: DashboardMenu;
|
|
16
22
|
/** `freshness` of every block inside that does not set its own. */
|
|
@@ -22,11 +28,12 @@ type __VLS_Slots = {} & {
|
|
|
22
28
|
default?: (props: typeof __VLS_1) => any;
|
|
23
29
|
};
|
|
24
30
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
31
|
+
fill: boolean;
|
|
32
|
+
columns: string;
|
|
25
33
|
variant: "cards" | "panels";
|
|
26
34
|
menu: DashboardMenu;
|
|
27
|
-
columns: string;
|
|
28
|
-
freshness: boolean;
|
|
29
35
|
gap: string;
|
|
36
|
+
freshness: boolean;
|
|
30
37
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
31
38
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
32
39
|
declare const _default: typeof __VLS_export;
|
|
@@ -2,37 +2,52 @@
|
|
|
2
2
|
import { twMerge } from "tailwind-merge";
|
|
3
3
|
import { computed } from "vue";
|
|
4
4
|
import { useResponsiveValue } from "#ui-tools/shared/composables/use-responsive-value";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
provideDashboardGrid,
|
|
7
|
+
useDashboardGridContext,
|
|
8
|
+
useDashboardUi
|
|
9
|
+
} from "../composables/use-dashboard-ui";
|
|
10
|
+
import { parseDashboardSpan, resolveDashboardCellStyle } from "../utils/grid";
|
|
6
11
|
const props = defineProps({
|
|
7
12
|
columns: { type: String, required: false, default: "12" },
|
|
8
13
|
variant: { type: String, required: false, default: "cards" },
|
|
9
14
|
gap: { type: String, required: false, default: "1rem" },
|
|
10
15
|
size: { type: String, required: false },
|
|
16
|
+
fill: { type: Boolean, required: false, default: true },
|
|
11
17
|
menu: { type: [Boolean, Array, Function], required: false, default: void 0 },
|
|
12
18
|
freshness: { type: Boolean, required: false, default: void 0 },
|
|
13
19
|
ui: { type: Object, required: false }
|
|
14
20
|
});
|
|
21
|
+
const parent = useDashboardGridContext();
|
|
22
|
+
const resolvedColumns = useResponsiveValue(() => props.columns, "integer");
|
|
23
|
+
const trackCount = computed(() => parseDashboardSpan(resolvedColumns.value) ?? 12);
|
|
24
|
+
const gap = computed(() => props.variant === "panels" ? "1px" : props.gap);
|
|
15
25
|
provideDashboardGrid({
|
|
26
|
+
columns: () => trackCount.value,
|
|
27
|
+
fill: () => props.fill,
|
|
16
28
|
freshness: () => props.freshness,
|
|
29
|
+
gap: () => gap.value,
|
|
17
30
|
menu: () => props.menu,
|
|
18
31
|
panels: () => props.variant === "panels"
|
|
19
32
|
});
|
|
20
33
|
const appUi = useDashboardUi();
|
|
21
|
-
const
|
|
22
|
-
const span = useResponsiveValue(() => props.size ?? "", "col");
|
|
34
|
+
const span = useResponsiveValue(() => props.size ?? "", "integer");
|
|
23
35
|
const style = computed(
|
|
24
36
|
() => [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
`gap: ${gap.value}`,
|
|
38
|
+
parent && resolveDashboardCellStyle({
|
|
39
|
+
columns: parent.columns.value,
|
|
40
|
+
fill: parent.fill.value,
|
|
41
|
+
gap: parent.gap.value,
|
|
42
|
+
span: parseDashboardSpan(span.value)
|
|
43
|
+
})
|
|
29
44
|
].filter(Boolean).join("; ")
|
|
30
45
|
);
|
|
31
46
|
const classes = computed(
|
|
32
47
|
() => twMerge(
|
|
33
|
-
"min-w-0",
|
|
48
|
+
"flex min-w-0 flex-wrap empty:hidden",
|
|
34
49
|
props.variant === "panels" && [
|
|
35
|
-
"
|
|
50
|
+
"overflow-hidden rounded-lg border border-default bg-(--ui-border)",
|
|
36
51
|
appUi.value.grid?.panels,
|
|
37
52
|
props.ui?.panels
|
|
38
53
|
],
|
|
@@ -4,13 +4,19 @@ type __VLS_Props = {
|
|
|
4
4
|
columns?: string;
|
|
5
5
|
/**
|
|
6
6
|
* `cards`: separate cards with a gap. `panels`: one bordered surface whose cells are separated by
|
|
7
|
-
* 1px rules
|
|
7
|
+
* 1px rules.
|
|
8
8
|
*/
|
|
9
9
|
variant?: 'cards' | 'panels';
|
|
10
10
|
/** Gap between cards, any CSS length. Defaults to `1rem`; ignored by `panels`. */
|
|
11
11
|
gap?: string;
|
|
12
12
|
/** Grid span when this grid is nested in another grid, responsive. */
|
|
13
13
|
size?: string;
|
|
14
|
+
/**
|
|
15
|
+
* A row that is not full (a block hidden because its source is disabled, or a short last row)
|
|
16
|
+
* shares its free width between its cells, in proportion to their span. Defaults to `true`;
|
|
17
|
+
* `false` keeps every cell at its span.
|
|
18
|
+
*/
|
|
19
|
+
fill?: boolean;
|
|
14
20
|
/** Card menu of every block inside that does not set its own `menu`. */
|
|
15
21
|
menu?: DashboardMenu;
|
|
16
22
|
/** `freshness` of every block inside that does not set its own. */
|
|
@@ -22,11 +28,12 @@ type __VLS_Slots = {} & {
|
|
|
22
28
|
default?: (props: typeof __VLS_1) => any;
|
|
23
29
|
};
|
|
24
30
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
31
|
+
fill: boolean;
|
|
32
|
+
columns: string;
|
|
25
33
|
variant: "cards" | "panels";
|
|
26
34
|
menu: DashboardMenu;
|
|
27
|
-
columns: string;
|
|
28
|
-
freshness: boolean;
|
|
29
35
|
gap: string;
|
|
36
|
+
freshness: boolean;
|
|
30
37
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
31
38
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
32
39
|
declare const _default: typeof __VLS_export;
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import type { LazyTextValue } from '#ui-tools/shared/types/utils';
|
|
2
|
-
import type { DashboardAxisOptions, DashboardBlockBaseProps, DashboardReferenceLine, DashboardSelected, DashboardSelectEvent, DashboardSeries, DashboardSourceLike, DashboardValueFormat } from '../types/index.js';
|
|
3
|
-
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<{
|
|
2
|
+
import type { DashboardAxisOptions, DashboardBlockBaseProps, DashboardChartTotals, DashboardFilterControl, DashboardOptionValue, DashboardReferenceLine, DashboardSelected, DashboardSelectEvent, DashboardSeries, DashboardSourceLike, DashboardValueFormat } from '../types/index.js';
|
|
3
|
+
declare const __VLS_export: <TRow, TItem extends DashboardOptionValue = DashboardOptionValue>(__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<{
|
|
4
4
|
props: import("vue").PublicProps & __VLS_PrettifyLocal<DashboardBlockBaseProps & {
|
|
5
5
|
source: DashboardSourceLike<readonly TRow[] | undefined>;
|
|
6
6
|
x: (row: TRow, index: number) => string | number | Date;
|
|
7
7
|
xFormat?: (value: string | number | Date) => string;
|
|
8
8
|
/** Header of the category column in the table view and CSV export. */
|
|
9
9
|
xLabel?: LazyTextValue;
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* The series, or a multiple filter whose picks become the series (one per option, in pick
|
|
12
|
+
* order): the chart then draws the picker and one removable chip per series.
|
|
13
|
+
*/
|
|
14
|
+
series: readonly DashboardSeries<TRow>[] | DashboardFilterControl<unknown, TItem>;
|
|
15
|
+
/** With `series` bound to a filter: the value of one picked option's series in a row. */
|
|
16
|
+
seriesValue?: (row: TRow, item: TItem) => number | null | undefined;
|
|
11
17
|
/** Dashed line, e.g. the previous period. */
|
|
12
18
|
comparison?: DashboardSeries<TRow>;
|
|
13
19
|
/** Fills the area under every solid series. */
|
|
@@ -21,6 +27,11 @@ declare const __VLS_export: <TRow>(__VLS_props: NonNullable<Awaited<typeof __VLS
|
|
|
21
27
|
points?: number;
|
|
22
28
|
/** Rows shown as selected: a band marks their x position. */
|
|
23
29
|
selected?: DashboardSelected<TRow>;
|
|
30
|
+
/**
|
|
31
|
+
* Footer totals of the solid series, formatted like their axis: `true` / `'sum'` adds each
|
|
32
|
+
* series up, `'average'` averages it. Footer slot content follows them.
|
|
33
|
+
*/
|
|
34
|
+
totals?: DashboardChartTotals;
|
|
24
35
|
/** A click on the chart selects the x position under the pointer. */
|
|
25
36
|
onSelect?: (event: DashboardSelectEvent<TRow>) => void;
|
|
26
37
|
}> & (typeof globalThis extends {
|
|
@@ -5,9 +5,13 @@ import {
|
|
|
5
5
|
resolveDashboardExpandedHeight,
|
|
6
6
|
useDashboardChart
|
|
7
7
|
} from "../composables/use-dashboard-chart";
|
|
8
|
+
import { useDashboardSeriesPicker } from "../composables/use-dashboard-series-picker";
|
|
9
|
+
import DashboardChips from "./block/dashboard-chips.vue";
|
|
10
|
+
import DashboardSeriesPicker from "./block/dashboard-series-picker.vue";
|
|
8
11
|
import DashboardSkeleton from "./block/dashboard-skeleton.vue";
|
|
9
12
|
import { dashboardChartRenderer } from "./charts/renderer";
|
|
10
13
|
import DashboardCard from "./dashboard-card.vue";
|
|
14
|
+
import DashboardTotal from "./dashboard-total.vue";
|
|
11
15
|
const {
|
|
12
16
|
source,
|
|
13
17
|
card = true,
|
|
@@ -17,6 +21,7 @@ const {
|
|
|
17
21
|
xFormat,
|
|
18
22
|
xLabel,
|
|
19
23
|
series,
|
|
24
|
+
seriesValue,
|
|
20
25
|
comparison,
|
|
21
26
|
area = false,
|
|
22
27
|
yAxis,
|
|
@@ -26,40 +31,47 @@ const {
|
|
|
26
31
|
legend = true,
|
|
27
32
|
points = 12,
|
|
28
33
|
selected,
|
|
34
|
+
totals,
|
|
29
35
|
onSelect,
|
|
30
36
|
...block
|
|
31
37
|
} = defineProps({
|
|
32
38
|
title: { type: [String, Number, Function], required: false },
|
|
33
39
|
subtitle: { type: [String, Number, Function], required: false },
|
|
34
40
|
size: { type: String, required: false },
|
|
35
|
-
rows: { type: String, required: false },
|
|
36
41
|
card: { type: Boolean, required: false },
|
|
37
42
|
activation: { type: String, required: false },
|
|
38
43
|
empty: { type: Object, required: false },
|
|
39
44
|
menu: { type: [Boolean, Array, Function], required: false },
|
|
40
45
|
actions: { type: Array, required: false },
|
|
46
|
+
filters: { type: Array, required: false },
|
|
41
47
|
freshness: { type: Boolean, required: false },
|
|
42
48
|
ui: { type: Object, required: false },
|
|
43
49
|
source: { type: Object, required: true },
|
|
44
50
|
x: { type: Function, required: true },
|
|
45
51
|
xFormat: { type: Function, required: false },
|
|
46
52
|
xLabel: { type: [String, Number, Function], required: false },
|
|
47
|
-
series: { type: Array, required: true },
|
|
53
|
+
series: { type: [Array, Object], required: true },
|
|
54
|
+
seriesValue: { type: Function, required: false },
|
|
48
55
|
comparison: { type: Object, required: false },
|
|
49
56
|
area: { type: Boolean, required: false },
|
|
50
57
|
yAxis: { type: Object, required: false },
|
|
51
|
-
format: { type: Function, required: false },
|
|
58
|
+
format: { type: [String, Function], required: false, skipCheck: true },
|
|
52
59
|
reference: { type: [Object, Array], required: false },
|
|
53
60
|
height: { type: Number, required: false },
|
|
54
61
|
legend: { type: Boolean, required: false },
|
|
55
62
|
points: { type: Number, required: false },
|
|
56
63
|
selected: { type: Function, required: false },
|
|
64
|
+
totals: { type: [Boolean, String], required: false },
|
|
57
65
|
onSelect: { type: Function, required: false }
|
|
58
66
|
});
|
|
59
67
|
defineSlots();
|
|
60
68
|
const mounted = useMounted();
|
|
69
|
+
const picked = useDashboardSeriesPicker({
|
|
70
|
+
series: () => series,
|
|
71
|
+
value: () => seriesValue
|
|
72
|
+
});
|
|
61
73
|
const allSeries = computed(() => {
|
|
62
|
-
const solid = series.map((entry, index) => ({
|
|
74
|
+
const solid = picked.series.value.map((entry, index) => ({
|
|
63
75
|
...entry,
|
|
64
76
|
color: entry.color ?? `series-${index % 6 + 1}`,
|
|
65
77
|
type: entry.type ?? (area && !entry.dashed ? "area" : "line")
|
|
@@ -67,9 +79,10 @@ const allSeries = computed(() => {
|
|
|
67
79
|
return comparison ? [{ color: "series-2", ...comparison, dashed: true, type: "line" }, ...solid] : solid;
|
|
68
80
|
});
|
|
69
81
|
const seed = computed(() => allSeries.value.map((entry) => entry.key).join("|"));
|
|
70
|
-
const skeletonSeries = computed(() => series.length);
|
|
82
|
+
const skeletonSeries = computed(() => picked.series.value.length || 1);
|
|
71
83
|
const skeletonPoints = computed(() => source.data?.length || points);
|
|
72
84
|
const chart = useDashboardChart({
|
|
85
|
+
totals: () => totals,
|
|
73
86
|
defaultType: "line",
|
|
74
87
|
format: () => format,
|
|
75
88
|
onSelect: () => onSelect,
|
|
@@ -91,7 +104,7 @@ const chart = useDashboardChart({
|
|
|
91
104
|
:menu
|
|
92
105
|
:freshness
|
|
93
106
|
:source
|
|
94
|
-
:legend="legend ? chart.legend.value : void 0"
|
|
107
|
+
:legend="legend && !picked.picker.value ? chart.legend.value : void 0"
|
|
95
108
|
:is-empty="chart.frame.value.data.length === 0 || chart.frame.value.series.length === 0"
|
|
96
109
|
:tabulate="chart.tabulate"
|
|
97
110
|
>
|
|
@@ -104,13 +117,21 @@ const chart = useDashboardChart({
|
|
|
104
117
|
:seed
|
|
105
118
|
/>
|
|
106
119
|
</template>
|
|
107
|
-
<template v-if="$slots['header-right']" #header-right>
|
|
120
|
+
<template v-if="$slots['header-right'] || picked.picker.value" #header-right>
|
|
121
|
+
<DashboardSeriesPicker v-if="picked.picker.value" :filter="picked.picker.value" />
|
|
108
122
|
<slot name="header-right" />
|
|
109
123
|
</template>
|
|
110
|
-
<template v-if="$slots.toolbar" #toolbar>
|
|
124
|
+
<template v-if="$slots.toolbar || picked.chips.value.length" #toolbar>
|
|
125
|
+
<DashboardChips v-if="picked.chips.value.length" :chips="picked.chips.value" />
|
|
111
126
|
<slot name="toolbar" />
|
|
112
127
|
</template>
|
|
113
|
-
<template v-if="$slots.footer" #footer>
|
|
128
|
+
<template v-if="$slots.footer || chart.totals.value.length" #footer>
|
|
129
|
+
<DashboardTotal
|
|
130
|
+
v-for="total in chart.totals.value"
|
|
131
|
+
:key="total.key"
|
|
132
|
+
:label="total.label"
|
|
133
|
+
:value="total.text"
|
|
134
|
+
/>
|
|
114
135
|
<slot name="footer" />
|
|
115
136
|
</template>
|
|
116
137
|
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import type { LazyTextValue } from '#ui-tools/shared/types/utils';
|
|
2
|
-
import type { DashboardAxisOptions, DashboardBlockBaseProps, DashboardReferenceLine, DashboardSelected, DashboardSelectEvent, DashboardSeries, DashboardSourceLike, DashboardValueFormat } from '../types/index.js';
|
|
3
|
-
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<{
|
|
2
|
+
import type { DashboardAxisOptions, DashboardBlockBaseProps, DashboardChartTotals, DashboardFilterControl, DashboardOptionValue, DashboardReferenceLine, DashboardSelected, DashboardSelectEvent, DashboardSeries, DashboardSourceLike, DashboardValueFormat } from '../types/index.js';
|
|
3
|
+
declare const __VLS_export: <TRow, TItem extends DashboardOptionValue = DashboardOptionValue>(__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<{
|
|
4
4
|
props: import("vue").PublicProps & __VLS_PrettifyLocal<DashboardBlockBaseProps & {
|
|
5
5
|
source: DashboardSourceLike<readonly TRow[] | undefined>;
|
|
6
6
|
x: (row: TRow, index: number) => string | number | Date;
|
|
7
7
|
xFormat?: (value: string | number | Date) => string;
|
|
8
8
|
/** Header of the category column in the table view and CSV export. */
|
|
9
9
|
xLabel?: LazyTextValue;
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* The series, or a multiple filter whose picks become the series (one per option, in pick
|
|
12
|
+
* order): the chart then draws the picker and one removable chip per series.
|
|
13
|
+
*/
|
|
14
|
+
series: readonly DashboardSeries<TRow>[] | DashboardFilterControl<unknown, TItem>;
|
|
15
|
+
/** With `series` bound to a filter: the value of one picked option's series in a row. */
|
|
16
|
+
seriesValue?: (row: TRow, item: TItem) => number | null | undefined;
|
|
11
17
|
/** Dashed line, e.g. the previous period. */
|
|
12
18
|
comparison?: DashboardSeries<TRow>;
|
|
13
19
|
/** Fills the area under every solid series. */
|
|
@@ -21,6 +27,11 @@ declare const __VLS_export: <TRow>(__VLS_props: NonNullable<Awaited<typeof __VLS
|
|
|
21
27
|
points?: number;
|
|
22
28
|
/** Rows shown as selected: a band marks their x position. */
|
|
23
29
|
selected?: DashboardSelected<TRow>;
|
|
30
|
+
/**
|
|
31
|
+
* Footer totals of the solid series, formatted like their axis: `true` / `'sum'` adds each
|
|
32
|
+
* series up, `'average'` averages it. Footer slot content follows them.
|
|
33
|
+
*/
|
|
34
|
+
totals?: DashboardChartTotals;
|
|
24
35
|
/** A click on the chart selects the x position under the pointer. */
|
|
25
36
|
onSelect?: (event: DashboardSelectEvent<TRow>) => void;
|
|
26
37
|
}> & (typeof globalThis extends {
|
|
@@ -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. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import UButton from "@nuxt/ui/components/Button.vue";
|
|
2
3
|
import UIcon from "@nuxt/ui/components/Icon.vue";
|
|
3
4
|
import { computed } from "vue";
|
|
4
5
|
import { useUiToolsLocale } from "#ui-tools/i18n";
|
|
@@ -36,6 +37,7 @@ const {
|
|
|
36
37
|
limit,
|
|
37
38
|
rowKey,
|
|
38
39
|
selected,
|
|
40
|
+
to,
|
|
39
41
|
rowActions,
|
|
40
42
|
onSelect,
|
|
41
43
|
ui,
|
|
@@ -44,18 +46,18 @@ const {
|
|
|
44
46
|
title: { type: [String, Number, Function], required: false },
|
|
45
47
|
subtitle: { type: [String, Number, Function], required: false },
|
|
46
48
|
size: { type: String, required: false },
|
|
47
|
-
rows: { type: String, required: false },
|
|
48
49
|
card: { type: Boolean, required: false },
|
|
49
50
|
activation: { type: String, required: false },
|
|
50
51
|
empty: { type: Object, required: false },
|
|
51
52
|
menu: { type: [Boolean, Array, Function], required: false },
|
|
52
53
|
actions: { type: Array, required: false },
|
|
54
|
+
filters: { type: Array, required: false },
|
|
53
55
|
freshness: { type: Boolean, required: false },
|
|
54
56
|
source: { type: Object, required: true },
|
|
55
57
|
label: { type: Function, required: true },
|
|
56
58
|
description: { type: Function, required: false },
|
|
57
59
|
value: { type: Function, required: false },
|
|
58
|
-
format: { type: Function, required: false },
|
|
60
|
+
format: { type: [String, Function], required: false, skipCheck: true },
|
|
59
61
|
percent: { type: Function, required: false },
|
|
60
62
|
delta: { type: Function, required: false },
|
|
61
63
|
leading: { type: String, required: false },
|
|
@@ -65,6 +67,7 @@ const {
|
|
|
65
67
|
limit: { type: Number, required: false },
|
|
66
68
|
rowKey: { type: Function, required: false },
|
|
67
69
|
selected: { type: Function, required: false },
|
|
70
|
+
to: { type: Function, required: false },
|
|
68
71
|
rowActions: { type: Function, required: false },
|
|
69
72
|
onSelect: { type: Function, required: false },
|
|
70
73
|
ui: { type: Object, required: false }
|
|
@@ -98,7 +101,7 @@ const entries = computed(
|
|
|
98
101
|
const share = percent?.(row);
|
|
99
102
|
return {
|
|
100
103
|
actions: rowActions?.(row, index) ?? [],
|
|
101
|
-
change: isNumber(change) ? { good: change >= 0, label: formats.delta
|
|
104
|
+
change: isNumber(change) ? { good: change >= 0, label: formats.delta(change) } : null,
|
|
102
105
|
color: resolveDashboardColor(color?.(row, index), index),
|
|
103
106
|
delta: change,
|
|
104
107
|
description: description ? resolveTextValue(description(row)) : "",
|
|
@@ -111,8 +114,9 @@ const entries = computed(
|
|
|
111
114
|
raw,
|
|
112
115
|
row,
|
|
113
116
|
selected: selected?.(row, index) ?? false,
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
target: to?.(row, index),
|
|
118
|
+
share: isNumber(share) ? formats.percent(share) : "",
|
|
119
|
+
value: isNumber(raw) ? formats.resolve(format)(raw) : resolveTextValue(raw)
|
|
116
120
|
};
|
|
117
121
|
})
|
|
118
122
|
);
|
|
@@ -179,7 +183,7 @@ function initials(text) {
|
|
|
179
183
|
:data-selected="entry.selected || void 0"
|
|
180
184
|
:class="[
|
|
181
185
|
classes.row,
|
|
182
|
-
onSelect && DASHBOARD_SELECTABLE_ROW,
|
|
186
|
+
(onSelect || entry.target !== void 0) && DASHBOARD_SELECTABLE_ROW,
|
|
183
187
|
entry.selected && DASHBOARD_SELECTED_ROW
|
|
184
188
|
]"
|
|
185
189
|
>
|
|
@@ -227,6 +231,14 @@ function initials(text) {
|
|
|
227
231
|
:aria-pressed="selected ? entry.selected : void 0"
|
|
228
232
|
@click="onSelect({ index: entry.index, row: entry.row })"
|
|
229
233
|
/>
|
|
234
|
+
<UButton
|
|
235
|
+
v-else-if="entry.target !== void 0"
|
|
236
|
+
:to="entry.target"
|
|
237
|
+
variant="link"
|
|
238
|
+
:aria-label="entry.label"
|
|
239
|
+
:class="DASHBOARD_ROW_BUTTON"
|
|
240
|
+
data-row-link
|
|
241
|
+
/>
|
|
230
242
|
<DashboardRowActionsMenu
|
|
231
243
|
v-if="entry.actions.length"
|
|
232
244
|
:actions="entry.actions"
|