sprintify-ui 0.4.6 → 0.4.7

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.
@@ -9531,7 +9531,7 @@ const Gd = /* @__PURE__ */ Ce({
9531
9531
  ], 6));
9532
9532
  }
9533
9533
  }), JS = /* @__PURE__ */ Ce({
9534
- __name: "BaseBelongsTo",
9534
+ __name: "BaseBelongsToFetch",
9535
9535
  props: {
9536
9536
  modelValue: {
9537
9537
  default: void 0,
@@ -45609,7 +45609,7 @@ const CL = /* @__PURE__ */ Kn(AL, [["__scopeId", "data-v-a3256401"]]), TL = { cl
45609
45609
  BaseAvatar: Da,
45610
45610
  BaseAvatarGroup: LS,
45611
45611
  BaseBadge: Gd,
45612
- BaseBelongsTo: JS,
45612
+ BaseBelongsToFetch: JS,
45613
45613
  BaseBoolean: n_,
45614
45614
  BaseBreadcrumbs: Pg,
45615
45615
  BaseButton: Bg,
@@ -45743,7 +45743,7 @@ export {
45743
45743
  Da as BaseAvatar,
45744
45744
  LS as BaseAvatarGroup,
45745
45745
  Gd as BaseBadge,
45746
- JS as BaseBelongsTo,
45746
+ JS as BaseBelongsToFetch,
45747
45747
  n_ as BaseBoolean,
45748
45748
  Pg as BaseBreadcrumbs,
45749
45749
  Bg as BaseButton,
@@ -5,13 +5,9 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
5
5
  default: undefined;
6
6
  type: PropType<string | number | null | undefined>;
7
7
  };
8
- url: {
8
+ options: {
9
9
  required: true;
10
- type: StringConstructor;
11
- };
12
- showRouteUrl: {
13
- default: undefined;
14
- type: PropType<((id: string | number) => string) | undefined>;
10
+ type: PropType<Option[]>;
15
11
  };
16
12
  primaryKey: {
17
13
  default: string;
@@ -88,13 +84,9 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
88
84
  default: undefined;
89
85
  type: PropType<string | number | null | undefined>;
90
86
  };
91
- url: {
87
+ options: {
92
88
  required: true;
93
- type: StringConstructor;
94
- };
95
- showRouteUrl: {
96
- default: undefined;
97
- type: PropType<((id: string | number) => string) | undefined>;
89
+ type: PropType<Option[]>;
98
90
  };
99
91
  primaryKey: {
100
92
  default: string;
@@ -177,7 +169,6 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
177
169
  visibleFocus: boolean;
178
170
  showEmptyOption: boolean;
179
171
  emptyOptionLabel: string;
180
- showRouteUrl: ((id: string | number) => string) | undefined;
181
172
  primaryKey: string;
182
173
  currentModel: Option | null;
183
174
  }, {}>, {
@@ -192,7 +183,6 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
192
183
  active: boolean;
193
184
  }): any;
194
185
  empty?(_: {
195
- firstSearch: boolean;
196
186
  focus: () => void;
197
187
  blur: () => void;
198
188
  open: () => void;
@@ -200,11 +190,11 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
200
190
  keywords: import("vue").ComputedRef<string>;
201
191
  }): any;
202
192
  footer?(_: {
203
- keywords: string;
204
193
  focus: () => void;
205
194
  blur: () => void;
206
195
  open: () => void;
207
196
  close: () => void;
197
+ keywords: import("vue").ComputedRef<string>;
208
198
  options: import("@/types").NormalizedOption[];
209
199
  }): any;
210
200
  }>;
@@ -0,0 +1,216 @@
1
+ import { PropType } from 'vue';
2
+ import { Option, SelectConfiguration } from '@/types';
3
+ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
4
+ modelValue: {
5
+ default: undefined;
6
+ type: PropType<string | number | null | undefined>;
7
+ };
8
+ url: {
9
+ required: true;
10
+ type: StringConstructor;
11
+ };
12
+ showRouteUrl: {
13
+ default: undefined;
14
+ type: PropType<((id: string | number) => string) | undefined>;
15
+ };
16
+ primaryKey: {
17
+ default: string;
18
+ type: StringConstructor;
19
+ };
20
+ field: {
21
+ required: true;
22
+ type: StringConstructor;
23
+ };
24
+ required: {
25
+ default: boolean;
26
+ type: BooleanConstructor;
27
+ };
28
+ disabled: {
29
+ default: boolean;
30
+ type: BooleanConstructor;
31
+ };
32
+ name: {
33
+ default: undefined;
34
+ type: StringConstructor;
35
+ };
36
+ placeholder: {
37
+ default: undefined;
38
+ type: StringConstructor;
39
+ };
40
+ currentModel: {
41
+ default: null;
42
+ type: PropType<Option | null>;
43
+ };
44
+ hasError: {
45
+ default: boolean;
46
+ type: BooleanConstructor;
47
+ };
48
+ inline: {
49
+ default: boolean;
50
+ type: BooleanConstructor;
51
+ };
52
+ size: {
53
+ default: string;
54
+ type: PropType<"base" | "xs" | "sm">;
55
+ };
56
+ dropdownShow: {
57
+ default: string;
58
+ type: PropType<"focus" | "always">;
59
+ };
60
+ showModelValue: {
61
+ default: boolean;
62
+ type: BooleanConstructor;
63
+ };
64
+ visibleFocus: {
65
+ default: boolean;
66
+ type: BooleanConstructor;
67
+ };
68
+ showEmptyOption: {
69
+ default: boolean;
70
+ type: BooleanConstructor;
71
+ };
72
+ emptyOptionLabel: {
73
+ default: undefined;
74
+ type: StringConstructor;
75
+ };
76
+ select: {
77
+ default: undefined;
78
+ type: PropType<SelectConfiguration | undefined>;
79
+ };
80
+ }, {
81
+ focus: () => void | undefined;
82
+ blur: () => void | undefined;
83
+ open: () => void | undefined;
84
+ close: () => void | undefined;
85
+ setKeywords: (input: string) => void | undefined;
86
+ }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:modelValue"[], "update:modelValue", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
87
+ modelValue: {
88
+ default: undefined;
89
+ type: PropType<string | number | null | undefined>;
90
+ };
91
+ url: {
92
+ required: true;
93
+ type: StringConstructor;
94
+ };
95
+ showRouteUrl: {
96
+ default: undefined;
97
+ type: PropType<((id: string | number) => string) | undefined>;
98
+ };
99
+ primaryKey: {
100
+ default: string;
101
+ type: StringConstructor;
102
+ };
103
+ field: {
104
+ required: true;
105
+ type: StringConstructor;
106
+ };
107
+ required: {
108
+ default: boolean;
109
+ type: BooleanConstructor;
110
+ };
111
+ disabled: {
112
+ default: boolean;
113
+ type: BooleanConstructor;
114
+ };
115
+ name: {
116
+ default: undefined;
117
+ type: StringConstructor;
118
+ };
119
+ placeholder: {
120
+ default: undefined;
121
+ type: StringConstructor;
122
+ };
123
+ currentModel: {
124
+ default: null;
125
+ type: PropType<Option | null>;
126
+ };
127
+ hasError: {
128
+ default: boolean;
129
+ type: BooleanConstructor;
130
+ };
131
+ inline: {
132
+ default: boolean;
133
+ type: BooleanConstructor;
134
+ };
135
+ size: {
136
+ default: string;
137
+ type: PropType<"base" | "xs" | "sm">;
138
+ };
139
+ dropdownShow: {
140
+ default: string;
141
+ type: PropType<"focus" | "always">;
142
+ };
143
+ showModelValue: {
144
+ default: boolean;
145
+ type: BooleanConstructor;
146
+ };
147
+ visibleFocus: {
148
+ default: boolean;
149
+ type: BooleanConstructor;
150
+ };
151
+ showEmptyOption: {
152
+ default: boolean;
153
+ type: BooleanConstructor;
154
+ };
155
+ emptyOptionLabel: {
156
+ default: undefined;
157
+ type: StringConstructor;
158
+ };
159
+ select: {
160
+ default: undefined;
161
+ type: PropType<SelectConfiguration | undefined>;
162
+ };
163
+ }>> & {
164
+ "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
165
+ }, {
166
+ select: SelectConfiguration | undefined;
167
+ placeholder: string;
168
+ name: string;
169
+ disabled: boolean;
170
+ required: boolean;
171
+ inline: boolean;
172
+ modelValue: string | number | null | undefined;
173
+ hasError: boolean;
174
+ size: "base" | "xs" | "sm";
175
+ dropdownShow: "focus" | "always";
176
+ showModelValue: boolean;
177
+ visibleFocus: boolean;
178
+ showEmptyOption: boolean;
179
+ emptyOptionLabel: string;
180
+ showRouteUrl: ((id: string | number) => string) | undefined;
181
+ primaryKey: string;
182
+ currentModel: Option | null;
183
+ }, {}>, {
184
+ option?(_: {
185
+ focus: () => void;
186
+ blur: () => void;
187
+ open: () => void;
188
+ close: () => void;
189
+ keywords: import("vue").ComputedRef<string>;
190
+ option: Option;
191
+ selected: boolean;
192
+ active: boolean;
193
+ }): any;
194
+ empty?(_: {
195
+ firstSearch: boolean;
196
+ focus: () => void;
197
+ blur: () => void;
198
+ open: () => void;
199
+ close: () => void;
200
+ keywords: import("vue").ComputedRef<string>;
201
+ }): any;
202
+ footer?(_: {
203
+ keywords: string;
204
+ focus: () => void;
205
+ blur: () => void;
206
+ open: () => void;
207
+ close: () => void;
208
+ options: import("@/types").NormalizedOption[];
209
+ }): any;
210
+ }>;
211
+ export default _default;
212
+ type __VLS_WithTemplateSlots<T, S> = T & {
213
+ new (): {
214
+ $slots: S;
215
+ };
216
+ };
@@ -9,7 +9,7 @@ import BaseAutocompleteFetch from './BaseAutocompleteFetch.vue';
9
9
  import BaseAvatar from './BaseAvatar.vue';
10
10
  import BaseAvatarGroup from './BaseAvatarGroup.vue';
11
11
  import BaseBadge from './BaseBadge.vue';
12
- import BaseBelongsTo from './BaseBelongsTo.vue';
12
+ import BaseBelongsToFetch from './BaseBelongsToFetch.vue';
13
13
  import BaseBoolean from './BaseBoolean.vue';
14
14
  import BaseBreadcrumbs from './BaseBreadcrumbs.vue';
15
15
  import BaseButton from './BaseButton.vue';
@@ -94,4 +94,4 @@ import BaseLayoutStacked from './BaseLayoutStacked.vue';
94
94
  import BaseLayoutStackedConfigurable from './BaseLayoutStackedConfigurable.vue';
95
95
  import BaseLayoutSidebar from './BaseLayoutSidebar.vue';
96
96
  import BaseLayoutSidebarConfigurable from './BaseLayoutSidebarConfigurable.vue';
97
- export { BaseActionItem, BaseAddressForm, BaseAlert, BaseApp, BaseAppDialogs, BaseAppNotifications, BaseAutocomplete, BaseAutocompleteFetch, BaseAvatar, BaseAvatarGroup, BaseBadge, BaseBelongsTo, BaseBoolean, BaseBreadcrumbs, BaseButton, BaseButtonGroup, BaseCard, BaseCardRow, BaseCharacterCounter, BaseClickOutside, BaseClipboard, BaseCalendar, BaseColor, BaseContainer, BaseCounter, BaseCropper, BaseCropperModal, BaseDataIterator, BaseDataTable, BaseDatePicker, BaseDateSelect, BaseDescriptionList, BaseDescriptionListItem, BaseDialog, BaseDisplayRelativeTime, BaseDropdown, BaseDropdownAutocomplete, BaseEmptyState, BaseField, BaseFieldI18n, BaseFilePicker, BaseFilePickerCrop, BaseFileUploader, BaseForm, BaseGantt, BaseHasMany, BaseHeader, BaseIcon, BaseIconPicker, BaseInput, BaseInputLabel, BaseInputPercent, BaseLoadingCover, BaseMediaItem, BaseMediaLibrary, BaseMediaPreview, BaseMenu, BaseMenuItem, BaseModalCenter, BaseModalSide, BaseNavbar, BaseNavbarItem, BaseNavbarItemContent, BaseNavbarSideItem, BasePagination, BasePanel, BasePassword, BaseProgressCircle, BaseRadioGroup, BaseReadMore, BaseRichText, BaseSelect, BaseShortcut, BaseSideNavigation, BaseSideNavigationItem, BaseSkeleton, BaseStatistic, BaseStepper, BaseStepperItem, BaseSwitch, BaseSystemAlert, BaseTabs, BaseTabItem, BaseTagAutocomplete, BaseTagAutocompleteFetch, BaseTable, BaseTableColumn, BaseTextarea, BaseTextareaAutoresize, BaseTimeline, BaseTimelineItem, BaseUniqueCode, BaseLayoutStacked, BaseLayoutStackedConfigurable, BaseLayoutSidebar, BaseLayoutSidebarConfigurable, };
97
+ export { BaseActionItem, BaseAddressForm, BaseAlert, BaseApp, BaseAppDialogs, BaseAppNotifications, BaseAutocomplete, BaseAutocompleteFetch, BaseAvatar, BaseAvatarGroup, BaseBadge, BaseBelongsToFetch, BaseBoolean, BaseBreadcrumbs, BaseButton, BaseButtonGroup, BaseCard, BaseCardRow, BaseCharacterCounter, BaseClickOutside, BaseClipboard, BaseCalendar, BaseColor, BaseContainer, BaseCounter, BaseCropper, BaseCropperModal, BaseDataIterator, BaseDataTable, BaseDatePicker, BaseDateSelect, BaseDescriptionList, BaseDescriptionListItem, BaseDialog, BaseDisplayRelativeTime, BaseDropdown, BaseDropdownAutocomplete, BaseEmptyState, BaseField, BaseFieldI18n, BaseFilePicker, BaseFilePickerCrop, BaseFileUploader, BaseForm, BaseGantt, BaseHasMany, BaseHeader, BaseIcon, BaseIconPicker, BaseInput, BaseInputLabel, BaseInputPercent, BaseLoadingCover, BaseMediaItem, BaseMediaLibrary, BaseMediaPreview, BaseMenu, BaseMenuItem, BaseModalCenter, BaseModalSide, BaseNavbar, BaseNavbarItem, BaseNavbarItemContent, BaseNavbarSideItem, BasePagination, BasePanel, BasePassword, BaseProgressCircle, BaseRadioGroup, BaseReadMore, BaseRichText, BaseSelect, BaseShortcut, BaseSideNavigation, BaseSideNavigationItem, BaseSkeleton, BaseStatistic, BaseStepper, BaseStepperItem, BaseSwitch, BaseSystemAlert, BaseTabs, BaseTabItem, BaseTagAutocomplete, BaseTagAutocompleteFetch, BaseTable, BaseTableColumn, BaseTextarea, BaseTextareaAutoresize, BaseTimeline, BaseTimelineItem, BaseUniqueCode, BaseLayoutStacked, BaseLayoutStackedConfigurable, BaseLayoutSidebar, BaseLayoutSidebarConfigurable, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprintify-ui",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
4
4
  "scripts": {
5
5
  "build": "rimraf dist && vue-tsc && vite build",
6
6
  "build-fast": "rimraf dist && vite build",
@@ -17,8 +17,9 @@ export default {
17
17
  },
18
18
  },
19
19
  args: {
20
- url: 'https://effettandem.com/api/content/articles',
21
- field: 'title',
20
+ options: options,
21
+ field: 'label',
22
+ primaryKey: 'value',
22
23
  },
23
24
  decorators: [() => ({ template: '<div class="mb-36"><story/></div>' })],
24
25
  };
@@ -104,8 +105,8 @@ export const SlotOption = (args) => {
104
105
  'bg-blue-600 text-white hover:bg-blue-700': active && selected,
105
106
  }"
106
107
  >
107
- <p class="text-sm font-medium">{{ option.title }}</p>
108
- <p class="opacity-60 text-xs">{{ option.owner?.name }}</p>
108
+ <p class="text-sm font-medium">{{ option.label }}</p>
109
+ <p class="opacity-60 text-xs">{{ option.type }}</p>
109
110
  </div>
110
111
  </template>
111
112
  </BaseBelongsTo>
@@ -153,10 +154,7 @@ export const SlotEmpty = (args) => {
153
154
  v-bind="args"
154
155
  >
155
156
  <template #empty="props">
156
- <div>
157
- <div v-if="props.firstSearch" class="text-center py-10 p-6">🤓🤓🤓</div>
158
- <div v-else class="text-center p-6">Start your search... 🔎</div>
159
- </div>
157
+ <div class="text-center p-6 py-10 flex items-center justify-center">🤓🤓🤓</div>
160
158
  </template>
161
159
  </BaseBelongsTo>
162
160
  `,
@@ -173,8 +171,8 @@ export const WithSelect = (args) => {
173
171
  const select = {
174
172
  options: [
175
173
  { label: 'All', value: 'all' },
176
- { label: 'Video', value: 'video' },
177
- { label: 'Article', value: 'article' },
174
+ { label: 'Sith', value: 'sith' },
175
+ { label: 'Jedi', value: 'jedi' },
178
176
  ],
179
177
  labelKey: 'label',
180
178
  valueKey: 'value',
@@ -183,24 +181,20 @@ export const WithSelect = (args) => {
183
181
  },
184
182
  };
185
183
 
186
- const url = computed(() => {
184
+ const options2 = computed(() => {
187
185
  if (selected.value == 'all' || !selected.value) {
188
- return 'https://effettandem.com/api/content/articles';
186
+ return options;
189
187
  }
190
- return (
191
- 'https://effettandem.com/api/content/articles' +
192
- '?type=' +
193
- selected.value
194
- );
188
+ return options.filter((option) => option.type === selected.value);
195
189
  });
196
190
 
197
- return { args, value, url, selected, select };
191
+ return { args, value, options2, selected, select };
198
192
  },
199
193
  template: `
200
194
  <BaseBelongsTo
201
195
  v-model="value"
202
196
  v-bind="args"
203
- :url="url"
197
+ :options="options2"
204
198
  :select="select"
205
199
  >
206
200
  </BaseBelongsTo>
@@ -1,8 +1,8 @@
1
1
  <template>
2
- <BaseAutocompleteFetch
3
- ref="autocompleteFetch"
2
+ <BaseAutocomplete
3
+ ref="autocomplete"
4
4
  :model-value="model"
5
- :url="url"
5
+ :options="options"
6
6
  :disabled="disabled"
7
7
  :name="name"
8
8
  :placeholder="placeholder"
@@ -38,14 +38,12 @@
38
38
  v-bind="footerProps"
39
39
  />
40
40
  </template>
41
- </BaseAutocompleteFetch>
41
+ </BaseAutocomplete>
42
42
  </template>
43
43
 
44
44
  <script lang="ts" setup>
45
45
  import { PropType } from 'vue';
46
- import { AxiosResponse } from 'axios';
47
- import { config } from '@/index';
48
- import BaseAutocompleteFetch from './BaseAutocompleteFetch.vue';
46
+ import BaseAutocomplete from './BaseAutocomplete.vue';
49
47
  import { Option, SelectConfiguration } from '@/types';
50
48
 
51
49
  const props = defineProps({
@@ -55,13 +53,9 @@ const props = defineProps({
55
53
  string | number | null | undefined
56
54
  >,
57
55
  },
58
- url: {
56
+ options: {
59
57
  required: true,
60
- type: String,
61
- },
62
- showRouteUrl: {
63
- default: undefined,
64
- type: Function as PropType<((id: string | number) => string) | undefined>,
58
+ type: Array as PropType<Option[]>,
65
59
  },
66
60
  primaryKey: {
67
61
  default: 'id',
@@ -129,13 +123,9 @@ const props = defineProps({
129
123
  },
130
124
  });
131
125
 
132
- const http = config.http;
133
-
134
126
  const emit = defineEmits(['update:modelValue']);
135
127
 
136
- const autocompleteFetch = ref<InstanceType<
137
- typeof BaseAutocompleteFetch
138
- > | null>(null);
128
+ const autocomplete = ref<InstanceType<typeof BaseAutocomplete> | null>(null);
139
129
 
140
130
  const model = ref(props.currentModel);
141
131
 
@@ -147,32 +137,6 @@ watch(
147
137
  { deep: true }
148
138
  );
149
139
 
150
- watch(
151
- () => props.modelValue,
152
- (newValue, oldValue) => {
153
- if (!props.modelValue) {
154
- model.value = null;
155
- return;
156
- }
157
-
158
- if (newValue == oldValue) {
159
- return;
160
- }
161
-
162
- if (props.showRouteUrl == null) {
163
- return;
164
- }
165
-
166
- http
167
- .get(props.showRouteUrl(props.modelValue))
168
- .then((response: AxiosResponse) => {
169
- model.value = response.data.data;
170
- })
171
- .catch((e: Error) => e);
172
- },
173
- { immediate: true }
174
- );
175
-
176
140
  function onUpdate(newModel: Option | null) {
177
141
  if (!newModel) {
178
142
  model.value = null;
@@ -184,10 +148,10 @@ function onUpdate(newModel: Option | null) {
184
148
  }
185
149
 
186
150
  defineExpose({
187
- focus: () => autocompleteFetch.value?.focus(),
188
- blur: () => autocompleteFetch.value?.blur(),
189
- open: () => autocompleteFetch.value?.open(),
190
- close: () => autocompleteFetch.value?.close(),
191
- setKeywords: (input: string) => autocompleteFetch.value?.setKeywords(input),
151
+ focus: () => autocomplete.value?.focus(),
152
+ blur: () => autocomplete.value?.blur(),
153
+ open: () => autocomplete.value?.open(),
154
+ close: () => autocomplete.value?.close(),
155
+ setKeywords: (input: string) => autocomplete.value?.setKeywords(input),
192
156
  });
193
157
  </script>
@@ -0,0 +1,223 @@
1
+ import BaseBelongsToFetch from './BaseBelongsToFetch.vue';
2
+ import ShowValue from '@/../.storybook/components/ShowValue.vue';
3
+ import { options } from '@/../.storybook/utils';
4
+ import { createFieldStory } from '../../.storybook/utils';
5
+
6
+ const sizes = ['xs', 'sm', 'base'];
7
+
8
+ export default {
9
+ title: 'Form/BaseBelongsToFetch',
10
+ component: BaseBelongsToFetch,
11
+ argTypes: {
12
+ size: {
13
+ control: {
14
+ type: 'select',
15
+ options: sizes,
16
+ },
17
+ },
18
+ },
19
+ args: {
20
+ url: 'https://effettandem.com/api/content/articles',
21
+ field: 'title',
22
+ },
23
+ decorators: [() => ({ template: '<div class="mb-36"><story/></div>' })],
24
+ };
25
+
26
+ const Template = (args) => ({
27
+ components: { BaseBelongsToFetch, ShowValue },
28
+ setup() {
29
+ const value = ref(null);
30
+ return { args, value };
31
+ },
32
+ template: `
33
+ <BaseBelongsToFetch v-model="value" v-bind="args"></BaseBelongsToFetch>
34
+ <ShowValue :value="value" />
35
+ `,
36
+ });
37
+
38
+ export const Demo = Template.bind({});
39
+ Demo.args = {};
40
+
41
+ export const AlwaysShowDropdown = Template.bind({});
42
+ AlwaysShowDropdown.args = {
43
+ inline: true,
44
+ dropdownShow: 'always',
45
+ };
46
+
47
+ export const NoFocus = Template.bind({});
48
+ NoFocus.args = {
49
+ visibleFocus: false,
50
+ };
51
+
52
+ export const Inline = Template.bind({});
53
+ Inline.args = {
54
+ inline: true,
55
+ };
56
+
57
+ export const ShowEmptyOption = Template.bind({});
58
+ ShowEmptyOption.args = {
59
+ showEmptyOption: true,
60
+ emptyOptionLabel: 'No Jedi',
61
+ };
62
+
63
+ export const Sizes = (args) => ({
64
+ components: { BaseBelongsToFetch },
65
+ setup() {
66
+ const value = ref(null);
67
+ return { args, sizes, value };
68
+ },
69
+ template: `
70
+ <div v-for="size in sizes" class="mb-1">
71
+ <p class="text-xs text-slate-600 leading-tight">{{ size }}</p>
72
+ <BaseBelongsToFetch v-model="value" v-bind="args" :size="size"></BaseBelongsToFetch>
73
+ </div>
74
+ `,
75
+ });
76
+
77
+ export const Disabled = Template.bind({});
78
+ Disabled.args = {
79
+ currentModel: options[0],
80
+ primaryKey: 'value',
81
+ field: 'label',
82
+ disabled: true,
83
+ };
84
+
85
+ export const SlotOption = (args) => {
86
+ return {
87
+ components: { BaseBelongsToFetch },
88
+ setup() {
89
+ const value = ref(null);
90
+ return { args, value };
91
+ },
92
+ template: `
93
+ <BaseBelongsToFetch
94
+ v-model="value"
95
+ v-bind="args"
96
+ >
97
+ <template #option="{ option, active, selected }">
98
+ <div
99
+ class="rounded px-2 py-1"
100
+ :class="{
101
+ 'hover:bg-slate-100': !active && !selected,
102
+ 'bg-slate-200 hover:bg-slate-300': active && !selected,
103
+ 'bg-blue-500 text-white hover:bg-blue-600': !active && selected,
104
+ 'bg-blue-600 text-white hover:bg-blue-700': active && selected,
105
+ }"
106
+ >
107
+ <p class="text-sm font-medium">{{ option.title }}</p>
108
+ <p class="opacity-60 text-xs">{{ option.owner?.name }}</p>
109
+ </div>
110
+ </template>
111
+ </BaseBelongsToFetch>
112
+ `,
113
+ };
114
+ };
115
+
116
+ export const SlotFooter = (args) => {
117
+ return {
118
+ components: { BaseBelongsToFetch },
119
+ setup() {
120
+ const value = ref(null);
121
+ function onClick() {
122
+ setTimeout(() => {
123
+ alert(1);
124
+ }, 150);
125
+ }
126
+ return { args, value, onClick };
127
+ },
128
+ template: `
129
+ <BaseBelongsToFetch
130
+ v-model="value"
131
+ v-bind="args"
132
+ >
133
+ <template #footer>
134
+ <div class="text-center p-2 border-t">
135
+ <button @click=onClick class="btn btn-sm w-full btn-slate-200-outline">This is the footer 💯</button>
136
+ </div>
137
+ </template>
138
+ </BaseBelongsToFetch>
139
+ `,
140
+ };
141
+ };
142
+
143
+ export const SlotEmpty = (args) => {
144
+ return {
145
+ components: { BaseBelongsToFetch },
146
+ setup() {
147
+ const value = ref(null);
148
+ return { args, value };
149
+ },
150
+ template: `
151
+ <BaseBelongsToFetch
152
+ v-model="value"
153
+ v-bind="args"
154
+ >
155
+ <template #empty="props">
156
+ <div>
157
+ <div v-if="props.firstSearch" class="text-center py-10 p-6">🤓🤓🤓</div>
158
+ <div v-else class="text-center p-6">Start your search... 🔎</div>
159
+ </div>
160
+ </template>
161
+ </BaseBelongsToFetch>
162
+ `,
163
+ };
164
+ };
165
+
166
+ export const WithSelect = (args) => {
167
+ return {
168
+ components: { BaseBelongsToFetch, ShowValue },
169
+ setup() {
170
+ const value = ref(options[0]);
171
+ const selected = ref(null);
172
+
173
+ const select = {
174
+ options: [
175
+ { label: 'All', value: 'all' },
176
+ { label: 'Video', value: 'video' },
177
+ { label: 'Article', value: 'article' },
178
+ ],
179
+ labelKey: 'label',
180
+ valueKey: 'value',
181
+ onChange: (option) => {
182
+ selected.value = option.value;
183
+ },
184
+ };
185
+
186
+ const url = computed(() => {
187
+ if (selected.value == 'all' || !selected.value) {
188
+ return 'https://effettandem.com/api/content/articles';
189
+ }
190
+ return (
191
+ 'https://effettandem.com/api/content/articles' +
192
+ '?type=' +
193
+ selected.value
194
+ );
195
+ });
196
+
197
+ return { args, value, url, selected, select };
198
+ },
199
+ template: `
200
+ <BaseBelongsToFetch
201
+ v-model="value"
202
+ v-bind="args"
203
+ :url="url"
204
+ :select="select"
205
+ >
206
+ </BaseBelongsToFetch>
207
+
208
+ <div class="mb-2"></div>
209
+
210
+ <p class="text-xs mb-0">Selection</p>
211
+ <ShowValue class="mt-0 mb-2" :value="selected" />
212
+
213
+ <p class="text-xs mb-0">Model Value</p>
214
+ <ShowValue class="mt-0" :value="value" />
215
+ `,
216
+ };
217
+ };
218
+
219
+ export const Field = createFieldStory({
220
+ component: BaseBelongsToFetch,
221
+ componentName: 'BaseBelongsToFetch',
222
+ label: 'Article',
223
+ });
@@ -0,0 +1,193 @@
1
+ <template>
2
+ <BaseAutocompleteFetch
3
+ ref="autocompleteFetch"
4
+ :model-value="model"
5
+ :url="url"
6
+ :disabled="disabled"
7
+ :name="name"
8
+ :placeholder="placeholder"
9
+ :required="required"
10
+ :value-key="primaryKey"
11
+ :label-key="field"
12
+ :has-error="hasError"
13
+ :inline="inline"
14
+ :size="size"
15
+ :dropdown-show="dropdownShow"
16
+ :show-model-value="showModelValue"
17
+ :show-empty-option="showEmptyOption"
18
+ :empty-option-label="emptyOptionLabel"
19
+ :visible-focus="visibleFocus"
20
+ :select="select"
21
+ @update:model-value="onUpdate"
22
+ >
23
+ <template #option="optionProps">
24
+ <slot
25
+ name="option"
26
+ v-bind="optionProps"
27
+ />
28
+ </template>
29
+ <template #empty="emptyProps">
30
+ <slot
31
+ name="empty"
32
+ v-bind="emptyProps"
33
+ />
34
+ </template>
35
+ <template #footer="footerProps">
36
+ <slot
37
+ name="footer"
38
+ v-bind="footerProps"
39
+ />
40
+ </template>
41
+ </BaseAutocompleteFetch>
42
+ </template>
43
+
44
+ <script lang="ts" setup>
45
+ import { PropType } from 'vue';
46
+ import { AxiosResponse } from 'axios';
47
+ import { config } from '@/index';
48
+ import BaseAutocompleteFetch from './BaseAutocompleteFetch.vue';
49
+ import { Option, SelectConfiguration } from '@/types';
50
+
51
+ const props = defineProps({
52
+ modelValue: {
53
+ default: undefined,
54
+ type: [String, Number, null] as PropType<
55
+ string | number | null | undefined
56
+ >,
57
+ },
58
+ url: {
59
+ required: true,
60
+ type: String,
61
+ },
62
+ showRouteUrl: {
63
+ default: undefined,
64
+ type: Function as PropType<((id: string | number) => string) | undefined>,
65
+ },
66
+ primaryKey: {
67
+ default: 'id',
68
+ type: String,
69
+ },
70
+ field: {
71
+ required: true,
72
+ type: String,
73
+ },
74
+ required: {
75
+ default: false,
76
+ type: Boolean,
77
+ },
78
+ disabled: {
79
+ default: false,
80
+ type: Boolean,
81
+ },
82
+ name: {
83
+ default: undefined,
84
+ type: String,
85
+ },
86
+ placeholder: {
87
+ default: undefined,
88
+ type: String,
89
+ },
90
+ currentModel: {
91
+ default: null,
92
+ type: [Object, null] as PropType<Option | null>,
93
+ },
94
+ hasError: {
95
+ default: false,
96
+ type: Boolean,
97
+ },
98
+ inline: {
99
+ default: false,
100
+ type: Boolean,
101
+ },
102
+ size: {
103
+ default: 'base',
104
+ type: String as PropType<'xs' | 'sm' | 'base'>,
105
+ },
106
+ dropdownShow: {
107
+ default: 'focus',
108
+ type: String as PropType<'focus' | 'always'>,
109
+ },
110
+ showModelValue: {
111
+ default: true,
112
+ type: Boolean,
113
+ },
114
+ visibleFocus: {
115
+ default: true,
116
+ type: Boolean,
117
+ },
118
+ showEmptyOption: {
119
+ default: false,
120
+ type: Boolean,
121
+ },
122
+ emptyOptionLabel: {
123
+ default: undefined,
124
+ type: String,
125
+ },
126
+ select: {
127
+ default: undefined,
128
+ type: Object as PropType<SelectConfiguration | undefined>,
129
+ },
130
+ });
131
+
132
+ const http = config.http;
133
+
134
+ const emit = defineEmits(['update:modelValue']);
135
+
136
+ const autocompleteFetch = ref<InstanceType<
137
+ typeof BaseAutocompleteFetch
138
+ > | null>(null);
139
+
140
+ const model = ref(props.currentModel);
141
+
142
+ watch(
143
+ () => props.currentModel,
144
+ (newValue, oldValue) => {
145
+ model.value = newValue;
146
+ },
147
+ { deep: true }
148
+ );
149
+
150
+ watch(
151
+ () => props.modelValue,
152
+ (newValue, oldValue) => {
153
+ if (!props.modelValue) {
154
+ model.value = null;
155
+ return;
156
+ }
157
+
158
+ if (newValue == oldValue) {
159
+ return;
160
+ }
161
+
162
+ if (props.showRouteUrl == null) {
163
+ return;
164
+ }
165
+
166
+ http
167
+ .get(props.showRouteUrl(props.modelValue))
168
+ .then((response: AxiosResponse) => {
169
+ model.value = response.data.data;
170
+ })
171
+ .catch((e: Error) => e);
172
+ },
173
+ { immediate: true }
174
+ );
175
+
176
+ function onUpdate(newModel: Option | null) {
177
+ if (!newModel) {
178
+ model.value = null;
179
+ emit('update:modelValue', null);
180
+ } else {
181
+ model.value = newModel;
182
+ emit('update:modelValue', newModel[props.primaryKey]);
183
+ }
184
+ }
185
+
186
+ defineExpose({
187
+ focus: () => autocompleteFetch.value?.focus(),
188
+ blur: () => autocompleteFetch.value?.blur(),
189
+ open: () => autocompleteFetch.value?.open(),
190
+ close: () => autocompleteFetch.value?.close(),
191
+ setKeywords: (input: string) => autocompleteFetch.value?.setKeywords(input),
192
+ });
193
+ </script>
@@ -9,7 +9,7 @@ import BaseAutocompleteFetch from './BaseAutocompleteFetch.vue';
9
9
  import BaseAvatar from './BaseAvatar.vue';
10
10
  import BaseAvatarGroup from './BaseAvatarGroup.vue';
11
11
  import BaseBadge from './BaseBadge.vue';
12
- import BaseBelongsTo from './BaseBelongsTo.vue';
12
+ import BaseBelongsToFetch from './BaseBelongsToFetch.vue';
13
13
  import BaseBoolean from './BaseBoolean.vue';
14
14
  import BaseBreadcrumbs from './BaseBreadcrumbs.vue';
15
15
  import BaseButton from './BaseButton.vue';
@@ -108,7 +108,7 @@ export {
108
108
  BaseAvatar,
109
109
  BaseAvatarGroup,
110
110
  BaseBadge,
111
- BaseBelongsTo,
111
+ BaseBelongsToFetch,
112
112
  BaseBoolean,
113
113
  BaseBreadcrumbs,
114
114
  BaseButton,