@xen-orchestra/web-core 0.26.1 → 0.28.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/card/VtsCardRowKeyValue.vue +1 -0
- package/lib/components/cell-object/VtsCellObject.vue +1 -2
- package/lib/components/console/VtsActionsConsole.vue +3 -9
- package/lib/components/copy-button/VtsCopyButton.vue +1 -3
- package/lib/components/dropdown/DropdownTitle.vue +3 -3
- package/lib/components/icon/VtsIcon.vue +32 -76
- package/lib/components/input-wrapper/VtsInputWrapper.vue +2 -2
- package/lib/components/layout/VtsLayoutSidebar.vue +1 -2
- package/lib/components/menu/MenuItem.vue +4 -5
- package/lib/components/menu/MenuTrigger.vue +3 -3
- package/lib/components/object-icon/VtsObjectIcon.vue +2 -2
- package/lib/components/resources/VtsResource.vue +3 -3
- package/lib/components/select/VtsSelect.vue +4 -5
- package/lib/components/table/ColumnTitle.vue +11 -12
- package/lib/components/task/VtsQuickTaskButton.vue +1 -2
- package/lib/components/tree/VtsTreeLoadingItem.vue +3 -3
- package/lib/components/ui/alarm-item/UiAlarmItem.vue +1 -2
- package/lib/components/ui/alert/UiAlert.vue +14 -13
- package/lib/components/ui/button/UiButton.vue +4 -5
- package/lib/components/ui/button-icon/UiButtonIcon.vue +3 -3
- package/lib/components/ui/checkbox/UiCheckbox.vue +2 -9
- package/lib/components/ui/chip/ChipIcon.vue +3 -3
- package/lib/components/ui/chip/ChipRemoveIcon.vue +1 -2
- package/lib/components/ui/chip/UiChip.vue +2 -2
- package/lib/components/ui/circle-progress-bar/UiCircleProgressBar.vue +7 -4
- package/lib/components/ui/collapsible-list/UiCollapsibleList.vue +73 -0
- package/lib/components/ui/donut-chart/UiDonutChart.vue +30 -17
- package/lib/components/ui/dropdown/UiDropdown.vue +5 -7
- package/lib/components/ui/dropdown-button/UiDropdownButton.vue +4 -5
- package/lib/components/ui/head-bar/UiHeadBar.vue +6 -11
- package/lib/components/ui/info/UiInfo.vue +14 -20
- package/lib/components/ui/input/UiInput.vue +6 -7
- package/lib/components/ui/label/UiLabel.vue +3 -3
- package/lib/components/ui/legend/UiLegend.vue +3 -3
- package/lib/components/ui/legend-title/UiLegendTitle.vue +7 -3
- package/lib/components/ui/link/UiLink.vue +4 -5
- package/lib/components/ui/{quoteCode/UiQuoteCode.vue → log-entry-viewer/UiLogEntryViewer.vue} +58 -21
- package/lib/components/ui/object-link/UiObjectLink.vue +4 -4
- package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +3 -4
- package/lib/components/ui/quick-task-item/UiQuickTaskItem.vue +3 -4
- package/lib/components/ui/radio-button/UiRadioButton.vue +1 -2
- package/lib/components/ui/table-pagination/PaginationButton.vue +2 -25
- package/lib/components/ui/table-pagination/UiTablePagination.vue +56 -95
- package/lib/components/ui/tag/UiTag.vue +3 -3
- package/lib/components/ui/text-area/UiTextarea.vue +2 -2
- package/lib/components/ui/toaster/UiToaster.vue +15 -13
- package/lib/components/ui/tree-item-label/UiTreeItemLabel.vue +4 -5
- package/lib/composables/default-tab.composable.md +42 -0
- package/lib/composables/default-tab.composable.ts +26 -0
- package/lib/composables/link-component.composable.ts +3 -2
- package/lib/composables/pagination.composable.ts +5 -0
- package/lib/i18n.ts +4 -0
- package/lib/icons/fa-icons.ts +48 -2
- package/lib/icons/index.ts +4 -0
- package/lib/icons/legacy-icons.ts +10 -0
- package/lib/icons/object-icons.ts +1 -1
- package/lib/layouts/CoreLayout.vue +1 -2
- package/lib/locales/cs.json +29 -10
- package/lib/locales/de.json +70 -7
- package/lib/locales/en.json +25 -0
- package/lib/locales/es.json +3 -3
- package/lib/locales/fr.json +25 -0
- package/lib/locales/it.json +17 -5
- package/lib/locales/nl.json +28 -10
- package/lib/locales/pt_BR.json +67 -0
- package/lib/locales/sv.json +17 -0
- package/lib/packages/form-select/types.ts +3 -0
- package/lib/packages/form-select/use-form-option-controller.ts +5 -6
- package/lib/packages/form-select/use-form-select-controller.ts +1 -0
- package/lib/packages/form-select/use-form-select.ts +153 -109
- package/lib/packages/icon/DisplayIcon.vue +1 -0
- package/lib/packages/progress/README.md +62 -0
- package/lib/packages/progress/types.ts +19 -0
- package/lib/packages/progress/use-progress-group.ts +68 -0
- package/lib/packages/progress/use-progress.ts +22 -0
- package/lib/packages/remote-resource/README.md +115 -0
- package/lib/packages/remote-resource/define-remote-resource.ts +294 -0
- package/lib/packages/remote-resource/types.ts +28 -0
- package/lib/packages/threshold/README.md +30 -0
- package/lib/packages/threshold/type.ts +3 -0
- package/lib/packages/threshold/use-threshold.ts +19 -0
- package/lib/types/object-icon.type.ts +0 -40
- package/package.json +2 -2
- package/lib/components/icon/NewVtsIcon.vue +0 -49
- package/lib/components/ui/complex-icon/UiComplexIcon.vue +0 -45
- package/lib/components/ui/object-icon/UiObjectIcon.vue +0 -251
|
@@ -7,34 +7,33 @@ import {
|
|
|
7
7
|
} from '@core/packages/collection'
|
|
8
8
|
import type { EmptyObject, MaybeArray } from '@core/types/utility.type.ts'
|
|
9
9
|
import { toArray } from '@core/utils/to-array.utils.ts'
|
|
10
|
-
import type
|
|
11
|
-
ExtractValue,
|
|
12
|
-
FormOptionCollectionItemProperties,
|
|
13
|
-
FormSelect,
|
|
14
|
-
FormSelectId,
|
|
15
|
-
GetOptionLabel,
|
|
16
|
-
GetOptionValue,
|
|
17
|
-
UseFormSelectReturn,
|
|
18
|
-
} from './types.ts'
|
|
19
|
-
import { computed, type ComputedRef, type MaybeRefOrGetter, provide, ref, type Ref, toValue, watch } from 'vue'
|
|
10
|
+
import { computed, type ComputedRef, type MaybeRefOrGetter, provide, ref, type Ref, toRaw, toValue, watch } from 'vue'
|
|
20
11
|
import { guessLabel } from './guess-label.ts'
|
|
21
12
|
import { guessValue } from './guess-value.ts'
|
|
22
13
|
import { normalizeSearchTerm } from './normalize-search-term.ts'
|
|
14
|
+
import {
|
|
15
|
+
EMPTY_OPTION,
|
|
16
|
+
type ExtractValue,
|
|
17
|
+
type FormOptionCollectionItemProperties,
|
|
18
|
+
type FormSelect,
|
|
19
|
+
type FormSelectId,
|
|
20
|
+
type GetOptionLabel,
|
|
21
|
+
type GetOptionValue,
|
|
22
|
+
type UseFormSelectReturn,
|
|
23
|
+
} from './types.ts'
|
|
23
24
|
|
|
24
25
|
// Overload #1: Source is CollectionItemId
|
|
25
26
|
|
|
26
27
|
export function useFormSelect<
|
|
27
|
-
|
|
28
|
-
TAllowEmpty extends boolean = false,
|
|
28
|
+
TSource extends CollectionItemId,
|
|
29
29
|
TCustomProperties extends CollectionItemProperties = EmptyObject,
|
|
30
|
-
TGetValue extends GetOptionValue
|
|
30
|
+
TGetValue extends GetOptionValue<TSource, TCustomProperties> = undefined,
|
|
31
31
|
TMultiple extends boolean = false,
|
|
32
|
-
|
|
33
|
-
$TValue = ExtractValue
|
|
32
|
+
TEmptyValue = never,
|
|
33
|
+
$TValue = ExtractValue<TSource, TGetValue>,
|
|
34
34
|
>(
|
|
35
|
-
sources: MaybeRefOrGetter<
|
|
35
|
+
sources: MaybeRefOrGetter<TSource[]>,
|
|
36
36
|
config?: {
|
|
37
|
-
allowEmpty?: MaybeRefOrGetter<TAllowEmpty>
|
|
38
37
|
multiple?: MaybeRefOrGetter<TMultiple>
|
|
39
38
|
model?: Ref<unknown>
|
|
40
39
|
disabled?: MaybeRefOrGetter<boolean>
|
|
@@ -44,32 +43,36 @@ export function useFormSelect<
|
|
|
44
43
|
loading?: MaybeRefOrGetter<boolean>
|
|
45
44
|
required?: MaybeRefOrGetter<boolean>
|
|
46
45
|
searchable?: MaybeRefOrGetter<boolean>
|
|
46
|
+
emptyOption?: MaybeRefOrGetter<{
|
|
47
|
+
value: TEmptyValue
|
|
48
|
+
properties?: TCustomProperties
|
|
49
|
+
label: string
|
|
50
|
+
selectedLabel?: string
|
|
51
|
+
}>
|
|
47
52
|
option?: {
|
|
48
|
-
id?: GetItemId<
|
|
49
|
-
value?: TGetValue | ((source:
|
|
50
|
-
properties?: (source:
|
|
51
|
-
label?: GetOptionLabel
|
|
52
|
-
selectedLabel?: (source:
|
|
53
|
-
disabled?: (source:
|
|
54
|
-
searchableTerm?: (source:
|
|
53
|
+
id?: GetItemId<TSource>
|
|
54
|
+
value?: TGetValue | ((source: TSource, properties: TCustomProperties) => $TValue)
|
|
55
|
+
properties?: (source: TSource) => TCustomProperties
|
|
56
|
+
label?: GetOptionLabel<TSource, TCustomProperties>
|
|
57
|
+
selectedLabel?: (source: TSource, properties: TCustomProperties) => string
|
|
58
|
+
disabled?: (source: TSource, properties: TCustomProperties) => boolean
|
|
59
|
+
searchableTerm?: (source: TSource, properties: TCustomProperties) => MaybeArray<string>
|
|
55
60
|
}
|
|
56
61
|
}
|
|
57
|
-
): UseFormSelectReturn<TCustomProperties,
|
|
62
|
+
): UseFormSelectReturn<TCustomProperties, TSource, $TValue | TEmptyValue, TMultiple>
|
|
58
63
|
|
|
59
64
|
// Overload #2: Source is an object with id and label
|
|
60
65
|
|
|
61
66
|
export function useFormSelect<
|
|
62
|
-
|
|
63
|
-
TAllowEmpty extends boolean = false,
|
|
67
|
+
TSource extends { id: CollectionItemId; label: string },
|
|
64
68
|
TCustomProperties extends CollectionItemProperties = EmptyObject,
|
|
65
|
-
TGetValue extends GetOptionValue
|
|
69
|
+
TGetValue extends GetOptionValue<TSource, TCustomProperties> = undefined,
|
|
66
70
|
TMultiple extends boolean = false,
|
|
67
|
-
|
|
68
|
-
$TValue = ExtractValue
|
|
71
|
+
TEmptyValue = never,
|
|
72
|
+
$TValue = ExtractValue<TSource, TGetValue>,
|
|
69
73
|
>(
|
|
70
|
-
sources: MaybeRefOrGetter<
|
|
74
|
+
sources: MaybeRefOrGetter<TSource[]>,
|
|
71
75
|
config?: {
|
|
72
|
-
allowEmpty?: MaybeRefOrGetter<TAllowEmpty>
|
|
73
76
|
multiple?: MaybeRefOrGetter<TMultiple>
|
|
74
77
|
model?: Ref<unknown>
|
|
75
78
|
disabled?: MaybeRefOrGetter<boolean>
|
|
@@ -79,32 +82,36 @@ export function useFormSelect<
|
|
|
79
82
|
loading?: MaybeRefOrGetter<boolean>
|
|
80
83
|
required?: MaybeRefOrGetter<boolean>
|
|
81
84
|
searchable?: MaybeRefOrGetter<boolean>
|
|
85
|
+
emptyOption?: MaybeRefOrGetter<{
|
|
86
|
+
value: TEmptyValue
|
|
87
|
+
properties?: TCustomProperties
|
|
88
|
+
label: string
|
|
89
|
+
selectedLabel?: string
|
|
90
|
+
}>
|
|
82
91
|
option?: {
|
|
83
|
-
id?: GetItemId<
|
|
84
|
-
value?: TGetValue | ((source:
|
|
85
|
-
properties?: (source:
|
|
86
|
-
label?: GetOptionLabel
|
|
87
|
-
selectedLabel?: (source:
|
|
88
|
-
disabled?: (source:
|
|
89
|
-
searchableTerm?: (source:
|
|
92
|
+
id?: GetItemId<TSource>
|
|
93
|
+
value?: TGetValue | ((source: TSource, properties: TCustomProperties) => $TValue)
|
|
94
|
+
properties?: (source: TSource) => TCustomProperties
|
|
95
|
+
label?: GetOptionLabel<TSource, TCustomProperties>
|
|
96
|
+
selectedLabel?: (source: TSource, properties: TCustomProperties) => string
|
|
97
|
+
disabled?: (source: TSource, properties: TCustomProperties) => boolean
|
|
98
|
+
searchableTerm?: (source: TSource, properties: TCustomProperties) => MaybeArray<string>
|
|
90
99
|
}
|
|
91
100
|
}
|
|
92
|
-
): UseFormSelectReturn<TCustomProperties,
|
|
101
|
+
): UseFormSelectReturn<TCustomProperties, TSource, $TValue | TEmptyValue, TMultiple>
|
|
93
102
|
|
|
94
103
|
// Overload #3: Source is an object with id only
|
|
95
104
|
|
|
96
105
|
export function useFormSelect<
|
|
97
|
-
|
|
98
|
-
TAllowEmpty extends boolean = false,
|
|
106
|
+
TSource extends { id: CollectionItemId },
|
|
99
107
|
TCustomProperties extends CollectionItemProperties = EmptyObject,
|
|
100
|
-
TGetValue extends GetOptionValue
|
|
108
|
+
TGetValue extends GetOptionValue<TSource, TCustomProperties> = undefined,
|
|
101
109
|
TMultiple extends boolean = false,
|
|
102
|
-
|
|
103
|
-
$TValue = ExtractValue
|
|
110
|
+
TEmptyValue = never,
|
|
111
|
+
$TValue = ExtractValue<TSource, TGetValue>,
|
|
104
112
|
>(
|
|
105
|
-
sources: MaybeRefOrGetter<
|
|
113
|
+
sources: MaybeRefOrGetter<TSource[]>,
|
|
106
114
|
config: {
|
|
107
|
-
allowEmpty?: MaybeRefOrGetter<TAllowEmpty>
|
|
108
115
|
multiple?: MaybeRefOrGetter<TMultiple>
|
|
109
116
|
model?: Ref<unknown>
|
|
110
117
|
disabled?: MaybeRefOrGetter<boolean>
|
|
@@ -114,32 +121,36 @@ export function useFormSelect<
|
|
|
114
121
|
loading?: MaybeRefOrGetter<boolean>
|
|
115
122
|
required?: MaybeRefOrGetter<boolean>
|
|
116
123
|
searchable?: MaybeRefOrGetter<boolean>
|
|
124
|
+
emptyOption?: MaybeRefOrGetter<{
|
|
125
|
+
value: TEmptyValue
|
|
126
|
+
properties?: TCustomProperties
|
|
127
|
+
label: string
|
|
128
|
+
selectedLabel?: string
|
|
129
|
+
}>
|
|
117
130
|
option: {
|
|
118
|
-
id?: GetItemId<
|
|
119
|
-
value?: TGetValue | ((source:
|
|
120
|
-
properties?: (source:
|
|
121
|
-
label: GetOptionLabel
|
|
122
|
-
selectedLabel?: (source:
|
|
123
|
-
disabled?: (source:
|
|
124
|
-
searchableTerm?: (source:
|
|
131
|
+
id?: GetItemId<TSource>
|
|
132
|
+
value?: TGetValue | ((source: TSource, properties: TCustomProperties) => $TValue)
|
|
133
|
+
properties?: (source: TSource) => TCustomProperties
|
|
134
|
+
label: GetOptionLabel<TSource, TCustomProperties>
|
|
135
|
+
selectedLabel?: (source: TSource, properties: TCustomProperties) => string
|
|
136
|
+
disabled?: (source: TSource, properties: TCustomProperties) => boolean
|
|
137
|
+
searchableTerm?: (source: TSource, properties: TCustomProperties) => MaybeArray<string>
|
|
125
138
|
}
|
|
126
139
|
}
|
|
127
|
-
): UseFormSelectReturn<TCustomProperties,
|
|
140
|
+
): UseFormSelectReturn<TCustomProperties, TSource, $TValue | TEmptyValue, TMultiple>
|
|
128
141
|
|
|
129
142
|
// Overload #4: Source is an object with label only
|
|
130
143
|
|
|
131
144
|
export function useFormSelect<
|
|
132
|
-
|
|
133
|
-
TAllowEmpty extends boolean = false,
|
|
145
|
+
TSource extends { label: string },
|
|
134
146
|
TCustomProperties extends CollectionItemProperties = EmptyObject,
|
|
135
|
-
TGetValue extends GetOptionValue
|
|
147
|
+
TGetValue extends GetOptionValue<TSource, TCustomProperties> = undefined,
|
|
136
148
|
TMultiple extends boolean = false,
|
|
137
|
-
|
|
138
|
-
$TValue = ExtractValue
|
|
149
|
+
TEmptyValue = never,
|
|
150
|
+
$TValue = ExtractValue<TSource, TGetValue>,
|
|
139
151
|
>(
|
|
140
|
-
sources: MaybeRefOrGetter<
|
|
152
|
+
sources: MaybeRefOrGetter<TSource[]>,
|
|
141
153
|
config: {
|
|
142
|
-
allowEmpty?: MaybeRefOrGetter<TAllowEmpty>
|
|
143
154
|
multiple?: MaybeRefOrGetter<TMultiple>
|
|
144
155
|
model?: Ref<unknown>
|
|
145
156
|
disabled?: MaybeRefOrGetter<boolean>
|
|
@@ -149,32 +160,36 @@ export function useFormSelect<
|
|
|
149
160
|
loading?: MaybeRefOrGetter<boolean>
|
|
150
161
|
required?: MaybeRefOrGetter<boolean>
|
|
151
162
|
searchable?: MaybeRefOrGetter<boolean>
|
|
163
|
+
emptyOption?: MaybeRefOrGetter<{
|
|
164
|
+
value: TEmptyValue
|
|
165
|
+
properties?: TCustomProperties
|
|
166
|
+
label: string
|
|
167
|
+
selectedLabel?: string
|
|
168
|
+
}>
|
|
152
169
|
option: {
|
|
153
|
-
id: GetItemId<
|
|
154
|
-
value?: TGetValue | ((source:
|
|
155
|
-
properties?: (source:
|
|
156
|
-
label?: GetOptionLabel
|
|
157
|
-
selectedLabel?: (source:
|
|
158
|
-
disabled?: (source:
|
|
159
|
-
searchableTerm?: (source:
|
|
170
|
+
id: GetItemId<TSource>
|
|
171
|
+
value?: TGetValue | ((source: TSource, properties: TCustomProperties) => $TValue)
|
|
172
|
+
properties?: (source: TSource) => TCustomProperties
|
|
173
|
+
label?: GetOptionLabel<TSource, TCustomProperties>
|
|
174
|
+
selectedLabel?: (source: TSource, properties: TCustomProperties) => string
|
|
175
|
+
disabled?: (source: TSource, properties: TCustomProperties) => boolean
|
|
176
|
+
searchableTerm?: (source: TSource, properties: TCustomProperties) => MaybeArray<string>
|
|
160
177
|
}
|
|
161
178
|
}
|
|
162
|
-
): UseFormSelectReturn<TCustomProperties,
|
|
179
|
+
): UseFormSelectReturn<TCustomProperties, TSource, $TValue | TEmptyValue, TMultiple>
|
|
163
180
|
|
|
164
181
|
// Overload #5: Any other case
|
|
165
182
|
|
|
166
183
|
export function useFormSelect<
|
|
167
|
-
|
|
168
|
-
TAllowEmpty extends boolean = false,
|
|
184
|
+
TSource,
|
|
169
185
|
TCustomProperties extends CollectionItemProperties = EmptyObject,
|
|
170
|
-
TGetValue extends GetOptionValue
|
|
186
|
+
TGetValue extends GetOptionValue<TSource, TCustomProperties> = undefined,
|
|
171
187
|
TMultiple extends boolean = false,
|
|
172
|
-
|
|
173
|
-
$TValue = ExtractValue
|
|
188
|
+
TEmptyValue = never,
|
|
189
|
+
$TValue = ExtractValue<TSource, TGetValue>,
|
|
174
190
|
>(
|
|
175
|
-
sources: MaybeRefOrGetter<
|
|
191
|
+
sources: MaybeRefOrGetter<TSource[]>,
|
|
176
192
|
config: {
|
|
177
|
-
allowEmpty?: MaybeRefOrGetter<TAllowEmpty>
|
|
178
193
|
multiple?: MaybeRefOrGetter<TMultiple>
|
|
179
194
|
model?: Ref<unknown>
|
|
180
195
|
disabled?: MaybeRefOrGetter<boolean>
|
|
@@ -184,32 +199,36 @@ export function useFormSelect<
|
|
|
184
199
|
loading?: MaybeRefOrGetter<boolean>
|
|
185
200
|
required?: MaybeRefOrGetter<boolean>
|
|
186
201
|
searchable?: MaybeRefOrGetter<boolean>
|
|
202
|
+
emptyOption?: MaybeRefOrGetter<{
|
|
203
|
+
value: TEmptyValue
|
|
204
|
+
properties?: TCustomProperties
|
|
205
|
+
label: string
|
|
206
|
+
selectedLabel?: string
|
|
207
|
+
}>
|
|
187
208
|
option: {
|
|
188
|
-
id: GetItemId<
|
|
189
|
-
value?: TGetValue | ((source:
|
|
190
|
-
properties?: (source:
|
|
191
|
-
label: GetOptionLabel
|
|
192
|
-
selectedLabel?: (source:
|
|
193
|
-
disabled?: (source:
|
|
194
|
-
searchableTerm?: (source:
|
|
209
|
+
id: GetItemId<TSource>
|
|
210
|
+
value?: TGetValue | ((source: TSource, properties: TCustomProperties) => $TValue)
|
|
211
|
+
properties?: (source: TSource) => TCustomProperties
|
|
212
|
+
label: GetOptionLabel<TSource, TCustomProperties>
|
|
213
|
+
selectedLabel?: (source: TSource, properties: TCustomProperties) => string
|
|
214
|
+
disabled?: (source: TSource, properties: TCustomProperties) => boolean
|
|
215
|
+
searchableTerm?: (source: TSource, properties: TCustomProperties) => MaybeArray<string>
|
|
195
216
|
}
|
|
196
217
|
}
|
|
197
|
-
): UseFormSelectReturn<TCustomProperties,
|
|
218
|
+
): UseFormSelectReturn<TCustomProperties, TSource, $TValue | TEmptyValue, TMultiple>
|
|
198
219
|
|
|
199
220
|
// Implementation
|
|
200
221
|
|
|
201
222
|
export function useFormSelect<
|
|
202
|
-
|
|
203
|
-
TAllowEmpty extends boolean = false,
|
|
223
|
+
TSource,
|
|
204
224
|
TCustomProperties extends CollectionItemProperties = EmptyObject,
|
|
205
|
-
TGetValue extends GetOptionValue
|
|
225
|
+
TGetValue extends GetOptionValue<TSource, TCustomProperties> = undefined,
|
|
206
226
|
TMultiple extends boolean = false,
|
|
207
|
-
|
|
208
|
-
$TValue = ExtractValue
|
|
227
|
+
TEmptyValue = never,
|
|
228
|
+
$TValue = ExtractValue<TSource, TGetValue>,
|
|
209
229
|
>(
|
|
210
|
-
baseSources: MaybeRefOrGetter<
|
|
230
|
+
baseSources: MaybeRefOrGetter<TSource[]>,
|
|
211
231
|
config?: {
|
|
212
|
-
allowEmpty?: MaybeRefOrGetter<boolean>
|
|
213
232
|
multiple?: MaybeRefOrGetter<boolean>
|
|
214
233
|
model?: Ref<unknown>
|
|
215
234
|
disabled?: MaybeRefOrGetter<boolean>
|
|
@@ -219,17 +238,23 @@ export function useFormSelect<
|
|
|
219
238
|
loading?: MaybeRefOrGetter<boolean>
|
|
220
239
|
required?: MaybeRefOrGetter<boolean>
|
|
221
240
|
searchable?: MaybeRefOrGetter<boolean>
|
|
241
|
+
emptyOption?: MaybeRefOrGetter<{
|
|
242
|
+
value: TEmptyValue
|
|
243
|
+
properties?: TCustomProperties
|
|
244
|
+
label: string
|
|
245
|
+
selectedLabel?: string
|
|
246
|
+
}>
|
|
222
247
|
option?: {
|
|
223
|
-
id?: GetItemId<
|
|
224
|
-
value?: GetOptionValue
|
|
225
|
-
properties?: (source:
|
|
226
|
-
label?: GetOptionLabel
|
|
227
|
-
selectedLabel?: (source:
|
|
228
|
-
disabled?: (source:
|
|
229
|
-
searchableTerm?: (source:
|
|
248
|
+
id?: GetItemId<TSource>
|
|
249
|
+
value?: GetOptionValue<TSource, TCustomProperties>
|
|
250
|
+
properties?: (source: TSource) => TCustomProperties
|
|
251
|
+
label?: GetOptionLabel<TSource, TCustomProperties>
|
|
252
|
+
selectedLabel?: (source: TSource, properties: TCustomProperties) => string
|
|
253
|
+
disabled?: (source: TSource, properties: TCustomProperties) => boolean
|
|
254
|
+
searchableTerm?: (source: TSource, properties: TCustomProperties) => MaybeArray<string>
|
|
230
255
|
}
|
|
231
256
|
}
|
|
232
|
-
): UseFormSelectReturn<TCustomProperties,
|
|
257
|
+
): UseFormSelectReturn<TCustomProperties, TSource, $TValue | TEmptyValue, TMultiple> {
|
|
233
258
|
const searchTerm = ref('')
|
|
234
259
|
|
|
235
260
|
const normalizedSearchTerm = computed(() => normalizeSearchTerm(searchTerm))
|
|
@@ -249,8 +274,8 @@ export function useFormSelect<
|
|
|
249
274
|
const isSearchable = computed(() => toValue(config?.searchable) ?? false)
|
|
250
275
|
|
|
251
276
|
const sources = computed(() =>
|
|
252
|
-
config?.
|
|
253
|
-
) as ComputedRef
|
|
277
|
+
config?.emptyOption !== undefined ? [EMPTY_OPTION, ...toValue(baseSources)] : toValue(baseSources)
|
|
278
|
+
) as ComputedRef<(TSource | typeof EMPTY_OPTION)[]>
|
|
254
279
|
|
|
255
280
|
const {
|
|
256
281
|
items: allOptions,
|
|
@@ -258,12 +283,25 @@ export function useFormSelect<
|
|
|
258
283
|
useFlag,
|
|
259
284
|
} = useCollection(sources, {
|
|
260
285
|
itemId: source =>
|
|
261
|
-
source ===
|
|
286
|
+
source === EMPTY_OPTION ? '__EMPTY_OPTION__' : guessItemId(source as TSource, config?.option?.id),
|
|
262
287
|
flags: {
|
|
263
288
|
active: { multiple: false },
|
|
264
289
|
selected: { multiple: isMultiple },
|
|
265
290
|
},
|
|
266
291
|
properties: (source): FormOptionCollectionItemProperties<TCustomProperties, $TValue> => {
|
|
292
|
+
if (source === EMPTY_OPTION) {
|
|
293
|
+
const emptyOption = toValue(config?.emptyOption)
|
|
294
|
+
|
|
295
|
+
return {
|
|
296
|
+
value: computed(() => emptyOption?.value as $TValue),
|
|
297
|
+
label: computed(() => emptyOption?.label ?? ''),
|
|
298
|
+
selectedLabel: computed(() => emptyOption?.selectedLabel),
|
|
299
|
+
matching: computed(() => normalizedSearchTerm.value === ''),
|
|
300
|
+
disabled: computed(() => false),
|
|
301
|
+
...(emptyOption?.properties ?? ({} as TCustomProperties)),
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
267
305
|
const customProperties = config?.option?.properties?.(source) ?? ({} as TCustomProperties)
|
|
268
306
|
const label = computed(() => guessLabel(source, customProperties, config?.option?.label))
|
|
269
307
|
const value = computed(() => guessValue(source, customProperties, config?.option?.value) as $TValue)
|
|
@@ -296,7 +334,7 @@ export function useFormSelect<
|
|
|
296
334
|
|
|
297
335
|
const { items: options } = useSubset(option => option.properties.matching)
|
|
298
336
|
|
|
299
|
-
const { items: selectedOptions } = useFlag('selected')
|
|
337
|
+
const { items: selectedOptions, toggleAll: toggleSelectAll } = useFlag('selected')
|
|
300
338
|
|
|
301
339
|
const selectedOption = computed(() => selectedOptions.value[0])
|
|
302
340
|
|
|
@@ -318,12 +356,18 @@ export function useFormSelect<
|
|
|
318
356
|
watch(
|
|
319
357
|
model,
|
|
320
358
|
modelValue => {
|
|
359
|
+
toggleSelectAll(false)
|
|
360
|
+
|
|
321
361
|
if (isMultiple.value) {
|
|
322
362
|
allOptions.value.forEach(option => {
|
|
323
|
-
|
|
363
|
+
if ((modelValue as $TValue[]).includes(toRaw(option.properties.value) as $TValue)) {
|
|
364
|
+
option.toggleFlag('selected', true)
|
|
365
|
+
}
|
|
324
366
|
})
|
|
325
367
|
} else {
|
|
326
|
-
allOptions.value
|
|
368
|
+
allOptions.value
|
|
369
|
+
.find(option => toRaw(option.properties.value) === toRaw(modelValue))
|
|
370
|
+
?.toggleFlag('selected', true)
|
|
327
371
|
}
|
|
328
372
|
},
|
|
329
373
|
{ immediate: true }
|
|
@@ -358,14 +402,14 @@ export function useFormSelect<
|
|
|
358
402
|
selectedOption,
|
|
359
403
|
selectedOptions,
|
|
360
404
|
selectedLabel,
|
|
361
|
-
} satisfies FormSelect<TCustomProperties, any> as FormSelect<TCustomProperties,
|
|
405
|
+
} satisfies FormSelect<TCustomProperties, any> as FormSelect<TCustomProperties, TSource, $TValue, TMultiple>
|
|
362
406
|
|
|
363
|
-
const id = Symbol('useFormSelect ID') as FormSelectId<TCustomProperties,
|
|
407
|
+
const id = Symbol('useFormSelect ID') as FormSelectId<TCustomProperties, TSource, $TValue, TMultiple>
|
|
364
408
|
|
|
365
409
|
provide(id, select)
|
|
366
410
|
|
|
367
411
|
return {
|
|
368
412
|
id,
|
|
369
413
|
...select,
|
|
370
|
-
} satisfies UseFormSelectReturn<TCustomProperties,
|
|
414
|
+
} satisfies UseFormSelectReturn<TCustomProperties, TSource, $TValue, TMultiple>
|
|
371
415
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# `useProgress` / `useProgressGroup`
|
|
2
|
+
|
|
3
|
+
## `useProgress`
|
|
4
|
+
|
|
5
|
+
### Arguments
|
|
6
|
+
|
|
7
|
+
| Argument | Type | Required | Description |
|
|
8
|
+
| --------- | -------------------------- | :------: | ------------------ |
|
|
9
|
+
| `current` | `MaybeRefOrGetter<number>` | ✓ | The current value. |
|
|
10
|
+
| `total` | `MaybeRefOrGetter<number>` | ✓ | The total value. |
|
|
11
|
+
|
|
12
|
+
### Returns
|
|
13
|
+
|
|
14
|
+
| Property | Type | Description |
|
|
15
|
+
| --------------- | ------------------------- | ---------------------------------------------------------- |
|
|
16
|
+
| `current` | `ComputedRef<number>` | The normalized `current` input |
|
|
17
|
+
| `total` | `ComputedRef<number>` | The normalized `total` input |
|
|
18
|
+
| `fillWidth` | `ComputedRef<${number}%>` | The width of the progress bar to be filled (e.g. `"35%"`). |
|
|
19
|
+
| `percentage` | `ComputedRef<number>` | The percentage between `current` and `total`. |
|
|
20
|
+
| `percentageCap` | `number` | The percentage cap of the progress bar. (see below) |
|
|
21
|
+
|
|
22
|
+
`percentageCap` is the `percentage` rounded up to the nearest hundred.
|
|
23
|
+
|
|
24
|
+
For example, if `current` is `15` and `total` is `10`, then `percentage` will be `150` and `percentageCap` will be `200`.
|
|
25
|
+
|
|
26
|
+
`fillWidth` is the percentage of the progress bar to be filled.
|
|
27
|
+
|
|
28
|
+
In the example above, `fillWidth` will be `"75%"` (`150` / `200` = `0.75`).
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
const { fillWidth, percentage, percentageCap } = useProgress(current, total)
|
|
32
|
+
|
|
33
|
+
// current = 15; total = 60
|
|
34
|
+
// → percentage = 25
|
|
35
|
+
// → percentageCap = 100
|
|
36
|
+
// → fillWidth = '25%'
|
|
37
|
+
|
|
38
|
+
// current = 90; total = 60
|
|
39
|
+
// → percentage = 150
|
|
40
|
+
// → percentageCap = 200
|
|
41
|
+
// → fillWidth = '75%'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## `useProgressGroup`
|
|
45
|
+
|
|
46
|
+
This composable will allow handling multiple progress bars and normalize their fill width across all of them.
|
|
47
|
+
|
|
48
|
+
### Arguments
|
|
49
|
+
|
|
50
|
+
| Argument | Type | Required | Description |
|
|
51
|
+
| --------- | --------------------------------------------------- | :------: | ------------------------------------------------------------------------------------------------------------------------ |
|
|
52
|
+
| `sources` | `MaybeRefOrGetter<T[]>` | ✓ | The sources array |
|
|
53
|
+
| `fn` | `(source: T) => { current: number; total: number }` | ~ | Returns `current` and `total` for each `source`. If `source` already has these properties, this argument can be omitted. |
|
|
54
|
+
| `options` | `{ sort?: 'asc' \| 'desc' } | | Whether to sort the progress items |
|
|
55
|
+
|
|
56
|
+
### Returns
|
|
57
|
+
|
|
58
|
+
| Property | Type | Description |
|
|
59
|
+
| ---------------------- | --------------------------------------------------------- | ----------------------------------------------------- |
|
|
60
|
+
| `progressItems` | `ComputedRef<Reactive<Progress & { source: TSource }>[]>` | The normalized progress items. |
|
|
61
|
+
| `highestPercentage` | `ComputedRef<number>` | The highest `percentage` among all progress items. |
|
|
62
|
+
| `highestPercentageCap` | `ComputedRef<number>` | The highest `percentageCap` among all progress items. |
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ComputedRef, MaybeRefOrGetter, Reactive } from 'vue'
|
|
2
|
+
|
|
3
|
+
export type Progress = {
|
|
4
|
+
current: ComputedRef<number>
|
|
5
|
+
total: ComputedRef<number>
|
|
6
|
+
percentage: ComputedRef<number>
|
|
7
|
+
fillWidth: ComputedRef<string>
|
|
8
|
+
percentageCap: ComputedRef<number>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type ProgressGroup<TSource> = {
|
|
12
|
+
progressItems: ComputedRef<Reactive<Progress & { source: TSource }>[]>
|
|
13
|
+
highestPercentage: ComputedRef<number>
|
|
14
|
+
highestPercentageCap: ComputedRef<number>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type UseProgressGroupOptions = {
|
|
18
|
+
sort?: MaybeRefOrGetter<'asc' | 'desc' | undefined>
|
|
19
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ProgressGroup, UseProgressGroupOptions } from './types.ts'
|
|
2
|
+
import { useArrayMap } from '@vueuse/shared'
|
|
3
|
+
import { computed, markRaw, type MaybeRefOrGetter, reactive, toValue } from 'vue'
|
|
4
|
+
import { useProgress } from './use-progress.ts'
|
|
5
|
+
|
|
6
|
+
export function useProgressGroup<TSource extends { current: number; total: number }>(
|
|
7
|
+
rawSources: MaybeRefOrGetter<TSource[]>,
|
|
8
|
+
options?: UseProgressGroupOptions
|
|
9
|
+
): ProgressGroup<TSource>
|
|
10
|
+
|
|
11
|
+
export function useProgressGroup<TSource>(
|
|
12
|
+
rawSources: MaybeRefOrGetter<TSource[]>,
|
|
13
|
+
fn: (item: TSource) => { current: number; total: number },
|
|
14
|
+
options?: UseProgressGroupOptions
|
|
15
|
+
): ProgressGroup<TSource>
|
|
16
|
+
|
|
17
|
+
export function useProgressGroup<TSource>(
|
|
18
|
+
rawSources: MaybeRefOrGetter<TSource[]>,
|
|
19
|
+
fnOrOptions?: UseProgressGroupOptions | ((item: TSource) => { current: number; total: number }),
|
|
20
|
+
optionsOrNone?: UseProgressGroupOptions
|
|
21
|
+
): ProgressGroup<TSource> {
|
|
22
|
+
const fn =
|
|
23
|
+
typeof fnOrOptions === 'function' ? fnOrOptions : (item: TSource) => item as { current: number; total: number }
|
|
24
|
+
const options = typeof fnOrOptions === 'function' ? optionsOrNone : fnOrOptions
|
|
25
|
+
|
|
26
|
+
const progressItems = useArrayMap(rawSources, source => {
|
|
27
|
+
const { current, total } = fn(source)
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
source: typeof source === 'object' && source !== null ? markRaw(source) : source,
|
|
31
|
+
...useProgress(current, total),
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const highestPercentage = computed(() =>
|
|
36
|
+
progressItems.value.reduce((highestPercentage, item) => Math.max(highestPercentage, item.percentage.value), 0)
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
const highestPercentageCap = computed(() =>
|
|
40
|
+
progressItems.value.reduce((highestCap, item) => Math.max(highestCap, item.percentageCap.value), 0)
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
const normalizedProgressItems = useArrayMap(progressItems, item => {
|
|
44
|
+
const fillWidth = computed(() => `${(item.percentage.value / highestPercentageCap.value) * 100}%`)
|
|
45
|
+
|
|
46
|
+
return reactive({
|
|
47
|
+
...item,
|
|
48
|
+
fillWidth,
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const sortedProgressItems = computed(() => {
|
|
53
|
+
switch (toValue(options?.sort)) {
|
|
54
|
+
case 'asc':
|
|
55
|
+
return [...normalizedProgressItems.value].sort((a, b) => a.percentage - b.percentage)
|
|
56
|
+
case 'desc':
|
|
57
|
+
return [...normalizedProgressItems.value].sort((a, b) => b.percentage - a.percentage)
|
|
58
|
+
default:
|
|
59
|
+
return normalizedProgressItems.value
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
progressItems: sortedProgressItems,
|
|
65
|
+
highestPercentage,
|
|
66
|
+
highestPercentageCap,
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Progress } from './types.ts'
|
|
2
|
+
import { computed, type MaybeRefOrGetter, toValue } from 'vue'
|
|
3
|
+
|
|
4
|
+
export function useProgress(rawCurrent: MaybeRefOrGetter<number>, rawTotal: MaybeRefOrGetter<number>): Progress {
|
|
5
|
+
const current = computed(() => toValue(rawCurrent))
|
|
6
|
+
|
|
7
|
+
const total = computed(() => toValue(rawTotal))
|
|
8
|
+
|
|
9
|
+
const percentage = computed(() => (total.value === 0 ? 0 : (current.value / total.value) * 100))
|
|
10
|
+
|
|
11
|
+
const percentageCap = computed(() => Math.max(100, Math.ceil(percentage.value / 100) * 100))
|
|
12
|
+
|
|
13
|
+
const fillWidth = computed(() => `${(percentage.value / percentageCap.value) * 100}%`)
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
current,
|
|
17
|
+
total,
|
|
18
|
+
percentage,
|
|
19
|
+
fillWidth,
|
|
20
|
+
percentageCap,
|
|
21
|
+
}
|
|
22
|
+
}
|