sprintify-ui 0.0.41 → 0.0.42

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 (89) hide show
  1. package/dist/sprintify-ui.es.js +6033 -5518
  2. package/dist/types/src/components/BaseAutocomplete.vue.d.ts +32 -12
  3. package/dist/types/src/components/BaseAutocompleteFetch.vue.d.ts +28 -28
  4. package/dist/types/src/components/BaseBelongsTo.vue.d.ts +35 -35
  5. package/dist/types/src/components/BaseButtonGroup.vue.d.ts +46 -8
  6. package/dist/types/src/components/BaseDatePicker.vue.d.ts +18 -9
  7. package/dist/types/src/components/BaseDateSelect.vue.d.ts +14 -5
  8. package/dist/types/src/components/BaseField.vue.d.ts +151 -0
  9. package/dist/types/src/components/BaseFieldI18n.vue.d.ts +93 -0
  10. package/dist/types/src/components/BaseForm.vue.d.ts +267 -0
  11. package/dist/types/src/components/BaseFormField.d.ts +81 -0
  12. package/dist/types/src/components/BaseHasMany.vue.d.ts +31 -31
  13. package/dist/types/src/components/BaseInput.vue.d.ts +1 -1
  14. package/dist/types/src/components/BaseInputError.vue.d.ts +48 -0
  15. package/dist/types/src/components/BaseInputPercent.vue.d.ts +1 -1
  16. package/dist/types/src/components/BaseLocaleForm.vue.d.ts +420 -0
  17. package/dist/types/src/components/BaseMediaLibrary.vue.d.ts +46 -24
  18. package/dist/types/src/components/BaseNumberForm.vue.d.ts +382 -0
  19. package/dist/types/src/components/BasePassword.vue.d.ts +10 -14
  20. package/dist/types/src/components/BasePasswordForm.vue.d.ts +365 -0
  21. package/dist/types/src/components/BaseRadioGroup.vue.d.ts +23 -4
  22. package/dist/types/src/components/BaseSelect.vue.d.ts +20 -1
  23. package/dist/types/src/components/BaseSwitch.vue.d.ts +155 -23
  24. package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +31 -12
  25. package/dist/types/src/components/BaseTagAutocompleteFetch.vue.d.ts +20 -20
  26. package/dist/types/src/components/BaseTextarea.vue.d.ts +9 -0
  27. package/dist/types/src/components/BaseTextareaAutoresize.vue.d.ts +18 -0
  28. package/dist/types/src/components/BaseTextareaForm.vue.d.ts +394 -0
  29. package/dist/types/src/components/index.d.ts +4 -1
  30. package/dist/types/src/composables/field.d.ts +17 -0
  31. package/dist/types/src/index.d.ts +3 -0
  32. package/dist/types/src/types/index.d.ts +11 -0
  33. package/package.json +4 -1
  34. package/src/components/BaseAutocomplete.stories.js +56 -51
  35. package/src/components/BaseAutocomplete.vue +25 -8
  36. package/src/components/BaseAutocompleteFetch.stories.js +67 -65
  37. package/src/components/BaseAutocompleteFetch.vue +9 -29
  38. package/src/components/BaseBelongsTo.stories.js +72 -82
  39. package/src/components/BaseBelongsTo.vue +10 -11
  40. package/src/components/BaseButtonGroup.stories.js +11 -10
  41. package/src/components/BaseButtonGroup.vue +22 -9
  42. package/src/components/BaseCharacterCounter.stories.js +1 -1
  43. package/src/components/BaseDatePicker.stories.js +13 -9
  44. package/src/components/BaseDatePicker.vue +25 -8
  45. package/src/components/BaseDateSelect.stories.js +15 -9
  46. package/src/components/BaseDateSelect.vue +20 -8
  47. package/src/components/BaseField.vue +109 -0
  48. package/src/components/BaseFieldI18n.stories.js +38 -0
  49. package/src/components/BaseFieldI18n.vue +162 -0
  50. package/src/components/BaseFileUploader.stories.js +3 -3
  51. package/src/components/BaseFileUploader.vue +3 -3
  52. package/src/components/BaseForm.vue +298 -0
  53. package/src/components/BaseFormField.ts +117 -0
  54. package/src/components/BaseHasMany.stories.js +25 -10
  55. package/src/components/BaseHasMany.vue +9 -9
  56. package/src/components/BaseInput.stories.js +27 -14
  57. package/src/components/BaseInput.vue +17 -8
  58. package/src/components/BaseInputError.vue +7 -0
  59. package/src/components/BaseInputPercent.stories.js +10 -3
  60. package/src/components/BaseInputPercent.vue +2 -1
  61. package/src/components/BaseLocaleForm.vue +142 -0
  62. package/src/components/BaseMediaLibrary.stories.js +7 -6
  63. package/src/components/BaseMediaLibrary.vue +32 -31
  64. package/src/components/BaseMenu.vue +1 -1
  65. package/src/components/BaseNumberForm.vue +67 -0
  66. package/src/components/BasePassword.stories.js +9 -4
  67. package/src/components/BasePassword.vue +49 -44
  68. package/src/components/BasePasswordForm.vue +59 -0
  69. package/src/components/BaseRadioGroup.stories.js +9 -8
  70. package/src/components/BaseRadioGroup.vue +17 -3
  71. package/src/components/BaseSelect.stories.js +15 -2
  72. package/src/components/BaseSelect.vue +26 -10
  73. package/src/components/BaseSwitch.stories.js +7 -0
  74. package/src/components/BaseSwitch.vue +134 -124
  75. package/src/components/BaseTagAutocomplete.stories.js +21 -14
  76. package/src/components/BaseTagAutocomplete.vue +25 -14
  77. package/src/components/BaseTagAutocompleteFetch.stories.js +37 -21
  78. package/src/components/BaseTagAutocompleteFetch.vue +5 -5
  79. package/src/components/BaseTextarea.stories.js +11 -3
  80. package/src/components/BaseTextarea.vue +20 -6
  81. package/src/components/BaseTextareaAutoresize.stories.js +11 -2
  82. package/src/components/BaseTextareaAutoresize.vue +28 -4
  83. package/src/components/BaseTextareaForm.vue +101 -0
  84. package/src/components/BaseTimeline.vue +1 -1
  85. package/src/components/BaseTimelineItem.vue +4 -4
  86. package/src/components/index.ts +6 -0
  87. package/src/composables/field.ts +100 -0
  88. package/src/index.ts +11 -1
  89. package/src/types/index.ts +12 -0
