@fastkit/vui 0.16.79 → 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.
@@ -37,6 +37,7 @@ import {
37
37
  import { VUI_SELECT_SYMBOL, useVui } from '../../injections';
38
38
  import { VIcon } from '../VIcon';
39
39
  import { VMenu } from '../VMenu';
40
+ import { VStackActivatorPayload } from '@fastkit/vue-stack';
40
41
  import { VOptionGroup } from '../VOptionGroup';
41
42
  import { VOption } from '../VOption';
42
43
  import { VButton } from '../VButton';
@@ -46,12 +47,14 @@ export const ARROW_KEY_TYPES = useKeyboard.Key(['ArrowUp', 'ArrowDown']);
46
47
 
47
48
  export const CHOICE_KEY_TYPES = useKeyboard.Key(['Enter', ' ']);
48
49
 
49
- export const KEYBORD_EVENT_TYPES = useKeyboard.Key([
50
+ export const KEYBOARD_EVENT_TYPES = useKeyboard.Key([
50
51
  ...ARROW_KEY_TYPES,
51
52
  ...CHOICE_KEY_TYPES,
52
53
  ]);
53
54
 
54
- const { props, emits } = createFormSelectorSettings();
55
+ const { props, emits } = createFormSelectorSettings({
56
+ defaultValidateTiming: 'blur',
57
+ });
55
58
 
56
59
  const slots = defineSlots<
57
60
  FormControlSlots &
@@ -265,189 +268,197 @@ export const VSelect = defineComponent({
265
268
  useKeyboard(
266
269
  [
267
270
  {
268
- key: KEYBORD_EVENT_TYPES,
271
+ key: KEYBOARD_EVENT_TYPES,
269
272
  handler: keyboardEventHandler,
270
273
  },
271
274
  ],
272
275
  { autorun: true },
273
276
  );
274
277
 
275
- return {
276
- ...inputControl.expose(),
277
- ...control,
278
- iconName,
279
- menuOpened,
280
- fieldRef: () => fieldRef,
278
+ ctx.expose({
279
+ control: inputControl,
281
280
  focus,
282
281
  showMenu,
283
282
  closeMenu,
284
- renderSelections,
285
- menuRef: () => menuRef,
286
- clearKeyFocused,
283
+ });
284
+
285
+ const handleClickLabel = (ev: MouseEvent) => {
286
+ focus();
287
287
  };
288
- },
289
- render() {
290
- const { nodeControl, selectorControl, selectorItems, selectedItems } = this;
291
- const children = this.$slots.default?.() || [];
292
- const propGroups = this.propGroups.map((group) => {
293
- return (
294
- <VOptionGroup
295
- key={group.id}
296
- groupId={group.id}
297
- label={group.label(selectorControl)}
298
- disabled={group.disabled}>
299
- {group.items.map((item) => (
300
- <VOption
301
- disabled={item.disabled}
302
- value={item.value}
303
- key={item.value}>
304
- {{
305
- default: () => item.label(selectorControl),
288
+
289
+ return () => {
290
+ const children = ctx.slots.default?.() || [];
291
+ const propGroups = inputControl.propGroups.map((group) => {
292
+ return (
293
+ <VOptionGroup
294
+ key={group.id}
295
+ groupId={group.id}
296
+ label={group.label(inputControl)}
297
+ disabled={group.disabled}>
298
+ {group.items.map((item) => (
299
+ <VOption
300
+ disabled={item.disabled}
301
+ value={item.value}
302
+ key={item.value}>
303
+ {item.label(inputControl)}
304
+ </VOption>
305
+ ))}
306
+ </VOptionGroup>
307
+ );
308
+ });
309
+
310
+ const classes = computed(() => [
311
+ 'v-select',
312
+ control.classes.value,
313
+ {
314
+ 'v-select--multiple': inputControl.multiple,
315
+ },
316
+ ]);
317
+
318
+ const controlDefaultSlot = () => {
319
+ return [
320
+ <select
321
+ class="v-select__input__element"
322
+ name={inputControl.name}
323
+ tabindex={inputControl.tabindex}
324
+ disabled={inputControl.isDisabled}
325
+ multiple={inputControl.multiple}
326
+ onFocus={inputControl.focusHandler}
327
+ onBlur={inputControl.blurHandler}
328
+ v-model={inputControl.value}>
329
+ {inputControl.items.map((item) => {
330
+ return (
331
+ <option value={item.propValue} key={item.propValue}>
332
+ {item.renderDefaultSlot()}
333
+ </option>
334
+ );
335
+ })}
336
+ </select>,
337
+ <div class="v-select__selections">
338
+ <div class="v-select__selections__inner">
339
+ {renderSelections(inputControl.selectedItems)}
340
+ </div>
341
+ </div>,
342
+ ];
343
+ };
344
+
345
+ const endAdornmentSlot = () => {
346
+ if (inputControl.itemsLoadFailed) {
347
+ return (
348
+ <VButton
349
+ key="reload"
350
+ icon={vui.icon('reload')}
351
+ rounded
352
+ onClick={(ev) => {
353
+ ev.stopPropagation();
354
+ inputControl.loadItems();
306
355
  }}
307
- </VOption>
308
- ))}
309
- </VOptionGroup>
310
- );
311
- });
356
+ />
357
+ );
358
+ }
312
359
 
313
- return (
314
- <VFormControl
315
- nodeControl={nodeControl}
316
- // focused={this.nodeControl.focused}
317
- class={[
318
- 'v-select',
319
- this.classes,
320
- {
321
- 'v-select--multiple': this.multiple,
322
- },
323
- ]}
324
- label={this.label}
325
- hint={this.hint}
326
- hinttip={this.hinttip}
327
- hiddenInfo={this.hiddenInfo}
328
- requiredChip={this.requiredChip}
329
- onClickLabel={(ev) => {
330
- this.focus();
331
- }}
332
- v-slots={{
333
- ...this.$slots,
334
- default: () => (
335
- <VMenu
336
- width="fit"
337
- maxWidth="fit"
338
- closeOnNavigation={this.closeOnNavigation}
339
- distance={0}
340
- alwaysRender
341
- v-model={this.menuOpened}
342
- ref={this.menuRef()}
343
- onClose={this.clearKeyFocused}
344
- v-slots={{
345
- activator: ({ attrs, control }) => [
346
- <VControlField
347
- class="v-select__input"
348
- ref={this.fieldRef()}
349
- loading={selectorControl.itemsLoading}
350
- error={selectorControl.itemsLoadFailed}
351
- startAdornment={this.startAdornment}
352
- endAdornment={this.endAdornment}
353
- // tabindex={this.computedTabindex}
354
- size={this.size}
355
- focused={this.menuOpened}
356
- autoHeight={this.multiple}
357
- onClick={(ev) => {
358
- if (this.canOperation && !control.isActive) {
359
- let t = ev.target as HTMLElement;
360
- const count = 0;
361
- let hit = false;
362
- while (count < 5) {
363
- if (t.classList.contains('v-select__input')) {
364
- hit = true;
365
- break;
366
- }
367
- t = t.parentElement as HTMLElement;
368
- }
369
- control.setActivator(hit ? t : ev).show();
370
- }
371
- }}
372
- v-slots={{
373
- ...this.$slots,
374
- default: () => [
375
- <select
376
- class="v-select__input__element"
377
- name={this.name}
378
- tabindex={this.computedTabindex}
379
- disabled={this.isDisabled}
380
- multiple={this.multiple}
381
- onFocus={nodeControl.focusHandler}
382
- onBlur={nodeControl.blurHandler}
383
- v-model={this.currentValue}
384
- // value={nodeControl.value}
385
- >
386
- {selectorItems.map((item) => {
387
- return (
388
- <option
389
- value={item.propValue}
390
- key={item.propValue}>
391
- {item.renderDefaultSlot()}
392
- </option>
393
- );
394
- })}
395
- </select>,
396
- <div class="v-select__selections">
397
- <div class="v-select__selections__inner">
398
- {this.renderSelections(selectedItems)}
399
- </div>
400
- </div>,
401
- ],
402
- endAdornment: () => {
403
- if (selectorControl.itemsLoadFailed) {
404
- return (
405
- <VButton
406
- key="reload"
407
- icon={this.$vui.icon('reload')}
408
- rounded
409
- onClick={(ev) => {
410
- ev.stopPropagation();
411
- selectorControl.loadItems();
412
- }}
413
- />
414
- );
415
- }
416
-
417
- if (this.clearable && this.nodeControl.value != null) {
418
- return (
419
- <VButton
420
- key="clear"
421
- icon={this.$vui.icon('clear')}
422
- rounded
423
- onClick={(ev) => {
424
- ev.stopPropagation();
425
- this.nodeControl.clear();
426
- }}
427
- />
428
- );
429
- }
430
-
431
- return (
432
- <VIcon
433
- key="icon"
434
- name={this.iconName}
435
- rotate={this.menuOpened ? 180 : 0}
436
- />
437
- );
438
- },
439
- }}
440
- />,
441
- ],
442
- }}>
443
- <div class={['v-select__body', this.classes]}>
444
- {children}
445
- {propGroups}
446
- </div>
447
- </VMenu>
448
- ),
449
- }}
450
- />
451
- );
360
+ if (props.clearable && inputControl.value != null) {
361
+ return (
362
+ <VButton
363
+ key="clear"
364
+ icon={vui.icon('clear')}
365
+ rounded
366
+ onClick={(ev) => {
367
+ ev.stopPropagation();
368
+ inputControl.clear();
369
+ }}
370
+ />
371
+ );
372
+ }
373
+
374
+ return (
375
+ <VIcon
376
+ key="icon"
377
+ name={iconName}
378
+ rotate={menuOpened.value ? 180 : 0}
379
+ />
380
+ );
381
+ };
382
+
383
+ const menuActivatorSlot = ({ control: menu }: VStackActivatorPayload) => {
384
+ return (
385
+ <VControlField
386
+ class="v-select__input"
387
+ ref={fieldRef}
388
+ loading={inputControl.itemsLoading}
389
+ error={inputControl.itemsLoadFailed}
390
+ startAdornment={props.startAdornment}
391
+ endAdornment={props.endAdornment}
392
+ size={control.size.value}
393
+ focused={menuOpened.value}
394
+ autoHeight={inputControl.multiple}
395
+ onClick={(ev) => {
396
+ if (inputControl.canOperation && !menu.isActive) {
397
+ let t = ev.target as HTMLElement;
398
+ const count = 0;
399
+ let hit = false;
400
+ while (count < 5) {
401
+ if (t.classList.contains('v-select__input')) {
402
+ hit = true;
403
+ break;
404
+ }
405
+ t = t.parentElement as HTMLElement;
406
+ }
407
+ menu.setActivator(hit ? t : ev).show();
408
+ }
409
+ }}
410
+ v-slots={{
411
+ ...ctx.slots,
412
+ default: controlDefaultSlot,
413
+ endAdornment: endAdornmentSlot,
414
+ }}
415
+ />
416
+ );
417
+ };
418
+
419
+ const menuSlots = {
420
+ activator: menuActivatorSlot,
421
+ default: () => (
422
+ <div class={['v-select__body', control.classes.value]}>
423
+ {children}
424
+ {propGroups}
425
+ </div>
426
+ ),
427
+ };
428
+
429
+ const defaultSlot = () => {
430
+ return (
431
+ <VMenu
432
+ width="fit"
433
+ maxWidth="fit"
434
+ closeOnNavigation={props.closeOnNavigation}
435
+ distance={0}
436
+ alwaysRender
437
+ v-model={menuOpened.value}
438
+ ref={menuRef}
439
+ onClose={clearKeyFocused}
440
+ v-slots={menuSlots}
441
+ />
442
+ );
443
+ };
444
+
445
+ return (
446
+ <VFormControl
447
+ nodeControl={inputControl}
448
+ // focused={this.nodeControl.focused}
449
+ class={classes.value}
450
+ label={props.label}
451
+ hint={props.hint}
452
+ hinttip={props.hinttip}
453
+ hiddenInfo={props.hiddenInfo}
454
+ requiredChip={props.requiredChip}
455
+ onClickLabel={handleClickLabel}
456
+ v-slots={{
457
+ ...ctx.slots,
458
+ default: defaultSlot,
459
+ }}
460
+ />
461
+ );
462
+ };
452
463
  },
453
464
  });
@@ -1,5 +1,5 @@
1
1
  import './VSwitch.scss';
2
- import { defineComponent } from 'vue';
2
+ import { defineComponent, computed } from 'vue';
3
3
  import {
4
4
  createFormSelectorItemSettings,
5
5
  useFormSelectorItemControl,
@@ -27,38 +27,41 @@ export const VSwitch = defineComponent({
27
27
  (window as any).yy = {};
28
28
  (window as any).yy[String(Date.now())] = nodeControl;
29
29
  }
30
- return {
31
- ...nodeControl.expose(),
32
- ...control,
30
+
31
+ const classes = computed(() => [
32
+ 'v-switch',
33
+ {
34
+ 'v-switch--selected': nodeControl.selected,
35
+ 'v-switch--disabled': nodeControl.isDisabled,
36
+ },
37
+ control.classes.value,
38
+ ]);
39
+
40
+ const slots = {
41
+ input: () => nodeControl.createInputElement({ type: 'checkbox' }),
42
+ icon: () => (
43
+ <span class="v-switch__faux">
44
+ <span class="v-switch__faux__pin"></span>
45
+ </span>
46
+ ),
47
+ label: () => ctx.slots.default?.(),
48
+ };
49
+
50
+ ctx.expose({
51
+ control: nodeControl,
52
+ });
53
+
54
+ return () => {
55
+ return (
56
+ <VCheckable
57
+ class={classes.value}
58
+ checked={nodeControl.selected}
59
+ invalid={nodeControl.invalid}
60
+ disabled={nodeControl.isDisabled}
61
+ readonly={nodeControl.isReadonly}
62
+ v-slots={slots}
63
+ />
64
+ );
33
65
  };
34
- },
35
- render() {
36
- const { selectorItemControl } = this;
37
- return (
38
- <VCheckable
39
- class={[
40
- 'v-switch',
41
- {
42
- 'v-switch--selected': selectorItemControl.selected,
43
- 'v-switch--disabled': selectorItemControl.isDisabled,
44
- },
45
- this.classes,
46
- ]}
47
- checked={this.selected}
48
- invalid={this.invalid}
49
- disabled={this.isDisabled}
50
- readonly={this.isReadonly}
51
- v-slots={{
52
- input: () =>
53
- selectorItemControl.createInputElement({ type: 'checkbox' }),
54
- icon: () => (
55
- <span class="v-switch__faux">
56
- <span class="v-switch__faux__pin"></span>
57
- </span>
58
- ),
59
- label: () => this.$slots.default?.(),
60
- }}
61
- />
62
- );
63
66
  },
64
67
  });
@@ -1,5 +1,5 @@
1
1
  import './VTextField.scss';
2
- import { defineComponent } from 'vue';
2
+ import { defineComponent, computed } from 'vue';
3
3
  import {
4
4
  createTextInputSettings,
5
5
  useTextInputControl,
@@ -58,49 +58,59 @@ export const VTextField = defineComponent({
58
58
  const control = useControl(props);
59
59
  useControlField(props);
60
60
 
61
- return {
62
- ...inputControl.expose(),
63
- ...control,
61
+ const classes = computed(() => ['v-text-field', control.classes.value]);
62
+
63
+ const handleClickLabel = (ev: MouseEvent) => {
64
+ inputControl.focus();
65
+ };
66
+
67
+ const defaultSlot = () => {
68
+ return (
69
+ <VControlField
70
+ class="v-text-field__input"
71
+ startAdornment={props.startAdornment}
72
+ endAdornment={props.endAdornment}
73
+ size={control.size.value}
74
+ v-slots={{
75
+ ...ctx.slots,
76
+ default: () =>
77
+ inputControl.createInputElement({
78
+ class: 'v-text-field__input__element',
79
+ }),
80
+ }}
81
+ />
82
+ );
83
+ };
84
+
85
+ const infoAppendsSlot = () => {
86
+ const { counterResult } = inputControl;
87
+ if (!counterResult) return;
88
+ return <VTextCounter {...counterResult} />;
89
+ };
90
+
91
+ ctx.expose({
92
+ control: inputControl,
93
+ });
94
+
95
+ return () => {
96
+ return (
97
+ <VFormControl
98
+ nodeControl={inputControl}
99
+ focused={inputControl.focused}
100
+ hiddenInfo={props.hiddenInfo}
101
+ class={classes.value}
102
+ label={props.label}
103
+ hint={props.hint}
104
+ hinttip={props.hinttip}
105
+ requiredChip={props.requiredChip}
106
+ onClickLabel={handleClickLabel}
107
+ v-slots={{
108
+ ...ctx.slots,
109
+ default: defaultSlot,
110
+ infoAppends: infoAppendsSlot,
111
+ }}
112
+ />
113
+ );
64
114
  };
65
- },
66
- render() {
67
- return (
68
- <VFormControl
69
- nodeControl={this.nodeControl}
70
- focused={this.nodeControl.focused}
71
- hiddenInfo={this.hiddenInfo}
72
- class={['v-text-field', this.classes]}
73
- label={this.label}
74
- hint={this.hint}
75
- hinttip={this.hinttip}
76
- requiredChip={this.requiredChip}
77
- onClickLabel={(ev) => {
78
- this.focus();
79
- }}
80
- v-slots={{
81
- ...this.$slots,
82
- default: () => (
83
- <VControlField
84
- class="v-text-field__input"
85
- startAdornment={this.startAdornment}
86
- endAdornment={this.endAdornment}
87
- size={this.size}
88
- v-slots={{
89
- ...this.$slots,
90
- default: () =>
91
- this.textInputControl.createInputElement({
92
- class: 'v-text-field__input__element',
93
- }),
94
- }}
95
- />
96
- ),
97
- infoAppends: () => {
98
- const { counterResult } = this;
99
- if (!counterResult) return;
100
- return <VTextCounter {...counterResult} />;
101
- },
102
- }}
103
- />
104
- );
105
115
  },
106
116
  });