@fastkit/vui 0.7.50 → 0.7.55
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/tool/index.js +1 -0
- package/dist/tool/vite-plugin.d.ts.map +1 -1
- package/dist/vui.cjs.js +160 -32
- package/dist/vui.cjs.prod.js +160 -32
- package/dist/vui.css +11 -0
- package/dist/vui.d.ts +376 -88
- package/dist/vui.min.css +1 -1
- package/dist/vui.min.css.map +1 -1
- package/dist/vui.mjs +160 -34
- package/package.json +7 -7
- package/src/components/.DS_Store +0 -0
- package/src/components/VButton/VButton.tsx +0 -1
- package/src/components/VControlField/VControlField.tsx +23 -6
- package/src/components/VDataTable/VDataTable.tsx +5 -5
- package/src/components/VFormControl/VFormControl.tsx +6 -1
- package/src/components/VNumberField/VNumberField.tsx +55 -0
- package/src/components/VNumberField/index.ts +1 -0
- package/src/components/VSelect/VSelect.tsx +67 -15
- package/src/components/VTextField/.DS_Store +0 -0
- package/src/components/VTextField/VTextField.tsx +6 -0
- package/src/components/VTextarea/VTextarea.tsx +1 -0
- package/src/components/VWysiwygEditor/VWysiwygEditor.tsx +1 -1
- package/src/components/index.ts +1 -0
- package/src/composables/control.ts +1 -0
- package/src/composables/form-selector.scss +13 -0
- package/src/composables/form-selector.tsx +48 -1
- package/src/schemes/control.ts +6 -0
- package/src/service.tsx +6 -2
- package/src/tool/vite-plugin.ts +1 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import './VSelect.scss';
|
|
2
|
-
import { ref, VNodeChild, defineComponent } from 'vue';
|
|
2
|
+
import { ref, VNodeChild, defineComponent, PropType, computed } from 'vue';
|
|
3
3
|
import {
|
|
4
4
|
createFormSelectorSettings,
|
|
5
5
|
useFormSelectorControl,
|
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
FormControlSlots,
|
|
9
9
|
FormSelectorItemControl,
|
|
10
10
|
createPropsOptions,
|
|
11
|
+
VNodeChildOrSlot,
|
|
12
|
+
resolveVNodeChildOrSlots,
|
|
11
13
|
} from '@fastkit/vue-kit';
|
|
12
14
|
import { VFormControl } from '../VFormControl';
|
|
13
15
|
import {
|
|
@@ -40,6 +42,8 @@ export const VSelect = defineComponent({
|
|
|
40
42
|
...defineSlotsProps<FormControlSlots & InputBoxSlots>(),
|
|
41
43
|
...createPropsOptions({
|
|
42
44
|
placeholder: String,
|
|
45
|
+
loadingMessage: {} as PropType<VNodeChildOrSlot>,
|
|
46
|
+
failedToLoadItemsMessage: {} as PropType<VNodeChildOrSlot>,
|
|
43
47
|
}),
|
|
44
48
|
},
|
|
45
49
|
emits,
|
|
@@ -62,6 +66,22 @@ export const VSelect = defineComponent({
|
|
|
62
66
|
const vui = useVui();
|
|
63
67
|
const iconName = vui.icon('menuDown');
|
|
64
68
|
const fieldRef = ref<HTMLElement | null>(null);
|
|
69
|
+
const loadingMessageRef = computed(() => {
|
|
70
|
+
const slot = resolveVNodeChildOrSlots(
|
|
71
|
+
props.loadingMessage,
|
|
72
|
+
vui.setting('loadingMessage'),
|
|
73
|
+
'Loading...',
|
|
74
|
+
);
|
|
75
|
+
return slot && slot(vui);
|
|
76
|
+
});
|
|
77
|
+
const failedToLoadItemsMessageRef = computed(() => {
|
|
78
|
+
const slot = resolveVNodeChildOrSlots(
|
|
79
|
+
props.failedToLoadItemsMessage,
|
|
80
|
+
vui.setting('failedToLoadDataMessage'),
|
|
81
|
+
'Failed to load data.',
|
|
82
|
+
);
|
|
83
|
+
return slot && slot(vui);
|
|
84
|
+
});
|
|
65
85
|
|
|
66
86
|
const focus = (opts?: FocusOptions): void => {
|
|
67
87
|
fieldRef.value && fieldRef.value.focus(opts);
|
|
@@ -69,7 +89,17 @@ export const VSelect = defineComponent({
|
|
|
69
89
|
|
|
70
90
|
const renderSelections = (selectedItems: FormSelectorItemControl[]) => {
|
|
71
91
|
const children: VNodeChild[] = [];
|
|
72
|
-
if (
|
|
92
|
+
if (inputControl.itemsLoadFailed) {
|
|
93
|
+
children.push(
|
|
94
|
+
<span class="v-select__placeholder">
|
|
95
|
+
{failedToLoadItemsMessageRef.value}
|
|
96
|
+
</span>,
|
|
97
|
+
);
|
|
98
|
+
} else if (inputControl.itemsLoading) {
|
|
99
|
+
children.push(
|
|
100
|
+
<span class="v-select__placeholder">{loadingMessageRef.value}</span>,
|
|
101
|
+
);
|
|
102
|
+
} else if (selectedItems.length) {
|
|
73
103
|
selectedItems.forEach((item, index) => {
|
|
74
104
|
if (index > 0) {
|
|
75
105
|
children.push(vui.selectionSeparator());
|
|
@@ -136,9 +166,12 @@ export const VSelect = defineComponent({
|
|
|
136
166
|
<VControlField
|
|
137
167
|
class="v-select__input"
|
|
138
168
|
ref={this.fieldRef()}
|
|
169
|
+
loading={selectorControl.itemsLoading}
|
|
170
|
+
error={selectorControl.itemsLoadFailed}
|
|
139
171
|
startAdornment={this.startAdornment}
|
|
140
172
|
endAdornment={this.endAdornment}
|
|
141
173
|
// tabindex={this.computedTabindex}
|
|
174
|
+
size={this.size}
|
|
142
175
|
focused={this.menuOpened}
|
|
143
176
|
onClick={(ev) => {
|
|
144
177
|
if (this.canOperation && !control.isActive) {
|
|
@@ -185,24 +218,43 @@ export const VSelect = defineComponent({
|
|
|
185
218
|
</div>
|
|
186
219
|
</div>,
|
|
187
220
|
],
|
|
188
|
-
endAdornment: () =>
|
|
189
|
-
(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
ev
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
221
|
+
endAdornment: () => {
|
|
222
|
+
if (selectorControl.itemsLoadFailed) {
|
|
223
|
+
return (
|
|
224
|
+
<VButton
|
|
225
|
+
key="reload"
|
|
226
|
+
icon={this.$vui.icon('reload')}
|
|
227
|
+
rounded
|
|
228
|
+
onClick={(ev) => {
|
|
229
|
+
ev.stopPropagation();
|
|
230
|
+
selectorControl.loadItems();
|
|
231
|
+
}}
|
|
232
|
+
/>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (this.clearable && this.nodeControl.value != null) {
|
|
237
|
+
return (
|
|
238
|
+
<VButton
|
|
239
|
+
key="clear"
|
|
240
|
+
icon={this.$vui.icon('clear')}
|
|
241
|
+
rounded
|
|
242
|
+
onClick={(ev) => {
|
|
243
|
+
ev.stopPropagation();
|
|
244
|
+
this.nodeControl.clear();
|
|
245
|
+
}}
|
|
246
|
+
/>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return (
|
|
200
251
|
<VIcon
|
|
201
252
|
key="icon"
|
|
202
253
|
name={this.iconName}
|
|
203
254
|
rotate={this.menuOpened ? 180 : 0}
|
|
204
255
|
/>
|
|
205
|
-
)
|
|
256
|
+
);
|
|
257
|
+
},
|
|
206
258
|
}}
|
|
207
259
|
/>,
|
|
208
260
|
],
|
|
Binary file
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
createFormControlProps,
|
|
7
7
|
FormControlSlots,
|
|
8
8
|
defineSlotsProps,
|
|
9
|
+
TextInputEmits,
|
|
9
10
|
} from '@fastkit/vue-kit';
|
|
10
11
|
import { VFormControl } from '../VFormControl';
|
|
11
12
|
import {
|
|
@@ -36,6 +37,10 @@ function createTextFieldProps() {
|
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
export type TextFieldPropsOptions = ReturnType<typeof createTextFieldProps>;
|
|
41
|
+
|
|
42
|
+
export type TextFieldEmits = TextInputEmits;
|
|
43
|
+
|
|
39
44
|
export type TextFieldInput = ExtractPropInput<
|
|
40
45
|
ReturnType<typeof createTextFieldProps>
|
|
41
46
|
>;
|
|
@@ -77,6 +82,7 @@ export const VTextField = defineComponent({
|
|
|
77
82
|
class="v-text-field__input"
|
|
78
83
|
startAdornment={this.startAdornment}
|
|
79
84
|
endAdornment={this.endAdornment}
|
|
85
|
+
size={this.size}
|
|
80
86
|
v-slots={{
|
|
81
87
|
...this.$slots,
|
|
82
88
|
default: () =>
|
|
@@ -120,7 +120,6 @@ export const VWysiwygEditor = defineComponent({
|
|
|
120
120
|
onUpdate: (ev) => {
|
|
121
121
|
inputControl.value = ev.editor.getHTML();
|
|
122
122
|
textRef.value = ev.editor.getText();
|
|
123
|
-
console.log(textRef.value);
|
|
124
123
|
},
|
|
125
124
|
autofocus: props.autofocus,
|
|
126
125
|
content: props.modelValue,
|
|
@@ -256,6 +255,7 @@ export const VWysiwygEditor = defineComponent({
|
|
|
256
255
|
autoHeight
|
|
257
256
|
startAdornment={this.startAdornment}
|
|
258
257
|
endAdornment={this.endAdornment}
|
|
258
|
+
size={this.size}
|
|
259
259
|
// onClickHost={(ev) => {
|
|
260
260
|
// this.focus();
|
|
261
261
|
// }}
|
package/src/components/index.ts
CHANGED
|
@@ -3,6 +3,19 @@
|
|
|
3
3
|
display: block;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
+
&__placeholder {
|
|
7
|
+
display: flex;
|
|
8
|
+
align-items: center;
|
|
9
|
+
margin-top: 8px;
|
|
10
|
+
font-style: italic;
|
|
11
|
+
opacity: 0.5;
|
|
12
|
+
|
|
13
|
+
&--error {
|
|
14
|
+
color: var(--main-color);
|
|
15
|
+
opacity: 1;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
6
19
|
&--stacked &__body {
|
|
7
20
|
display: flex;
|
|
8
21
|
flex-direction: column;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import './form-selector.scss';
|
|
2
|
-
import { VNodeChild, defineComponent } from 'vue';
|
|
2
|
+
import { VNodeChild, defineComponent, PropType, computed } from 'vue';
|
|
3
3
|
import {
|
|
4
4
|
defineSlotsProps,
|
|
5
5
|
TypedSlot,
|
|
@@ -11,9 +11,14 @@ import {
|
|
|
11
11
|
ResolvedFormSelectorItemData,
|
|
12
12
|
FormNodeControl,
|
|
13
13
|
renderSlotOrEmpty,
|
|
14
|
+
VNodeChildOrSlot,
|
|
15
|
+
resolveVNodeChildOrSlots,
|
|
14
16
|
} from '@fastkit/vue-kit';
|
|
15
17
|
import { createControlProps, useControl } from './control';
|
|
16
18
|
import { VFormControl } from '../components/VFormControl';
|
|
19
|
+
import { useVui } from '../injections';
|
|
20
|
+
import { VProgressCircular } from '../components/loading';
|
|
21
|
+
import { CONTROL_LOADING_SPINNER_SIZES } from '../schemes';
|
|
17
22
|
|
|
18
23
|
export interface DefineFormSelectorComponentOptions {
|
|
19
24
|
name: string;
|
|
@@ -51,6 +56,10 @@ export function defineFormSelectorComponent(
|
|
|
51
56
|
type: Boolean,
|
|
52
57
|
default: true,
|
|
53
58
|
},
|
|
59
|
+
// eslint-disable-next-line vue/require-prop-types
|
|
60
|
+
loadingMessage: {} as PropType<VNodeChildOrSlot>,
|
|
61
|
+
// eslint-disable-next-line vue/require-prop-types
|
|
62
|
+
failedToLoadItemsMessage: {} as PropType<VNodeChildOrSlot>,
|
|
54
63
|
...defineSlotsProps<FormControlSlots>(),
|
|
55
64
|
},
|
|
56
65
|
emits,
|
|
@@ -60,9 +69,28 @@ export function defineFormSelectorComponent(
|
|
|
60
69
|
defaultMultiple,
|
|
61
70
|
});
|
|
62
71
|
const control = useControl(props);
|
|
72
|
+
const vui = useVui();
|
|
73
|
+
const loadingMessageRef = computed(() => {
|
|
74
|
+
const slot = resolveVNodeChildOrSlots(
|
|
75
|
+
props.loadingMessage,
|
|
76
|
+
vui.setting('loadingMessage'),
|
|
77
|
+
'Loading...',
|
|
78
|
+
);
|
|
79
|
+
return slot && slot(vui);
|
|
80
|
+
});
|
|
81
|
+
const failedToLoadItemsMessageRef = computed(() => {
|
|
82
|
+
const slot = resolveVNodeChildOrSlots(
|
|
83
|
+
props.failedToLoadItemsMessage,
|
|
84
|
+
vui.setting('failedToLoadDataMessage'),
|
|
85
|
+
'Failed to load data.',
|
|
86
|
+
);
|
|
87
|
+
return slot && slot(vui);
|
|
88
|
+
});
|
|
63
89
|
return {
|
|
64
90
|
...selectorControl.expose(),
|
|
65
91
|
...control,
|
|
92
|
+
loadingMessageRef,
|
|
93
|
+
failedToLoadItemsMessageRef,
|
|
66
94
|
};
|
|
67
95
|
},
|
|
68
96
|
render() {
|
|
@@ -84,10 +112,29 @@ export function defineFormSelectorComponent(
|
|
|
84
112
|
hint={this.hint}
|
|
85
113
|
hinttip={this.hinttip}
|
|
86
114
|
requiredChip={this.requiredChip}
|
|
115
|
+
error={selectorControl.itemsLoadFailed}
|
|
87
116
|
v-slots={{
|
|
88
117
|
...this.$slots,
|
|
89
118
|
default: () => (
|
|
90
119
|
<div class="v-form-selector__body">
|
|
120
|
+
{selectorControl.itemsLoadFailed && (
|
|
121
|
+
<div
|
|
122
|
+
key="failed"
|
|
123
|
+
class="v-form-selector__placeholder v-form-selector__placeholder--error">
|
|
124
|
+
{this.failedToLoadItemsMessageRef}
|
|
125
|
+
</div>
|
|
126
|
+
)}
|
|
127
|
+
{selectorControl.itemsLoading && (
|
|
128
|
+
<div key="loading" class="v-form-selector__placeholder">
|
|
129
|
+
<VProgressCircular
|
|
130
|
+
indeterminate
|
|
131
|
+
class="mr-1"
|
|
132
|
+
size={CONTROL_LOADING_SPINNER_SIZES[this.size || 'md']}
|
|
133
|
+
/>
|
|
134
|
+
|
|
135
|
+
{this.loadingMessageRef}
|
|
136
|
+
</div>
|
|
137
|
+
)}
|
|
91
138
|
{this.propItems.map((attrs) => {
|
|
92
139
|
const selected = selectorControl.isSelected(attrs.value);
|
|
93
140
|
return itemRenderer({
|
package/src/schemes/control.ts
CHANGED
|
@@ -5,3 +5,9 @@ export type ControlSize = typeof CONTROL_SIZES[number];
|
|
|
5
5
|
export const CONTROL_FIELD_VARIANTS = ['outlined', 'filled', 'flat'] as const;
|
|
6
6
|
|
|
7
7
|
export type ControlFieldVariant = typeof CONTROL_FIELD_VARIANTS[number];
|
|
8
|
+
|
|
9
|
+
export const CONTROL_LOADING_SPINNER_SIZES: Record<ControlSize, number> = {
|
|
10
|
+
sm: 16,
|
|
11
|
+
md: 20,
|
|
12
|
+
lg: 24,
|
|
13
|
+
};
|
package/src/service.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type VueStackService,
|
|
9
9
|
type VDialogProps,
|
|
10
10
|
type VStackControl,
|
|
11
|
+
type VNodeChildOrSlot,
|
|
11
12
|
resolveVStackDynamicInput,
|
|
12
13
|
} from '@fastkit/vue-kit';
|
|
13
14
|
import type { Router } from 'vue-router';
|
|
@@ -60,8 +61,10 @@ export interface VuiServiceUISettings {
|
|
|
60
61
|
variant?: ColorVariant;
|
|
61
62
|
};
|
|
62
63
|
hinttipDelay?: FormControlHinttipDelay;
|
|
63
|
-
noDataMessage?:
|
|
64
|
-
noResultsMessage?:
|
|
64
|
+
noDataMessage?: VNodeChildOrSlot;
|
|
65
|
+
noResultsMessage?: VNodeChildOrSlot;
|
|
66
|
+
loadingMessage?: VNodeChildOrSlot;
|
|
67
|
+
failedToLoadDataMessage?: VNodeChildOrSlot;
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
export type RawVuiServiceUISettings = Partial<VuiServiceUISettings>;
|
|
@@ -102,6 +105,7 @@ export interface VuiServiceIconSettings {
|
|
|
102
105
|
editorRedo: IconName;
|
|
103
106
|
hinttip: IconName;
|
|
104
107
|
clear: IconName;
|
|
108
|
+
reload: IconName;
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
export type RawVuiServiceIconSettings = Partial<VuiServiceIconSettings>;
|
package/src/tool/vite-plugin.ts
CHANGED
|
@@ -173,6 +173,7 @@ export function viteVuiPlugin(
|
|
|
173
173
|
editorRedo: 'mdi-redo-variant' as any,
|
|
174
174
|
hinttip: 'mdi-help-circle-outline' as any,
|
|
175
175
|
clear: 'mdi-close' as any,
|
|
176
|
+
reload: 'mdi-reload' as any,
|
|
176
177
|
// navigationExpand: (gen, active) => {
|
|
177
178
|
// return gen({
|
|
178
179
|
// name: 'mdi-menu-down' as any,
|