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.
- package/dist/sprintify-ui.es.js +3 -3
- package/dist/types/src/components/BaseBelongsTo.vue.d.ts +5 -15
- package/dist/types/src/components/BaseBelongsToFetch.vue.d.ts +216 -0
- package/dist/types/src/components/index.d.ts +2 -2
- package/package.json +1 -1
- package/src/components/BaseBelongsTo.stories.js +13 -19
- package/src/components/BaseBelongsTo.vue +13 -49
- package/src/components/BaseBelongsToFetch.stories.js +223 -0
- package/src/components/BaseBelongsToFetch.vue +193 -0
- package/src/components/index.ts +2 -2
package/dist/sprintify-ui.es.js
CHANGED
|
@@ -9531,7 +9531,7 @@ const Gd = /* @__PURE__ */ Ce({
|
|
|
9531
9531
|
], 6));
|
|
9532
9532
|
}
|
|
9533
9533
|
}), JS = /* @__PURE__ */ Ce({
|
|
9534
|
-
__name: "
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
8
|
+
options: {
|
|
9
9
|
required: true;
|
|
10
|
-
type:
|
|
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
|
-
|
|
87
|
+
options: {
|
|
92
88
|
required: true;
|
|
93
|
-
type:
|
|
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
|
|
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,
|
|
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
|
@@ -17,8 +17,9 @@ export default {
|
|
|
17
17
|
},
|
|
18
18
|
},
|
|
19
19
|
args: {
|
|
20
|
-
|
|
21
|
-
field: '
|
|
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.
|
|
108
|
-
<p class="opacity-60 text-xs">{{ option.
|
|
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: '
|
|
177
|
-
{ label: '
|
|
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
|
|
184
|
+
const options2 = computed(() => {
|
|
187
185
|
if (selected.value == 'all' || !selected.value) {
|
|
188
|
-
return
|
|
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,
|
|
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
|
-
:
|
|
197
|
+
:options="options2"
|
|
204
198
|
:select="select"
|
|
205
199
|
>
|
|
206
200
|
</BaseBelongsTo>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
ref="
|
|
2
|
+
<BaseAutocomplete
|
|
3
|
+
ref="autocomplete"
|
|
4
4
|
:model-value="model"
|
|
5
|
-
:
|
|
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
|
-
</
|
|
41
|
+
</BaseAutocomplete>
|
|
42
42
|
</template>
|
|
43
43
|
|
|
44
44
|
<script lang="ts" setup>
|
|
45
45
|
import { PropType } from 'vue';
|
|
46
|
-
import
|
|
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
|
-
|
|
56
|
+
options: {
|
|
59
57
|
required: true,
|
|
60
|
-
type:
|
|
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
|
|
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: () =>
|
|
188
|
-
blur: () =>
|
|
189
|
-
open: () =>
|
|
190
|
-
close: () =>
|
|
191
|
-
setKeywords: (input: string) =>
|
|
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>
|
package/src/components/index.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
111
|
+
BaseBelongsToFetch,
|
|
112
112
|
BaseBoolean,
|
|
113
113
|
BaseBreadcrumbs,
|
|
114
114
|
BaseButton,
|