nuxt-ui-tools 1.4.0 → 1.6.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 +3 -1
- package/dist/runtime/dashboard/composables/use-dashboard-remote-options.js +8 -3
- package/dist/runtime/dashboard/types/filters.d.ts +7 -1
- package/dist/runtime/dashboard/utils/builders/dashboard-filters.js +19 -2
- package/dist/runtime/form/composables/use-field-options.js +19 -0
- package/dist/runtime/form/composables/use-remote-field-options.js +21 -2
- package/dist/runtime/form/types/options.d.ts +22 -2
- package/dist/runtime/i18n/locales/en.js +23 -2
- package/dist/runtime/i18n/locales/fr.js +23 -2
- package/dist/runtime/i18n/types.d.ts +21 -0
- package/dist/runtime/shared/index.d.ts +1 -0
- package/dist/runtime/shared/index.js +1 -0
- package/dist/runtime/shared/types/query.d.ts +5 -1
- package/dist/runtime/shared/types/remote-options.d.ts +56 -0
- package/dist/runtime/shared/utils/define-remote-options.d.ts +23 -0
- package/dist/runtime/shared/utils/define-remote-options.js +24 -0
- package/dist/runtime/shared/utils/remote-options-query.d.ts +6 -0
- package/dist/runtime/shared/utils/remote-options-query.js +18 -0
- package/dist/runtime/table/components/data-list/data-list-content.vue +7 -1
- package/dist/runtime/table/components/data-list/data-list-error-state.d.vue.ts +18 -1
- package/dist/runtime/table/components/data-list/data-list-error-state.vue +65 -41
- package/dist/runtime/table/components/data-list/data-list-error-state.vue.d.ts +18 -1
- package/dist/runtime/table/components/data-list/data-list-filter-tags.d.vue.ts +1 -1
- package/dist/runtime/table/components/data-list/data-list-filter-tags.vue +1 -1
- package/dist/runtime/table/components/data-list/data-list-filter-tags.vue.d.ts +1 -1
- package/dist/runtime/table/components/data-list/sort-menu-panel.vue +33 -25
- package/dist/runtime/table/components/drawers/column-panel.vue +19 -6
- package/dist/runtime/table/components/filters/panel/filter-panel.vue +14 -2
- package/dist/runtime/table/components/filters/shared/dynamic-filter-picker.vue +1 -1
- package/dist/runtime/table/components/filters/shared/filter-editor-header.d.vue.ts +16 -0
- package/dist/runtime/table/components/filters/shared/filter-editor-header.vue +46 -0
- package/dist/runtime/table/components/filters/shared/filter-editor-header.vue.d.ts +16 -0
- package/dist/runtime/table/components/filters/shared/filter-option-multiple-list.d.vue.ts +3 -1
- package/dist/runtime/table/components/filters/shared/filter-option-multiple-list.vue +6 -5
- package/dist/runtime/table/components/filters/shared/filter-option-multiple-list.vue.d.ts +3 -1
- package/dist/runtime/table/components/filters/shared/filter-option-picker-content.vue +4 -1
- package/dist/runtime/table/components/filters/shared/filter-option-single-list.vue +4 -4
- package/dist/runtime/table/components/filters/shared/filter-option-tree-content.vue +12 -8
- package/dist/runtime/table/components/filters/shared/filter-popover-shell.vue +10 -1
- package/dist/runtime/table/components/filters/shared/filter-searchable-panel.vue +14 -6
- package/dist/runtime/table/components/filters/shared/filter-trigger-tag.vue +12 -2
- package/dist/runtime/table/components/filters/tags/boolean-filter-tag.d.vue.ts +6 -1
- package/dist/runtime/table/components/filters/tags/boolean-filter-tag.vue +19 -5
- package/dist/runtime/table/components/filters/tags/boolean-filter-tag.vue.d.ts +6 -1
- package/dist/runtime/table/components/filters/tags/date-filter-tag.d.vue.ts +6 -1
- package/dist/runtime/table/components/filters/tags/date-filter-tag.vue +65 -29
- package/dist/runtime/table/components/filters/tags/date-filter-tag.vue.d.ts +6 -1
- package/dist/runtime/table/components/filters/tags/number-filter-tag.d.vue.ts +6 -1
- package/dist/runtime/table/components/filters/tags/number-filter-tag.vue +66 -18
- package/dist/runtime/table/components/filters/tags/number-filter-tag.vue.d.ts +6 -1
- package/dist/runtime/table/components/filters/tags/option-filter-tag.d.vue.ts +2 -2
- package/dist/runtime/table/components/filters/tags/option-filter-tag.vue +10 -34
- package/dist/runtime/table/components/filters/tags/option-filter-tag.vue.d.ts +2 -2
- package/dist/runtime/table/components/filters/tags/text-filter-tag.d.vue.ts +6 -1
- package/dist/runtime/table/components/filters/tags/text-filter-tag.vue +39 -14
- package/dist/runtime/table/components/filters/tags/text-filter-tag.vue.d.ts +6 -1
- package/dist/runtime/table/components/grid/grid-renderer.d.vue.ts +8 -2
- package/dist/runtime/table/components/grid/grid-renderer.vue +47 -115
- package/dist/runtime/table/components/grid/grid-renderer.vue.d.ts +8 -2
- package/dist/runtime/table/components/layout/progress-line.d.vue.ts +9 -0
- package/dist/runtime/table/components/layout/progress-line.vue +43 -0
- package/dist/runtime/table/components/layout/progress-line.vue.d.ts +9 -0
- package/dist/runtime/table/components/table/table-empty-state.d.vue.ts +1 -1
- package/dist/runtime/table/components/table/table-empty-state.vue +1 -1
- package/dist/runtime/table/components/table/table-empty-state.vue.d.ts +1 -1
- package/dist/runtime/table/components/table/table-layout.d.ts +57 -0
- package/dist/runtime/table/components/table/table-layout.js +23 -0
- package/dist/runtime/table/components/table/table-renderer.d.vue.ts +8 -16
- package/dist/runtime/table/components/table/table-renderer.vue +180 -274
- package/dist/runtime/table/components/table/table-renderer.vue.d.ts +8 -16
- package/dist/runtime/table/components/table/table-row.d.vue.ts +19 -0
- package/dist/runtime/table/components/table/table-row.vue +51 -0
- package/dist/runtime/table/components/table/table-row.vue.d.ts +19 -0
- package/dist/runtime/table/components/table/table-skeleton-cell.d.ts +9 -0
- package/dist/runtime/table/components/table/table-skeleton-cell.js +104 -0
- package/dist/runtime/table/components/utils/search-query-input.vue +27 -1
- package/dist/runtime/table/composables/use-deferred-commit.d.ts +20 -0
- package/dist/runtime/table/composables/use-deferred-commit.js +31 -0
- package/dist/runtime/table/composables/use-table-data.d.ts +5 -1
- package/dist/runtime/table/composables/use-table-data.js +20 -2
- package/dist/runtime/table/composables/use-table-filter-selected-options.js +16 -1
- package/dist/runtime/table/composables/use-table-summaries.js +10 -1
- package/dist/runtime/table/types/columns.d.ts +15 -1
- package/dist/runtime/table/types/data-list.d.ts +1 -0
- package/dist/runtime/table/types/filters.d.ts +7 -0
- package/dist/runtime/table/types/remote-options.d.ts +3 -16
- package/dist/runtime/table/utils/columns/defs.js +1 -1
- package/dist/runtime/table/utils/filters/date.d.ts +6 -0
- package/dist/runtime/table/utils/filters/date.js +26 -2
- package/dist/runtime/table/utils/filters/index.d.ts +1 -0
- package/dist/runtime/table/utils/filters/index.js +1 -0
- package/dist/runtime/table/utils/filters/number.d.ts +5 -0
- package/dist/runtime/table/utils/filters/number.js +11 -0
- package/dist/runtime/table/utils/filters/ui.js +5 -5
- package/dist/runtime/table/utils/remote-table-options.js +37 -37
- package/package.json +1 -1
|
@@ -4,11 +4,15 @@ import UIcon from "@nuxt/ui/components/Icon.vue";
|
|
|
4
4
|
import { computed } from "vue";
|
|
5
5
|
import { useUiToolsLocale } from "#ui-tools/i18n";
|
|
6
6
|
import { useDataListUi } from "../../composables/use-data-list-ui";
|
|
7
|
-
import { mergeDataListUiClass
|
|
7
|
+
import { mergeDataListUiClass } from "../../utils";
|
|
8
8
|
const props = defineProps({
|
|
9
9
|
minHeight: { type: String, required: false },
|
|
10
10
|
size: { type: String, required: false },
|
|
11
|
-
ui: { type: Object, required: false }
|
|
11
|
+
ui: { type: Object, required: false },
|
|
12
|
+
title: { type: String, required: false },
|
|
13
|
+
description: { type: String, required: false },
|
|
14
|
+
reference: { type: String, required: false },
|
|
15
|
+
icon: { type: String, required: false }
|
|
12
16
|
});
|
|
13
17
|
const emit = defineEmits(["retry"]);
|
|
14
18
|
const dataListUi = useDataListUi();
|
|
@@ -17,75 +21,95 @@ const rootUi = computed(() => dataListUi.ui.value.content?.ui);
|
|
|
17
21
|
const resolvedSize = computed(
|
|
18
22
|
() => props.size ?? dataListUi.ui.value.content?.size ?? dataListUi.controlSize.value
|
|
19
23
|
);
|
|
20
|
-
const
|
|
24
|
+
const resolvedTitle = computed(() => props.title ?? t("table.states.gridError.title"));
|
|
25
|
+
const resolvedDescription = computed(
|
|
26
|
+
() => props.description ?? t("table.states.gridError.description")
|
|
27
|
+
);
|
|
21
28
|
</script>
|
|
22
29
|
|
|
23
30
|
<template>
|
|
24
31
|
<div
|
|
25
32
|
:class="
|
|
26
33
|
mergeDataListUiClass(
|
|
27
|
-
'
|
|
34
|
+
'nut-dl-error flex w-full flex-col items-center justify-center px-6 py-12 text-center',
|
|
28
35
|
rootUi?.error,
|
|
29
36
|
ui?.error
|
|
30
37
|
)
|
|
31
38
|
"
|
|
32
39
|
:style="{ minHeight }"
|
|
40
|
+
role="alert"
|
|
33
41
|
>
|
|
34
42
|
<div
|
|
35
43
|
:class="
|
|
36
44
|
mergeDataListUiClass(
|
|
37
|
-
|
|
38
|
-
rootUi?.
|
|
39
|
-
ui?.
|
|
45
|
+
'nut-dl-error__art relative mb-4 flex size-14 items-center justify-center',
|
|
46
|
+
rootUi?.errorIcon,
|
|
47
|
+
ui?.errorIcon
|
|
40
48
|
)
|
|
41
49
|
"
|
|
42
50
|
>
|
|
43
51
|
<span
|
|
52
|
+
class="nut-dl-error__ring absolute inset-0 rounded-2xl bg-error/10 ring ring-inset ring-error/15"
|
|
53
|
+
/>
|
|
54
|
+
<span
|
|
55
|
+
class="nut-dl-error__ring nut-dl-error__ring--back absolute inset-1.5 -z-10 -rotate-6 rounded-xl bg-error/5"
|
|
56
|
+
/>
|
|
57
|
+
<UIcon :name="icon ?? 'i-lucide-cloud-alert'" class="relative size-5 text-error" />
|
|
58
|
+
</div>
|
|
59
|
+
<div :class="mergeDataListUiClass('min-w-0 max-w-md', rootUi?.errorCopy, ui?.errorCopy)">
|
|
60
|
+
<div
|
|
44
61
|
:class="
|
|
45
62
|
mergeDataListUiClass(
|
|
46
|
-
'
|
|
47
|
-
rootUi?.
|
|
48
|
-
ui?.
|
|
63
|
+
'nut-dl-error__title text-[14px] font-medium text-highlighted',
|
|
64
|
+
rootUi?.errorTitle,
|
|
65
|
+
ui?.errorTitle
|
|
49
66
|
)
|
|
50
67
|
"
|
|
51
68
|
>
|
|
52
|
-
|
|
53
|
-
</
|
|
54
|
-
<
|
|
69
|
+
{{ resolvedTitle }}
|
|
70
|
+
</div>
|
|
71
|
+
<p
|
|
55
72
|
:class="
|
|
56
|
-
mergeDataListUiClass(`min-w-0 flex-1 ${geometry.text}`, rootUi?.errorCopy, ui?.errorCopy)
|
|
57
|
-
"
|
|
58
|
-
>
|
|
59
|
-
<div
|
|
60
|
-
:class="
|
|
61
|
-
mergeDataListUiClass('font-medium text-highlighted', rootUi?.errorTitle, ui?.errorTitle)
|
|
62
|
-
"
|
|
63
|
-
>
|
|
64
|
-
{{ t("table.states.gridError.title") }}
|
|
65
|
-
</div>
|
|
66
|
-
<p
|
|
67
|
-
:class="
|
|
68
73
|
mergeDataListUiClass(
|
|
69
|
-
'mt-
|
|
74
|
+
'nut-dl-error__description mx-auto mt-1 max-w-[40ch] text-[12.5px] leading-relaxed text-muted',
|
|
70
75
|
rootUi?.errorDescription,
|
|
71
76
|
ui?.errorDescription
|
|
72
77
|
)
|
|
73
78
|
"
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
79
|
+
>
|
|
80
|
+
{{ resolvedDescription }}
|
|
81
|
+
</p>
|
|
82
|
+
<code
|
|
83
|
+
v-if="reference"
|
|
84
|
+
class="nut-dl-error__reference mt-2.5 inline-block rounded-md bg-elevated px-2 py-1 font-mono text-[11.5px] text-muted select-all"
|
|
85
|
+
>
|
|
86
|
+
{{ reference }}
|
|
87
|
+
</code>
|
|
88
|
+
</div>
|
|
89
|
+
<div
|
|
90
|
+
:class="
|
|
91
|
+
mergeDataListUiClass(
|
|
92
|
+
'nut-dl-error__actions mt-4 flex items-center gap-2',
|
|
93
|
+
rootUi?.errorBody,
|
|
94
|
+
ui?.errorBody
|
|
95
|
+
)
|
|
96
|
+
"
|
|
97
|
+
>
|
|
98
|
+
<UButton
|
|
99
|
+
color="neutral"
|
|
100
|
+
variant="outline"
|
|
101
|
+
:size="resolvedSize"
|
|
102
|
+
icon="i-lucide-refresh-cw"
|
|
103
|
+
:ui="{ base: mergeDataListUiClass(rootUi?.retry, ui?.retry) }"
|
|
104
|
+
@click="emit('retry')"
|
|
105
|
+
>
|
|
106
|
+
{{ t("table.states.gridError.action") }}
|
|
107
|
+
</UButton>
|
|
108
|
+
<slot name="actions" />
|
|
89
109
|
</div>
|
|
90
110
|
</div>
|
|
91
111
|
</template>
|
|
112
|
+
|
|
113
|
+
<style>
|
|
114
|
+
.nut-dl-error{animation:nut-dl-error-in .24s cubic-bezier(.2,.9,.3,1) both}@keyframes nut-dl-error-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}@media (prefers-reduced-motion:reduce){.nut-dl-error{animation:none}}
|
|
115
|
+
</style>
|
|
@@ -3,11 +3,28 @@ type __VLS_Props = {
|
|
|
3
3
|
minHeight?: string;
|
|
4
4
|
size?: DataListControlSize;
|
|
5
5
|
ui?: DataListContentUi;
|
|
6
|
+
/** Replaces the localized default title. */
|
|
7
|
+
title?: string;
|
|
8
|
+
/** Replaces the localized default description. */
|
|
9
|
+
description?: string;
|
|
10
|
+
/** Support reference shown under the description, such as a request identifier. */
|
|
11
|
+
reference?: string;
|
|
12
|
+
icon?: string;
|
|
6
13
|
};
|
|
7
|
-
declare
|
|
14
|
+
declare var __VLS_14: {};
|
|
15
|
+
type __VLS_Slots = {} & {
|
|
16
|
+
actions?: (props: typeof __VLS_14) => any;
|
|
17
|
+
};
|
|
18
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
8
19
|
retry: () => any;
|
|
9
20
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
10
21
|
onRetry?: (() => any) | undefined;
|
|
11
22
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
23
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
12
24
|
declare const _default: typeof __VLS_export;
|
|
13
25
|
export default _default;
|
|
26
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
27
|
+
new (): {
|
|
28
|
+
$slots: S;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -2,7 +2,7 @@ import type { DataListControlSize, DataListFilterTagsUi } from '../../types/inde
|
|
|
2
2
|
type __VLS_Props = {
|
|
3
3
|
showAdd?: boolean;
|
|
4
4
|
showClear?: boolean;
|
|
5
|
-
/** `
|
|
5
|
+
/** `tags` keeps inline tags on mobile (default); `sheet` moves all filters into a bottom sheet. */
|
|
6
6
|
mobile?: 'sheet' | 'tags';
|
|
7
7
|
size?: DataListControlSize;
|
|
8
8
|
ui?: DataListFilterTagsUi;
|
|
@@ -9,7 +9,7 @@ import FilterTagsBar from "../filters/tags/filter-tags-bar.vue";
|
|
|
9
9
|
const props = defineProps({
|
|
10
10
|
showAdd: { type: Boolean, required: false, default: false },
|
|
11
11
|
showClear: { type: Boolean, required: false, default: false },
|
|
12
|
-
mobile: { type: String, required: false, default: "
|
|
12
|
+
mobile: { type: String, required: false, default: "tags" },
|
|
13
13
|
size: { type: String, required: false },
|
|
14
14
|
ui: { type: Object, required: false }
|
|
15
15
|
});
|
|
@@ -2,7 +2,7 @@ import type { DataListControlSize, DataListFilterTagsUi } from '../../types/inde
|
|
|
2
2
|
type __VLS_Props = {
|
|
3
3
|
showAdd?: boolean;
|
|
4
4
|
showClear?: boolean;
|
|
5
|
-
/** `
|
|
5
|
+
/** `tags` keeps inline tags on mobile (default); `sheet` moves all filters into a bottom sheet. */
|
|
6
6
|
mobile?: 'sheet' | 'tags';
|
|
7
7
|
size?: DataListControlSize;
|
|
8
8
|
ui?: DataListFilterTagsUi;
|
|
@@ -31,7 +31,7 @@ function humanize(value) {
|
|
|
31
31
|
v-for="key in keys"
|
|
32
32
|
:key="key"
|
|
33
33
|
type="button"
|
|
34
|
-
class="nut-dl-sort__row flex w-full items-center gap-[10px] rounded-lg text-left transition-colors hover:bg-elevated active:bg-elevated"
|
|
34
|
+
class="nut-dl-sort__row flex w-full items-center gap-[10px] rounded-lg text-left outline-none transition-colors hover:bg-elevated focus-visible:ring-2 focus-visible:ring-primary/40 active:bg-elevated"
|
|
35
35
|
:class="[
|
|
36
36
|
compact ? 'h-8 px-2.5 text-[13px]' : 'h-[46px] px-[10px] text-[15px]',
|
|
37
37
|
activeKey === key ? 'nut-dl-sort__row--active font-semibold text-highlighted' : 'text-default'
|
|
@@ -52,35 +52,43 @@ function humanize(value) {
|
|
|
52
52
|
/>
|
|
53
53
|
</button>
|
|
54
54
|
</div>
|
|
55
|
-
<div
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
<div class="w-full min-w-0" :class="compact ? 'mt-1.5 px-1' : 'mt-2'">
|
|
56
|
+
<div
|
|
57
|
+
class="nut-dl-sort__caption border-t border-default font-semibold tracking-[0.06em] text-dimmed uppercase"
|
|
58
|
+
:class="compact ? 'px-1.5 pt-2 pb-1 text-[10.5px]' : 'px-5 pt-4 pb-2 text-[11px]'"
|
|
59
|
+
>
|
|
60
|
+
{{ t("table.filters.sheet.order") }}
|
|
61
|
+
</div>
|
|
62
62
|
</div>
|
|
63
63
|
<div
|
|
64
|
-
class="nut-dl-sort__dir
|
|
65
|
-
:class="compact ? '
|
|
64
|
+
class="nut-dl-sort__dir-wrap w-full min-w-0"
|
|
65
|
+
:class="compact ? 'px-2.5 pb-2.5' : 'px-4 pb-5'"
|
|
66
66
|
>
|
|
67
|
-
<
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
<div
|
|
68
|
+
class="nut-dl-sort__dir grid w-full min-w-0 grid-cols-[repeat(2,minmax(0,1fr))] gap-0.5 overflow-hidden rounded-md bg-elevated p-0.5"
|
|
69
|
+
role="radiogroup"
|
|
70
|
+
:aria-label="t('table.filters.sheet.order')"
|
|
71
|
+
>
|
|
72
|
+
<button
|
|
73
|
+
v-for="dir in ['asc', 'desc']"
|
|
74
|
+
:key="dir"
|
|
75
|
+
type="button"
|
|
76
|
+
role="radio"
|
|
77
|
+
:aria-checked="activeDirection === dir"
|
|
78
|
+
class="flex min-w-0 items-center justify-center gap-1.5 overflow-hidden rounded-[5px] px-1 font-medium whitespace-nowrap outline-none transition-colors focus-visible:ring-2 focus-visible:ring-primary/40"
|
|
79
|
+
:class="[
|
|
73
80
|
compact ? 'h-7 text-[12px]' : 'h-8 text-[12.5px]',
|
|
74
|
-
activeDirection === dir ? 'nut-dl-sort__dir--active bg-default text-highlighted shadow-[0_0_0_1px_var(--ui-border)]' : 'text-muted'
|
|
81
|
+
activeDirection === dir ? 'nut-dl-sort__dir--active bg-default text-highlighted shadow-[0_0_0_1px_var(--ui-border)]' : 'text-muted hover:text-default'
|
|
75
82
|
]"
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
@click="emit('selectDirection', dir)"
|
|
84
|
+
>
|
|
85
|
+
<UIcon
|
|
86
|
+
:name="dir === 'asc' ? 'i-lucide-arrow-up' : 'i-lucide-arrow-down'"
|
|
87
|
+
class="size-3.5 shrink-0"
|
|
88
|
+
/>
|
|
89
|
+
<span class="truncate">{{ dir === "asc" ? "A \u2192 Z" : "Z \u2192 A" }}</span>
|
|
90
|
+
</button>
|
|
91
|
+
</div>
|
|
84
92
|
</div>
|
|
85
93
|
</div>
|
|
86
94
|
</template>
|
|
@@ -124,6 +124,15 @@ function toggleColumn(columnId) {
|
|
|
124
124
|
const isVisible2 = internals.tableColumns.tableState.value.columnVisibility?.[columnId] !== false;
|
|
125
125
|
internals.tableColumns.setVisibility({ columnId, visible: !isVisible2 });
|
|
126
126
|
}
|
|
127
|
+
function toggleRow(event, column) {
|
|
128
|
+
if (event.target instanceof Element && event.target.closest('button, input, [role="checkbox"]')) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (isRequired(column)) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
toggleColumn(column.id);
|
|
135
|
+
}
|
|
127
136
|
function open() {
|
|
128
137
|
internals.controls.columnsPanelOpen.value = true;
|
|
129
138
|
}
|
|
@@ -226,7 +235,7 @@ function toggle() {
|
|
|
226
235
|
<div
|
|
227
236
|
:class="
|
|
228
237
|
mergeDataListUiClass(
|
|
229
|
-
'nut-dl-colpanel__list grid max-h-80 gap-px overflow-y-auto px-2 py-1',
|
|
238
|
+
'nut-dl-colpanel__list grid max-h-80 grid-cols-1 gap-px overflow-y-auto px-2 py-1',
|
|
230
239
|
void 0,
|
|
231
240
|
ui.list
|
|
232
241
|
)
|
|
@@ -238,11 +247,12 @@ function toggle() {
|
|
|
238
247
|
:key="column.id"
|
|
239
248
|
:class="
|
|
240
249
|
mergeDataListUiClass(
|
|
241
|
-
'nut-dl-colpanel__row group/col flex h-8 items-center gap-2.5 rounded-md px-2 hover:bg-elevated',
|
|
250
|
+
'nut-dl-colpanel__row group/col flex h-8 cursor-pointer items-center gap-2.5 rounded-md px-2 hover:bg-elevated',
|
|
242
251
|
void 0,
|
|
243
252
|
ui.row
|
|
244
253
|
)
|
|
245
254
|
"
|
|
255
|
+
@click="toggleRow($event, column)"
|
|
246
256
|
>
|
|
247
257
|
<UCheckbox
|
|
248
258
|
v-bind="checkboxProps"
|
|
@@ -278,18 +288,19 @@ function toggle() {
|
|
|
278
288
|
ghost-class="column-panel-row-ghost"
|
|
279
289
|
chosen-class="column-panel-row-chosen"
|
|
280
290
|
drag-class="column-panel-row-dragging"
|
|
281
|
-
:class="mergeDataListUiClass('grid gap-px', void 0, ui.section)"
|
|
291
|
+
:class="mergeDataListUiClass('grid grid-cols-1 gap-px', void 0, ui.section)"
|
|
282
292
|
>
|
|
283
293
|
<div
|
|
284
294
|
v-for="column in draggableColumns"
|
|
285
295
|
:key="column.id"
|
|
286
296
|
:class="
|
|
287
297
|
mergeDataListUiClass(
|
|
288
|
-
'nut-dl-colpanel__row group/col flex h-8 items-center gap-2.5 rounded-md px-2 hover:bg-elevated',
|
|
298
|
+
'nut-dl-colpanel__row group/col flex h-8 cursor-pointer items-center gap-2.5 rounded-md px-2 hover:bg-elevated',
|
|
289
299
|
void 0,
|
|
290
300
|
ui.row
|
|
291
301
|
)
|
|
292
302
|
"
|
|
303
|
+
@click="toggleRow($event, column)"
|
|
293
304
|
>
|
|
294
305
|
<UCheckbox
|
|
295
306
|
v-bind="checkboxProps"
|
|
@@ -328,11 +339,12 @@ function toggle() {
|
|
|
328
339
|
:key="column.id"
|
|
329
340
|
:class="
|
|
330
341
|
mergeDataListUiClass(
|
|
331
|
-
'nut-dl-colpanel__row group/col flex h-8 items-center gap-2.5 rounded-md px-2 hover:bg-elevated',
|
|
342
|
+
'nut-dl-colpanel__row group/col flex h-8 cursor-pointer items-center gap-2.5 rounded-md px-2 hover:bg-elevated',
|
|
332
343
|
void 0,
|
|
333
344
|
ui.row
|
|
334
345
|
)
|
|
335
346
|
"
|
|
347
|
+
@click="toggleRow($event, column)"
|
|
336
348
|
>
|
|
337
349
|
<UCheckbox
|
|
338
350
|
v-bind="checkboxProps"
|
|
@@ -365,11 +377,12 @@ function toggle() {
|
|
|
365
377
|
:key="column.id"
|
|
366
378
|
:class="
|
|
367
379
|
mergeDataListUiClass(
|
|
368
|
-
'nut-dl-colpanel__row flex h-8 items-center gap-2.5 rounded-md px-2 hover:bg-elevated',
|
|
380
|
+
'nut-dl-colpanel__row flex h-8 cursor-pointer items-center gap-2.5 rounded-md px-2 hover:bg-elevated',
|
|
369
381
|
void 0,
|
|
370
382
|
ui.row
|
|
371
383
|
)
|
|
372
384
|
"
|
|
385
|
+
@click="toggleRow($event, column)"
|
|
373
386
|
>
|
|
374
387
|
<UCheckbox
|
|
375
388
|
v-bind="checkboxProps"
|
|
@@ -5,6 +5,7 @@ import USlideover from "@nuxt/ui/components/Slideover.vue";
|
|
|
5
5
|
import { computed, onMounted, watch } from "vue";
|
|
6
6
|
import { useUiToolsLocale } from "#ui-tools/i18n";
|
|
7
7
|
import { isNullish } from "../../../../shared/utils/predicate";
|
|
8
|
+
import { useDataListBreakpoint } from "../../../composables/use-data-list-breakpoint";
|
|
8
9
|
import { useDataListUi } from "../../../composables/use-data-list-ui";
|
|
9
10
|
import { useTableInternals } from "../../../composables/use-table-internals";
|
|
10
11
|
import { mergeDataListProps, mergeDataListUiClass } from "../../../utils";
|
|
@@ -19,6 +20,7 @@ const props = defineProps({
|
|
|
19
20
|
});
|
|
20
21
|
const internals = useTableInternals();
|
|
21
22
|
const dataListUi = useDataListUi();
|
|
23
|
+
const { isMobile } = useDataListBreakpoint();
|
|
22
24
|
const { locale, t } = useUiToolsLocale();
|
|
23
25
|
const config = computed(() => dataListUi.ui.value.filterPanel);
|
|
24
26
|
const resolvedUi = computed(() => ({ ...config.value?.ui, ...props.ui }));
|
|
@@ -39,6 +41,7 @@ const triggerBind = computed(() => {
|
|
|
39
41
|
return rest;
|
|
40
42
|
});
|
|
41
43
|
const triggerLabel = computed(() => triggerProps.value.label ?? t("table.filters.panel.trigger"));
|
|
44
|
+
const hasTriggerIcon = computed(() => Boolean(triggerProps.value.icon));
|
|
42
45
|
const countProps = computed(
|
|
43
46
|
() => controlProps.value.count === false ? null : mergeDataListProps(
|
|
44
47
|
{ color: "neutral", size: "xs", variant: "solid" },
|
|
@@ -212,6 +215,10 @@ onMounted(() => {
|
|
|
212
215
|
<UButton
|
|
213
216
|
v-bind="triggerBind"
|
|
214
217
|
:aria-expanded="open"
|
|
218
|
+
:aria-label="triggerLabel"
|
|
219
|
+
:square="
|
|
220
|
+
triggerProps.square ?? (isMobile && hasTriggerIcon && (!countProps || activeCount === 0))
|
|
221
|
+
"
|
|
215
222
|
:ui="{
|
|
216
223
|
base: mergeDataListUiClass(
|
|
217
224
|
'nut-dl-fpanel-trigger shrink-0',
|
|
@@ -221,11 +228,16 @@ onMounted(() => {
|
|
|
221
228
|
}"
|
|
222
229
|
>
|
|
223
230
|
<span
|
|
231
|
+
v-if="!isMobile || !hasTriggerIcon || countProps && activeCount > 0"
|
|
224
232
|
:class="
|
|
225
|
-
mergeDataListUiClass(
|
|
233
|
+
mergeDataListUiClass(
|
|
234
|
+
'nut-dl-fpanel-trigger__content flex items-center gap-2',
|
|
235
|
+
void 0,
|
|
236
|
+
resolvedUi.triggerContent
|
|
237
|
+
)
|
|
226
238
|
"
|
|
227
239
|
>
|
|
228
|
-
<span>{{ triggerLabel }}</span>
|
|
240
|
+
<span v-if="!isMobile || !hasTriggerIcon">{{ triggerLabel }}</span>
|
|
229
241
|
<UBadge
|
|
230
242
|
v-if="countProps && activeCount > 0"
|
|
231
243
|
v-bind="countProps"
|
|
@@ -203,7 +203,7 @@ function toggle() {
|
|
|
203
203
|
"
|
|
204
204
|
:ui="{
|
|
205
205
|
base: mergeDataListUiClass(
|
|
206
|
-
|
|
206
|
+
'nut-dl-tag nut-dl-tag--add shrink-0 border border-dashed border-[var(--ui-border-accented)] text-muted hover:text-default hover:border-[var(--ui-text-dimmed)]',
|
|
207
207
|
void 0,
|
|
208
208
|
ui?.trigger
|
|
209
209
|
),
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DataListFilterEditorUi } from '../../../types/index.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
label: string;
|
|
4
|
+
active?: boolean;
|
|
5
|
+
embedded?: boolean;
|
|
6
|
+
ui?: DataListFilterEditorUi;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
9
|
+
clear: () => any;
|
|
10
|
+
back: () => any;
|
|
11
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
|
+
onClear?: (() => any) | undefined;
|
|
13
|
+
onBack?: (() => any) | undefined;
|
|
14
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import UIcon from "@nuxt/ui/components/Icon.vue";
|
|
3
|
+
import { useUiToolsLocale } from "#ui-tools/i18n";
|
|
4
|
+
import { mergeDataListUiClass } from "../../../utils";
|
|
5
|
+
defineProps({
|
|
6
|
+
label: { type: String, required: true },
|
|
7
|
+
active: { type: Boolean, required: false },
|
|
8
|
+
embedded: { type: Boolean, required: false },
|
|
9
|
+
ui: { type: Object, required: false }
|
|
10
|
+
});
|
|
11
|
+
const emit = defineEmits(["back", "clear"]);
|
|
12
|
+
const { t } = useUiToolsLocale();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<div
|
|
17
|
+
:class="
|
|
18
|
+
mergeDataListUiClass(
|
|
19
|
+
'nut-dl-editor__head flex items-center gap-2 border-b border-default py-2 pr-3',
|
|
20
|
+
embedded ? 'pl-1.5' : 'pl-3',
|
|
21
|
+
ui?.editorHeader
|
|
22
|
+
)
|
|
23
|
+
"
|
|
24
|
+
>
|
|
25
|
+
<button
|
|
26
|
+
v-if="embedded"
|
|
27
|
+
type="button"
|
|
28
|
+
class="nut-dl-editor__back flex size-6 items-center justify-center rounded-md text-muted outline-none hover:bg-elevated hover:text-default focus-visible:ring-2 focus-visible:ring-primary/40"
|
|
29
|
+
:aria-label="t('table.filters.sheet.back')"
|
|
30
|
+
@click="emit('back')"
|
|
31
|
+
>
|
|
32
|
+
<UIcon name="i-lucide-arrow-left" class="size-4" />
|
|
33
|
+
</button>
|
|
34
|
+
<span class="min-w-0 flex-1 truncate text-[12.5px] font-semibold text-highlighted">
|
|
35
|
+
{{ label }}
|
|
36
|
+
</span>
|
|
37
|
+
<button
|
|
38
|
+
type="button"
|
|
39
|
+
class="nut-dl-editor__clear rounded text-[12.5px] font-semibold text-primary outline-none focus-visible:ring-2 focus-visible:ring-primary/40 disabled:opacity-40"
|
|
40
|
+
:disabled="!active"
|
|
41
|
+
@click="emit('clear')"
|
|
42
|
+
>
|
|
43
|
+
{{ t("table.filters.editor.clear") }}
|
|
44
|
+
</button>
|
|
45
|
+
</div>
|
|
46
|
+
</template>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DataListFilterEditorUi } from '../../../types/index.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
label: string;
|
|
4
|
+
active?: boolean;
|
|
5
|
+
embedded?: boolean;
|
|
6
|
+
ui?: DataListFilterEditorUi;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
9
|
+
clear: () => any;
|
|
10
|
+
back: () => any;
|
|
11
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
|
+
onClear?: (() => any) | undefined;
|
|
13
|
+
onBack?: (() => any) | undefined;
|
|
14
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
@@ -36,6 +36,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
36
36
|
index: number;
|
|
37
37
|
sectionKey: string;
|
|
38
38
|
}) => any) | undefined;
|
|
39
|
-
}>, {
|
|
39
|
+
}>, {
|
|
40
|
+
truncate: boolean;
|
|
41
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
40
42
|
declare const _default: typeof __VLS_export;
|
|
41
43
|
export default _default;
|
|
@@ -15,7 +15,7 @@ const props = defineProps({
|
|
|
15
15
|
showCounts: { type: Boolean, required: true },
|
|
16
16
|
countLoading: { type: Boolean, required: true },
|
|
17
17
|
selectedIcon: { type: String, required: false },
|
|
18
|
-
truncate: { type: Boolean, required: false },
|
|
18
|
+
truncate: { type: Boolean, required: false, default: true },
|
|
19
19
|
size: { type: String, required: false },
|
|
20
20
|
ui: { type: Object, required: false }
|
|
21
21
|
});
|
|
@@ -36,7 +36,7 @@ const geometry = computed(() => resolveDataListControlGeometry(size.value));
|
|
|
36
36
|
</script>
|
|
37
37
|
|
|
38
38
|
<template>
|
|
39
|
-
<div :class="mergeDataListUiClass('grid gap-0.5', void 0, ui?.list)">
|
|
39
|
+
<div :class="mergeDataListUiClass('grid grid-cols-1 gap-0.5', void 0, ui?.list)">
|
|
40
40
|
<template v-for="section in props.sections" :key="section.key">
|
|
41
41
|
<div
|
|
42
42
|
v-if="section.dividerBefore && section.entries.length"
|
|
@@ -48,11 +48,12 @@ const geometry = computed(() => resolveDataListControlGeometry(size.value));
|
|
|
48
48
|
:key="entry.value == null ? entry.label : String(entry.value)"
|
|
49
49
|
:class="
|
|
50
50
|
mergeDataListUiClass(
|
|
51
|
-
`nut-dl-option flex items-center rounded-md text-left outline-none transition-colors hover:bg-elevated ${sizeClasses.option} ${entry.selected ? 'text-highlighted' : 'text-default'}`,
|
|
51
|
+
`nut-dl-option flex min-w-0 cursor-pointer items-center rounded-md text-left outline-none transition-colors hover:bg-elevated ${sizeClasses.option} ${entry.selected ? 'text-highlighted' : 'text-default'}`,
|
|
52
52
|
void 0,
|
|
53
53
|
ui?.option
|
|
54
54
|
)
|
|
55
55
|
"
|
|
56
|
+
@click="emit('select', { event: $event, entry, index, sectionKey: section.key })"
|
|
56
57
|
>
|
|
57
58
|
<UCheckbox
|
|
58
59
|
:model-value="entry.selected ?? false"
|
|
@@ -67,7 +68,6 @@ const geometry = computed(() => resolveDataListControlGeometry(size.value));
|
|
|
67
68
|
<button
|
|
68
69
|
type="button"
|
|
69
70
|
:class="['flex min-w-0 flex-1 items-center text-left', geometry.toolbarGap]"
|
|
70
|
-
@click="emit('select', { event: $event, entry, index, sectionKey: section.key })"
|
|
71
71
|
>
|
|
72
72
|
<span
|
|
73
73
|
v-if="entry.color"
|
|
@@ -89,11 +89,12 @@ const geometry = computed(() => resolveDataListControlGeometry(size.value));
|
|
|
89
89
|
<span
|
|
90
90
|
:class="
|
|
91
91
|
mergeDataListUiClass(
|
|
92
|
-
`min-w-0 flex-1 ${sizeClasses.optionLabel} ${props.truncate
|
|
92
|
+
`min-w-0 flex-1 ${sizeClasses.optionLabel} ${props.truncate ? 'truncate' : ''}`,
|
|
93
93
|
void 0,
|
|
94
94
|
ui?.optionLabel
|
|
95
95
|
)
|
|
96
96
|
"
|
|
97
|
+
:title="entry.label"
|
|
97
98
|
>
|
|
98
99
|
{{ entry.label }}
|
|
99
100
|
</span>
|
|
@@ -36,6 +36,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
36
36
|
index: number;
|
|
37
37
|
sectionKey: string;
|
|
38
38
|
}) => any) | undefined;
|
|
39
|
-
}>, {
|
|
39
|
+
}>, {
|
|
40
|
+
truncate: boolean;
|
|
41
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
40
42
|
declare const _default: typeof __VLS_export;
|
|
41
43
|
export default _default;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useMediaQuery } from "@vueuse/core";
|
|
2
3
|
import { isNullish } from "../../../../shared/utils/predicate";
|
|
3
4
|
import FilterOptionListEnd from "./filter-option-list-end.vue";
|
|
4
5
|
import FilterOptionLoadingList from "./filter-option-loading-list.vue";
|
|
@@ -13,6 +14,7 @@ const props = defineProps({
|
|
|
13
14
|
ui: { type: Object, required: false }
|
|
14
15
|
});
|
|
15
16
|
const searchQuery = defineModel("searchQuery", { type: String, ...{ default: "" } });
|
|
17
|
+
const finePointer = useMediaQuery("(pointer: fine)");
|
|
16
18
|
const flatRadioValue = defineModel("flatRadioValue", { type: null, ...{ default: void 0 } });
|
|
17
19
|
const treeRadioValue = defineModel("treeRadioValue", { type: null, ...{ default: void 0 } });
|
|
18
20
|
const emit = defineEmits(["selectEntry", "toggleTreeEntry", "toggleExpanded"]);
|
|
@@ -33,10 +35,11 @@ function handleSelect(options) {
|
|
|
33
35
|
<FilterSearchablePanel
|
|
34
36
|
v-model:search-query="searchQuery"
|
|
35
37
|
:searchable="props.state.filterUi.value.searchable"
|
|
38
|
+
:autofocus="props.state.filterUi.value.searchable && finePointer"
|
|
36
39
|
:search-placeholder="props.state.filterUi.value.labels.searchPlaceholder"
|
|
37
40
|
:search-loading="props.state.optionSource.isStaleLoading.value"
|
|
38
41
|
:show-empty="
|
|
39
|
-
!props.state.optionSource.isLoading.value && !props.state.
|
|
42
|
+
!props.state.optionSource.isLoading.value && (props.state.filterUi.value.presentation === 'tree' ? !props.state.visibleTreeEntries.value.length : !props.state.displayEntries.value.length)
|
|
40
43
|
"
|
|
41
44
|
:empty-label="props.state.filterUi.value.labels.empty"
|
|
42
45
|
:size="props.size"
|