sprintify-ui 0.6.33 → 0.6.35

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.
Files changed (58) hide show
  1. package/dist/sprintify-ui.es.js +12984 -12888
  2. package/dist/style.css +1 -1
  3. package/dist/tailwindcss/button.js +3 -2
  4. package/dist/tailwindcss/theme.js +14 -7
  5. package/dist/types/src/components/BaseButtonGroup.vue.d.ts +9 -0
  6. package/dist/types/src/components/BaseDataIterator.vue.d.ts +3 -3
  7. package/dist/types/src/components/BaseDataIteratorSectionButton.vue.d.ts +2 -2
  8. package/dist/types/src/components/BaseDataIteratorSectionColumns.vue.d.ts +8 -8
  9. package/dist/types/src/components/BaseDataTable.vue.d.ts +3 -3
  10. package/dist/types/src/components/BaseDataTableRowAction.vue.d.ts +4 -3
  11. package/dist/types/src/components/BaseDatePicker.vue.d.ts +10 -0
  12. package/dist/types/src/components/BaseDateSelect.vue.d.ts +9 -0
  13. package/dist/types/src/components/BaseInput.vue.d.ts +18 -0
  14. package/dist/types/src/components/BasePassword.vue.d.ts +13 -0
  15. package/dist/types/src/components/BaseRichText.vue.d.ts +9 -0
  16. package/dist/types/src/components/BaseTable.vue.d.ts +3 -3
  17. package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +11 -2
  18. package/dist/types/src/components/BaseTextarea.vue.d.ts +18 -0
  19. package/dist/types/src/components/BaseTextareaAutoresize.vue.d.ts +12 -2
  20. package/dist/types/src/stories/PageInputSizes.vue.d.ts +2 -0
  21. package/dist/types/src/utils/slots.d.ts +1 -0
  22. package/package.json +1 -1
  23. package/src/assets/base-rich-text.css +148 -26
  24. package/src/components/BaseButton.vue +3 -2
  25. package/src/components/BaseButtonGroup.vue +37 -9
  26. package/src/components/BaseColor.vue +29 -31
  27. package/src/components/BaseDataIterator.stories.js +8 -1
  28. package/src/components/BaseDataIterator.vue +36 -76
  29. package/src/components/BaseDataIteratorSectionButton.vue +8 -19
  30. package/src/components/BaseDataTable.vue +25 -18
  31. package/src/components/BaseDataTableRowAction.vue +8 -7
  32. package/src/components/BaseDatePicker.stories.js +23 -0
  33. package/src/components/BaseDatePicker.vue +71 -11
  34. package/src/components/BaseDateSelect.stories.js +25 -1
  35. package/src/components/BaseDateSelect.vue +80 -101
  36. package/src/components/BaseDraggable.vue +5 -1
  37. package/src/components/BaseDropdownAutocomplete.stories.js +30 -15
  38. package/src/components/BaseHasMany.stories.js +22 -1
  39. package/src/components/BaseInput.stories.js +4 -4
  40. package/src/components/BaseInput.vue +61 -15
  41. package/src/components/BaseMediaPicturesItem.vue +2 -2
  42. package/src/components/BasePassword.stories.js +25 -0
  43. package/src/components/BasePassword.vue +35 -55
  44. package/src/components/BaseRichText.stories.js +6 -0
  45. package/src/components/BaseRichText.vue +12 -2
  46. package/src/components/BaseSelect.vue +5 -0
  47. package/src/components/BaseTable.vue +2 -1
  48. package/src/components/BaseTagAutocomplete.stories.js +1 -1
  49. package/src/components/BaseTagAutocomplete.vue +143 -88
  50. package/src/components/BaseTagAutocompleteFetch.stories.js +22 -1
  51. package/src/components/BaseTextarea.stories.js +25 -0
  52. package/src/components/BaseTextarea.vue +34 -3
  53. package/src/components/BaseTextareaAutoresize.stories.js +27 -2
  54. package/src/components/BaseTextareaAutoresize.vue +28 -9
  55. package/src/composables/inputSize.ts +5 -1
  56. package/src/stories/InputSizes.stories.js +22 -0
  57. package/src/stories/PageInputSizes.vue +205 -0
  58. package/src/utils/slots.ts +13 -0
