@fastkit/vui 0.16.80 → 0.16.81
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/vui.d.ts +458 -679
- package/dist/vui.mjs +680 -652
- package/dist/vui.mjs.map +1 -1
- package/package.json +23 -23
- package/src/components/VCheckbox/VCheckbox.tsx +36 -29
- package/src/components/VForm/VForm.tsx +12 -24
- package/src/components/VFormControl/VFormControl.tsx +7 -4
- package/src/components/VFormGroup/VFormGroup.tsx +45 -0
- package/src/components/VFormGroup/index.ts +1 -0
- package/src/components/VOption/VOption.tsx +12 -18
- package/src/components/VOptionGroup/VOptionGroup.tsx +13 -14
- package/src/components/VRadio/VRadio.tsx +25 -28
- package/src/components/VSelect/VSelect.tsx +185 -174
- package/src/components/VSwitch/VSwitch.tsx +36 -33
- package/src/components/VTextField/VTextField.tsx +54 -44
- package/src/components/VTextarea/VTextarea.tsx +53 -47
- package/src/components/index.ts +1 -0
- package/src/composables/form-selector.tsx +80 -77
- package/src/injections.ts +1 -0
- package/src/plugin.tsx +18 -1
|
@@ -46,53 +46,59 @@ export const VTextarea = defineComponent({
|
|
|
46
46
|
const control = useControl(props);
|
|
47
47
|
useControlField(props);
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
ctx.expose({
|
|
50
|
+
control: inputControl,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const defaultSlot = () => {
|
|
54
|
+
return (
|
|
55
|
+
<VControlField
|
|
56
|
+
class="v-textarea__input"
|
|
57
|
+
size={control.size.value}
|
|
58
|
+
autoHeight
|
|
59
|
+
startAdornment={props.startAdornment}
|
|
60
|
+
endAdornment={props.endAdornment}
|
|
61
|
+
// onClickHost={(ev) => {
|
|
62
|
+
// this.focus();
|
|
63
|
+
// }}
|
|
64
|
+
v-slots={{
|
|
65
|
+
...ctx.slots,
|
|
66
|
+
default: () =>
|
|
67
|
+
inputControl.createInputElement({
|
|
68
|
+
class: 'v-textarea__input__element',
|
|
69
|
+
}),
|
|
70
|
+
}}
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const infoAppendsSlot = () => {
|
|
76
|
+
const { counterResult } = inputControl;
|
|
77
|
+
if (!counterResult) return;
|
|
78
|
+
return <VTextCounter {...counterResult} />;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
return () => {
|
|
82
|
+
return (
|
|
83
|
+
<VFormControl
|
|
84
|
+
nodeControl={inputControl}
|
|
85
|
+
focused={inputControl.focused}
|
|
86
|
+
class={['v-textarea', control.classes.value]}
|
|
87
|
+
label={props.label}
|
|
88
|
+
hint={props.hint}
|
|
89
|
+
hinttip={props.hinttip}
|
|
90
|
+
hiddenInfo={props.hiddenInfo}
|
|
91
|
+
requiredChip={props.requiredChip}
|
|
92
|
+
onClickLabel={(ev) => {
|
|
93
|
+
inputControl.focus();
|
|
94
|
+
}}
|
|
95
|
+
v-slots={{
|
|
96
|
+
...ctx.slots,
|
|
97
|
+
default: defaultSlot,
|
|
98
|
+
infoAppends: infoAppendsSlot,
|
|
99
|
+
}}
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
52
102
|
};
|
|
53
|
-
},
|
|
54
|
-
render() {
|
|
55
|
-
return (
|
|
56
|
-
<VFormControl
|
|
57
|
-
nodeControl={this.nodeControl}
|
|
58
|
-
focused={this.nodeControl.focused}
|
|
59
|
-
class={['v-textarea', this.classes]}
|
|
60
|
-
label={this.label}
|
|
61
|
-
hint={this.hint}
|
|
62
|
-
hinttip={this.hinttip}
|
|
63
|
-
hiddenInfo={this.hiddenInfo}
|
|
64
|
-
requiredChip={this.requiredChip}
|
|
65
|
-
onClickLabel={(ev) => {
|
|
66
|
-
this.focus();
|
|
67
|
-
}}
|
|
68
|
-
v-slots={{
|
|
69
|
-
...this.$slots,
|
|
70
|
-
default: () => (
|
|
71
|
-
<VControlField
|
|
72
|
-
class="v-textarea__input"
|
|
73
|
-
size={this.size}
|
|
74
|
-
autoHeight
|
|
75
|
-
startAdornment={this.startAdornment}
|
|
76
|
-
endAdornment={this.endAdornment}
|
|
77
|
-
// onClickHost={(ev) => {
|
|
78
|
-
// this.focus();
|
|
79
|
-
// }}
|
|
80
|
-
v-slots={{
|
|
81
|
-
...this.$slots,
|
|
82
|
-
default: () =>
|
|
83
|
-
this.textareaControl.createInputElement({
|
|
84
|
-
class: 'v-textarea__input__element',
|
|
85
|
-
}),
|
|
86
|
-
}}
|
|
87
|
-
/>
|
|
88
|
-
),
|
|
89
|
-
infoAppends: () => {
|
|
90
|
-
const { counterResult } = this;
|
|
91
|
-
if (!counterResult) return;
|
|
92
|
-
return <VTextCounter {...counterResult} />;
|
|
93
|
-
},
|
|
94
|
-
}}
|
|
95
|
-
/>
|
|
96
|
-
);
|
|
97
103
|
},
|
|
98
104
|
});
|
package/src/components/index.ts
CHANGED
|
@@ -77,6 +77,14 @@ export function defineFormSelectorComponent(
|
|
|
77
77
|
defaultMultiple,
|
|
78
78
|
});
|
|
79
79
|
const control = useControl(props);
|
|
80
|
+
const classes = computed(() => [
|
|
81
|
+
'v-form-selector',
|
|
82
|
+
className,
|
|
83
|
+
{
|
|
84
|
+
...control.classes.value,
|
|
85
|
+
'v-form-selector--stacked': props.stacked,
|
|
86
|
+
},
|
|
87
|
+
]);
|
|
80
88
|
const vui = useVui();
|
|
81
89
|
const loadingMessageRef = computed<VNodeChild | undefined>(() => {
|
|
82
90
|
const slot = resolveVNodeChildOrSlots(
|
|
@@ -94,85 +102,80 @@ export function defineFormSelectorComponent(
|
|
|
94
102
|
);
|
|
95
103
|
return slot && slot(vui);
|
|
96
104
|
});
|
|
97
|
-
return {
|
|
98
|
-
...selectorControl.expose(),
|
|
99
|
-
...control,
|
|
100
|
-
loadingMessageRef,
|
|
101
|
-
failedToLoadItemsMessageRef,
|
|
102
|
-
};
|
|
103
|
-
},
|
|
104
|
-
render() {
|
|
105
|
-
const { selectorControl } = this;
|
|
106
|
-
return (
|
|
107
|
-
<VFormControl
|
|
108
|
-
nodeControl={this.nodeControl}
|
|
109
|
-
focused={this.nodeControl.focused}
|
|
110
|
-
hiddenInfo={this.hiddenInfo}
|
|
111
|
-
class={[
|
|
112
|
-
'v-form-selector',
|
|
113
|
-
className,
|
|
114
|
-
{
|
|
115
|
-
...this.classes,
|
|
116
|
-
'v-form-selector--stacked': this.stacked,
|
|
117
|
-
},
|
|
118
|
-
]}
|
|
119
|
-
label={this.label}
|
|
120
|
-
hint={this.hint}
|
|
121
|
-
hinttip={this.hinttip}
|
|
122
|
-
requiredChip={this.requiredChip}
|
|
123
|
-
error={selectorControl.itemsLoadFailed}
|
|
124
|
-
v-slots={{
|
|
125
|
-
...this.$slots,
|
|
126
|
-
default: () => (
|
|
127
|
-
<div class="v-form-selector__body">
|
|
128
|
-
{selectorControl.itemsLoadFailed && (
|
|
129
|
-
<div
|
|
130
|
-
key="failed"
|
|
131
|
-
class="v-form-selector__placeholder v-form-selector__placeholder--error">
|
|
132
|
-
{this.failedToLoadItemsMessageRef}
|
|
133
|
-
</div>
|
|
134
|
-
)}
|
|
135
|
-
{selectorControl.itemsLoading && (
|
|
136
|
-
<div key="loading" class="v-form-selector__placeholder">
|
|
137
|
-
<VProgressCircular
|
|
138
|
-
indeterminate
|
|
139
|
-
class="mr-1"
|
|
140
|
-
size={CONTROL_LOADING_SPINNER_SIZES[this.size || 'md']}
|
|
141
|
-
/>
|
|
142
105
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
},
|
|
165
|
-
});
|
|
166
|
-
})}
|
|
167
|
-
</>
|
|
168
|
-
);
|
|
169
|
-
})}
|
|
170
|
-
{this.$slots.default?.()}
|
|
106
|
+
const defaultSlot = () => {
|
|
107
|
+
return (
|
|
108
|
+
<div class="v-form-selector__body">
|
|
109
|
+
{selectorControl.itemsLoadFailed && (
|
|
110
|
+
<div
|
|
111
|
+
key="failed"
|
|
112
|
+
class="v-form-selector__placeholder v-form-selector__placeholder--error">
|
|
113
|
+
{failedToLoadItemsMessageRef.value}
|
|
114
|
+
</div>
|
|
115
|
+
)}
|
|
116
|
+
{selectorControl.itemsLoading && (
|
|
117
|
+
<div key="loading" class="v-form-selector__placeholder">
|
|
118
|
+
<VProgressCircular
|
|
119
|
+
indeterminate
|
|
120
|
+
class="mr-1"
|
|
121
|
+
size={
|
|
122
|
+
CONTROL_LOADING_SPINNER_SIZES[control.size.value || 'md']
|
|
123
|
+
}
|
|
124
|
+
/>
|
|
125
|
+
|
|
126
|
+
{loadingMessageRef.value}
|
|
171
127
|
</div>
|
|
172
|
-
)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
128
|
+
)}
|
|
129
|
+
{selectorControl.propGroups.map((group) => {
|
|
130
|
+
const { items } = group;
|
|
131
|
+
return (
|
|
132
|
+
<>
|
|
133
|
+
{items.map((attrs) => {
|
|
134
|
+
const selected = selectorControl.isSelected(attrs.value);
|
|
135
|
+
return itemRenderer({
|
|
136
|
+
selected,
|
|
137
|
+
control: selectorControl,
|
|
138
|
+
attrs: {
|
|
139
|
+
...attrs,
|
|
140
|
+
modelValue: selected,
|
|
141
|
+
key: attrs.value,
|
|
142
|
+
},
|
|
143
|
+
slots: {
|
|
144
|
+
default: () => attrs.label(selectorControl),
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
})}
|
|
148
|
+
</>
|
|
149
|
+
);
|
|
150
|
+
})}
|
|
151
|
+
{ctx.slots.default?.()}
|
|
152
|
+
</div>
|
|
153
|
+
);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
ctx.expose({
|
|
157
|
+
control: selectorControl,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
return () => {
|
|
161
|
+
return (
|
|
162
|
+
<VFormControl
|
|
163
|
+
nodeControl={selectorControl}
|
|
164
|
+
focused={selectorControl.focused}
|
|
165
|
+
hiddenInfo={props.hiddenInfo}
|
|
166
|
+
class={classes.value}
|
|
167
|
+
label={props.label}
|
|
168
|
+
hint={props.hint}
|
|
169
|
+
hinttip={props.hinttip}
|
|
170
|
+
requiredChip={props.requiredChip}
|
|
171
|
+
error={selectorControl.itemsLoadFailed}
|
|
172
|
+
v-slots={{
|
|
173
|
+
...ctx.slots,
|
|
174
|
+
default: defaultSlot,
|
|
175
|
+
}}
|
|
176
|
+
/>
|
|
177
|
+
);
|
|
178
|
+
};
|
|
176
179
|
},
|
|
177
180
|
});
|
|
178
181
|
}
|
package/src/injections.ts
CHANGED
|
@@ -27,6 +27,7 @@ export const VUI_RADIO_GROUP_SYMBOL = 'vui-radio-group';
|
|
|
27
27
|
export const VUI_RADIO_SYMBOL = 'vui-radio';
|
|
28
28
|
export const VUI_SWITCH_GROUP_SYMBOL = 'vui-switch-group';
|
|
29
29
|
export const VUI_SWITCH_SYMBOL = 'vui-switch';
|
|
30
|
+
export const VUI_FORM_GROUP_SYMBOL = 'vui-form-group';
|
|
30
31
|
export const VUI_FORM_SYMBOL = 'vui-form';
|
|
31
32
|
|
|
32
33
|
export function useVui() {
|
package/src/plugin.tsx
CHANGED
|
@@ -20,6 +20,9 @@ import { installResizeDirective } from '@fastkit/vue-resize';
|
|
|
20
20
|
import { VueColorSchemePlugin } from '@fastkit/vue-color-scheme';
|
|
21
21
|
import { installVueAppLayout } from '@fastkit/vue-app-layout';
|
|
22
22
|
import { onAppUnmount } from '@fastkit/vue-utils';
|
|
23
|
+
import { getDocumentScroller } from '@fastkit/vue-scroller';
|
|
24
|
+
|
|
25
|
+
const scroller = getDocumentScroller();
|
|
23
26
|
|
|
24
27
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
25
28
|
export interface VuiPluginStackOptions extends VueStackServiceOptions {}
|
|
@@ -70,7 +73,21 @@ export class VuiPlugin {
|
|
|
70
73
|
app.use(vueColorSchemePlugin);
|
|
71
74
|
|
|
72
75
|
installVueStackPlugin(app, stack);
|
|
73
|
-
installVueFormPlugin(app,
|
|
76
|
+
installVueFormPlugin(app, {
|
|
77
|
+
scroll: {
|
|
78
|
+
options: {
|
|
79
|
+
behavior: 'smooth',
|
|
80
|
+
},
|
|
81
|
+
fn: (el, opts) => {
|
|
82
|
+
const duration = opts?.behavior === 'smooth' ? undefined : 0;
|
|
83
|
+
return scroller.toElement(el, {
|
|
84
|
+
offset: $vui.getAutoScrollToElementOffsetTop(),
|
|
85
|
+
duration,
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
...form,
|
|
90
|
+
});
|
|
74
91
|
installVueAppLayout(app);
|
|
75
92
|
installBodyScrollLockDirective(app);
|
|
76
93
|
installClickOutsideDirective(app);
|