quasar-ui-danx 0.0.11 → 0.0.12
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/package.json +6 -1
- package/src/components/ActionTable/ActionTable.vue +49 -41
- package/src/components/ActionTable/BatchActionMenu.vue +20 -20
- package/src/components/ActionTable/EmptyTableState.vue +5 -5
- package/src/components/ActionTable/Filters/CollapsableFiltersSidebar.vue +11 -11
- package/src/components/ActionTable/Filters/FilterGroupItem.vue +7 -7
- package/src/components/ActionTable/Filters/FilterGroupList.vue +29 -29
- package/src/components/ActionTable/Filters/FilterListToggle.vue +15 -15
- package/src/components/ActionTable/Filters/FilterableField.vue +82 -80
- package/src/components/ActionTable/Filters/index.ts +5 -0
- package/src/components/ActionTable/Form/Fields/BooleanField.vue +13 -13
- package/src/components/ActionTable/Form/Fields/ConfirmPasswordField.vue +11 -11
- package/src/components/ActionTable/Form/Fields/DateField.vue +13 -13
- package/src/components/ActionTable/Form/Fields/DateRangeField.vue +25 -25
- package/src/components/ActionTable/Form/Fields/DateTimeField.vue +21 -21
- package/src/components/ActionTable/Form/Fields/DateTimePicker.vue +23 -23
- package/src/components/ActionTable/Form/Fields/FileUploadButton.vue +31 -31
- package/src/components/ActionTable/Form/Fields/InlineDateTimeField.vue +19 -19
- package/src/components/ActionTable/Form/Fields/IntegerField.vue +7 -7
- package/src/components/ActionTable/Form/Fields/LabelValueBlock.vue +22 -0
- package/src/components/ActionTable/Form/Fields/LabeledInput.vue +19 -19
- package/src/components/ActionTable/Form/Fields/MultiFileField.vue +40 -40
- package/src/components/ActionTable/Form/Fields/MultiKeywordField.vue +23 -23
- package/src/components/ActionTable/Form/Fields/NewPasswordField.vue +10 -10
- package/src/components/ActionTable/Form/Fields/NumberField.vue +29 -29
- package/src/components/ActionTable/Form/Fields/NumberRangeField.vue +33 -33
- package/src/components/ActionTable/Form/Fields/SelectDrawer.vue +36 -36
- package/src/components/ActionTable/Form/Fields/SelectField.vue +66 -66
- package/src/components/ActionTable/Form/Fields/SelectWithChildrenField.vue +23 -23
- package/src/components/ActionTable/Form/Fields/SingleFileField.vue +32 -32
- package/src/components/ActionTable/Form/Fields/TextField.vue +36 -36
- package/src/components/ActionTable/Form/Fields/WysiwygField.vue +16 -16
- package/src/components/ActionTable/Form/Fields/index.ts +23 -23
- package/src/components/ActionTable/Form/RenderedForm.vue +27 -25
- package/src/components/ActionTable/Form/index.ts +2 -0
- package/src/components/ActionTable/TableSummaryRow.vue +33 -33
- package/src/components/ActionTable/index.ts +8 -13
- package/src/components/ActionTable/listActions.ts +340 -339
- package/src/components/ActionTable/listHelpers.ts +74 -0
- package/src/components/ActionTable/tableColumns.ts +56 -56
- package/src/components/DragAndDrop/HandleDraggable.vue +29 -29
- package/src/components/DragAndDrop/ListItemDraggable.vue +10 -10
- package/src/components/DragAndDrop/index.ts +0 -1
- package/src/components/DragAndDrop/listDragAndDrop.ts +1 -1
- package/src/components/Utility/CollapsableSidebar.vue +35 -35
- package/src/components/Utility/ContentDrawer.vue +20 -20
- package/src/components/Utility/Dialogs/ConfirmDialog.vue +55 -55
- package/src/components/Utility/Dialogs/FullScreenDialog.vue +18 -18
- package/src/components/Utility/Dialogs/FullscreenCarouselDialog.vue +105 -0
- package/src/components/Utility/Dialogs/InfoDialog.vue +10 -10
- package/src/components/Utility/Dialogs/InputDialog.vue +13 -13
- package/src/components/Utility/ImagePreview.vue +192 -0
- package/src/components/Utility/Popover/PopoverMenu.vue +64 -0
- package/src/components/Utility/Transitions/StaggeredListTransition.vue +15 -15
- package/src/components/Utility/index.ts +11 -9
- package/src/components/index.ts +1 -1
- package/src/helpers/FileUpload.ts +274 -273
- package/src/helpers/compatibility.ts +45 -45
- package/src/helpers/date.ts +2 -2
- package/src/helpers/download.ts +166 -158
- package/src/helpers/downloadPdf.ts +48 -48
- package/src/helpers/files.ts +42 -42
- package/src/helpers/index.ts +2 -0
- package/src/helpers/multiFileUpload.ts +56 -56
- package/src/helpers/singleFileUpload.ts +49 -49
- package/src/index.esm.js +3 -4
- package/src/svg/FilterIcon.svg +7 -0
- package/src/svg/ImageIcon.svg +30 -0
- package/src/svg/PdfIcon.svg +21 -0
- package/src/svg/PercentIcon.svg +13 -0
- package/src/svg/TrashIcon.svg +15 -0
- package/src/svg/XIcon.svg +18 -0
- package/src/svg/index.ts +8 -0
- package/src/vendor/tinymce-config.ts +1 -0
- package/src/vue-plugin.js +7 -4
- package/tsconfig.json +14 -13
- package/src/components/ActionTable/tableHelpers.ts +0 -83
- package/src/components/DragAndDrop/Icons/index.ts +0 -2
- /package/src/{components/DragAndDrop/Icons → svg}/DragHandleDotsIcon.svg +0 -0
- /package/src/{components/DragAndDrop/Icons → svg}/DragHandleIcon.svg +0 -0
@@ -1,15 +1,15 @@
|
|
1
1
|
<template>
|
2
2
|
<div>
|
3
3
|
<div
|
4
|
-
|
5
|
-
|
4
|
+
v-if="label"
|
5
|
+
class="font-bold text-xs mb-2"
|
6
6
|
>
|
7
7
|
{{ label }}
|
8
8
|
</div>
|
9
9
|
<div class="flex items-center flex-nowrap cursor-pointer">
|
10
10
|
<component
|
11
|
-
|
12
|
-
|
11
|
+
:is="previewIcon"
|
12
|
+
class="w-5 text-blue-base"
|
13
13
|
/>
|
14
14
|
<div class="text-sm ml-3 hover:text-blue-base whitespace-nowrap">
|
15
15
|
<template v-if="range">
|
@@ -20,31 +20,31 @@
|
|
20
20
|
</template>
|
21
21
|
</div>
|
22
22
|
</div>
|
23
|
-
<
|
23
|
+
<q-popup-proxy>
|
24
24
|
<NumberField
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
v-model="range.from"
|
26
|
+
:field="minField"
|
27
|
+
@update:model-value="onSave"
|
28
28
|
/>
|
29
29
|
<NumberField
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
v-model="range.to"
|
31
|
+
class="mt-2"
|
32
|
+
:field="maxField"
|
33
|
+
@update:model-value="onSave"
|
34
34
|
/>
|
35
|
-
|
35
|
+
</q-popup-proxy>
|
36
36
|
</div>
|
37
37
|
</template>
|
38
38
|
|
39
39
|
<script setup>
|
40
|
-
import {
|
41
|
-
import {
|
42
|
-
import {
|
43
|
-
import
|
44
|
-
import {
|
45
|
-
import
|
40
|
+
import { CurrencyDollarIcon as CurrencyIcon, HashtagIcon as NumberIcon } from '@heroicons/vue/outline';
|
41
|
+
import { fCurrency, fNumber, fPercent } from '@ui/helpers';
|
42
|
+
import { PercentIcon } from '@ui/svg';
|
43
|
+
import { useDebounceFn } from '@vueuse/core';
|
44
|
+
import { computed, ref, watch } from 'vue';
|
45
|
+
import NumberField from './NumberField';
|
46
46
|
|
47
|
-
const emit = defineEmits([
|
47
|
+
const emit = defineEmits(['update:model-value']);
|
48
48
|
const props = defineProps({
|
49
49
|
modelValue: {
|
50
50
|
type: Object,
|
@@ -68,28 +68,28 @@ const props = defineProps({
|
|
68
68
|
|
69
69
|
const symbol = computed(() => {
|
70
70
|
if (props.currency) {
|
71
|
-
return
|
71
|
+
return '$';
|
72
72
|
} else if (props.percent) {
|
73
|
-
return
|
73
|
+
return '%';
|
74
74
|
} else {
|
75
|
-
return
|
75
|
+
return '';
|
76
76
|
}
|
77
77
|
});
|
78
78
|
const minField = computed(() => {
|
79
79
|
return {
|
80
|
-
id:
|
81
|
-
name:
|
82
|
-
label:
|
83
|
-
placeholder:
|
80
|
+
id: 'min-field',
|
81
|
+
name: 'from',
|
82
|
+
label: 'Min' + symbol.value,
|
83
|
+
placeholder: '0'
|
84
84
|
};
|
85
85
|
});
|
86
86
|
|
87
87
|
const maxField = computed(() => {
|
88
88
|
return {
|
89
|
-
id:
|
90
|
-
name:
|
91
|
-
label:
|
92
|
-
placeholder:
|
89
|
+
id: 'max-field',
|
90
|
+
name: 'to',
|
91
|
+
label: 'Max' + symbol.value,
|
92
|
+
placeholder: 'No Limit'
|
93
93
|
};
|
94
94
|
});
|
95
95
|
|
@@ -112,7 +112,7 @@ setRange(props.modelValue || { from: undefined, to: undefined });
|
|
112
112
|
* @returns {string}
|
113
113
|
*/
|
114
114
|
function formatNum(num) {
|
115
|
-
if (num === undefined) return
|
115
|
+
if (num === undefined) return 'No Limit';
|
116
116
|
if (props.currency) {
|
117
117
|
return fCurrency(num);
|
118
118
|
}
|
@@ -134,7 +134,7 @@ const onSave = useDebounceFn(() => {
|
|
134
134
|
from: (range.value.from ? range.value.from * multiplier : undefined),
|
135
135
|
to: (range.value.to ? range.value.to * multiplier : undefined)
|
136
136
|
};
|
137
|
-
emit(
|
137
|
+
emit('update:model-value', newVal);
|
138
138
|
}
|
139
139
|
}, props.debounce);
|
140
140
|
</script>
|
@@ -1,36 +1,36 @@
|
|
1
1
|
<template>
|
2
2
|
<div>
|
3
3
|
<ContentDrawer
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
v-model:show="showDrawer"
|
5
|
+
content-class=""
|
6
|
+
position="bottom"
|
7
|
+
:title="'Filter ' + label"
|
8
8
|
>
|
9
9
|
<div
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
v-for="option in formattedOptions"
|
11
|
+
:key="'select-drawer-' + option.value"
|
12
|
+
:data-dusk="'drawer-opt-' + option.value"
|
13
|
+
class="cursor-pointer hover:bg-gray-light px-8 py-3 flex items-center border-b border-gray-light"
|
14
|
+
@click="toggleSelect(option)"
|
15
15
|
>
|
16
|
-
<
|
17
|
-
|
18
|
-
|
16
|
+
<q-checkbox
|
17
|
+
:model-value="isSelected(option)"
|
18
|
+
class="mr-2"
|
19
19
|
/>
|
20
20
|
<slot
|
21
|
-
|
22
|
-
|
21
|
+
name="option"
|
22
|
+
:opt="option"
|
23
23
|
>{{ option.label }}
|
24
24
|
</slot>
|
25
25
|
</div>
|
26
26
|
</ContentDrawer>
|
27
27
|
|
28
|
-
<
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
<q-chip
|
29
|
+
ref="select"
|
30
|
+
outline
|
31
|
+
clickable
|
32
|
+
size="16px"
|
33
|
+
@click="showDrawer = true"
|
34
34
|
>
|
35
35
|
<slot name="selected">
|
36
36
|
<slot name="label">{{ label }}: </slot>
|
@@ -39,7 +39,7 @@
|
|
39
39
|
<template v-if="multiple">
|
40
40
|
{{ getOptionLabel(modelValue[0]) }}
|
41
41
|
<template
|
42
|
-
|
42
|
+
v-if="modelValue.length > 1"
|
43
43
|
>+ {{ modelValue.length - 1 }}
|
44
44
|
</template
|
45
45
|
>
|
@@ -53,15 +53,15 @@
|
|
53
53
|
<slot name="placeholder">{{ placeholder }}</slot>
|
54
54
|
</template>
|
55
55
|
</slot>
|
56
|
-
|
56
|
+
</q-chip>
|
57
57
|
</div>
|
58
58
|
</template>
|
59
59
|
|
60
60
|
<script setup>
|
61
|
-
import { ContentDrawer } from
|
62
|
-
import { computed, ref } from
|
61
|
+
import { ContentDrawer } from '@ui/components';
|
62
|
+
import { computed, ref } from 'vue';
|
63
63
|
|
64
|
-
const emit = defineEmits([
|
64
|
+
const emit = defineEmits(['update:modelValue']);
|
65
65
|
const props = defineProps({
|
66
66
|
modelValue: {
|
67
67
|
type: [Object, String, Array, null],
|
@@ -74,24 +74,24 @@ const props = defineProps({
|
|
74
74
|
multiple: Boolean,
|
75
75
|
label: {
|
76
76
|
type: String,
|
77
|
-
default:
|
77
|
+
default: 'Select'
|
78
78
|
},
|
79
79
|
placeholder: {
|
80
80
|
type: String,
|
81
|
-
default:
|
81
|
+
default: 'All'
|
82
82
|
}
|
83
83
|
});
|
84
84
|
|
85
85
|
const showDrawer = ref(false);
|
86
86
|
const formattedOptions = computed(() =>
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
87
|
+
props.options.map((opt) =>
|
88
|
+
typeof opt === 'string'
|
89
|
+
? {
|
90
|
+
label: opt,
|
91
|
+
value: opt
|
92
|
+
}
|
93
|
+
: opt
|
94
|
+
)
|
95
95
|
);
|
96
96
|
|
97
97
|
function getOptionValue(option) {
|
@@ -131,6 +131,6 @@ function toggleSelect(option) {
|
|
131
131
|
}
|
132
132
|
}
|
133
133
|
|
134
|
-
emit(
|
134
|
+
emit('update:modelValue', selection);
|
135
135
|
}
|
136
136
|
</script>
|
@@ -1,73 +1,73 @@
|
|
1
1
|
<template>
|
2
2
|
<div>
|
3
|
-
<
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
3
|
+
<q-select
|
4
|
+
ref="selectField"
|
5
|
+
v-bind="$props"
|
6
|
+
:model-value="selectedValue"
|
7
|
+
outlined
|
8
|
+
hide-dropdown-icon
|
9
|
+
dense
|
10
|
+
emit-value
|
11
|
+
:use-input="filterable"
|
12
|
+
:hide-selected="filterable && isShowing && !$props.multiple"
|
13
|
+
:input-debounce="100"
|
14
|
+
:options="filteredOptions"
|
15
|
+
option-label="label"
|
16
|
+
option-value="value"
|
17
|
+
placeholder=""
|
18
|
+
:input-class="{'is-hidden': !isShowing, [inputClass]: true}"
|
19
|
+
class="max-w-full"
|
20
|
+
@filter="onFilter"
|
21
|
+
@clear="onClear"
|
22
|
+
@popup-show="onShow"
|
23
|
+
@popup-hide="onHide"
|
24
|
+
@update:model-value="onUpdate"
|
25
25
|
>
|
26
26
|
<template #append>
|
27
27
|
<DropDownIcon
|
28
|
-
|
29
|
-
|
28
|
+
class="w-4 transition"
|
29
|
+
:class="isShowing ? 'rotate-180' : ''"
|
30
30
|
/>
|
31
31
|
</template>
|
32
32
|
<template #selected>
|
33
33
|
<div
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
v-if="$props.multiple"
|
35
|
+
class="flex gap-y-1 overflow-hidden"
|
36
|
+
:class="{'flex-nowrap gap-y-0': chipLimit === 1, [selectionClass]: true}"
|
37
37
|
>
|
38
38
|
<template v-if="chipOptions.length > 0">
|
39
|
-
<
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
<q-chip
|
40
|
+
v-for="chipOption in chipOptions"
|
41
|
+
:key="'selected-' + chipOption.label"
|
42
|
+
class="!mr-1"
|
43
43
|
>{{ chipOption.label }}
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
</q-chip>
|
45
|
+
<q-chip
|
46
|
+
v-if="selectedOptions.length > chipOptions.length"
|
47
|
+
class="!mr-1"
|
48
|
+
>
|
49
|
+
+{{ selectedOptions.length - chipOptions.length }}
|
50
|
+
</q-chip>
|
51
51
|
</template>
|
52
52
|
<template v-else>
|
53
53
|
{{ placeholder }}
|
54
54
|
</template>
|
55
55
|
</div>
|
56
56
|
<div
|
57
|
-
|
58
|
-
|
57
|
+
v-else
|
58
|
+
:class="selectionClass"
|
59
59
|
>{{ selectedLabel }}
|
60
60
|
</div>
|
61
61
|
</template>
|
62
|
-
|
62
|
+
</q-select>
|
63
63
|
</div>
|
64
64
|
</template>
|
65
65
|
<script setup>
|
66
|
-
import { ChevronDownIcon as DropDownIcon } from
|
67
|
-
import { QSelect } from
|
68
|
-
import { computed, isRef, nextTick, ref } from
|
66
|
+
import { ChevronDownIcon as DropDownIcon } from '@heroicons/vue/outline';
|
67
|
+
import { QSelect } from 'quasar';
|
68
|
+
import { computed, isRef, nextTick, ref } from 'vue';
|
69
69
|
|
70
|
-
const emit = defineEmits([
|
70
|
+
const emit = defineEmits(['update:model-value', 'search']);
|
71
71
|
const props = defineProps({
|
72
72
|
...QSelect.props,
|
73
73
|
modelValue: {
|
@@ -76,7 +76,7 @@ const props = defineProps({
|
|
76
76
|
},
|
77
77
|
placeholder: {
|
78
78
|
type: String,
|
79
|
-
default:
|
79
|
+
default: ''
|
80
80
|
},
|
81
81
|
selectionLabel: {
|
82
82
|
type: String,
|
@@ -88,11 +88,11 @@ const props = defineProps({
|
|
88
88
|
},
|
89
89
|
inputClass: {
|
90
90
|
type: String,
|
91
|
-
default:
|
91
|
+
default: ''
|
92
92
|
},
|
93
93
|
selectionClass: {
|
94
94
|
type: String,
|
95
|
-
default:
|
95
|
+
default: ''
|
96
96
|
},
|
97
97
|
options: {
|
98
98
|
type: Array,
|
@@ -148,10 +148,10 @@ const selectedValue = computed(() => {
|
|
148
148
|
if (props.multiple) {
|
149
149
|
const arrVal = Array.isArray(props.modelValue) ? props.modelValue : [];
|
150
150
|
return arrVal.map((v) => {
|
151
|
-
return v === null ?
|
151
|
+
return v === null ? '__null__' : v;
|
152
152
|
}) || [];
|
153
153
|
} else {
|
154
|
-
return props.modelValue === null ?
|
154
|
+
return props.modelValue === null ? '__null__' : props.modelValue;
|
155
155
|
}
|
156
156
|
});
|
157
157
|
|
@@ -165,7 +165,7 @@ const selectedOptions = computed(() => {
|
|
165
165
|
values = (values || values === 0) ? [values] : [];
|
166
166
|
}
|
167
167
|
return computedOptions.value.filter((o) => {
|
168
|
-
return values.includes(o.value) || values.map(v => typeof v ===
|
168
|
+
return values.includes(o.value) || values.map(v => typeof v === 'object' && v.id).includes(o.value?.id);
|
169
169
|
});
|
170
170
|
});
|
171
171
|
|
@@ -175,10 +175,10 @@ const selectedOptions = computed(() => {
|
|
175
175
|
* @type {ComputedRef<unknown>}
|
176
176
|
*/
|
177
177
|
const selectedLabel = computed(() => {
|
178
|
-
if (props.filterable && isShowing.value) return
|
178
|
+
if (props.filterable && isShowing.value) return '';
|
179
179
|
|
180
180
|
if (!selectedOptions.value || selectedOptions.value.length === 0) {
|
181
|
-
return props.placeholder ||
|
181
|
+
return props.placeholder || '(Select Option)';
|
182
182
|
}
|
183
183
|
return selectedOptions.value[0].selectionLabel;
|
184
184
|
});
|
@@ -197,13 +197,13 @@ const chipOptions = computed(() => {
|
|
197
197
|
* @returns {*|string}
|
198
198
|
*/
|
199
199
|
function resolveLabel(option) {
|
200
|
-
if (typeof option ===
|
200
|
+
if (typeof option === 'string') {
|
201
201
|
return option;
|
202
202
|
}
|
203
|
-
if (typeof props.optionLabel ===
|
203
|
+
if (typeof props.optionLabel === 'string') {
|
204
204
|
return option[props.optionLabel];
|
205
205
|
}
|
206
|
-
if (typeof props.optionLabel ===
|
206
|
+
if (typeof props.optionLabel === 'function') {
|
207
207
|
return props.optionLabel(option);
|
208
208
|
}
|
209
209
|
return option?.label;
|
@@ -216,13 +216,13 @@ function resolveLabel(option) {
|
|
216
216
|
* @returns {*|{default: null, type: String | StringConstructor}|string}
|
217
217
|
*/
|
218
218
|
function resolveSelectionLabel(option) {
|
219
|
-
if (typeof option ===
|
219
|
+
if (typeof option === 'string') {
|
220
220
|
return option;
|
221
221
|
}
|
222
|
-
if (typeof props.selectionLabel ===
|
222
|
+
if (typeof props.selectionLabel === 'string') {
|
223
223
|
return option[props.selectionLabel];
|
224
224
|
}
|
225
|
-
if (typeof props.selectionLabel ===
|
225
|
+
if (typeof props.selectionLabel === 'function') {
|
226
226
|
return props.selectionLabel(option);
|
227
227
|
}
|
228
228
|
return option?.selectionLabel || option?.label;
|
@@ -234,17 +234,17 @@ function resolveSelectionLabel(option) {
|
|
234
234
|
* @returns {string|*|string}
|
235
235
|
*/
|
236
236
|
function resolveValue(option) {
|
237
|
-
if (typeof option ===
|
237
|
+
if (typeof option === 'string') {
|
238
238
|
return option;
|
239
239
|
}
|
240
240
|
let value = option.value;
|
241
|
-
if (typeof props.optionValue ===
|
241
|
+
if (typeof props.optionValue === 'string') {
|
242
242
|
value = option[props.optionValue];
|
243
|
-
} else if (typeof props.optionValue ===
|
243
|
+
} else if (typeof props.optionValue === 'function') {
|
244
244
|
value = props.optionValue(option);
|
245
245
|
}
|
246
246
|
// Note the __null__ special case here. See the onUpdate function for more details
|
247
|
-
return value === null ?
|
247
|
+
return value === null ? '__null__' : value;
|
248
248
|
}
|
249
249
|
|
250
250
|
/**
|
@@ -255,9 +255,9 @@ function resolveValue(option) {
|
|
255
255
|
*/
|
256
256
|
function onUpdate(value) {
|
257
257
|
if (Array.isArray(value)) {
|
258
|
-
value = value.map((v) => v ===
|
258
|
+
value = value.map((v) => v === '__null__' ? null : v);
|
259
259
|
}
|
260
|
-
emit(
|
260
|
+
emit('update:model-value', value === '__null__' ? null : value);
|
261
261
|
}
|
262
262
|
|
263
263
|
/** XXX: This tells us when we should apply the filter. QSelect likes to trigger a new filter everytime you open the dropdown
|
@@ -291,7 +291,7 @@ async function onFilter(val, update) {
|
|
291
291
|
* See the onUpdate function for more details
|
292
292
|
*/
|
293
293
|
function onClear() {
|
294
|
-
emit(
|
294
|
+
emit('update:model-value', undefined);
|
295
295
|
}
|
296
296
|
|
297
297
|
/**
|
@@ -4,35 +4,35 @@
|
|
4
4
|
<div class="text-gray-silver">No options available</div>
|
5
5
|
</template>
|
6
6
|
<SelectField
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
v-model="selectedOption"
|
8
|
+
:options="options"
|
9
|
+
:label="label"
|
10
|
+
:placeholder="placeholder"
|
11
|
+
:option-value="opt => opt"
|
12
|
+
:loading="loading"
|
13
|
+
@update:model-value="onSelectOption"
|
14
14
|
/>
|
15
15
|
<div v-if="selectedOption">
|
16
|
-
<
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
16
|
+
<q-checkbox
|
17
|
+
v-for="child in selectedOption.children"
|
18
|
+
:key="child.id"
|
19
|
+
:model-value="selectedChildren.includes(child.id)"
|
20
|
+
:field="child"
|
21
|
+
class="mt-3"
|
22
|
+
@update:model-value="onSelectChild(child)"
|
23
23
|
>
|
24
24
|
<div>{{ child.label }}</div>
|
25
25
|
<div class="text-xs text-gray-silver">{{ child.name }}</div>
|
26
|
-
|
26
|
+
</q-checkbox>
|
27
27
|
</div>
|
28
28
|
</div>
|
29
29
|
</template>
|
30
30
|
<script setup>
|
31
|
-
import
|
32
|
-
import {
|
33
|
-
import
|
31
|
+
import { remove } from '@ui/helpers/array';
|
32
|
+
import { ref, watch } from 'vue';
|
33
|
+
import SelectField from './SelectField';
|
34
34
|
|
35
|
-
const emit = defineEmits([
|
35
|
+
const emit = defineEmits(['update:model-value']);
|
36
36
|
const props = defineProps({
|
37
37
|
modelValue: {
|
38
38
|
type: Array,
|
@@ -40,11 +40,11 @@ const props = defineProps({
|
|
40
40
|
},
|
41
41
|
label: {
|
42
42
|
type: String,
|
43
|
-
default:
|
43
|
+
default: 'Selection'
|
44
44
|
},
|
45
45
|
placeholder: {
|
46
46
|
type: String,
|
47
|
-
default:
|
47
|
+
default: 'Select an option'
|
48
48
|
},
|
49
49
|
options: {
|
50
50
|
type: Array,
|
@@ -68,11 +68,11 @@ function onSelectChild(child) {
|
|
68
68
|
} else {
|
69
69
|
selectedChildren.value.push(child.id);
|
70
70
|
}
|
71
|
-
emit(
|
71
|
+
emit('update:model-value', selectedChildren.value.length > 0 ? selectedChildren.value : undefined);
|
72
72
|
}
|
73
73
|
function onSelectOption() {
|
74
74
|
selectedChildren.value = [];
|
75
|
-
emit(
|
75
|
+
emit('update:model-value', undefined);
|
76
76
|
}
|
77
77
|
watch(() => props.modelValue, (value) => {
|
78
78
|
selectedOption.value = resolveSelectedOption();
|