@@ -6,11 +6,11 @@
6
6
  ref="inputElement"
7
7
  :value="keywords"
8
8
  type="text"
9
- :class="inputClass + ' pl-9'"
10
9
  :placeholder="
11
10
  placeholder ? placeholder : $t('sui.autocomplete_placeholder')
12
11
  "
13
- class="rounded disabled:cursor-not-allowed disabled:text-slate-300"
12
+ class="w-full rounded pl-9 disabled:cursor-not-allowed disabled:text-slate-300"
13
+ :class="[hasErrorInternal ? 'border-red-600' : 'border-slate-300']"
14
14
  autocomplete="off"
15
15
  :disabled="disabled"
16
16
  @focus="onTextFocus"
@@ -95,7 +95,11 @@
95
95
 
96
96
  <div ref="footer">
97
97
  <div v-if="$slots.footer" class="bg-white">
98
- <slot :options="filteredNormalizedOptions" name="footer" />
98
+ <slot
99
+ :options="filteredNormalizedOptions"
100
+ :keywords="keywords"
101
+ name="footer"
102
+ />
99
103
  </div>
100
104
  </div>
101
105
 
@@ -125,8 +129,10 @@ import { get } from 'lodash';
125
129
  import { PropType, Ref, ComputedRef } from 'vue';
126
130
  import { NormalizedOption, Option } from '@/types';
