sprintify-ui 0.0.76 → 0.0.78
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 +7357 -6179
- package/dist/types/src/components/BaseAutocomplete.vue.d.ts +130 -6
- package/dist/types/src/components/BaseAutocompleteFetch.vue.d.ts +99 -5
- package/dist/types/src/components/BaseBelongsTo.vue.d.ts +96 -2
- package/dist/types/src/components/BaseDropdown.vue.d.ts +131 -0
- package/dist/types/src/components/BaseInput.vue.d.ts +1 -1
- package/dist/types/src/components/BaseLocaleForm.vue.d.ts +1 -1
- package/dist/types/src/components/BaseNavbarSideItem.vue.d.ts +3 -3
- package/dist/types/src/components/BaseRadioGroup.vue.d.ts +4 -4
- package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +3 -3
- package/dist/types/src/components/BaseTagAutocompleteFetch.vue.d.ts +3 -3
- package/dist/types/src/components/index.d.ts +2 -1
- package/package.json +3 -1
- package/src/components/BaseAutocomplete.stories.js +46 -0
- package/src/components/BaseAutocomplete.vue +223 -108
- package/src/components/BaseAutocompleteFetch.stories.js +40 -0
- package/src/components/BaseAutocompleteFetch.vue +43 -6
- package/src/components/BaseBelongsTo.stories.js +40 -0
- package/src/components/BaseBelongsTo.vue +25 -0
- package/src/components/BaseDropdown.stories.js +102 -0
- package/src/components/BaseDropdown.vue +144 -0
- package/src/components/index.ts +2 -0
|
@@ -3,9 +3,19 @@ import ShowValue from '@/../.storybook/components/ShowValue.vue';
|
|
|
3
3
|
import { options } from '@/../.storybook/utils';
|
|
4
4
|
import { createFieldStory } from '../../.storybook/utils';
|
|
5
5
|
|
|
6
|
+
const sizes = ['xs', 'sm', 'base'];
|
|
7
|
+
|
|
6
8
|
export default {
|
|
7
9
|
title: 'Form/BaseBelongsTo',
|
|
8
10
|
component: BaseBelongsTo,
|
|
11
|
+
argTypes: {
|
|
12
|
+
size: {
|
|
13
|
+
control: {
|
|
14
|
+
type: 'select',
|
|
15
|
+
options: sizes,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
9
19
|
args: {
|
|
10
20
|
url: 'https://effettandem.com/api/content/articles',
|
|
11
21
|
field: 'title',
|
|
@@ -28,6 +38,36 @@ const Template = (args) => ({
|
|
|
28
38
|
export const Demo = Template.bind({});
|
|
29
39
|
Demo.args = {};
|
|
30
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 Sizes = (args) => ({
|
|
58
|
+
components: { BaseBelongsTo },
|
|
59
|
+
setup() {
|
|
60
|
+
const value = ref(null);
|
|
61
|
+
return { args, sizes, value };
|
|
62
|
+
},
|
|
63
|
+
template: `
|
|
64
|
+
<div v-for="size in sizes" class="mb-1">
|
|
65
|
+
<p class="text-xs text-slate-600 leading-tight">{{ size }}</p>
|
|
66
|
+
<BaseBelongsTo v-model="value" v-bind="args" :size="size"></BaseBelongsTo>
|
|
67
|
+
</div>
|
|
68
|
+
`,
|
|
69
|
+
});
|
|
70
|
+
|
|
31
71
|
export const Disabled = Template.bind({});
|
|
32
72
|
Disabled.args = {
|
|
33
73
|
currentModel: options[0],
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
:value-key="primaryKey"
|
|
10
10
|
:label-key="field"
|
|
11
11
|
:has-error="hasError"
|
|
12
|
+
:inline="inline"
|
|
13
|
+
:size="size"
|
|
14
|
+
:dropdown-show="dropdownShow"
|
|
15
|
+
:model-value-show="modelValueShow"
|
|
16
|
+
:visible-focus="visibleFocus"
|
|
12
17
|
@update:model-value="onUpdate"
|
|
13
18
|
>
|
|
14
19
|
<template #option="optionProps">
|
|
@@ -77,6 +82,26 @@ const props = defineProps({
|
|
|
77
82
|
default: false,
|
|
78
83
|
type: Boolean,
|
|
79
84
|
},
|
|
85
|
+
inline: {
|
|
86
|
+
default: false,
|
|
87
|
+
type: Boolean,
|
|
88
|
+
},
|
|
89
|
+
size: {
|
|
90
|
+
default: 'base',
|
|
91
|
+
type: String as PropType<'xs' | 'sm' | 'base'>,
|
|
92
|
+
},
|
|
93
|
+
dropdownShow: {
|
|
94
|
+
default: 'focus',
|
|
95
|
+
type: String as PropType<'focus' | 'always'>,
|
|
96
|
+
},
|
|
97
|
+
modelValueShow: {
|
|
98
|
+
default: true,
|
|
99
|
+
type: Boolean,
|
|
100
|
+
},
|
|
101
|
+
visibleFocus: {
|
|
102
|
+
default: true,
|
|
103
|
+
type: Boolean,
|
|
104
|
+
},
|
|
80
105
|
});
|
|
81
106
|
|
|
82
107
|
const http = config.http;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import BaseBadge from './BaseBadge.vue';
|
|
2
|
+
import BaseAutocomplete from './BaseAutocomplete.vue';
|
|
3
|
+
import BaseDropdown from './BaseDropdown.vue';
|
|
4
|
+
import { options } from '../../.storybook/utils';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: 'Components/BaseDropdown',
|
|
8
|
+
component: BaseDropdown,
|
|
9
|
+
args: {
|
|
10
|
+
placement: 'bottom-start',
|
|
11
|
+
offset: [0, 8],
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const Template = (args) => ({
|
|
16
|
+
components: { BaseDropdown },
|
|
17
|
+
setup() {
|
|
18
|
+
return { args };
|
|
19
|
+
},
|
|
20
|
+
template: `
|
|
21
|
+
<BaseDropdown v-bind="args">
|
|
22
|
+
<template #button>
|
|
23
|
+
<div class="btn btn-primary">Click me</div>
|
|
24
|
+
</template>
|
|
25
|
+
<template #dropdown>
|
|
26
|
+
<div class="bg-white shadow py-1 px-1 rounded">
|
|
27
|
+
<button type="button" class="block text-sm px-4 py-1.5">Item 1</button>
|
|
28
|
+
<button type="button" class="block text-sm px-4 py-1.5">Item 2</button>
|
|
29
|
+
<button type="button" class="block text-sm px-4 py-1.5">Item 3</button>
|
|
30
|
+
</div>
|
|
31
|
+
</template>
|
|
32
|
+
</BaseDropdown>
|
|
33
|
+
`,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export const Demo = Template.bind({});
|
|
37
|
+
|
|
38
|
+
export const Animated = Template.bind({});
|
|
39
|
+
Animated.args = {
|
|
40
|
+
animated: true,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const WithAutocomplete = (args) => ({
|
|
44
|
+
components: { BaseDropdown, BaseAutocomplete, BaseBadge },
|
|
45
|
+
setup() {
|
|
46
|
+
const value = ref(null);
|
|
47
|
+
const autocomplete = ref(null);
|
|
48
|
+
|
|
49
|
+
function onOpen() {
|
|
50
|
+
if (autocomplete.value) {
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
autocomplete.value.open();
|
|
53
|
+
}, 1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function onClose() {
|
|
58
|
+
if (autocomplete.value) {
|
|
59
|
+
setTimeout(() => {
|
|
60
|
+
autocomplete.value.setKeywords('');
|
|
61
|
+
}, 10);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function onUpdate(v, close) {
|
|
66
|
+
if (v) {
|
|
67
|
+
close();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return { args, options, value, onOpen, onClose, onUpdate, autocomplete };
|
|
71
|
+
},
|
|
72
|
+
template: `
|
|
73
|
+
<BaseDropdown @open="onOpen" @close="onClose" v-bind="args">
|
|
74
|
+
<template #button>
|
|
75
|
+
<BaseBadge>{{ value ? value.label : 'Select a Character' }}</BaseBadge>
|
|
76
|
+
</template>
|
|
77
|
+
<template #dropdown="{close}">
|
|
78
|
+
<div class="bg-white shadow border border-slate-300 py-1 px-1 rounded" style="min-width: 250px">
|
|
79
|
+
<BaseAutocomplete
|
|
80
|
+
ref="autocomplete"
|
|
81
|
+
required
|
|
82
|
+
v-model="value"
|
|
83
|
+
label-key="label"
|
|
84
|
+
value-key="value"
|
|
85
|
+
size="xs"
|
|
86
|
+
:options="options"
|
|
87
|
+
:inline="true"
|
|
88
|
+
:visibleFocus="false"
|
|
89
|
+
dropdownShow="always"
|
|
90
|
+
:modelValueShow="false"
|
|
91
|
+
@update:modelValue="onUpdate($event, close)"
|
|
92
|
+
></BaseAutocomplete>
|
|
93
|
+
</div>
|
|
94
|
+
</template>
|
|
95
|
+
</BaseDropdown>
|
|
96
|
+
`,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
WithAutocomplete.args = {
|
|
100
|
+
placement: 'bottom-start',
|
|
101
|
+
offset: [0, 3],
|
|
102
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<button ref="button" type="button" @click="toggle()">
|
|
4
|
+
<slot name="button"></slot>
|
|
5
|
+
</button>
|
|
6
|
+
<div ref="dropdown">
|
|
7
|
+
<Transition
|
|
8
|
+
:enter-active-class="
|
|
9
|
+
animated ? 'duration-100 transition ease-out' : ''
|
|
10
|
+
"
|
|
11
|
+
enter-from-class="transform scale-90 opacity-0"
|
|
12
|
+
enter-to-class="transform scale-100 opacity-100"
|
|
13
|
+
:leave-active-class="animated ? 'duration-75 transition ease-in' : ''"
|
|
14
|
+
leave-from-class="transform scale-100 opacity-100"
|
|
15
|
+
leave-to-class="transform scale-90 opacity-0"
|
|
16
|
+
>
|
|
17
|
+
<div v-show="showDropdown" ref="dropdown" class="inline-block">
|
|
18
|
+
<slot
|
|
19
|
+
name="dropdown"
|
|
20
|
+
:close="close"
|
|
21
|
+
:open="open"
|
|
22
|
+
:toggle="toggle"
|
|
23
|
+
></slot>
|
|
24
|
+
</div>
|
|
25
|
+
</Transition>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script lang="ts" setup>
|
|
31
|
+
import { bottom, createPopper, Placement } from '@popperjs/core';
|
|
32
|
+
import { PropType } from 'vue';
|
|
33
|
+
|
|
34
|
+
const button = ref<HTMLElement | null>(null);
|
|
35
|
+
const dropdown = ref<HTMLElement | null>(null);
|
|
36
|
+
|
|
37
|
+
const showDropdown = ref(false);
|
|
38
|
+
|
|
39
|
+
const props = defineProps({
|
|
40
|
+
placement: {
|
|
41
|
+
type: String as PropType<Placement>,
|
|
42
|
+
default() {
|
|
43
|
+
return bottom;
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
offset: {
|
|
47
|
+
default() {
|
|
48
|
+
return [0, 8];
|
|
49
|
+
},
|
|
50
|
+
type: Array as unknown as PropType<[number, number]>,
|
|
51
|
+
},
|
|
52
|
+
animated: {
|
|
53
|
+
default: false,
|
|
54
|
+
type: Boolean,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const emit = defineEmits(['close', 'open']);
|
|
59
|
+
|
|
60
|
+
onMounted(() => {
|
|
61
|
+
if (button.value && dropdown.value) {
|
|
62
|
+
createPopper(button.value, dropdown.value, {
|
|
63
|
+
placement: props.placement,
|
|
64
|
+
modifiers: [
|
|
65
|
+
{
|
|
66
|
+
name: 'offset',
|
|
67
|
+
options: {
|
|
68
|
+
offset: props.offset,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
function toggle() {
|
|
77
|
+
if (showDropdown.value) {
|
|
78
|
+
close();
|
|
79
|
+
} else {
|
|
80
|
+
open();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function open() {
|
|
85
|
+
activate();
|
|
86
|
+
showDropdown.value = true;
|
|
87
|
+
emit('open');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function close() {
|
|
91
|
+
deactivate();
|
|
92
|
+
showDropdown.value = false;
|
|
93
|
+
emit('close');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function activate() {
|
|
97
|
+
window.addEventListener('keydown', onKeydown);
|
|
98
|
+
window.addEventListener('mousedown', onMouseDown);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function deactivate() {
|
|
102
|
+
window.removeEventListener('keydown', onKeydown);
|
|
103
|
+
window.removeEventListener('mousedown', onMouseDown);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function onKeydown(event: KeyboardEvent) {
|
|
107
|
+
if (event.code == 'Escape') {
|
|
108
|
+
if (showDropdown.value) {
|
|
109
|
+
close();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function onMouseDown(event: MouseEvent) {
|
|
115
|
+
if (!dropdown.value) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// Get the element that was clicked
|
|
119
|
+
const clickedElement = event.target as HTMLElement | null;
|
|
120
|
+
|
|
121
|
+
if (!clickedElement) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Button is clicked
|
|
126
|
+
if (
|
|
127
|
+
button.value == clickedElement ||
|
|
128
|
+
button.value?.contains(clickedElement)
|
|
129
|
+
) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// `el` is the element you're detecting clicks outside of
|
|
134
|
+
if (dropdown.value.contains(clickedElement)) {
|
|
135
|
+
// do nothing..
|
|
136
|
+
} else {
|
|
137
|
+
close();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
onBeforeUnmount(() => {
|
|
142
|
+
deactivate();
|
|
143
|
+
});
|
|
144
|
+
</script>
|
package/src/components/index.ts
CHANGED
|
@@ -26,6 +26,7 @@ import BaseDateSelect from './BaseDateSelect.vue';
|
|
|
26
26
|
import BaseDescriptionList from './BaseDescriptionList.vue';
|
|
27
27
|
import BaseDescriptionListItem from './BaseDescriptionListItem.vue';
|
|
28
28
|
import BaseDialog from './BaseDialog.vue';
|
|
29
|
+
import BaseDropdown from './BaseDropdown.vue';
|
|
29
30
|
import BaseField from './BaseField.vue';
|
|
30
31
|
import BaseFieldI18n from './BaseFieldI18n.vue';
|
|
31
32
|
import BaseFilePicker from './BaseFilePicker.vue';
|
|
@@ -105,6 +106,7 @@ export {
|
|
|
105
106
|
BaseDescriptionList,
|
|
106
107
|
BaseDescriptionListItem,
|
|
107
108
|
BaseDialog,
|
|
109
|
+
BaseDropdown,
|
|
108
110
|
BaseField,
|
|
109
111
|
BaseFieldI18n,
|
|
110
112
|
BaseFilePicker,
|