@fastkit/vui 0.16.80 → 0.16.82

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.
@@ -46,53 +46,59 @@ export const VTextarea = defineComponent({
46
46
  const control = useControl(props);
47
47
  useControlField(props);
48
48
 
49
- return {
50
- ...inputControl.expose(),
51
- ...control,
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
  });
@@ -35,6 +35,7 @@ export * from './VTextField';
35
35
  export * from './VNumberField';
36
36
  export * from './VTextarea';
37
37
  // export * from './VWysiwygEditor';
38
+ export * from './VFormGroup';
38
39
  export * from './VForm';
39
40
  export * from './VTabs';
40
41
  export * from './VBreadcrumbs';
@@ -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
- {this.loadingMessageRef}
144
- </div>
145
- )}
146
- {this.propGroups.map((group) => {
147
- const { items } = group;
148
- return (
149
- <>
150
- {items.map((attrs) => {
151
- const selected = selectorControl.isSelected(
152
- attrs.value,
153
- );
154
- return itemRenderer({
155
- selected,
156
- control: selectorControl,
157
- attrs: {
158
- ...attrs,
159
- modelValue: selected,
160
- key: attrs.value,
161
- },
162
- slots: {
163
- default: () => attrs.label(this.selectorControl),
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, form);
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);