127
131
  import { useInfiniteScroll, useMutationObserver } from '@vueuse/core';
128
- import BaseSkeleton from './BaseSkeleton.vue';
132
+ import BaseSkeleton from '@/components/BaseSkeleton.vue';
129
133
  import { useHasOptions } from '@/composables/hasOptions';
134
+ import { useField } from '@/composables/field';
135
+ import { BaseIcon } from './index';
130
136
 
131
137
  const props = defineProps({
132
138
  modelValue: {
@@ -145,8 +151,8 @@ const props = defineProps({
145
151
  required: true,
146
152
  type: String,
147
153
  },
148
- inputClass: {
149
- default: 'border-slate-300 w-full',
154
+ name: {
155
+ default: undefined,
150
156
  type: String,
151
157
  },
152
158
  placeholder: {
@@ -169,6 +175,10 @@ const props = defineProps({
169
175
  default: undefined,
170
176
  type: Function as PropType<(option: NormalizedOption) => boolean>,
171
177
  },
178
+ hasError: {
179
+ default: false,
180
+ type: Boolean,
181
+ },
172
182
  });
173
183
 
174
184
  const emit = defineEmits([
@@ -179,6 +189,13 @@ const emit = defineEmits([
179
189
  'clear',
180
190
  ]);
181
191
 
192
+ const { hasErrorInternal, emitUpdate } = useField({
193
+ name: computed(() => props.name),
194
+ required: computed(() => props.required),
195
+ hasError: computed(() => props.hasError),
196
+ emit: emit,
197
+ });
198
+
182
199
  const timerId = ref(0);
183
200
  const keywords = ref('');
184
201
  const showDropdown = ref(false);
@@ -358,7 +375,7 @@ const update = (normalizedSelection: Option | null | undefined) => {
358
375
  if (normalizedSelection) {
359
376
  setKeywordsWithoutEvent(normalizedSelection.label);
360
377
  }
361
- emit('update:modelValue', selection);
378
+ emitUpdate(selection);
362
379
  };
363
380
 
364
381
  const setKeywordsWithoutEvent = (input: string) => {
@@ -387,6 +404,6 @@ useMutationObserver(
387
404
  () => {
388
405
  preventUnfocusOnFooter();
389
406
  },
390
- { attributes: false, childList: true }
407
+ { attributes: false, childList: true, subtree: true }
391
408
  );
392
409
  </script>
@@ -1,43 +1,39 @@
1
1
  import BaseAutocompleteFetch from './BaseAutocompleteFetch.vue';
2
+ import ShowValue from '@/../.storybook/components/ShowValue.vue';
3
+ import { options } from '@/../.storybook/utils';
4
+ import { createFieldStory } from '../../.storybook/utils';
2
5
 
3
6
  export default {
4
7
  title: 'Form/BaseAutocompleteFetch',
5
8
  component: BaseAutocompleteFetch,
6
- argTypes: {},
7
9
  args: {
8
10
  url: 'https://effettandem.com/api/content/articles',
9
11
  labelKey: 'title',
10
12
  valueKey: 'id',
11
- disabled: false,
12
13
  },
13
14
  decorators: [() => ({ template: '<div class="mb-36"><story/></div>' })],
14
15
  };
15
16
 
16
- const Template = (args) => {
17
- return {
18
- components: { BaseAutocompleteFetch },
19
- setup() {
20
- const value = ref(null);
21
- return { args, value };
22
- },
23
- template: `
24
- <BaseAutocompleteFetch
25
- v-model="value"
26
- v-bind="args"
27
- ></BaseAutocompleteFetch>
28
- <p class="mt-5 text-sm">Value: <span class="bg-slate-200 font-mono px-1 py-px rounded">{{ value ?? 'NULL' }}</span></p>
29
- `,
30
- };
31
- };
17
+ const Template = (args) => ({
18
+ components: { BaseAutocompleteFetch, ShowValue },
19
+ setup() {
20
+ const value = ref(null);
21
+ return { args, value };
22
+ },
23
+ template: `
24
+ <BaseAutocompleteFetch v-model="value" v-bind="args"></BaseAutocompleteFetch>
25
+ <ShowValue :value="value" />
26
+ `,
27
+ });
32
28
 
33
29
  export const Demo = Template.bind({});
34
30
  Demo.args = {};
35
31
 
36
32
  export const Disabled = Template.bind({});
37
33
  Disabled.args = {
38
- modelValue: { label: 'Dark Maul', value: '1' },
39
34
  labelKey: 'label',
40
35
  valueKey: 'value',
36
+ modelValue: options[0],
41
37
  disabled: true,
42
38
  };
43
39
 
@@ -49,28 +45,26 @@ export const SlotOption = (args) => {
49
45
  return { args, value };
50
46
  },
51
47
  template: `
52
- <div class="mb-20">
53
- <BaseAutocompleteFetch
54
- v-model="value"
55
- v-bind="args"
56
- >
57
- <template #option="{ option, active, selected }">
58
- <div
59
- class="rounded px-2 py-1"
60
- :class="{
61
- 'hover:bg-slate-100': !active && !selected,
62
- 'bg-slate-200 hover:bg-slate-300': active && !selected,
63
- 'bg-blue-500 text-white hover:bg-blue-600': !active && selected,
64
- 'bg-blue-600 text-white hover:bg-blue-700': active && selected,
65
- }"
66
- >
67
- <p class="text-sm font-medium">{{ option.title }}</p>
68
- <p class="opacity-60 text-xs">{{ option.owner?.name }}</p>
69
- </div>
70
- </template>
71
- </BaseAutocompleteFetch>
72
- </div>
73
- `,
48
+ <BaseAutocompleteFetch
49
+ v-model="value"
50
+ v-bind="args"
51
+ >
52
+ <template #option="{ option, active, selected }">
53
+ <div
54
+ class="rounded px-2 py-1"
55
+ :class="{
56
+ 'hover:bg-slate-100': !active && !selected,
57
+ 'bg-slate-200 hover:bg-slate-300': active && !selected,
58
+ 'bg-blue-500 text-white hover:bg-blue-600': !active && selected,
59
+ 'bg-blue-600 text-white hover:bg-blue-700': active && selected,
60
+ }"
61
+ >
62
+ <p class="text-sm font-medium">{{ option.title }}</p>
63
+ <p class="opacity-60 text-xs">{{ option.owner?.name }}</p>
64
+ </div>
65
+ </template>
66
+ </BaseAutocompleteFetch>
67
+ `,
74
68
  };
75
69
  };
76
70
 
@@ -80,22 +74,24 @@ export const SlotFooter = (args) => {
80
74
  setup() {
81
75
  const value = ref(null);
82
76
  function onClick() {
83
- alert(1);
77
+ setTimeout(() => {
78
+ alert(1);
79
+ }, 150);
84
80
  }
85
81
  return { args, value, onClick };
86
82
  },
87
83
  template: `
88
- <BaseAutocompleteFetch
89
- v-model="value"
90
- v-bind="args"
91
- >
92
- <template #footer>
93
- <div class="text-center p-2 border-t">
94
- <button @click=onClick class="btn btn-sm w-full btn-slate-200-outline">This is the footer 💯</button>
95
- </div>
96
- </template>
97
- </BaseAutocompleteFetch>
98
- `,
84
+ <BaseAutocompleteFetch
85
+ v-model="value"
86
+ v-bind="args"
87
+ >
88
+ <template #footer>
89
+ <div class="text-center p-2 border-t">
90
+ <button @click=onClick class="btn btn-sm w-full btn-slate-200-outline">This is the footer 💯</button>
91
+ </div>
92
+ </template>
93
+ </BaseAutocompleteFetch>
94
+ `,
99
95
  };
100
96
  };
101
97
 
@@ -107,17 +103,23 @@ export const SlotEmpty = (args) => {
107
103
  return { args, value };
108
104
  },
109
105
  template: `
110
- <BaseAutocompleteFetch
111
- v-model="value"
112
- v-bind="args"
113
- >
114
- <template #empty="props">
115
- <div>
116
- <div v-if="props.firstSearch" class="text-center py-10 p-6">🤓🤓🤓</div>
117
- <div v-else class="text-center p-6">Start your search... 🔎</div>
118
- </div>
119
- </template>
120
- </BaseAutocompleteFetch>
121
- `,
106
+ <BaseAutocompleteFetch
107
+ v-model="value"
108
+ v-bind="args"
109
+ >
110
+ <template #empty="props">
111
+ <div>
112
+ <div v-if="props.firstSearch" class="text-center py-10 p-6">🤓🤓🤓</div>
113
+ <div v-else class="text-center p-6">Start your search... 🔎</div>
114
+ </div>
115
+ </template>
116
+ </BaseAutocompleteFetch>
117
+ `,
122
118
  };
123
119
  };
120
+
121
+ export const Field = createFieldStory({
122
+ component: BaseAutocompleteFetch,
123
+ componentName: 'BaseAutocompleteFetch',
124
+ label: 'Article',
125
+ });
@@ -4,11 +4,12 @@
4
4
  :loading="showLoading && page == 1"
5
5
  :model-value="modelValue"
6
6
  :disabled="disabled"
7
+ :name="name"
7
8
  :placeholder="placeholder"
8
9
  :options="options"
9
10
  :value-key="valueKey"
10
11
  :label-key="labelKey"
11
- :input-class="inputClass"
12
+ :has-error="hasError"
12
13
  :filter="() => true"
13
14
  @clear="onClear"
14
15
  @focus="onFocus"
@@ -21,27 +22,7 @@
21
22
  </template>
22
23
 
23
24
  <template #footer="footerProps">
24
- <slot name="footer" v-bind="footerProps" :keywords="keywords">
25
- <div
26
- v-if="createNewUrl"
27
- class="p-2"
28
- :class="{
29
- 'border-t border-slate-300': footerProps.options.length > 0,
30
- }"
31
- >
32
- <router-link
33
- :to="createNewUrl"
34
- target="_blank"
35
- class="btn btn-slate-200-outline flex items-center justify-center"
36
- >
37
- <BaseIcon
38
- icon="heroicons-solid:plus"
39
- class="mr-1.5 block h-5 w-5"
40
- />
41
- <span>{{ $t('sui.create_new') }}</span>
42
- </router-link>
43
- </div>
44
- </slot>
25
+ <slot name="footer" v-bind="footerProps" :keywords="keywords" />
45
26
  </template>
46
27
 
47
28
  <template #empty="emptyProps">
@@ -58,11 +39,10 @@
58
39
  </template>
59
40
 
60
41
  <script lang="ts" setup>
61
- import { config } from '../';
42
+ import { config } from '@/index';
62
43
  import { debounce } from 'lodash';
63
44
  import { PropType, Ref } from 'vue';
64
45
  import { Option } from '@/types';
65
- import { RouteLocationRaw } from 'vue-router';
66
46
  import BaseAutocomplete from './BaseAutocomplete.vue';
67
47
 
68
48
  const props = defineProps({
@@ -82,7 +62,7 @@ const props = defineProps({
82
62
  required: true,
83
63
  type: String,
84
64
  },
85
- inputClass: {
65
+ name: {
86
66
  default: undefined,
87
67
  type: String,
88
68
  },
@@ -98,14 +78,14 @@ const props = defineProps({
98
78
  default: false,
99
79
  type: Boolean,
100
80
  },
101
- createNewUrl: {
102
- default: '',
103
- type: [String, Object] as PropType<RouteLocationRaw>,
104
- },
105
81
  queryKey: {
106
82
  default: 'search',
107
83
  type: String,
108
84
  },
85
+ hasError: {
86
+ default: false,
87
+ type: Boolean,
88
+ },
109
89
  });
110
90
 
111
91
  const emit = defineEmits([
@@ -1,9 +1,11 @@
1
1
  import BaseBelongsTo from './BaseBelongsTo.vue';
2
+ import ShowValue from '@/../.storybook/components/ShowValue.vue';
3
+ import { options } from '@/../.storybook/utils';
4
+ import { createFieldStory } from '../../.storybook/utils';
2
5
 
3
6
  export default {
4
7
  title: 'Form/BaseBelongsTo',
5
8
  component: BaseBelongsTo,
6
- argTypes: {},
7
9
  args: {
8
10
  url: 'https://effettandem.com/api/content/articles',
9
11
  field: 'title',
@@ -11,45 +13,27 @@ export default {
11
13
  decorators: [() => ({ template: '<div class="mb-36"><story/></div>' })],
12
14
  };
13
15
 
14
- const Template = (args) => {
15
- return {
16
- components: { BaseBelongsTo },
17
- setup() {
18
- const value = ref(null);
19
- return { args, value };
20
- },
21
- template: `
22
- <BaseBelongsTo
23
- v-model="value"
24
- v-bind="args"
25
- ></BaseBelongsTo>
26
- <p class="mt-5 text-sm">Value: <span class="bg-slate-200 font-mono px-1 py-px rounded">{{ value ?? 'NULL' }}</span></p>
27
- `,
28
- };
29
- };
16
+ const Template = (args) => ({
17
+ components: { BaseBelongsTo, ShowValue },
18
+ setup() {
19
+ const value = ref(null);
20
+ return { args, value };
21
+ },
22
+ template: `
23
+ <BaseBelongsTo v-model="value" v-bind="args"></BaseBelongsTo>
24
+ <ShowValue :value="value" />
25
+ `,
26
+ });
30
27
 
31
28
  export const Demo = Template.bind({});
32
29
  Demo.args = {};
33
30
 
34
- export const CreateNew = Template.bind({});
35
- CreateNew.args = {
36
- createNewUrl: '/users/create',
37
- };
38
-
39
- export const Disabled = (args) => {
40
- return {
41
- components: { BaseBelongsTo },
42
- setup() {
43
- const value = ref(null);
44
- return { args, value };
45
- },
46
- template: `<BaseBelongsTo
47
- v-bind="args"
48
- v-model="value"
49
- :current-model="{title: 'Dark Vader', id: 1}"
50
- :disabled="true"
51
- ></BaseBelongsTo>`,
52
- };
31
+ export const Disabled = Template.bind({});
32
+ Disabled.args = {
33
+ currentModel: options[0],
34
+ primaryKey: 'value',
35
+ field: 'label',
36
+ disabled: true,
53
37
  };
54
38
 
55
39
  export const SlotOption = (args) => {
@@ -60,28 +44,26 @@ export const SlotOption = (args) => {
60
44
  return { args, value };
61
45
  },
62
46
  template: `
63
- <div class="mb-20">
64
- <BaseBelongsTo
65
- v-model="value"
66
- v-bind="args"
67
- >
68
- <template #option="{ option, active, selected }">
69
- <div
70
- class="rounded px-2 py-1"
71
- :class="{
72
- 'hover:bg-slate-100': !active && !selected,
73
- 'bg-slate-200 hover:bg-slate-300': active && !selected,
74
- 'bg-blue-500 text-white hover:bg-blue-600': !active && selected,
75
- 'bg-blue-600 text-white hover:bg-blue-700': active && selected,
76
- }"
77
- >
78
- <p class="text-sm font-medium">{{ option.title }}</p>
79
- <p class="opacity-60 text-xs">{{ option.owner?.name }}</p>
80
- </div>
81
- </template>
82
- </BaseBelongsTo>
83
- </div>
84
- `,
47
+ <BaseBelongsTo
48
+ v-model="value"
49
+ v-bind="args"
50
+ >
51
+ <template #option="{ option, active, selected }">
52
+ <div
53
+ class="rounded px-2 py-1"
54
+ :class="{
55
+ 'hover:bg-slate-100': !active && !selected,
56
+ 'bg-slate-200 hover:bg-slate-300': active && !selected,
57
+ 'bg-blue-500 text-white hover:bg-blue-600': !active && selected,
58
+ 'bg-blue-600 text-white hover:bg-blue-700': active && selected,
59
+ }"
60
+ >
61
+ <p class="text-sm font-medium">{{ option.title }}</p>
62
+ <p class="opacity-60 text-xs">{{ option.owner?.name }}</p>
63
+ </div>
64
+ </template>
65
+ </BaseBelongsTo>
66
+ `,
85
67
  };
86
68
  };
87
69
 
@@ -91,22 +73,24 @@ export const SlotFooter = (args) => {
91
73
  setup() {
92
74
  const value = ref(null);
93
75
  function onClick() {
94
- alert(1);
76
+ setTimeout(() => {
77
+ alert(1);
78
+ }, 150);
95
79
  }
96
80
  return { args, value, onClick };
97
81
  },
98
82
  template: `
99
- <BaseBelongsTo
100
- v-model="value"
101
- v-bind="args"
102
- >
103
- <template #footer>
104
- <div class="text-center p-2 border-t">
105
- <button @click=onClick class="btn btn-sm w-full btn-slate-200-outline">This is the footer 💯</button>
106
- </div>
107
- </template>
108
- </BaseBelongsTo>
109
- `,
83
+ <BaseBelongsTo
84
+ v-model="value"
85
+ v-bind="args"
86
+ >
87
+ <template #footer>
88
+ <div class="text-center p-2 border-t">
89
+ <button @click=onClick class="btn btn-sm w-full btn-slate-200-outline">This is the footer 💯</button>
90
+ </div>
91
+ </template>
92
+ </BaseBelongsTo>
93
+ `,
110
94
  };
111
95
  };
112
96
 
@@ -118,17 +102,23 @@ export const SlotEmpty = (args) => {
118
102
  return { args, value };
119
103
  },
120
104
  template: `
121
- <BaseBelongsTo
122
- v-model="value"
123
- v-bind="args"
124
- >
125
- <template #empty="props">
126
- <div>
127
- <div v-if="props.firstSearch" class="text-center py-10 p-6">🤓🤓🤓</div>
128
- <div v-else class="text-center px-6 py-20">Start your search... 🔎</div>
129
- </div>
130
- </template>
131
- </BaseBelongsTo>
132
- `,
105
+ <BaseBelongsTo
106
+ v-model="value"
107
+ v-bind="args"
108
+ >
109
+ <template #empty="props">
110
+ <div>
111
+ <div v-if="props.firstSearch" class="text-center py-10 p-6">🤓🤓🤓</div>
112
+ <div v-else class="text-center p-6">Start your search... 🔎</div>
113
+ </div>
114
+ </template>
115
+ </BaseBelongsTo>
116
+ `,
133
117
  };
134
118
  };
119
+
120
+ export const Field = createFieldStory({
121
+ component: BaseBelongsTo,
122
+ componentName: 'BaseBelongsTo',
123
+ label: 'Article',
124
+ });
@@ -3,12 +3,12 @@
3
3
  :model-value="model"
4
4
  :url="url"
5
5
  :disabled="disabled"
6
+ :name="name"
6
7
  :placeholder="placeholder"
7
8
  :required="required"
8
- :value-key="foreignKey"
9
+ :value-key="primaryKey"
9
10
  :label-key="field"
10
- :create-new-url="createNewUrl"
11
- :input-class="inputClass"
11
+ :has-error="hasError"
12
12
  @update:model-value="onUpdate"
13
13
  >
14
14
  <template #option="optionProps">
@@ -25,7 +25,6 @@
25
25
 
26
26
  <script lang="ts" setup>
27
27
  import { PropType } from 'vue';
28
- import { RouteLocationRaw } from 'vue-router';
29
28
  import { AxiosResponse } from 'axios';
30
29
  import { config } from '@/index';
31
30
  import BaseAutocompleteFetch from './BaseAutocompleteFetch.vue';
@@ -46,7 +45,7 @@ const props = defineProps({
46
45
  default: undefined,
47
46
  type: Function as PropType<((id: string | number) => string) | undefined>,
48
47
  },
49
- foreignKey: {
48
+ primaryKey: {
50
49
  default: 'id',
51
50
  type: String,
52
51
  },
@@ -62,11 +61,11 @@ const props = defineProps({
62
61
  default: false,
63
62
  type: Boolean,
64
63
  },
65
- placeholder: {
64
+ name: {
66
65
  default: undefined,
67
66
  type: String,
68
67
  },
69
- inputClass: {
68
+ placeholder: {
70
69
  default: undefined,
71
70
  type: String,
72
71
  },
@@ -74,9 +73,9 @@ const props = defineProps({
74
73
  default: null,
75
74
  type: [Object, null] as PropType<Option | null>,
76
75
  },
77
- createNewUrl: {
78
- default: '',
79
- type: [String, Object] as PropType<RouteLocationRaw>,
76
+ hasError: {
77
+ default: false,
78
+ type: Boolean,
80
79
  },
81
80
  });
82
81
 
@@ -126,7 +125,7 @@ function onUpdate(newModel: Option | null) {
126
125
  emit('update:modelValue', null);
127
126
  } else {
128
127
  model.value = newModel;
129
- emit('update:modelValue', newModel[props.foreignKey]);
128
+ emit('update:modelValue', newModel[props.primaryKey]);
130
129
  }
131
130
  }
132
131
  </script>
@@ -1,4 +1,6 @@
1
+ import { createFieldStory, options } from '../../.storybook/utils';
1
2
  import BaseButtonGroup from './BaseButtonGroup.vue';
3
+ import ShowValue from '../../.storybook/components/ShowValue.vue';
2
4
 
3
5
  export default {
4
6
  title: 'Form/BaseButtonGroup',
@@ -7,27 +9,20 @@ export default {
7
9
  args: {
8
10
  labelKey: 'label',
9
11
  valueKey: 'value',
10
- options: [
11
- { label: 'Dark Vader', value: 'dark_vader' },
12
- { label: 'Darth Maul', value: 'darth_maul' },
13
- { label: 'Dark Sidious', value: 'dark_sidious' },
14
- { label: 'Obi Wan Kenobi', value: 'obiwan' },
15
- { label: 'Anakin Skywalker', value: 'anakin' },
16
- { label: 'Mace Windu', value: 'windu' },
17
- ],
12
+ options: options,
18
13
  },
19
14
  decorators: [() => ({ template: '<div class="mb-36"><story/></div>' })],
20
15
  };
21
16
 
22
17
  const Template = (args) => ({
23
- components: { BaseButtonGroup },
18
+ components: { BaseButtonGroup, ShowValue },
24
19
  setup() {
25
20
  const value = ref(null);
26
21
  return { args, value };
27
22
  },
28
23
  template: `
29
24
  <BaseButtonGroup v-model="value" v-bind="args"></BaseButtonGroup>
30
- <p class="mt-5 text-sm">Value: <span class="bg-slate-200 font-mono px-1 py-px rounded">{{ value ?? 'NULL' }}</span></p>
25
+ <ShowValue :value="value"></ShowValue>
31
26
  `,
32
27
  });
33
28
 
@@ -82,3 +77,9 @@ export const SlotOption = (args) => ({
82
77
  </BaseButtonGroup>
83
78
  `,
84
79
  });
80
+
81
+ export const Field = createFieldStory({
82
+ component: BaseButtonGroup,
83
+ componentName: 'BaseButtonGroup',
84
+ label: 'Choose your Jedi ou Sith',
85
+ });