@@ -1,50 +1,25 @@
1
1
  <template>
2
- <div
3
- class="flex rounded border bg-white"
4
- :class="[
5
- disabled ? 'cursor-not-allowed text-slate-300' : '',
6
- hasErrorInternal ? 'border-red-500' : 'border-slate-300',
7
- ]"
8
- >
9
- <input
10
- ref="input"
11
- :value="modelValue"
12
- :type="showPassword ? 'text' : 'password'"
13
- :name="nameInternal"
14
- :disabled="disabled"
15
- :placeholder="placeholder"
16
- :required="requiredInternal"
17
- class="grow rounded-l rounded-r-none border-none focus:ring-2 focus:ring-primary-500 disabled:cursor-not-allowed"
18
- @input="onInput"
19
- >
20
- <div class="flex shrink-0 pl-3">
21
- <button
22
- tabindex="-1"
23
- type="button"
24
- class="pr-3 text-slate-500 disabled:cursor-not-allowed disabled:text-slate-300"
25
- :disabled="disabled"
26
- @click="showPassword = !showPassword"
27
- >
28
- <BaseIcon
29
- v-if="!showPassword"
30
- icon="heroicons:eye-slash-20-solid"
31
- class="h-5 w-5"
32
- />
33
- <BaseIcon
34
- v-else
35
- icon="heroicons:eye-20-solid"
36
- class="h-5 w-5"
37
- />
38
- </button>
39
- </div>
40
- </div>
2
+ <BaseInput
3
+ ref="input"
4
+ :model-value="modelValue"
5
+ :type="showPassword ? 'text' : 'password'"
6
+ :disabled="disabled"
7
+ :placeholder="placeholder"
8
+ :size="size"
9
+ :icon-right="showPassword ? 'heroicons:eye-20-solid' : 'heroicons:eye-slash-20-solid'"
10
+ @icon-right-click="onIconRightClick"
11
+ @update:model-value="onUpdateModelValue"
12
+ @focus="onFocus"
13
+ @blur="onBlur"
14
+ />
41
15
  </template>
42
16
 
43
17
  <script lang="ts" setup>
44
- import { trim } from 'lodash';
45
- import { Icon as BaseIcon } from '@iconify/vue';
46
18
  import { PropType } from 'vue';
47
- import { useField } from '@/composables/field';
19
+ import { Size } from '@/utils/sizes';
20
+ import BaseInput from './BaseInput.vue';
21
+
22
+ const emit = defineEmits(['update:modelValue', 'blur', 'focus']);
48
23
 
