sprintify-ui 0.4.6 → 0.4.8
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 +2636 -2490
- 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 -1
- 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 -0
|
@@ -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
|
@@ -10,6 +10,7 @@ import BaseAvatar from './BaseAvatar.vue';
|
|
|
10
10
|
import BaseAvatarGroup from './BaseAvatarGroup.vue';
|
|
11
11
|
import BaseBadge from './BaseBadge.vue';
|
|
12
12
|
import BaseBelongsTo from './BaseBelongsTo.vue';
|
|
13
|
+
import BaseBelongsToFetch from './BaseBelongsToFetch.vue';
|
|
13
14
|
import BaseBoolean from './BaseBoolean.vue';
|
|
14
15
|
import BaseBreadcrumbs from './BaseBreadcrumbs.vue';
|
|
15
16
|
import BaseButton from './BaseButton.vue';
|
|
@@ -109,6 +110,7 @@ export {
|
|
|
109
110
|
BaseAvatarGroup,
|
|
110
111
|
BaseBadge,
|
|
111
112
|
BaseBelongsTo,
|
|
113
|
+
BaseBelongsToFetch,
|
|
112
114
|
BaseBoolean,
|
|
113
115
|
BaseBreadcrumbs,
|
|
114
116
|
BaseButton,
|