@xen-orchestra/web-core 0.20.1 → 0.21.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/lib/components/backup-state/VtsBackupState.vue +20 -17
- package/lib/components/cell-object/VtsCellObject.vue +4 -1
- package/lib/components/console/VtsActionsConsole.vue +7 -4
- package/lib/components/console/VtsClipboardConsole.vue +9 -6
- package/lib/components/copy-button/VtsCopyButton.vue +7 -14
- package/lib/components/dropdown/DropdownTitle.vue +5 -2
- package/lib/components/icon/NewVtsIcon.vue +49 -0
- package/lib/components/input-group/VtsInputGroup.vue +41 -0
- package/lib/components/input-wrapper/VtsInputWrapper.vue +2 -2
- package/lib/components/layout/VtsLayoutSidebar.vue +6 -3
- package/lib/components/linear-chart/VtsLinearChart.vue +4 -0
- package/lib/components/object-icon/VtsObjectIcon.vue +22 -0
- package/lib/components/quick-info-card/VtsQuickInfoCard.vue +4 -1
- package/lib/components/select/VtsOption.vue +10 -6
- package/lib/components/select/VtsSelect.vue +74 -50
- package/lib/components/state-hero/VtsAllDoneHero.vue +4 -1
- package/lib/components/state-hero/VtsAllGoodHero.vue +4 -1
- package/lib/components/state-hero/VtsComingSoonHero.vue +4 -1
- package/lib/components/state-hero/VtsErrorNoDataHero.vue +4 -1
- package/lib/components/state-hero/VtsLoadingHero.vue +4 -1
- package/lib/components/state-hero/VtsNoDataHero.vue +4 -1
- package/lib/components/state-hero/VtsNoSelectionHero.vue +4 -1
- package/lib/components/state-hero/VtsObjectNotFoundHero.vue +4 -1
- package/lib/components/state-hero/VtsOfflineHero.vue +4 -1
- package/lib/components/state-hero/VtsPageNotFoundHero.vue +4 -1
- package/lib/components/table/ColumnTitle.vue +2 -2
- package/lib/components/task/VtsQuickTaskButton.vue +4 -1
- package/lib/components/task/VtsQuickTaskList.vue +5 -2
- package/lib/components/task/VtsQuickTaskTabBar.vue +8 -5
- package/lib/components/ui/card-numbers/UiCardNumbers.vue +4 -1
- package/lib/components/ui/character-limit/UiCharacterLimit.vue +4 -1
- package/lib/components/ui/input/UiInput.vue +2 -2
- package/lib/components/ui/label/UiLabel.vue +4 -1
- package/lib/components/ui/progress-bar/UiProgressBar.vue +5 -2
- package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +9 -6
- package/lib/components/ui/quick-task-item/UiQuickTaskItem.vue +6 -3
- package/lib/components/ui/stacked-bar/StackedBarSegment.vue +4 -1
- package/lib/components/ui/table-pagination/UiTablePagination.vue +6 -3
- package/lib/components/ui/text-area/UiTextarea.vue +4 -1
- package/lib/components/ui/top-bottom-table/UiTopBottomTable.vue +6 -3
- package/lib/components/ui/tree-item-label/UiTreeItemLabel.vue +4 -1
- package/lib/composables/local-time-ago.composable.ts +53 -0
- package/lib/composables/locale-time-ago.composable.ts +53 -0
- package/lib/icons/fa-icons.ts +164 -0
- package/lib/icons/index.ts +15 -0
- package/lib/icons/legacy-icons.ts +80 -0
- package/lib/icons/object-icons.ts +187 -0
- package/lib/layouts/CoreLayout.vue +7 -3
- package/lib/locales/cs.json +0 -1
- package/lib/locales/de.json +1 -1
- package/lib/locales/en.json +32 -4
- package/lib/locales/es.json +1 -1
- package/lib/locales/fr.json +31 -3
- package/lib/locales/it.json +1 -1
- package/lib/locales/nl.json +1 -1
- package/lib/locales/ru.json +1 -1
- package/lib/locales/sv.json +1 -2
- package/lib/packages/collection/README.md +23 -18
- package/lib/packages/collection/create-collection.ts +22 -21
- package/lib/packages/collection/create-item.ts +21 -20
- package/lib/packages/collection/create-use-subset.ts +23 -0
- package/lib/packages/collection/guess-item-id.ts +26 -16
- package/lib/packages/collection/index.ts +4 -0
- package/lib/packages/collection/types.ts +65 -37
- package/lib/packages/collection/use-collection.ts +68 -18
- package/lib/packages/collection/use-flag-registry.ts +38 -17
- package/lib/packages/form-select/guess-label.ts +45 -0
- package/lib/packages/form-select/guess-value.ts +23 -0
- package/lib/packages/form-select/index.ts +6 -0
- package/lib/packages/form-select/normalize-search-term.ts +11 -0
- package/lib/packages/form-select/types.ts +90 -42
- package/lib/packages/form-select/use-form-option-controller.ts +7 -3
- package/lib/packages/form-select/use-form-select-controller.ts +38 -27
- package/lib/packages/form-select/use-form-select-keyboard-navigation.ts +1 -1
- package/lib/packages/form-select/use-form-select.ts +308 -130
- package/lib/packages/icon/DisplayIcon.vue +25 -0
- package/lib/packages/icon/DisplayIconAny.vue +16 -0
- package/lib/packages/icon/DisplayIconSingle.vue +35 -0
- package/lib/packages/icon/DisplayIconStack.vue +34 -0
- package/lib/packages/icon/README.md +286 -0
- package/lib/packages/icon/create-icon-bindings.ts +27 -0
- package/lib/packages/icon/define-icon-pack.ts +23 -0
- package/lib/packages/icon/define-icon-single.ts +17 -0
- package/lib/packages/icon/define-icon-stack.ts +20 -0
- package/lib/packages/icon/define-icon.ts +40 -0
- package/lib/packages/icon/generate-icon-variants.ts +17 -0
- package/lib/packages/icon/index.ts +8 -0
- package/lib/packages/icon/is-icon-stack.ts +5 -0
- package/lib/packages/icon/merge-icons.ts +25 -0
- package/lib/packages/icon/merge-transforms.ts +12 -0
- package/lib/packages/icon/normalize-icon.ts +25 -0
- package/lib/packages/icon/to-tuple.ts +7 -0
- package/lib/packages/icon/types.ts +72 -0
- package/lib/packages/job/README.md +2 -2
- package/lib/packages/mapper/README.md +166 -0
- package/lib/packages/mapper/convert-to-map.ts +5 -0
- package/lib/packages/mapper/create-mapper.ts +30 -0
- package/lib/packages/mapper/index.ts +4 -0
- package/lib/packages/mapper/types.ts +1 -0
- package/lib/packages/mapper/use-mapper.ts +31 -0
- package/lib/stores/sidebar.store.ts +1 -1
- package/lib/types/chart.ts +2 -2
- package/lib/types/utility.type.ts +9 -0
- package/lib/utils/object.util.ts +16 -0
- package/lib/utils/size.util.ts +4 -2
- package/package.json +2 -1
- package/lib/components/backup-item/VtsBackupItem.vue +0 -47
- package/lib/composables/mapper.composable.md +0 -74
- package/lib/composables/mapper.composable.ts +0 -18
|
@@ -1,193 +1,371 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type CollectionItemId,
|
|
3
|
+
type CollectionItemProperties,
|
|
4
|
+
type GetItemId,
|
|
5
|
+
guessItemId,
|
|
6
|
+
useCollection,
|
|
7
|
+
} from '@core/packages/collection'
|
|
8
|
+
import type { EmptyObject, MaybeArray } from '@core/types/utility.type.ts'
|
|
9
|
+
import { toArray } from '@core/utils/to-array.utils.ts'
|
|
2
10
|
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
11
|
+
ExtractValue,
|
|
12
|
+
FormOptionCollectionItemProperties,
|
|
13
|
+
FormSelect,
|
|
14
|
+
FormSelectId,
|
|
15
|
+
GetOptionLabel,
|
|
16
|
+
GetOptionValue,
|
|
7
17
|
UseFormSelectReturn,
|
|
8
|
-
} from '
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
18
|
+
} from './types.ts'
|
|
19
|
+
import { computed, type ComputedRef, type MaybeRefOrGetter, provide, ref, type Ref, toValue, watch } from 'vue'
|
|
20
|
+
import { guessLabel } from './guess-label.ts'
|
|
21
|
+
import { guessValue } from './guess-value.ts'
|
|
22
|
+
import { normalizeSearchTerm } from './normalize-search-term.ts'
|
|
12
23
|
|
|
13
|
-
|
|
14
|
-
TSource extends { value: FormOptionValue; label: string },
|
|
15
|
-
TValue extends FormOptionValue = TSource['value'],
|
|
16
|
-
TProperties extends FormSelectBaseProperties & {
|
|
17
|
-
value?: TValue
|
|
18
|
-
label?: string
|
|
19
|
-
} = FormSelectBaseProperties & {
|
|
20
|
-
value?: TValue
|
|
21
|
-
label?: string
|
|
22
|
-
},
|
|
23
|
-
>(
|
|
24
|
-
sources: MaybeRefOrGetter<TSource[]>,
|
|
25
|
-
config?: FormSelectBaseConfig & {
|
|
26
|
-
properties?: (source: TSource) => TProperties
|
|
27
|
-
}
|
|
28
|
-
): UseFormSelectReturn<TSource, TValue, TProperties>
|
|
24
|
+
// Overload #1: Source is CollectionItemId
|
|
29
25
|
|
|
30
26
|
export function useFormSelect<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
label?: string
|
|
39
|
-
},
|
|
27
|
+
TBaseSource extends CollectionItemId,
|
|
28
|
+
TAllowEmpty extends boolean = false,
|
|
29
|
+
TCustomProperties extends CollectionItemProperties = EmptyObject,
|
|
30
|
+
TGetValue extends GetOptionValue<$TSource, TCustomProperties> = undefined,
|
|
31
|
+
TMultiple extends boolean = false,
|
|
32
|
+
$TSource = TAllowEmpty extends true ? TBaseSource | undefined : TBaseSource,
|
|
33
|
+
$TValue = ExtractValue<$TSource, TGetValue>,
|
|
40
34
|
>(
|
|
41
|
-
sources: MaybeRefOrGetter<
|
|
42
|
-
config?:
|
|
43
|
-
|
|
35
|
+
sources: MaybeRefOrGetter<TBaseSource[]>,
|
|
36
|
+
config?: {
|
|
37
|
+
allowEmpty?: MaybeRefOrGetter<TAllowEmpty>
|
|
38
|
+
multiple?: MaybeRefOrGetter<TMultiple>
|
|
39
|
+
model?: Ref<unknown>
|
|
40
|
+
disabled?: MaybeRefOrGetter<boolean>
|
|
41
|
+
selectedLabel?: (count: number, labels: string[]) => string | undefined
|
|
42
|
+
placeholder?: MaybeRefOrGetter<string>
|
|
43
|
+
searchPlaceholder?: MaybeRefOrGetter<string>
|
|
44
|
+
loading?: MaybeRefOrGetter<boolean>
|
|
45
|
+
required?: MaybeRefOrGetter<boolean>
|
|
46
|
+
searchable?: MaybeRefOrGetter<boolean>
|
|
47
|
+
option?: {
|
|
48
|
+
id?: GetItemId<TBaseSource>
|
|
49
|
+
value?: TGetValue | ((source: $TSource, properties: TCustomProperties) => $TValue)
|
|
50
|
+
properties?: (source: $TSource) => TCustomProperties
|
|
51
|
+
label?: GetOptionLabel<$TSource, TCustomProperties>
|
|
52
|
+
selectedLabel?: (source: $TSource, properties: TCustomProperties) => string
|
|
53
|
+
disabled?: (source: $TSource, properties: TCustomProperties) => boolean
|
|
54
|
+
searchableTerm?: (source: $TSource, properties: TCustomProperties) => MaybeArray<string>
|
|
55
|
+
}
|
|
44
56
|
}
|
|
45
|
-
): UseFormSelectReturn<TSource, TValue,
|
|
57
|
+
): UseFormSelectReturn<TCustomProperties, $TSource, $TValue, TMultiple>
|
|
58
|
+
|
|
59
|
+
// Overload #2: Source is an object with id and label
|
|
46
60
|
|
|
47
61
|
export function useFormSelect<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
label: string
|
|
56
|
-
},
|
|
62
|
+
TBaseSource extends { id: CollectionItemId; label: string },
|
|
63
|
+
TAllowEmpty extends boolean = false,
|
|
64
|
+
TCustomProperties extends CollectionItemProperties = EmptyObject,
|
|
65
|
+
TGetValue extends GetOptionValue<$TSource, TCustomProperties> = undefined,
|
|
66
|
+
TMultiple extends boolean = false,
|
|
67
|
+
$TSource = TAllowEmpty extends true ? TBaseSource | undefined : TBaseSource,
|
|
68
|
+
$TValue = ExtractValue<$TSource, TGetValue>,
|
|
57
69
|
>(
|
|
58
|
-
sources: MaybeRefOrGetter<
|
|
59
|
-
config
|
|
60
|
-
|
|
70
|
+
sources: MaybeRefOrGetter<TBaseSource[]>,
|
|
71
|
+
config?: {
|
|
72
|
+
allowEmpty?: MaybeRefOrGetter<TAllowEmpty>
|
|
73
|
+
multiple?: MaybeRefOrGetter<TMultiple>
|
|
74
|
+
model?: Ref<unknown>
|
|
75
|
+
disabled?: MaybeRefOrGetter<boolean>
|
|
76
|
+
selectedLabel?: (count: number, labels: string[]) => string | undefined
|
|
77
|
+
placeholder?: MaybeRefOrGetter<string>
|
|
78
|
+
searchPlaceholder?: MaybeRefOrGetter<string>
|
|
79
|
+
loading?: MaybeRefOrGetter<boolean>
|
|
80
|
+
required?: MaybeRefOrGetter<boolean>
|
|
81
|
+
searchable?: MaybeRefOrGetter<boolean>
|
|
82
|
+
option?: {
|
|
83
|
+
id?: GetItemId<TBaseSource>
|
|
84
|
+
value?: TGetValue | ((source: $TSource, properties: TCustomProperties) => $TValue)
|
|
85
|
+
properties?: (source: $TSource) => TCustomProperties
|
|
86
|
+
label?: GetOptionLabel<$TSource, TCustomProperties>
|
|
87
|
+
selectedLabel?: (source: $TSource, properties: TCustomProperties) => string
|
|
88
|
+
disabled?: (source: $TSource, properties: TCustomProperties) => boolean
|
|
89
|
+
searchableTerm?: (source: $TSource, properties: TCustomProperties) => MaybeArray<string>
|
|
90
|
+
}
|
|
61
91
|
}
|
|
62
|
-
): UseFormSelectReturn<TSource, TValue,
|
|
92
|
+
): UseFormSelectReturn<TCustomProperties, $TSource, $TValue, TMultiple>
|
|
93
|
+
|
|
94
|
+
// Overload #3: Source is an object with id only
|
|
63
95
|
|
|
64
96
|
export function useFormSelect<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
label: string
|
|
73
|
-
},
|
|
97
|
+
TBaseSource extends { id: CollectionItemId },
|
|
98
|
+
TAllowEmpty extends boolean = false,
|
|
99
|
+
TCustomProperties extends CollectionItemProperties = EmptyObject,
|
|
100
|
+
TGetValue extends GetOptionValue<$TSource, TCustomProperties> = undefined,
|
|
101
|
+
TMultiple extends boolean = false,
|
|
102
|
+
$TSource = TAllowEmpty extends true ? TBaseSource | undefined : TBaseSource,
|
|
103
|
+
$TValue = ExtractValue<$TSource, TGetValue>,
|
|
74
104
|
>(
|
|
75
|
-
sources: MaybeRefOrGetter<
|
|
76
|
-
config:
|
|
77
|
-
|
|
105
|
+
sources: MaybeRefOrGetter<TBaseSource[]>,
|
|
106
|
+
config: {
|
|
107
|
+
allowEmpty?: MaybeRefOrGetter<TAllowEmpty>
|
|
108
|
+
multiple?: MaybeRefOrGetter<TMultiple>
|
|
109
|
+
model?: Ref<unknown>
|
|
110
|
+
disabled?: MaybeRefOrGetter<boolean>
|
|
111
|
+
selectedLabel?: (count: number, labels: string[]) => string | undefined
|
|
112
|
+
placeholder?: MaybeRefOrGetter<string>
|
|
113
|
+
searchPlaceholder?: MaybeRefOrGetter<string>
|
|
114
|
+
loading?: MaybeRefOrGetter<boolean>
|
|
115
|
+
required?: MaybeRefOrGetter<boolean>
|
|
116
|
+
searchable?: MaybeRefOrGetter<boolean>
|
|
117
|
+
option: {
|
|
118
|
+
id?: GetItemId<TBaseSource>
|
|
119
|
+
value?: TGetValue | ((source: $TSource, properties: TCustomProperties) => $TValue)
|
|
120
|
+
properties?: (source: $TSource) => TCustomProperties
|
|
121
|
+
label: GetOptionLabel<$TSource, TCustomProperties>
|
|
122
|
+
selectedLabel?: (source: $TSource, properties: TCustomProperties) => string
|
|
123
|
+
disabled?: (source: $TSource, properties: TCustomProperties) => boolean
|
|
124
|
+
searchableTerm?: (source: $TSource, properties: TCustomProperties) => MaybeArray<string>
|
|
125
|
+
}
|
|
78
126
|
}
|
|
79
|
-
): UseFormSelectReturn<TSource, TValue,
|
|
127
|
+
): UseFormSelectReturn<TCustomProperties, $TSource, $TValue, TMultiple>
|
|
128
|
+
|
|
129
|
+
// Overload #4: Source is an object with label only
|
|
80
130
|
|
|
81
131
|
export function useFormSelect<
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
label?: string
|
|
90
|
-
},
|
|
132
|
+
TBaseSource extends { label: string },
|
|
133
|
+
TAllowEmpty extends boolean = false,
|
|
134
|
+
TCustomProperties extends CollectionItemProperties = EmptyObject,
|
|
135
|
+
TGetValue extends GetOptionValue<$TSource, TCustomProperties> = undefined,
|
|
136
|
+
TMultiple extends boolean = false,
|
|
137
|
+
$TSource = TAllowEmpty extends true ? TBaseSource | undefined : TBaseSource,
|
|
138
|
+
$TValue = ExtractValue<$TSource, TGetValue>,
|
|
91
139
|
>(
|
|
92
|
-
sources: MaybeRefOrGetter<
|
|
93
|
-
config:
|
|
94
|
-
|
|
140
|
+
sources: MaybeRefOrGetter<TBaseSource[]>,
|
|
141
|
+
config: {
|
|
142
|
+
allowEmpty?: MaybeRefOrGetter<TAllowEmpty>
|
|
143
|
+
multiple?: MaybeRefOrGetter<TMultiple>
|
|
144
|
+
model?: Ref<unknown>
|
|
145
|
+
disabled?: MaybeRefOrGetter<boolean>
|
|
146
|
+
selectedLabel?: (count: number, labels: string[]) => string | undefined
|
|
147
|
+
placeholder?: MaybeRefOrGetter<string>
|
|
148
|
+
searchPlaceholder?: MaybeRefOrGetter<string>
|
|
149
|
+
loading?: MaybeRefOrGetter<boolean>
|
|
150
|
+
required?: MaybeRefOrGetter<boolean>
|
|
151
|
+
searchable?: MaybeRefOrGetter<boolean>
|
|
152
|
+
option: {
|
|
153
|
+
id: GetItemId<TBaseSource>
|
|
154
|
+
value?: TGetValue | ((source: $TSource, properties: TCustomProperties) => $TValue)
|
|
155
|
+
properties?: (source: $TSource) => TCustomProperties
|
|
156
|
+
label?: GetOptionLabel<$TSource, TCustomProperties>
|
|
157
|
+
selectedLabel?: (source: $TSource, properties: TCustomProperties) => string
|
|
158
|
+
disabled?: (source: $TSource, properties: TCustomProperties) => boolean
|
|
159
|
+
searchableTerm?: (source: $TSource, properties: TCustomProperties) => MaybeArray<string>
|
|
160
|
+
}
|
|
95
161
|
}
|
|
96
|
-
): UseFormSelectReturn<TSource, TValue,
|
|
162
|
+
): UseFormSelectReturn<TCustomProperties, $TSource, $TValue, TMultiple>
|
|
163
|
+
|
|
164
|
+
// Overload #5: Any other case
|
|
97
165
|
|
|
98
166
|
export function useFormSelect<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
label: string
|
|
107
|
-
},
|
|
167
|
+
TBaseSource,
|
|
168
|
+
TAllowEmpty extends boolean = false,
|
|
169
|
+
TCustomProperties extends CollectionItemProperties = EmptyObject,
|
|
170
|
+
TGetValue extends GetOptionValue<$TSource, TCustomProperties> = undefined,
|
|
171
|
+
TMultiple extends boolean = false,
|
|
172
|
+
$TSource = TAllowEmpty extends true ? TBaseSource | undefined : TBaseSource,
|
|
173
|
+
$TValue = ExtractValue<$TSource, TGetValue>,
|
|
108
174
|
>(
|
|
109
|
-
sources: MaybeRefOrGetter<
|
|
110
|
-
config:
|
|
111
|
-
|
|
175
|
+
sources: MaybeRefOrGetter<TBaseSource[]>,
|
|
176
|
+
config: {
|
|
177
|
+
allowEmpty?: MaybeRefOrGetter<TAllowEmpty>
|
|
178
|
+
multiple?: MaybeRefOrGetter<TMultiple>
|
|
179
|
+
model?: Ref<unknown>
|
|
180
|
+
disabled?: MaybeRefOrGetter<boolean>
|
|
181
|
+
selectedLabel?: (count: number, labels: string[]) => string | undefined
|
|
182
|
+
placeholder?: MaybeRefOrGetter<string>
|
|
183
|
+
searchPlaceholder?: MaybeRefOrGetter<string>
|
|
184
|
+
loading?: MaybeRefOrGetter<boolean>
|
|
185
|
+
required?: MaybeRefOrGetter<boolean>
|
|
186
|
+
searchable?: MaybeRefOrGetter<boolean>
|
|
187
|
+
option: {
|
|
188
|
+
id: GetItemId<TBaseSource>
|
|
189
|
+
value?: TGetValue | ((source: $TSource, properties: TCustomProperties) => $TValue)
|
|
190
|
+
properties?: (source: $TSource) => TCustomProperties
|
|
191
|
+
label: GetOptionLabel<$TSource, TCustomProperties>
|
|
192
|
+
selectedLabel?: (source: $TSource, properties: TCustomProperties) => string
|
|
193
|
+
disabled?: (source: $TSource, properties: TCustomProperties) => boolean
|
|
194
|
+
searchableTerm?: (source: $TSource, properties: TCustomProperties) => MaybeArray<string>
|
|
195
|
+
}
|
|
112
196
|
}
|
|
113
|
-
): UseFormSelectReturn<TSource, TValue,
|
|
197
|
+
): UseFormSelectReturn<TCustomProperties, $TSource, $TValue, TMultiple>
|
|
198
|
+
|
|
199
|
+
// Implementation
|
|
114
200
|
|
|
115
201
|
export function useFormSelect<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
202
|
+
TBaseSource,
|
|
203
|
+
TAllowEmpty extends boolean = false,
|
|
204
|
+
TCustomProperties extends CollectionItemProperties = EmptyObject,
|
|
205
|
+
TGetValue extends GetOptionValue<$TSource, TCustomProperties> = undefined,
|
|
206
|
+
TMultiple extends boolean = false,
|
|
207
|
+
$TSource = TAllowEmpty extends true ? TBaseSource | undefined : TBaseSource,
|
|
208
|
+
$TValue = ExtractValue<$TSource, TGetValue>,
|
|
121
209
|
>(
|
|
122
|
-
|
|
123
|
-
config?:
|
|
124
|
-
|
|
210
|
+
baseSources: MaybeRefOrGetter<TBaseSource[]>,
|
|
211
|
+
config?: {
|
|
212
|
+
allowEmpty?: MaybeRefOrGetter<boolean>
|
|
213
|
+
multiple?: MaybeRefOrGetter<boolean>
|
|
214
|
+
model?: Ref<unknown>
|
|
215
|
+
disabled?: MaybeRefOrGetter<boolean>
|
|
216
|
+
selectedLabel?: (count: number, labels: string[]) => string | undefined
|
|
217
|
+
placeholder?: MaybeRefOrGetter<string>
|
|
218
|
+
searchPlaceholder?: MaybeRefOrGetter<string>
|
|
219
|
+
loading?: MaybeRefOrGetter<boolean>
|
|
220
|
+
required?: MaybeRefOrGetter<boolean>
|
|
221
|
+
searchable?: MaybeRefOrGetter<boolean>
|
|
222
|
+
option?: {
|
|
223
|
+
id?: GetItemId<TBaseSource>
|
|
224
|
+
value?: GetOptionValue<$TSource, TCustomProperties>
|
|
225
|
+
properties?: (source: $TSource) => TCustomProperties
|
|
226
|
+
label?: GetOptionLabel<$TSource, TCustomProperties>
|
|
227
|
+
selectedLabel?: (source: $TSource, properties: TCustomProperties) => string
|
|
228
|
+
disabled?: (source: $TSource, properties: TCustomProperties) => boolean
|
|
229
|
+
searchableTerm?: (source: $TSource, properties: TCustomProperties) => MaybeArray<string>
|
|
230
|
+
}
|
|
125
231
|
}
|
|
126
|
-
) {
|
|
127
|
-
const
|
|
232
|
+
): UseFormSelectReturn<TCustomProperties, $TSource, $TValue, TMultiple> {
|
|
233
|
+
const searchTerm = ref('')
|
|
128
234
|
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
235
|
+
const normalizedSearchTerm = computed(() => normalizeSearchTerm(searchTerm))
|
|
236
|
+
|
|
237
|
+
const isMultiple = computed(() => toValue(config?.multiple) ?? false) as ComputedRef<TMultiple>
|
|
238
|
+
|
|
239
|
+
const isDisabled = computed(() => toValue(config?.disabled) ?? false)
|
|
240
|
+
|
|
241
|
+
const isLoading = computed(() => toValue(config?.loading) ?? false)
|
|
242
|
+
|
|
243
|
+
const isRequired = computed(() => toValue(config?.required) ?? false)
|
|
244
|
+
|
|
245
|
+
const placeholder = computed(() => toValue(config?.placeholder) ?? '')
|
|
246
|
+
|
|
247
|
+
const searchPlaceholder = computed(() => toValue(config?.searchPlaceholder) ?? '')
|
|
248
|
+
|
|
249
|
+
const isSearchable = computed(() => toValue(config?.searchable) ?? false)
|
|
250
|
+
|
|
251
|
+
const sources = computed(() =>
|
|
252
|
+
config?.allowEmpty ? [undefined, ...toValue(baseSources)] : toValue(baseSources)
|
|
253
|
+
) as ComputedRef<$TSource[]>
|
|
135
254
|
|
|
136
255
|
const {
|
|
137
256
|
items: allOptions,
|
|
138
|
-
useFlag,
|
|
139
257
|
useSubset,
|
|
258
|
+
useFlag,
|
|
140
259
|
} = useCollection(sources, {
|
|
260
|
+
itemId: source =>
|
|
261
|
+
source === undefined ? '__EMPTY_OPTION__' : guessItemId(source as TBaseSource, config?.option?.id),
|
|
141
262
|
flags: {
|
|
142
263
|
active: { multiple: false },
|
|
143
|
-
selected: { multiple:
|
|
264
|
+
selected: { multiple: isMultiple },
|
|
144
265
|
},
|
|
145
|
-
properties: (source:
|
|
146
|
-
const {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
266
|
+
properties: (source): FormOptionCollectionItemProperties<TCustomProperties, $TValue> => {
|
|
267
|
+
const customProperties = config?.option?.properties?.(source) ?? ({} as TCustomProperties)
|
|
268
|
+
const label = computed(() => guessLabel(source, customProperties, config?.option?.label))
|
|
269
|
+
const value = computed(() => guessValue(source, customProperties, config?.option?.value) as $TValue)
|
|
270
|
+
const disabled = computed(() => isDisabled.value || config?.option?.disabled?.(source, customProperties) === true)
|
|
271
|
+
const searchableTerm = computed(() => config?.option?.searchableTerm?.(source, customProperties))
|
|
272
|
+
const selectedLabel = computed(() => config?.option?.selectedLabel?.(source, customProperties))
|
|
273
|
+
|
|
274
|
+
const searchableTerms = computed(() =>
|
|
275
|
+
toArray(toValue(searchableTerm) ?? toValue(label)).map(term => normalizeSearchTerm(term))
|
|
276
|
+
)
|
|
153
277
|
|
|
154
278
|
const matching = computed(() => {
|
|
155
|
-
if (
|
|
279
|
+
if (normalizedSearchTerm.value === '') {
|
|
156
280
|
return true
|
|
157
281
|
}
|
|
158
282
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return searchableTerms.some(term => term.toLowerCase().includes(searchTerm.value))
|
|
283
|
+
return searchableTerms.value.some(term => term.includes(normalizedSearchTerm.value))
|
|
162
284
|
})
|
|
163
285
|
|
|
164
|
-
return
|
|
165
|
-
|
|
286
|
+
return {
|
|
287
|
+
value,
|
|
166
288
|
label,
|
|
167
|
-
|
|
289
|
+
selectedLabel,
|
|
168
290
|
disabled,
|
|
169
291
|
matching,
|
|
170
|
-
...
|
|
171
|
-
}
|
|
292
|
+
...customProperties,
|
|
293
|
+
}
|
|
172
294
|
},
|
|
173
295
|
})
|
|
174
296
|
|
|
175
297
|
const { items: options } = useSubset(option => option.properties.matching)
|
|
176
298
|
|
|
177
|
-
const { items: selectedOptions
|
|
299
|
+
const { items: selectedOptions } = useFlag('selected')
|
|
178
300
|
|
|
179
|
-
const
|
|
301
|
+
const selectedOption = computed(() => selectedOptions.value[0])
|
|
302
|
+
|
|
303
|
+
const selectedValues = computed(() => selectedOptions.value.map(option => option.properties.value))
|
|
304
|
+
|
|
305
|
+
const selectedValue = computed(() => selectedValues.value[0])
|
|
306
|
+
|
|
307
|
+
const selectedLabels = computed(() =>
|
|
308
|
+
selectedOptions.value.map(option => option.properties.selectedLabel ?? option.properties.label)
|
|
309
|
+
)
|
|
180
310
|
|
|
181
311
|
const selectedLabel = computed(
|
|
182
312
|
() => config?.selectedLabel?.(selectedLabels.value.length, selectedLabels.value) ?? selectedLabels.value.join(', ')
|
|
183
313
|
)
|
|
184
314
|
|
|
185
|
-
|
|
315
|
+
const { model } = config ?? {}
|
|
316
|
+
|
|
317
|
+
if (model) {
|
|
318
|
+
watch(
|
|
319
|
+
model,
|
|
320
|
+
modelValue => {
|
|
321
|
+
if (isMultiple.value) {
|
|
322
|
+
allOptions.value.forEach(option => {
|
|
323
|
+
option.toggleFlag('selected', (modelValue as $TValue[]).includes(option.properties.value as $TValue))
|
|
324
|
+
})
|
|
325
|
+
} else {
|
|
326
|
+
allOptions.value.find(option => option.properties.value === modelValue)?.toggleFlag('selected', true)
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
{ immediate: true }
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
watch(
|
|
333
|
+
selectedValues,
|
|
334
|
+
newValues => {
|
|
335
|
+
if (isMultiple.value) {
|
|
336
|
+
model.value = newValues as TMultiple extends true ? $TValue[] : $TValue
|
|
337
|
+
} else {
|
|
338
|
+
model.value = newValues[0] as TMultiple extends true ? $TValue[] : $TValue
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
{ deep: 1 }
|
|
342
|
+
)
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const select = {
|
|
346
|
+
isMultiple,
|
|
347
|
+
isDisabled,
|
|
348
|
+
isRequired,
|
|
349
|
+
isSearchable,
|
|
350
|
+
isLoading,
|
|
351
|
+
placeholder,
|
|
352
|
+
searchPlaceholder,
|
|
186
353
|
searchTerm,
|
|
187
354
|
allOptions,
|
|
188
355
|
options,
|
|
189
|
-
|
|
356
|
+
selectedValue,
|
|
190
357
|
selectedValues,
|
|
358
|
+
selectedOption,
|
|
359
|
+
selectedOptions,
|
|
191
360
|
selectedLabel,
|
|
192
|
-
}
|
|
361
|
+
} satisfies FormSelect<TCustomProperties, any> as FormSelect<TCustomProperties, $TSource, $TValue, TMultiple>
|
|
362
|
+
|
|
363
|
+
const id = Symbol('useFormSelect ID') as FormSelectId<TCustomProperties, $TSource, $TValue, TMultiple>
|
|
364
|
+
|
|
365
|
+
provide(id, select)
|
|
366
|
+
|
|
367
|
+
return {
|
|
368
|
+
id,
|
|
369
|
+
...select,
|
|
370
|
+
} satisfies UseFormSelectReturn<TCustomProperties, $TSource, $TValue, TMultiple>
|
|
193
371
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span class="display-icon-root">
|
|
3
|
+
<DisplayIconAny :icon />
|
|
4
|
+
</span>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts" setup>
|
|
8
|
+
import DisplayIconAny from './DisplayIconAny.vue'
|
|
9
|
+
import { type Icon } from './types.ts'
|
|
10
|
+
|
|
11
|
+
defineProps<{
|
|
12
|
+
icon: Icon
|
|
13
|
+
}>()
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<style lang="postcss" scoped>
|
|
17
|
+
.display-icon-root {
|
|
18
|
+
display: inline-grid;
|
|
19
|
+
height: 1em;
|
|
20
|
+
width: 1em;
|
|
21
|
+
transform-origin: 50% 50%;
|
|
22
|
+
grid-template-rows: 1fr;
|
|
23
|
+
grid-template-columns: 1fr;
|
|
24
|
+
}
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<DisplayIconStack v-if="isIconStack(icon)" :stack="icon" :stroke />
|
|
3
|
+
<DisplayIconSingle v-else :icon :stroke />
|
|
4
|
+
</template>
|
|
5
|
+
|
|
6
|
+
<script lang="ts" setup>
|
|
7
|
+
import DisplayIconSingle from './DisplayIconSingle.vue'
|
|
8
|
+
import DisplayIconStack from './DisplayIconStack.vue'
|
|
9
|
+
import { isIconStack } from './is-icon-stack.ts'
|
|
10
|
+
import { type Icon } from './types.ts'
|
|
11
|
+
|
|
12
|
+
defineProps<{
|
|
13
|
+
icon: Icon
|
|
14
|
+
stroke?: string
|
|
15
|
+
}>()
|
|
16
|
+
</script>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg v-if="icon.paths.length > 0" :viewBox="icon.viewBox" class="display-icon-single" v-bind="icon.bindings">
|
|
3
|
+
<path
|
|
4
|
+
v-for="(path, index) of icon.paths"
|
|
5
|
+
:key="index"
|
|
6
|
+
:d="path"
|
|
7
|
+
class="icon-path"
|
|
8
|
+
:stroke="stroke ?? icon.config.borderColor"
|
|
9
|
+
:stroke-width="stroke ? 64 : 32"
|
|
10
|
+
/>
|
|
11
|
+
</svg>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script lang="ts" setup>
|
|
15
|
+
import type { IconSingle } from './types.ts'
|
|
16
|
+
|
|
17
|
+
defineProps<{
|
|
18
|
+
icon: IconSingle
|
|
19
|
+
stroke?: string
|
|
20
|
+
}>()
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<style lang="postcss" scoped>
|
|
24
|
+
.display-icon-single {
|
|
25
|
+
height: 1em;
|
|
26
|
+
width: 1em;
|
|
27
|
+
overflow: visible;
|
|
28
|
+
grid-row: 1;
|
|
29
|
+
grid-column: 1;
|
|
30
|
+
|
|
31
|
+
.icon-path {
|
|
32
|
+
fill: currentColor;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
</style>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span v-bind="stack.bindings" class="display-icon-stack">
|
|
3
|
+
<DisplayIconAny
|
|
4
|
+
v-for="(icon, index) of stack.icons"
|
|
5
|
+
:key="index"
|
|
6
|
+
:icon
|
|
7
|
+
:stroke="stroke ?? stack.config.borderColor"
|
|
8
|
+
/>
|
|
9
|
+
<DisplayIconAny v-for="(icon, index) of stack.icons" :key="index" :icon />
|
|
10
|
+
</span>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script lang="ts" setup>
|
|
14
|
+
import DisplayIconAny from '@core/packages/icon/DisplayIconAny.vue'
|
|
15
|
+
import type { IconStack } from './types.ts'
|
|
16
|
+
|
|
17
|
+
defineProps<{
|
|
18
|
+
stack: IconStack
|
|
19
|
+
stroke?: string
|
|
20
|
+
}>()
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<style lang="postcss" scoped>
|
|
24
|
+
.display-icon-stack {
|
|
25
|
+
height: 1em;
|
|
26
|
+
width: 1em;
|
|
27
|
+
overflow: visible;
|
|
28
|
+
grid-row: 1;
|
|
29
|
+
grid-column: 1;
|
|
30
|
+
display: inline-grid;
|
|
31
|
+
grid-template-rows: 1fr;
|
|
32
|
+
grid-template-columns: 1fr;
|
|
33
|
+
}
|
|
34
|
+
</style>
|