49
24
  const props = defineProps({
50
25
  modelValue: {
@@ -55,6 +30,10 @@ const props = defineProps({
55
30
  default: false,
56
31
  type: Boolean,
57
32
  },
33
+ size: {
34
+ default: undefined,
35
+ type: String as PropType<Size>,
36
+ },
58
37
  name: {
59
38
  default: undefined,
60
39
  type: String,
@@ -75,21 +54,10 @@ const props = defineProps({
75
54
 
76
55
  const input = ref<HTMLInputElement | null>(null);
77
56
 
78
- const emit = defineEmits(['update:modelValue']);
79
-
80
- const { nameInternal, requiredInternal, hasErrorInternal, emitUpdate } =
81
- useField({
82
- name: computed(() => props.name),
83
- required: computed(() => props.required),
84
- hasError: computed(() => props.hasError),
85
- emit: emit,
86
- });
87
-
88
57
  const showPassword = ref(false);
89
58
 
90
- function onInput(event: any) {
91
- const value = event.target.value + '';
92
- emitUpdate(trim(value));
59
+ function onIconRightClick() {
60
+ showPassword.value = !showPassword.value;
93
61
  }
94
62
 
95
63
  function focus() {
@@ -100,6 +68,18 @@ function blur() {
100
68
  input.value?.blur();
101
69
  }
102
70
 
71
+ function onUpdateModelValue(value: string) {
72
+ emit('update:modelValue', value);
73
+ }
74
+
75
+ function onBlur() {
76
+ emit('blur');
77
+ }
78
+
79
+ function onFocus() {
80
+ emit('focus');
81
+ }
82
+
103
83
  defineExpose({
104
84
  focus,
105
85
  blur,
@@ -2,6 +2,8 @@ import BaseRichText from './BaseRichText.vue';
2
2
  import ShowValue from '@/../.storybook/components/ShowValue.vue';
3
3
  import { createFieldStory } from '@/../.storybook/utils';
4
4
 
5
+ const sizes = ['xs', 'sm', 'md'];
6
+
5
7
  const toolbarOptions = [
6
8
  'full',
7
9
  'essential',
@@ -28,6 +30,10 @@ export default {
28
30
  placeholder: 'Describe your complete life in 4 sentences...',
29
31
  },
30
32
  argTypes: {
33
+ size: {
34
+ control: { type: 'select' },
35
+ options: sizes,
36
+ },
31
37
  theme: {
32
38
  control: { type: 'select' },
33
39
  options: ['snow', 'bubble', ''],
@@ -1,7 +1,11 @@
1
1
  <template>
2
2
  <div
3
3
  class="base-rich-text relative"
4
- :class="[hasErrorInternal ? 'error' : '']"
4
+ :class="[
5
+ hasErrorInternal ? 'error' : '',
6
+ sizeInternal == 'sm' ? 'base-rich-text-sm' : '',
7
+ sizeInternal == 'xs' ? 'base-rich-text-xs' : '',
8
+ ]"
5
9
  >
6
10
  <quill-editor
7
11
  :name="nameInternal"
@@ -25,6 +29,7 @@ import { useField } from '@/composables/field';
25
29
 
26
30
  import { QuillEditor } from '@vueup/vue-quill';
27
31
  import Delta from 'quill-delta';
32
+ import { Size } from '@/utils/sizes';
28
33
 
29
34
 
30
35
  const props = defineProps({
@@ -38,6 +43,10 @@ const props = defineProps({
38
43
  type: String as PropType<'' | 'snow' | 'bubble'>,
39
44
  default: 'snow',
40
45
  },
46
+ size: {
47
+ default: undefined,
48
+ type: String as PropType<Size>,
49
+ },
41
50
  toolbar: {
42
51
  type: [String, Array, Object] as PropType<
43
52
  string | unknown[] | Record<string, any> | undefined
@@ -74,10 +83,11 @@ const props = defineProps({
74
83
 
75
84
  const emit = defineEmits(['update:modelValue']);
76
85
 
77
- const { nameInternal, requiredInternal, hasErrorInternal, emitUpdate } =
86
+ const { nameInternal, requiredInternal, hasErrorInternal, emitUpdate, sizeInternal } =
78
87
  useField({
79
88
  name: computed(() => props.name),
80
89
  required: computed(() => props.required),
90
+ size: computed(() => props.size),
81
91
  hasError: computed(() => props.hasError),
82
92
  emit: emit,
83
93
  });
@@ -209,6 +209,10 @@ const classes = computed(() => {
209
209
  }
210
210
  }
211
211
 
212
+ // For placeholder
213
+
214
+ const fontWeight = props.modelValue ? 'font-normal' : 'font-light';
215
+
212
216
  const disabled = 'disabled:cursor-not-allowed disabled:text-slate-300 disabled:opacity-100';
213
217
  const error = hasErrorInternal.value ? 'border-red-600' : 'border-slate-300';
214
218
  const textColor = !props.modelValue && requiredInternal ? 'text-slate-400' : '';
@@ -222,6 +226,7 @@ const classes = computed(() => {
222
226
  return twMerge([
223
227
  base,
224
228
  focusClass,
229
+ fontWeight,
225
230
  disabled,
226
231
  error,
227
232
  textColor,
@@ -286,6 +286,7 @@ import SlotComponent from './SlotComponent';
286
286
  import { useResizeObserver, useScroll } from '@vueuse/core';
287
287
  import { debounce, isArray } from 'lodash';
288
288
  import BaseSpinnerLarge from '../svg/BaseSpinnerLarge.vue';
289
+ import { Size } from '@/utils/sizes';
289
290
 
290
291
  const checkboxStyle =
291
292
  'disabled:bg-slate-100 group-hover:shadow-md disabled:border-slate-300 disabled:cursor-not-allowed duration-300 cursor-pointer focus:ring-blue-300 border border-slate-300 shadow h-[18px] w-[18px] rounded';
@@ -371,7 +372,7 @@ const props = defineProps({
371
372
  type: Number,
372
373
  },
373
374
  size: {
374
- type: String as PropType<'sm' | 'md'>,
375
+ type: String as PropType<Size>,
375
376
  default: 'md',
376
377
  },
377
378
  });
@@ -3,7 +3,7 @@ import BaseTagAutocomplete from './BaseTagAutocomplete.vue';
3
3
  import ShowValue from '@/../.storybook/components/ShowValue.vue';
4
4
  import BaseAppNotifications from './BaseAppNotifications.vue';
5
5
 
6
- const sizes = ['xs', 'sm', 'base'];
6
+ const sizes = ['xs', 'sm', 'md'];
7
7
 
8
8
  export default {
9
9
  title: 'Form/BaseTagAutocomplete',
@@ -1,63 +1,44 @@
1
1
  <template>
2
2
  <div ref="autocomplete">
3
- <div
4
- class="relative z-[1] rounded border bg-white p-1"
5
- :class="[
6
- hasErrorInternal ? 'border-red-600' : 'border-slate-300',
7
- wrapperClass,
8
- ]"
9
- >
10
- <div :class="twMerge('-m-0.5 flex flex-wrap', twContainer)">
11
- <slot
12
- name="items"
13
- :items="normalizedModelValue"
14
- :remove-option="removeOption"
15
- :disabled="disabled"
3
+ <div :class="wrapperClass">
4
+ <slot
5
+ name="items"
6
+ :items="normalizedModelValue"
7
+ :remove-option="removeOption"
8
+ :disabled="disabled"
9
+ >
10
+ <div
11
+ v-for="selection in normalizedModelValue"
12
+ :key="selection.value ? selection.value : 'null'"
13
+ :class="selectionClass(selection)"
16
14
  >
17
- <div
18
- v-for="selection in normalizedModelValue"
19
- :key="selection.value ? selection.value : 'null'"
20
- class="p-0.5"
21
- >
22
- <div
23
- class="flex items-stretch rounded border"
24
- :class="[
25
- disabled ? 'cursor-not-allowed opacity-60' : '',
26
- selectionClass(selection),
27
- ]"
28
- >
29
- <div :class="[selectionLabelClass]">
30
- {{ selection.label }}
31
- </div>
32
-
33
- <button
34
- v-if="!disabled"
35
- type="button"
36
- class="flex shrink-0 appearance-none items-center justify-center border-0 bg-transparent pl-1 pr-3 text-xs outline-none"
37
- @click="removeOption(selection)"
38
- >
39
-
40
- </button>
41
- </div>
15
+ <div>
16
+ {{ selection.label }}
42
17
  </div>
43
- </slot>
44
-
45
- <div class="grow p-0.5">
46
- <input
47
- ref="inputElement"
48
- :value="keywords"
49
- type="text"
50
- :placeholder="placeholder ? placeholder : t('sui.select_an_item')"
51
- class="w-full min-w-[50px] border-none p-0 pl-1 shadow-none outline-none focus:border-none focus:shadow-none focus:outline-none focus:ring-0 disabled:cursor-not-allowed"
52
- :class="[inputClass]"
53
- autocomplete="off"
54
- :disabled="disabled"
55
- @click="open"
56
- @input="onTextInput"
57
- @keydown="onTextKeydown"
18
+
19
+ <button
20
+ type="button"
21
+ tabindex="-1"
22
+ :class="selectionDeleteClasses"
23
+ @click="removeOption(selection)"
58
24
  >
25
+
26
+ </button>
59
27
  </div>
60
- </div>
28
+ </slot>
29
+
30
+ <input
31
+ ref="inputElement"
32
+ :value="keywords"
33
+ type="text"
34
+ :placeholder="placeholder ? placeholder : t('sui.select_an_item')"
35
+ :class="inputClasses"
36
+ autocomplete="off"
37
+ :disabled="disabled"
38
+ @focus="open"
39
+ @input="onTextInput"
40
+ @keydown="onTextKeydown"
41
+ >
61
42
  </div>
62
43
 
63
44
  <div class="relative">
@@ -116,7 +97,7 @@ import { useNotificationsStore } from '@/stores/notifications';
116
97
  import BaseAutocompleteDrawer from './BaseAutocompleteDrawer.vue';
117
98
  import { twMerge } from 'tailwind-merge';
118
99
  import { t } from '@/i18n';
119
- import { Size } from '@/utils/sizes';
100
+ import { Size, sizes } from '@/utils/sizes';
120
101
 
121
102
  const notifications = useNotificationsStore();
122
103
 
@@ -141,6 +122,7 @@ const props = defineProps({
141
122
  default: undefined,
142
123
  type: String,
143
124
  },
125
+
144
126
  placeholder: {
145
127
  default: undefined,
146
128
  type: String,
@@ -178,7 +160,7 @@ const props = defineProps({
178
160
  type: Boolean,
179
161
  },
180
162
  size: {
181
- default: 'md',
163
+ default: undefined,
182
164
  type: String as PropType<Size>,
183
165
  },
184
166
  dropdownShow: {
@@ -193,6 +175,10 @@ const props = defineProps({
193
175
  default: '',
194
176
  type: [String, Array] as PropType<string | string[]>,
195
177
  },
178
+ visibleFocus: {
179
+ default: true,
180
+ type: Boolean,
181
+ },
196
182
  });
197
183
 
198
184
  const emit = defineEmits([
@@ -203,9 +189,10 @@ const emit = defineEmits([
203
189
  'scrollBottom',
204
190
  ]);
205
191
 
206
- const { hasErrorInternal, emitUpdate } = useField({
192
+ const { hasErrorInternal, emitUpdate, sizeInternal } = useField({
207
193
  name: computed(() => props.name),
208
194
  required: computed(() => props.required),
195
+ size: computed(() => props.size),
209
196
  hasError: computed(() => props.hasError),
210
197
  emit: emit,
211
198
  });
@@ -218,6 +205,31 @@ const hasOptions = useHasOptions(
218
205
  computed(() => true)
219
206
  );
220
207
 
208
+ onMounted(() => {
209
+ window.addEventListener('keydown', onWindowKeydown);
210
+ });
211
+
212
+ onBeforeUnmount(() => {
213
+ window.removeEventListener('keydown', onWindowKeydown);
214
+ });
215
+
216
+ function onWindowKeydown(event: KeyboardEvent) {
217
+
218
+ if (!opened.value) {
219
+ return;
220
+ }
221
+
222
+ const key = event.key;
223
+
224
+ if (key === 'Tab') {
225
+ close();
226
+ }
227
+
228
+ if (key === 'Escape') {
229
+ close();
230
+ }
231
+ }
232
+
221
233
  let openOfFocusTimeout = 0;
222
234
 
223
235
  onMounted(() => {
@@ -283,6 +295,7 @@ function open() {
283
295
  function close() {
284
296
  shouldFilter.value = false;
285
297
  opened.value = false;
298
+ selectionToDelete.value = null;
286
299
  blur();
287
300
  emit('close');
288
301
  }
@@ -392,6 +405,11 @@ const attemptRemoveLastSelection = () => {
392
405
  };
393
406
 
394
407
  const removeOption = (option: NormalizedOption) => {
408
+
409
+ if (props.disabled) {
410
+ return;
411
+ }
412
+
395
413
  focus();
396
414
  let newModelValue = cloneDeep(normalizedModelValue.value);
397
415
  newModelValue = newModelValue.filter((v) => v.value != option.value);
@@ -401,49 +419,86 @@ const removeOption = (option: NormalizedOption) => {
401
419
  // Element Classes
402
420
 
403
421
  const wrapperClass = computed(() => {
404
- if (props.size == 'xs') {
405
- return 'min-h-[34px]';
406
- }
407
- if (props.size == 'sm') {
408
- return 'min-h-[38px]';
409
- }
410
- return 'min-h-[42px]';
422
+ const base = 'relative z-[1] input-rounded border bg-white flex flex-wrap';
423
+ const error = hasErrorInternal.value ? 'border-red-600' : 'border-slate-300'
424
+ const height = {
425
+ 'xs': 'min-h-control-xs gap-0.5 p-0.5',
426
+ 'sm': 'min-h-control-sm gap-0.5 p-0.5',
427
+ 'md': 'min-h-control-md gap-1 p-1',
428
+ }[sizeInternal.value];
429
+
430
+ const focus = opened.value ? 'input-focus border-blue-300' : '';
431
+
432
+ return twMerge(base, error, height, focus, props.twContainer);
411
433
  });
412
434
 
413
- const inputClass = computed(() => {
414
- const base = 'h-[32px] text-base';
415
- if (props.size == 'xs') {
416
- return base + ' xs:text-xs xs:h-[22px]';
417
- }
418
- if (props.size == 'sm') {
419
- return base + ' xs:text-sm xs:h-[28px]';
420
- }
421
- return base;
435
+ const innerHeight = computed(() => {
436
+ const height = {
437
+ 'xs': 'h-[calc(theme(spacing.control-xs)_-_theme(spacing[0.5])_-_theme(spacing[0.5])_-_2px)]',
438
+ 'sm': 'h-[calc(theme(spacing.control-sm)_-_theme(spacing[0.5])_-_theme(spacing[0.5])_-_2px)]',
439
+ 'md': 'h-[calc(theme(spacing.control-md)_-_theme(spacing.1)_-_theme(spacing.1)_-_2px)]',
440
+ }[sizeInternal.value];
441
+
442
+ return height;
443
+ });
444
+
445
+ const inputClasses = computed(() => {
446
+ const base = 'grow min-w-[50px] py-0 border-none shadow-none outline-none bg-transparent';
447
+ const focus = 'focus:border-none focus:shadow-none focus:outline-none focus:ring-0';
448
+ const disabled = 'disabled:cursor-not-allowed';
449
+ const sizeConfig = sizes[sizeInternal.value];
450
+
451
+ const padding = {
452
+ 'xs': 'pl-1.5',
453
+ 'sm': 'pl-2',
454
+ 'md': 'pl-2.5',
455
+ }[sizeInternal.value];
456
+
457
+ return [base, padding, innerHeight.value, focus, disabled, sizeConfig.fontSize];
422
458
  });
423
459
 
424
460
  const selectionClass = (selection: NormalizedOption): string => {
461
+
462
+ const base = 'flex items-center rounded border';
463
+
464
+ const fontSize = {
465
+ 'xs': 'text-xs',
466
+ 'sm': 'text-xs',
467
+ 'md': 'text-sm',
468
+ }[sizeInternal.value];
469
+
470
+ const padding = {
471
+ 'xs': 'pl-2',
472
+ 'sm': 'pl-2',
473
+ 'md': 'pl-3',
474
+ }[sizeInternal.value];
475
+
476
+ let color = 'bg-slate-200 border-slate-300';
477
+
425
478
  if (
426
479
  selectionToDelete.value &&
427
480
  selectionToDelete.value.value == selection.value
428
481
  ) {
429
- return 'bg-red-200 border-red-300 text-red-800';
482
+ color = 'bg-red-200 border-red-300 text-red-800';
430
483
  }
431
- return 'bg-slate-200 border-slate-300';
484
+
485
+ const disabled = props.disabled ? 'cursor-not-allowed opacity-60' : '';
486
+
487
+ return twMerge(base, innerHeight.value, padding, color, disabled, fontSize);
432
488
  };
433
489
 
434
- const selectionLabelClass = computed((): string => {
435
- let base = 'py-[5px] pl-[0.75em] text-sm';
436
- props.disabled ? (base += ' pr-[0.75em]') : (base += ' pr-1');
437
- if (props.size == 'xs') {
438
- const classes = base + ' xs:py-[3px] xs:pl-2 xs:text-xs';
439
- return classes;
440
- }
441
- if (props.size == 'sm') {
442
- const classes = base + ' xs:py-[3px] xs:pl-2 xs:text-sm';
443
- return classes;
444
- }
445
- const classes = base;
446
- return classes;
490
+ const selectionDeleteClasses = computed(() => {
491
+ const base = 'flex shrink-0 appearance-none items-center justify-center border-0 bg-transparent outline-none';
492
+
493
+ const padding = {
494
+ 'xs': 'pl-1 pr-2',
495
+ 'sm': 'pl-1 pr-2',
496
+ 'md': 'pl-1 pr-3',
497
+ }[sizeInternal.value];
498
+
499
+ const disabled = props.disabled ? 'cursor-not-allowed opacity-60' : '';
500
+
501
+ return twMerge(base, padding, disabled);
447
502
  });
448
503
 
449
504
  defineExpose({
@@ -3,10 +3,17 @@ import ShowValue from '@/../.storybook/components/ShowValue.vue';
3
3
  import { createFieldStory } from '../../.storybook/utils';
4
4
  import BaseAppNotifications from './BaseAppNotifications.vue';
5
5
 
6
+ const sizes = ['xs', 'sm', 'md'];
7
+
6
8
  export default {
7
9
  title: 'Form/BaseTagAutocompleteFetch',
8
10
  component: BaseTagAutocompleteFetch,
9
- argTypes: {},
11
+ argTypes: {
12
+ size: {
13
+ control: { type: 'select' },
14
+ options: sizes,
15
+ },
16
+ },
10
17
  args: {
11
18
  url: 'https://effettandem.com/api/content/articles',
12
19
  labelKey: 'title',
@@ -56,6 +63,20 @@ Maximum.args = {
56
63
  max: 3,
57
64
  };
58
65
 
66
+ export const Sizes = (args) => ({
67
+ components: { BaseTagAutocompleteFetch },
68
+ setup() {
69
+ const value = ref([]);
70
+ return { args, sizes, value };
71
+ },
72
+ template: `
73
+ <div v-for="size in sizes" class="mb-1">
74
+ <p class="text-xs text-slate-600 leading-tight">{{ size }}</p>
75
+ <BaseTagAutocompleteFetch v-model="value" v-bind="args" :size="size"></BaseTagAutocompleteFetch>
76
+ </div>
77
+ `,
78
+ });
79
+
59
80
  export const SlotOption = (args) => {
60
81
  return {
61
82
  components: { BaseTagAutocompleteFetch },
@@ -1,12 +1,20 @@
1
1
  import { createFieldStory } from '../../.storybook/utils';
2
2
  import BaseTextarea from './BaseTextarea.vue';
3
3
 
4
+ const sizes = ['xs', 'sm', 'md'];
5
+
4
6
  export default {
5
7
  title: 'Form/BaseTextarea',
6
8
  component: BaseTextarea,
7
9
  args: {
8
10
  placeholder: 'Describe your complete life in 4 sentences...',
9
11
  },
12
+ argTypes: {
13
+ size: {
14
+ control: { type: 'select' },
15
+ options: sizes,
16
+ },
17
+ },
10
18
  };
11
19
 
12
20
  const Template = (args) => ({
@@ -42,6 +50,23 @@ export const Field = createFieldStory({
42
50
  label: 'Biography',
43
51
  });
44
52
 
53
+ const TemplateSizes = (args) => ({
54
+ components: { BaseTextarea },
55
+ setup() {
56
+ const value = ref(null);
57
+ const sizes = ['xs', 'sm', 'md'];
58
+ return { args, value, sizes };
59
+ },
60
+ template: `
61
+ <div v-for="size in sizes" :key="size" class="mb-4">
62
+ <p class="text-xs text-slate-600 leading-tight mb-1">{{ size }}</p>
63
+ <BaseTextarea v-model="value" v-bind="args" :size="size" class="w-full"></BaseTextarea>
64
+ </div>
65
+ `,
66
+ });
67
+
68
+ export const Sizes = TemplateSizes.bind({});
69
+
45
70
  const FocusTemplate = (args) => ({
46
71
  components: { BaseTextarea },
47
72
  setup() {