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,142 @@
|
|
|
1
|
+
import type { QueryCodec } from '../../../query-state/index.js';
|
|
2
|
+
import type { DashboardComparison, DashboardDateRange, DashboardOption, DashboardOptionValue, DashboardFilterDefault, DashboardFilterDefinition, DashboardFilterFormatOptions, DashboardFilterListOptions, DashboardFilterMultipleOptions, DashboardFilterOptions, DashboardRemoteOptionsConfig } from '../../types/index.js';
|
|
3
|
+
/** Options of a single-value filter whose values carry no label of their own. */
|
|
4
|
+
type SingleOptions<TValue> = DashboardFilterOptions<DashboardFilterDefault<TValue>, TValue> & DashboardFilterFormatOptions<TValue> & {
|
|
5
|
+
multiple?: false;
|
|
6
|
+
};
|
|
7
|
+
/** Options of a `multiple` filter: the value is an always-defined array. */
|
|
8
|
+
type MultipleOptions<TItem> = DashboardFilterOptions<DashboardFilterDefault<readonly TItem[]>, TItem[]> & DashboardFilterMultipleOptions & {
|
|
9
|
+
multiple: true;
|
|
10
|
+
};
|
|
11
|
+
/** Options of a filter holding one value, or a list with `multiple: true`. */
|
|
12
|
+
type FilterOptions<TItem> = SingleOptions<TItem> | (MultipleOptions<TItem> & DashboardFilterFormatOptions<TItem>);
|
|
13
|
+
/** The same, for filters picked from a list. */
|
|
14
|
+
type ListFilterOptions<TItem> = FilterOptions<TItem> & DashboardFilterListOptions;
|
|
15
|
+
/** Options of filters whose items carry their own labels (`f.options`, `f.remote`). */
|
|
16
|
+
type LabeledFilterOptions<TItem> = ((DashboardFilterOptions<DashboardFilterDefault<TItem>, TItem> & {
|
|
17
|
+
multiple?: false;
|
|
18
|
+
}) | MultipleOptions<TItem>) & DashboardFilterListOptions;
|
|
19
|
+
/**
|
|
20
|
+
* Value of a filter declared with `TOptions`: an array with `multiple: true`; otherwise defined once
|
|
21
|
+
* a default is declared (a value, or a getter that never returns `undefined`).
|
|
22
|
+
*
|
|
23
|
+
* Builders infer the whole options object rather than overloading on its shape: every overload
|
|
24
|
+
* would contextually type a default or presets getter on its own, and the first one tried fixes
|
|
25
|
+
* the getter's result (widening `() => 2026` to `() => number`).
|
|
26
|
+
*/
|
|
27
|
+
type FilterValue<TItem, TOptions> = TOptions extends {
|
|
28
|
+
multiple: true;
|
|
29
|
+
} ? TItem[] : TOptions extends {
|
|
30
|
+
defaultValue: infer TDefault;
|
|
31
|
+
} ? undefined extends (TDefault extends () => infer TResult ? TResult : TDefault) ? TItem | undefined : TItem : TItem | undefined;
|
|
32
|
+
declare function stringFilter(): DashboardFilterDefinition<string | undefined> & {
|
|
33
|
+
readonly kind: 'string';
|
|
34
|
+
};
|
|
35
|
+
declare function stringFilter<const TOptions extends FilterOptions<string>>(options: TOptions): DashboardFilterDefinition<FilterValue<string, TOptions>> & {
|
|
36
|
+
readonly kind: 'string';
|
|
37
|
+
};
|
|
38
|
+
declare function numberFilter(): DashboardFilterDefinition<number | undefined> & {
|
|
39
|
+
readonly kind: 'number';
|
|
40
|
+
};
|
|
41
|
+
declare function numberFilter<const TOptions extends FilterOptions<number>>(options: TOptions): DashboardFilterDefinition<FilterValue<number, TOptions>> & {
|
|
42
|
+
readonly kind: 'number';
|
|
43
|
+
};
|
|
44
|
+
declare function booleanFilter(): DashboardFilterDefinition<boolean | undefined> & {
|
|
45
|
+
readonly kind: 'boolean';
|
|
46
|
+
};
|
|
47
|
+
declare function booleanFilter<const TOptions extends SingleOptions<boolean>>(options: TOptions): DashboardFilterDefinition<FilterValue<boolean, TOptions>> & {
|
|
48
|
+
readonly kind: 'boolean';
|
|
49
|
+
};
|
|
50
|
+
declare function dateFilter(): DashboardFilterDefinition<Date | undefined> & {
|
|
51
|
+
readonly kind: 'date';
|
|
52
|
+
};
|
|
53
|
+
declare function dateFilter<const TOptions extends SingleOptions<Date>>(options: TOptions): DashboardFilterDefinition<FilterValue<Date, TOptions>> & {
|
|
54
|
+
readonly kind: 'date';
|
|
55
|
+
};
|
|
56
|
+
declare function dateRangeFilter(): DashboardFilterDefinition<DashboardDateRange | undefined> & {
|
|
57
|
+
readonly kind: 'dateRange';
|
|
58
|
+
};
|
|
59
|
+
declare function dateRangeFilter<const TOptions extends SingleOptions<DashboardDateRange>>(options: TOptions): DashboardFilterDefinition<FilterValue<DashboardDateRange, TOptions>> & {
|
|
60
|
+
readonly kind: 'dateRange';
|
|
61
|
+
};
|
|
62
|
+
declare function enumFilter<const TValues extends readonly DashboardOptionValue[]>(values: TValues): DashboardFilterDefinition<TValues[number] | undefined> & {
|
|
63
|
+
readonly kind: 'enum';
|
|
64
|
+
};
|
|
65
|
+
declare function enumFilter<const TValues extends readonly DashboardOptionValue[], const TOptions extends ListFilterOptions<TValues[number]>>(values: TValues, options: TOptions): DashboardFilterDefinition<FilterValue<TValues[number], TOptions>> & {
|
|
66
|
+
readonly kind: 'enum';
|
|
67
|
+
};
|
|
68
|
+
declare function optionsFilter<const TItems extends readonly DashboardOption[]>(items: TItems): DashboardFilterDefinition<TItems[number]['value'] | undefined> & {
|
|
69
|
+
readonly kind: 'options';
|
|
70
|
+
};
|
|
71
|
+
declare function optionsFilter<const TItems extends readonly DashboardOption[], const TOptions extends LabeledFilterOptions<TItems[number]['value']>>(items: TItems, options: TOptions): DashboardFilterDefinition<FilterValue<TItems[number]['value'], TOptions>> & {
|
|
72
|
+
readonly kind: 'options';
|
|
73
|
+
};
|
|
74
|
+
declare function optionsFilter(items: () => readonly DashboardOption<string>[]): DashboardFilterDefinition<string | undefined> & {
|
|
75
|
+
readonly kind: 'options';
|
|
76
|
+
};
|
|
77
|
+
declare function optionsFilter<const TOptions extends LabeledFilterOptions<string>>(items: () => readonly DashboardOption<string>[], options: TOptions): DashboardFilterDefinition<FilterValue<string, TOptions>> & {
|
|
78
|
+
readonly kind: 'options';
|
|
79
|
+
};
|
|
80
|
+
type RemoteSource = DashboardRemoteOptionsConfig;
|
|
81
|
+
declare function remoteFilter<const TConfig extends RemoteSource & LabeledFilterOptions<string>>(config: TConfig): DashboardFilterDefinition<FilterValue<string, TConfig>> & {
|
|
82
|
+
readonly kind: 'remote';
|
|
83
|
+
};
|
|
84
|
+
declare function remoteFilter<const TOptions extends LabeledFilterOptions<string>>(source: RemoteSource, options: TOptions): DashboardFilterDefinition<FilterValue<string, TOptions>> & {
|
|
85
|
+
readonly kind: 'remote';
|
|
86
|
+
};
|
|
87
|
+
/** Values of `f.comparison`, in menu order. */
|
|
88
|
+
export declare const DASHBOARD_COMPARISONS: readonly ["previous", "year", "none"];
|
|
89
|
+
declare function comparisonFilter(): DashboardFilterDefinition<DashboardComparison | undefined> & {
|
|
90
|
+
readonly kind: 'comparison';
|
|
91
|
+
};
|
|
92
|
+
declare function comparisonFilter<const TOptions extends DashboardFilterOptions<DashboardFilterDefault<DashboardComparison>, DashboardComparison>>(options: TOptions): DashboardFilterDefinition<FilterValue<DashboardComparison, TOptions>> & {
|
|
93
|
+
readonly kind: 'comparison';
|
|
94
|
+
};
|
|
95
|
+
declare function customFilter<TValue>(codec: QueryCodec<TValue>): DashboardFilterDefinition<TValue | undefined> & {
|
|
96
|
+
readonly kind: 'custom';
|
|
97
|
+
};
|
|
98
|
+
declare function customFilter<TValue, const TOptions extends SingleOptions<TValue>>(codec: QueryCodec<TValue>, options: TOptions): DashboardFilterDefinition<FilterValue<TValue, TOptions>> & {
|
|
99
|
+
readonly kind: 'custom';
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* The `f` builder handed to every `filters` callback. Each method declares one typed filter: its
|
|
103
|
+
* value is `dashboard.filters.<key>`, and its control `dashboard.controls.<key>` drives it from any
|
|
104
|
+
* component.
|
|
105
|
+
*
|
|
106
|
+
* Every filter accepts `defaultValue` (a value or a getter; it narrows away `undefined`), `sync`
|
|
107
|
+
* (URL, memory, or an external store), `urlKey`, `omitDefault`, `historyMode`, `presets`, and the
|
|
108
|
+
* filter presentation: `label`, `placeholder`, `headless`. Filters picked from a list also accept
|
|
109
|
+
* `columns` and `searchable`; `multiple: true` turns the value into an always-defined array, capped
|
|
110
|
+
* by `max`.
|
|
111
|
+
*/
|
|
112
|
+
export declare const dashboardFilterBuilder: {
|
|
113
|
+
/** `true` / `false`. Its filter lists both, labeled by `format` or the localized Yes / No. */
|
|
114
|
+
boolean: typeof booleanFilter;
|
|
115
|
+
/**
|
|
116
|
+
* Comparison period: `'previous'`, `'year'`, or `'none'`. Its filter carries localized labels;
|
|
117
|
+
* `resolveDashboardComparisonRange(range, mode)` turns it into the range to fetch.
|
|
118
|
+
*/
|
|
119
|
+
comparison: typeof comparisonFilter;
|
|
120
|
+
custom: typeof customFilter;
|
|
121
|
+
date: typeof dateFilter;
|
|
122
|
+
/** Inclusive date range, serialized as `YYYY-MM-DD..YYYY-MM-DD`. */
|
|
123
|
+
dateRange: typeof dateRangeFilter;
|
|
124
|
+
/** Value(s) from a literal list, e.g. `f.enum([2024, 2025, 2026], { defaultValue: 2026 })`. */
|
|
125
|
+
enum: typeof enumFilter;
|
|
126
|
+
/** Number, or `number[]` with `multiple: true`. */
|
|
127
|
+
number: typeof numberFilter;
|
|
128
|
+
/**
|
|
129
|
+
* Value(s) from labeled items: `{ value, label, icon?, avatar?, hint?, description? }`. Pass a
|
|
130
|
+
* getter to read the items from data, e.g. `f.options(() => products.data?.map(toOption) ?? [])`;
|
|
131
|
+
* their values are strings.
|
|
132
|
+
*/
|
|
133
|
+
options: typeof optionsFilter;
|
|
134
|
+
/**
|
|
135
|
+
* Id(s) picked from a remote, searchable, paginated option source:
|
|
136
|
+
* `f.remote(remoteTableOptions(query, { ... }), { label: 'Account' })`.
|
|
137
|
+
*/
|
|
138
|
+
remote: typeof remoteFilter;
|
|
139
|
+
/** String, or `string[]` with `multiple: true`. */
|
|
140
|
+
string: typeof stringFilter;
|
|
141
|
+
};
|
|
142
|
+
export {};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { isFunction } from "../../../shared/utils/predicate.js";
|
|
2
|
+
import {
|
|
3
|
+
createListCodec,
|
|
4
|
+
createOptionValueCodec,
|
|
5
|
+
createSafeCodec,
|
|
6
|
+
dateRangeCodec,
|
|
7
|
+
localDateCodec,
|
|
8
|
+
optionalBooleanCodec,
|
|
9
|
+
optionalNumberCodec,
|
|
10
|
+
optionalStringCodec
|
|
11
|
+
} from "../codecs.js";
|
|
12
|
+
function defineFilter(kind, codec, options = {}) {
|
|
13
|
+
const multiple = options.multiple === true;
|
|
14
|
+
const { defaultValue, items, presets } = options;
|
|
15
|
+
const unset = multiple ? [] : void 0;
|
|
16
|
+
const resolveDefault = isFunction(defaultValue) ? () => defaultValue() ?? unset : () => defaultValue ?? unset;
|
|
17
|
+
let read = resolveDefault;
|
|
18
|
+
return {
|
|
19
|
+
bind(next) {
|
|
20
|
+
read = next;
|
|
21
|
+
},
|
|
22
|
+
codec: multiple ? createListCodec(codec) : codec,
|
|
23
|
+
columns: options.columns,
|
|
24
|
+
defaultValue: isFunction(defaultValue) ? unset : defaultValue ?? unset,
|
|
25
|
+
enabled: options.enabled,
|
|
26
|
+
format: options.format,
|
|
27
|
+
headless: options.headless === true,
|
|
28
|
+
historyMode: options.historyMode,
|
|
29
|
+
// Fixed lists become getters too, so the option list reads every list the same way.
|
|
30
|
+
items: items === void 0 || isItemsGetter(items) ? items : () => items,
|
|
31
|
+
kind,
|
|
32
|
+
label: options.label,
|
|
33
|
+
max: options.max,
|
|
34
|
+
multiple,
|
|
35
|
+
omitDefault: options.omitDefault,
|
|
36
|
+
placeholder: options.placeholder,
|
|
37
|
+
presets: presets === void 0 || isPresetsGetter(presets) ? presets : () => presets,
|
|
38
|
+
remote: options.remote,
|
|
39
|
+
resolveDefault,
|
|
40
|
+
searchable: options.searchable,
|
|
41
|
+
sync: options.sync,
|
|
42
|
+
urlKey: options.urlKey,
|
|
43
|
+
get value() {
|
|
44
|
+
return read();
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function isItemsGetter(items) {
|
|
49
|
+
return !Array.isArray(items);
|
|
50
|
+
}
|
|
51
|
+
function isPresetsGetter(presets) {
|
|
52
|
+
return !Array.isArray(presets);
|
|
53
|
+
}
|
|
54
|
+
function stringFilter(options) {
|
|
55
|
+
return defineFilter("string", optionalStringCodec, options);
|
|
56
|
+
}
|
|
57
|
+
function numberFilter(options) {
|
|
58
|
+
return defineFilter("number", optionalNumberCodec, options);
|
|
59
|
+
}
|
|
60
|
+
const BOOLEAN_ITEMS = [
|
|
61
|
+
{ label: "true", value: true },
|
|
62
|
+
{ label: "false", value: false }
|
|
63
|
+
];
|
|
64
|
+
function booleanFilter(options) {
|
|
65
|
+
return defineFilter("boolean", optionalBooleanCodec, { ...options, items: BOOLEAN_ITEMS });
|
|
66
|
+
}
|
|
67
|
+
function dateFilter(options) {
|
|
68
|
+
return defineFilter("date", localDateCodec, options);
|
|
69
|
+
}
|
|
70
|
+
function dateRangeFilter(options) {
|
|
71
|
+
return defineFilter("dateRange", dateRangeCodec, options);
|
|
72
|
+
}
|
|
73
|
+
function enumFilter(values, options) {
|
|
74
|
+
const items = values.map((value) => ({ label: String(value), value }));
|
|
75
|
+
return defineFilter("enum", createOptionValueCodec(values), { ...options, items });
|
|
76
|
+
}
|
|
77
|
+
function optionsFilter(items, options) {
|
|
78
|
+
const codec = isItemsGetter(items) ? optionalStringCodec : createOptionValueCodec(items.map((item) => item.value));
|
|
79
|
+
return defineFilter("options", codec, { ...options, items });
|
|
80
|
+
}
|
|
81
|
+
function remoteFilter(config, extra) {
|
|
82
|
+
const { load, pagination, queryKey, resolveSelected, search, ...options } = config;
|
|
83
|
+
const remote = { load, pagination, queryKey, resolveSelected, search };
|
|
84
|
+
return defineFilter("remote", optionalStringCodec, {
|
|
85
|
+
searchable: true,
|
|
86
|
+
...options,
|
|
87
|
+
...extra,
|
|
88
|
+
remote
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
export const DASHBOARD_COMPARISONS = [
|
|
92
|
+
"previous",
|
|
93
|
+
"year",
|
|
94
|
+
"none"
|
|
95
|
+
];
|
|
96
|
+
function comparisonFilter(options) {
|
|
97
|
+
const items = DASHBOARD_COMPARISONS.map((value) => ({ label: value, value }));
|
|
98
|
+
return defineFilter("comparison", createOptionValueCodec(DASHBOARD_COMPARISONS), {
|
|
99
|
+
...options,
|
|
100
|
+
items
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function customFilter(codec, options) {
|
|
104
|
+
return defineFilter("custom", createSafeCodec(codec), options);
|
|
105
|
+
}
|
|
106
|
+
export const dashboardFilterBuilder = {
|
|
107
|
+
/** `true` / `false`. Its filter lists both, labeled by `format` or the localized Yes / No. */
|
|
108
|
+
boolean: booleanFilter,
|
|
109
|
+
/**
|
|
110
|
+
* Comparison period: `'previous'`, `'year'`, or `'none'`. Its filter carries localized labels;
|
|
111
|
+
* `resolveDashboardComparisonRange(range, mode)` turns it into the range to fetch.
|
|
112
|
+
*/
|
|
113
|
+
comparison: comparisonFilter,
|
|
114
|
+
custom: customFilter,
|
|
115
|
+
date: dateFilter,
|
|
116
|
+
/** Inclusive date range, serialized as `YYYY-MM-DD..YYYY-MM-DD`. */
|
|
117
|
+
dateRange: dateRangeFilter,
|
|
118
|
+
/** Value(s) from a literal list, e.g. `f.enum([2024, 2025, 2026], { defaultValue: 2026 })`. */
|
|
119
|
+
enum: enumFilter,
|
|
120
|
+
/** Number, or `number[]` with `multiple: true`. */
|
|
121
|
+
number: numberFilter,
|
|
122
|
+
/**
|
|
123
|
+
* Value(s) from labeled items: `{ value, label, icon?, avatar?, hint?, description? }`. Pass a
|
|
124
|
+
* getter to read the items from data, e.g. `f.options(() => products.data?.map(toOption) ?? [])`;
|
|
125
|
+
* their values are strings.
|
|
126
|
+
*/
|
|
127
|
+
options: optionsFilter,
|
|
128
|
+
/**
|
|
129
|
+
* Id(s) picked from a remote, searchable, paginated option source:
|
|
130
|
+
* `f.remote(remoteTableOptions(query, { ... }), { label: 'Account' })`.
|
|
131
|
+
*/
|
|
132
|
+
remote: remoteFilter,
|
|
133
|
+
/** String, or `string[]` with `multiple: true`. */
|
|
134
|
+
string: stringFilter
|
|
135
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DashboardAxisOptions, DashboardChartFrameAxis, DashboardHighlight, DashboardLegendItem, DashboardSelected, DashboardSeries, DashboardSeriesColor
|
|
1
|
+
import type { DashboardAxisOptions, DashboardChartFrameAxis, DashboardHighlight, DashboardLegendItem, DashboardSelected, DashboardSeries, DashboardSeriesColor } from '../types/index.js';
|
|
2
2
|
export declare const DASHBOARD_PALETTE_SIZE = 6;
|
|
3
3
|
/**
|
|
4
4
|
* Resolves a series color to a CSS value. Palette slots and Nuxt UI colors map to CSS variables, so
|
|
@@ -39,22 +39,11 @@ export declare function niceDashboardTickCount(max: number): number;
|
|
|
39
39
|
/**
|
|
40
40
|
* Value domain and tick values covering every value: `0` included, the top rounded to a readable
|
|
41
41
|
* bound with some headroom, and evenly spaced ticks that land on round numbers.
|
|
42
|
+
*
|
|
43
|
+
* When every value is a whole number (counts, units, or nothing but zeros), so are the top and the
|
|
44
|
+
* step: a quarter tick would print as a repeated label once formatted as an integer.
|
|
42
45
|
*/
|
|
43
46
|
export declare function resolveDashboardAxis(values: readonly (number | null | undefined)[], axis: DashboardAxisOptions | undefined, headroom?: number): Pick<DashboardChartFrameAxis, 'domain' | 'ticks'>;
|
|
44
|
-
/** Default formatters of one locale: numbers, signed changes, and shares (both in percent). */
|
|
45
|
-
export interface DashboardFormats {
|
|
46
|
-
/** Locale number, compact from 10 000 (`12,6 k`). */
|
|
47
|
-
number: DashboardValueFormat;
|
|
48
|
-
/** Signed percent change: `12.4` → `+12,4 %`. */
|
|
49
|
-
delta: DashboardValueFormat;
|
|
50
|
-
/** Percent share: `57` → `57 %`. */
|
|
51
|
-
percent: DashboardValueFormat;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Formatters of one locale. `Intl.NumberFormat` instances are costly to build and stateless, so they
|
|
55
|
-
* are created once per locale and shared by every block.
|
|
56
|
-
*/
|
|
57
|
-
export declare function resolveDashboardFormats(locale: string): DashboardFormats;
|
|
58
47
|
/** Escapes text interpolated into chart tooltip HTML. */
|
|
59
48
|
export declare function escapeDashboardHtml(value: string): string;
|
|
60
49
|
/** Deterministic pseudo-random sequence, so placeholders render identically on server and client. */
|
|
@@ -83,21 +83,39 @@ export function niceDashboardTickCount(max) {
|
|
|
83
83
|
}
|
|
84
84
|
export function resolveDashboardAxis(values, axis, headroom = 1.05) {
|
|
85
85
|
const finite = values.filter((value) => Number.isFinite(value));
|
|
86
|
+
const integral = finite.every((value) => Number.isInteger(value));
|
|
86
87
|
const lowest = Math.min(0, ...finite);
|
|
87
88
|
if (lowest < 0 && axis?.min === void 0 && axis?.max === void 0)
|
|
88
|
-
return resolveDivergingAxis(
|
|
89
|
+
return resolveDivergingAxis({
|
|
90
|
+
headroom,
|
|
91
|
+
highest: Math.max(0, ...finite),
|
|
92
|
+
integral,
|
|
93
|
+
lowest,
|
|
94
|
+
ticks: axis?.ticks
|
|
95
|
+
});
|
|
89
96
|
const min = axis?.min ?? lowest;
|
|
90
|
-
const
|
|
91
|
-
const
|
|
97
|
+
const top = niceDashboardMax(Math.max(0, ...finite) * headroom);
|
|
98
|
+
const max = axis?.max ?? (integral ? Math.ceil(top) : top);
|
|
99
|
+
const nice = Math.max(1, Math.round(axis?.ticks ?? niceDashboardTickCount(max - min)));
|
|
100
|
+
const count = integral && axis?.ticks === void 0 && Number.isInteger(max - min) ? wholeStepCount(max - min, nice) : nice;
|
|
92
101
|
const ticks = Array.from({ length: count + 1 }, (_, index) => min + (max - min) * index / count);
|
|
93
102
|
return { domain: [min, max], ticks };
|
|
94
103
|
}
|
|
95
|
-
function
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
function wholeStepCount(range, count) {
|
|
105
|
+
for (let candidate = count; candidate > 1; candidate -= 1) {
|
|
106
|
+
if (Number.isInteger(range / candidate)) return candidate;
|
|
107
|
+
}
|
|
108
|
+
return 1;
|
|
109
|
+
}
|
|
110
|
+
function resolveDivergingAxis(params) {
|
|
111
|
+
const { headroom, integral } = params;
|
|
112
|
+
const bottom = -params.lowest * headroom;
|
|
113
|
+
const top = params.highest * headroom;
|
|
114
|
+
const rough = (top + bottom) / Math.max(1, params.ticks ?? 4);
|
|
99
115
|
const power = 10 ** Math.floor(Math.log10(rough));
|
|
100
|
-
const
|
|
116
|
+
const mantissas = integral && power <= 1 ? [1, 2, 5, 10] : [1, 2, 2.5, 5, 10];
|
|
117
|
+
const nice = (mantissas.find((candidate) => rough / power <= candidate) ?? 10) * power;
|
|
118
|
+
const step = integral ? Math.max(1, nice) : nice;
|
|
101
119
|
const min = -Math.ceil(bottom / step) * step;
|
|
102
120
|
const max = Math.ceil(top / step) * step;
|
|
103
121
|
const count = Math.max(1, Math.round((max - min) / step));
|
|
@@ -106,26 +124,6 @@ function resolveDivergingAxis(lowest, highest, headroom, ticks = 4) {
|
|
|
106
124
|
ticks: Array.from({ length: count + 1 }, (_, index) => min + step * index)
|
|
107
125
|
};
|
|
108
126
|
}
|
|
109
|
-
const formatsByLocale = /* @__PURE__ */ new Map();
|
|
110
|
-
export function resolveDashboardFormats(locale) {
|
|
111
|
-
const cached = formatsByLocale.get(locale);
|
|
112
|
-
if (cached) return cached;
|
|
113
|
-
const plain = new Intl.NumberFormat(locale, { maximumFractionDigits: 1 });
|
|
114
|
-
const compact = new Intl.NumberFormat(locale, { maximumFractionDigits: 1, notation: "compact" });
|
|
115
|
-
const delta = new Intl.NumberFormat(locale, {
|
|
116
|
-
maximumFractionDigits: 1,
|
|
117
|
-
signDisplay: "exceptZero",
|
|
118
|
-
style: "percent"
|
|
119
|
-
});
|
|
120
|
-
const percent = new Intl.NumberFormat(locale, { maximumFractionDigits: 1, style: "percent" });
|
|
121
|
-
const formats = {
|
|
122
|
-
delta: (value) => delta.format(value / 100),
|
|
123
|
-
number: (value) => Math.abs(value) >= 1e4 ? compact.format(value) : plain.format(value),
|
|
124
|
-
percent: (value) => percent.format(value / 100)
|
|
125
|
-
};
|
|
126
|
-
formatsByLocale.set(locale, formats);
|
|
127
|
-
return formats;
|
|
128
|
-
}
|
|
129
127
|
export function escapeDashboardHtml(value) {
|
|
130
128
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
131
129
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { QueryCodec } from '
|
|
2
|
-
import type { DashboardDateRange, DashboardOptionValue } from '
|
|
1
|
+
import type { QueryCodec } from '../../query-state/index.js';
|
|
2
|
+
import type { DashboardDateRange, DashboardOptionValue } from '../types/index.js';
|
|
3
3
|
export declare const optionalStringCodec: QueryCodec<string | undefined>;
|
|
4
4
|
export declare const optionalNumberCodec: QueryCodec<number | undefined>;
|
|
5
5
|
export declare const optionalBooleanCodec: QueryCodec<boolean | undefined>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isNullish } from "
|
|
1
|
+
import { isNullish } from "../../shared/utils/predicate.js";
|
|
2
2
|
export const optionalStringCodec = {
|
|
3
3
|
parse: (raw) => raw === "" ? void 0 : raw,
|
|
4
4
|
serialize: (value) => isNullish(value) || value === "" ? null : value
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { useUiToolsLocale } from '../../i18n/use-locale.js';
|
|
2
|
+
import type { DashboardRuntimeFilter } from '../types/index.js';
|
|
3
|
+
export type DashboardLocale = ReturnType<typeof useUiToolsLocale>;
|
|
4
|
+
/**
|
|
5
|
+
* Runs `build` with `locale` as the locale of the dashboard being built. A schema function runs
|
|
6
|
+
* again outside setup when its input changes; the formats it creates (`useDashboardFormat()`) keep
|
|
7
|
+
* the locale of the component that created the dashboard.
|
|
8
|
+
*/
|
|
9
|
+
export declare function withDashboardLocale<TResult>(locale: DashboardLocale, build: () => TResult): TResult;
|
|
10
|
+
/** Locale of the dashboard being built, while one builds. */
|
|
11
|
+
export declare function currentDashboardLocale(): import("../../i18n/index.js").UiToolsLocaleContext<import("../../i18n/index.js").Messages> | undefined;
|
|
12
|
+
/** URL-synced filters of one dashboard, by full URL key. */
|
|
13
|
+
export type DashboardFilterRegistry = Map<string, {
|
|
14
|
+
owner: string;
|
|
15
|
+
signature: string;
|
|
16
|
+
}>;
|
|
17
|
+
/**
|
|
18
|
+
* What a dashboard reads from the component that creates it, once, during setup. A dashboard built
|
|
19
|
+
* from a schema function is rebuilt outside setup when the function's input changes; it keeps these.
|
|
20
|
+
*/
|
|
21
|
+
export interface DashboardEnvironment {
|
|
22
|
+
/** Locale of the creating component (Nuxt UI's `UApp` locale, or the ui-tools one). */
|
|
23
|
+
locale: DashboardLocale;
|
|
24
|
+
/** Filters with a URL key, across the dashboard's scopes. */
|
|
25
|
+
registry: DashboardFilterRegistry;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Records a URL-synced filter. A URL key names one filter across the dashboard: two scopes may both
|
|
29
|
+
* declare `year` (they share its value), but not as two different kinds of filter, or with two
|
|
30
|
+
* defaults, which would make the shared value read differently from one tab to the next.
|
|
31
|
+
*/
|
|
32
|
+
export declare function registerDashboardFilter(registry: DashboardFilterRegistry, params: {
|
|
33
|
+
urlKey: string;
|
|
34
|
+
owner: string;
|
|
35
|
+
definition: DashboardRuntimeFilter;
|
|
36
|
+
}): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
let buildingLocale;
|
|
2
|
+
export function withDashboardLocale(locale, build) {
|
|
3
|
+
const previous = buildingLocale;
|
|
4
|
+
buildingLocale = locale;
|
|
5
|
+
try {
|
|
6
|
+
return build();
|
|
7
|
+
} finally {
|
|
8
|
+
buildingLocale = previous;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function currentDashboardLocale() {
|
|
12
|
+
return buildingLocale;
|
|
13
|
+
}
|
|
14
|
+
export function registerDashboardFilter(registry, params) {
|
|
15
|
+
const { definition } = params;
|
|
16
|
+
const signature = [
|
|
17
|
+
definition.kind,
|
|
18
|
+
definition.multiple ? "multiple" : "single",
|
|
19
|
+
definition.codec.serialize(definition.defaultValue)
|
|
20
|
+
].join(":");
|
|
21
|
+
const known = registry.get(params.urlKey);
|
|
22
|
+
if (!known) {
|
|
23
|
+
registry.set(params.urlKey, { owner: params.owner, signature });
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (known.signature !== signature)
|
|
27
|
+
throw new Error(
|
|
28
|
+
`[dashboard] The filter of ${params.owner} and the filter of ${known.owner} share the URL key "${params.urlKey}", so they share one value, but they are declared differently (${signature} vs ${known.signature}). Declare them the same way, or give one another key or \`urlKey\`.`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { DashboardFilterControl, DashboardOptionValue, DashboardRuntimeFilter, DashboardSeries } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* One chart series per option a filter picks, in pick order: keyed and labelled by the option,
|
|
4
|
+
* colored by position in the palette (as the picker chips are), valued by `value(row, option)`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveDashboardFilterSeries<TRow, TItem extends DashboardOptionValue>(filter: DashboardFilterControl<unknown, TItem>, value: ((row: TRow, item: TItem) => number | null | undefined) | undefined): DashboardSeries<TRow>[];
|
|
7
|
+
/** The filter has a menu: options to pick from, or presets. */
|
|
8
|
+
export declare function hasDashboardFilterMenu(filter: Pick<DashboardFilterControl, 'kind' | 'presets'>): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Default classes of `UiDashboardFilter`. Pills are 32px high, menus dense (28px rows, 13px text;
|
|
11
|
+
* taller rows on touch screens only). An active pill takes the `--nut-dash-filter-*` tokens.
|
|
12
|
+
*/
|
|
13
|
+
export declare const DASHBOARD_FILTER_CLASSES: {
|
|
14
|
+
avatar: string;
|
|
15
|
+
button: string;
|
|
16
|
+
check: string;
|
|
17
|
+
chevron: string;
|
|
18
|
+
clear: string;
|
|
19
|
+
content: string;
|
|
20
|
+
hint: string;
|
|
21
|
+
item: string;
|
|
22
|
+
label: string;
|
|
23
|
+
list: string;
|
|
24
|
+
note: string;
|
|
25
|
+
root: string;
|
|
26
|
+
search: string;
|
|
27
|
+
separator: string;
|
|
28
|
+
tick: string;
|
|
29
|
+
title: string;
|
|
30
|
+
trigger: string;
|
|
31
|
+
value: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The filter is state only: declared `headless`, or read from a getter (a read-only source no control
|
|
35
|
+
* can drive).
|
|
36
|
+
*/
|
|
37
|
+
export declare function isDashboardFilterHeadless(definition: DashboardRuntimeFilter): boolean;
|
|
38
|
+
/** A value a filter can pick from a list: a string, a number, or a boolean. */
|
|
39
|
+
export declare function isDashboardOptionValue(value: unknown): value is DashboardOptionValue;
|
|
40
|
+
/**
|
|
41
|
+
* Default text of a filter value without an option label: dates and ranges in the locale's medium
|
|
42
|
+
* style, numbers with its grouping, lists joined.
|
|
43
|
+
*/
|
|
44
|
+
export declare function formatDashboardFilterValue(value: unknown, locale: string): string;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { isRef } from "vue";
|
|
2
|
+
import { isBoolean, isDate, isNumber, isObject, isString } from "../../shared/utils/predicate.js";
|
|
3
|
+
import { DASHBOARD_PALETTE_SIZE } from "./charts.js";
|
|
4
|
+
const DASHBOARD_LISTED_KINDS = /* @__PURE__ */ new Set([
|
|
5
|
+
"boolean",
|
|
6
|
+
"comparison",
|
|
7
|
+
"enum",
|
|
8
|
+
"options",
|
|
9
|
+
"remote"
|
|
10
|
+
]);
|
|
11
|
+
export function resolveDashboardFilterSeries(filter, value) {
|
|
12
|
+
return filter.selected.map((option, index) => ({
|
|
13
|
+
color: `series-${index % DASHBOARD_PALETTE_SIZE + 1}`,
|
|
14
|
+
key: String(option.value),
|
|
15
|
+
label: option.label,
|
|
16
|
+
value: (row) => value?.(row, option.value) ?? null
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
export function hasDashboardFilterMenu(filter) {
|
|
20
|
+
return DASHBOARD_LISTED_KINDS.has(filter.kind) || filter.presets.length > 0;
|
|
21
|
+
}
|
|
22
|
+
export const DASHBOARD_FILTER_CLASSES = {
|
|
23
|
+
avatar: "inline-grid size-[18px] flex-none place-items-center rounded-[4px] bg-muted text-[8.5px] font-semibold text-muted",
|
|
24
|
+
button: "inline-flex h-7 flex-none items-center justify-center gap-1.5 rounded-[7px] border border-default bg-default px-2.5 text-[12.5px] font-medium whitespace-nowrap text-default transition-colors outline-none hover:bg-elevated/60 focus-visible:ring-2 focus-visible:ring-primary",
|
|
25
|
+
check: "inline-grid size-3.5 flex-none place-items-center rounded-[4px] border border-accented bg-default text-transparent transition-colors data-[checked]:border-primary data-[checked]:bg-primary data-[checked]:text-inverted",
|
|
26
|
+
chevron: "size-3.5 flex-none text-dimmed",
|
|
27
|
+
clear: "ms-px me-[5px] inline-grid size-5 flex-none place-items-center rounded-full text-[var(--nut-dash-filter-ink)] outline-none hover:bg-[var(--nut-dash-filter-active-line)] focus-visible:ring-2 focus-visible:ring-primary",
|
|
28
|
+
content: "min-w-[max(160px,var(--reka-popover-trigger-width,0px))] max-w-[min(320px,calc(100vw-24px))] p-1 text-[13px]",
|
|
29
|
+
hint: "ms-auto shrink-0 ps-2 text-[11px] text-dimmed tabular-nums",
|
|
30
|
+
item: "flex h-7 w-full min-w-0 items-center gap-2 rounded-[4px] px-2 text-start text-[13px] text-default outline-none hover:bg-[var(--nut-dash-row-hover)] focus-visible:bg-[var(--nut-dash-row-hover)] disabled:cursor-not-allowed disabled:opacity-45 disabled:hover:bg-transparent data-[selected]:font-medium pointer-coarse:h-9",
|
|
31
|
+
label: "text-muted",
|
|
32
|
+
list: "max-h-[300px] overflow-y-auto overscroll-contain",
|
|
33
|
+
note: "flex items-center justify-center px-2 py-1.5 text-xs text-dimmed",
|
|
34
|
+
// The trigger's keyboard focus rings the whole pill, clear button included.
|
|
35
|
+
root: "group/filter inline-flex h-8 max-w-full flex-none items-center rounded-[7px] border border-default bg-default text-[13px] whitespace-nowrap transition-[background-color,border-color] duration-150 hover:bg-elevated/60 has-[[data-dashboard-filter-trigger]:focus-visible]:ring-2 has-[[data-dashboard-filter-trigger]:focus-visible]:ring-primary data-[active]:border-[var(--nut-dash-filter-active-line)] data-[active]:bg-[var(--nut-dash-filter-active)] data-[active]:hover:bg-[var(--nut-dash-filter-active)]",
|
|
36
|
+
search: "mb-1 flex h-7 items-center gap-1.5 rounded-md border border-default px-2 focus-within:border-primary",
|
|
37
|
+
separator: "my-1 h-px bg-[var(--ui-border-muted)]",
|
|
38
|
+
tick: "ms-auto size-3.5 flex-none text-[var(--nut-dash-filter-ink)]",
|
|
39
|
+
title: "px-2 pt-1 pb-1 text-[11.5px] font-medium text-muted",
|
|
40
|
+
trigger: "inline-flex h-full min-w-0 items-center gap-1.5 rounded-[6px] ps-[11px] pe-[9px] outline-none group-data-[active]/filter:pe-1",
|
|
41
|
+
value: "max-w-[200px] min-w-0 truncate font-medium text-default group-data-[active]/filter:text-[var(--nut-dash-filter-ink)]"
|
|
42
|
+
};
|
|
43
|
+
export function isDashboardFilterHeadless(definition) {
|
|
44
|
+
const { sync } = definition;
|
|
45
|
+
if (definition.headless === true) return true;
|
|
46
|
+
return sync !== void 0 && sync !== "url" && sync !== "memory" && !isRef(sync);
|
|
47
|
+
}
|
|
48
|
+
export function isDashboardOptionValue(value) {
|
|
49
|
+
return isString(value) || isNumber(value) || isBoolean(value);
|
|
50
|
+
}
|
|
51
|
+
export function formatDashboardFilterValue(value, locale) {
|
|
52
|
+
if (Array.isArray(value))
|
|
53
|
+
return value.map((entry) => formatDashboardFilterValue(entry, locale)).join(", ");
|
|
54
|
+
if (isDate(value)) return new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(value);
|
|
55
|
+
if (isNumber(value)) return new Intl.NumberFormat(locale).format(value);
|
|
56
|
+
if (isObject(value) && isDate(value.start) && isDate(value.end))
|
|
57
|
+
return new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).formatRange(
|
|
58
|
+
value.start,
|
|
59
|
+
value.end
|
|
60
|
+
);
|
|
61
|
+
return String(value ?? "");
|
|
62
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DashboardFormatPreset, DashboardValueFormatter } from '../types/index.js';
|
|
2
|
+
/** Number formatters of one locale, one per preset except `points` (which needs messages). */
|
|
3
|
+
export type DashboardFormats = Record<Exclude<DashboardFormatPreset, 'points'>, DashboardValueFormatter>;
|
|
4
|
+
/**
|
|
5
|
+
* Intl uses a narrow no-break space (U+202F) to group digits in some locales (French). Several UI
|
|
6
|
+
* fonts draw it with no width, so it becomes a regular no-break space: digits never touch, and a
|
|
7
|
+
* value still never wraps.
|
|
8
|
+
*/
|
|
9
|
+
export declare function normalizeDashboardSpaces(text: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* One cached `Intl.NumberFormat` per locale and option set: building them is costly. A `currency`
|
|
12
|
+
* without a `style` is the currency shorthand: whole amounts in that currency (`{ currency: 'EUR' }`
|
|
13
|
+
* → `12 345 €`), unless the options set their own fraction digits.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveDashboardNumberFormat(locale: string, options: Intl.NumberFormatOptions): DashboardValueFormatter;
|
|
16
|
+
/**
|
|
17
|
+
* Preset formatters of one locale. They are created once per locale and shared by every block and
|
|
18
|
+
* every `useDashboardFormat()` caller.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveDashboardFormats(locale: string): DashboardFormats;
|
|
21
|
+
/**
|
|
22
|
+
* Name of a month, capitalized as a standalone label: `3` (1–12) or a date → "Mar" / "March".
|
|
23
|
+
* Months use the stand-alone form of the locale ("mars" in French becomes "Mars").
|
|
24
|
+
*/
|
|
25
|
+
export declare function formatDashboardMonth(locale: string, value: number | Date, width?: 'short' | 'long'): string;
|