sprintify-ui 0.5.12 → 0.6.0
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 +11791 -11616
- package/dist/types/src/components/BaseAutocomplete.vue.d.ts +9 -0
- package/dist/types/src/components/BaseAutocompleteFetch.vue.d.ts +9 -0
- package/dist/types/src/components/BaseBelongsTo.vue.d.ts +9 -0
- package/dist/types/src/components/BaseBelongsToFetch.vue.d.ts +9 -0
- package/dist/types/src/components/BaseDropdown.vue.d.ts +12 -35
- package/dist/types/src/components/BaseDropdownAutocomplete.vue.d.ts +4 -14
- package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +9 -0
- package/dist/types/src/components/BaseTagAutocompleteFetch.vue.d.ts +9 -0
- package/dist/types/src/components/BaseTooltip.vue.d.ts +2 -3
- package/dist/types/src/components/index.d.ts +1 -2
- package/package.json +1 -1
- package/src/components/BaseAutocomplete.vue +27 -5
- package/src/components/BaseAutocompleteFetch.vue +5 -0
- package/src/components/BaseBelongsTo.vue +5 -0
- package/src/components/BaseBelongsToFetch.vue +5 -0
- package/src/components/BaseDatePicker.vue +4 -4
- package/src/components/BaseDropdown.stories.js +22 -65
- package/src/components/BaseDropdown.vue +37 -243
- package/src/components/BaseDropdownAutocomplete.vue +5 -30
- package/src/components/BaseTagAutocomplete.vue +19 -2
- package/src/components/BaseTagAutocompleteFetch.vue +5 -0
- package/src/components/BaseTooltip.vue +3 -7
- package/src/components/index.ts +0 -2
- package/dist/types/src/components/BaseClickOutside.vue.d.ts +0 -28
- package/src/components/BaseClickOutside.vue +0 -37
|
@@ -3,7 +3,6 @@ import BaseAutocomplete from './BaseAutocomplete.vue';
|
|
|
3
3
|
import BaseModalCenter from './BaseModalCenter.vue';
|
|
4
4
|
import BaseDropdown from './BaseDropdown.vue';
|
|
5
5
|
import BaseDatePicker from './BaseDatePicker.vue';
|
|
6
|
-
import BaseClickOutside from './BaseClickOutside.vue';
|
|
7
6
|
import { options } from '../../.storybook/utils';
|
|
8
7
|
|
|
9
8
|
const items = [];
|
|
@@ -21,13 +20,12 @@ export default {
|
|
|
21
20
|
placement: {
|
|
22
21
|
control: {
|
|
23
22
|
type: 'select',
|
|
24
|
-
options: ['top-start', 'top-end', 'bottom-start', 'bottom-end'],
|
|
25
23
|
},
|
|
24
|
+
options: ['top-start', 'top-end', 'bottom-start', 'bottom-end'],
|
|
26
25
|
},
|
|
27
26
|
},
|
|
28
27
|
args: {
|
|
29
28
|
placement: 'bottom-start',
|
|
30
|
-
padding: 8,
|
|
31
29
|
},
|
|
32
30
|
};
|
|
33
31
|
|
|
@@ -73,40 +71,23 @@ export const WithAutocomplete = (args) => ({
|
|
|
73
71
|
components: { BaseDropdown, BaseAutocomplete, BaseBadge },
|
|
74
72
|
setup() {
|
|
75
73
|
const value = ref(null);
|
|
76
|
-
const autocomplete = ref(null);
|
|
77
|
-
|
|
78
|
-
function onOpen() {
|
|
79
|
-
if (autocomplete.value) {
|
|
80
|
-
setTimeout(() => {
|
|
81
|
-
autocomplete.value.open();
|
|
82
|
-
}, 1);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function onClose() {
|
|
87
|
-
setTimeout(() => {
|
|
88
|
-
if (autocomplete.value) {
|
|
89
|
-
autocomplete.value.setKeywords('');
|
|
90
|
-
}
|
|
91
|
-
}, 10);
|
|
92
|
-
}
|
|
93
74
|
|
|
94
75
|
function onUpdate(v, close) {
|
|
95
76
|
if (v) {
|
|
96
77
|
close();
|
|
97
78
|
}
|
|
98
79
|
}
|
|
99
|
-
|
|
80
|
+
|
|
81
|
+
return { args, options, value, onUpdate };
|
|
100
82
|
},
|
|
101
83
|
template: `
|
|
102
|
-
<BaseDropdown
|
|
84
|
+
<BaseDropdown v-bind="args">
|
|
103
85
|
<template #button>
|
|
104
86
|
<BaseBadge>{{ value ? value.label : 'Select a Character' }}</BaseBadge>
|
|
105
87
|
</template>
|
|
106
88
|
<template #dropdown="{close}">
|
|
107
|
-
<div class="bg-white shadow
|
|
89
|
+
<div class="bg-white shadow-lg rounded-md border py-2 px-2" style="min-width: 250px">
|
|
108
90
|
<BaseAutocomplete
|
|
109
|
-
ref="autocomplete"
|
|
110
91
|
required
|
|
111
92
|
v-model="value"
|
|
112
93
|
label-key="label"
|
|
@@ -117,6 +98,7 @@ export const WithAutocomplete = (args) => ({
|
|
|
117
98
|
:visibleFocus="false"
|
|
118
99
|
dropdownShow="always"
|
|
119
100
|
:showModelValue="false"
|
|
101
|
+
focus-on-mount
|
|
120
102
|
@update:modelValue="onUpdate($event, close)"
|
|
121
103
|
></BaseAutocomplete>
|
|
122
104
|
</div>
|
|
@@ -128,37 +110,8 @@ export const WithAutocomplete = (args) => ({
|
|
|
128
110
|
WithAutocomplete.args = {
|
|
129
111
|
animated: true,
|
|
130
112
|
placement: 'bottom-start',
|
|
131
|
-
padding: 3,
|
|
132
113
|
};
|
|
133
114
|
|
|
134
|
-
export const ModalWithScroll = (args) => ({
|
|
135
|
-
components: { BaseDropdown, BaseModalCenter },
|
|
136
|
-
setup() {
|
|
137
|
-
return { args, items };
|
|
138
|
-
},
|
|
139
|
-
template: `
|
|
140
|
-
<BaseModalCenter :model-value="true">
|
|
141
|
-
<div class="p-10 bg-white">
|
|
142
|
-
<BaseDropdown v-bind="args">
|
|
143
|
-
<template #button>
|
|
144
|
-
<div class="btn btn-primary">Click me</div>
|
|
145
|
-
</template>
|
|
146
|
-
<template #dropdown>
|
|
147
|
-
<div
|
|
148
|
-
class="bg-white shadow py-1 px-1 rounded"
|
|
149
|
-
style="max-height: 200px; overflow: auto;"
|
|
150
|
-
data-scroll-lock-scrollable>
|
|
151
|
-
<button type="button" v-for="item in items" :key="item.label" class="block text-sm px-4 py-1.5">{{ item.label }}</button>
|
|
152
|
-
</div>
|
|
153
|
-
</template>
|
|
154
|
-
</BaseDropdown>
|
|
155
|
-
|
|
156
|
-
<div style="height: 3000px;"></div>
|
|
157
|
-
</div>
|
|
158
|
-
</BaseModalCenter>
|
|
159
|
-
`,
|
|
160
|
-
});
|
|
161
|
-
|
|
162
115
|
export const WithDatePicker = (args) => ({
|
|
163
116
|
components: { BaseDropdown, BaseDatePicker },
|
|
164
117
|
setup() {
|
|
@@ -171,7 +124,7 @@ export const WithDatePicker = (args) => ({
|
|
|
171
124
|
<div class="btn btn-primary">Click me</div>
|
|
172
125
|
</template>
|
|
173
126
|
<template #dropdown>
|
|
174
|
-
<div class="bg-white shadow-lg rounded
|
|
127
|
+
<div class="bg-white shadow-lg rounded-md ring-1 ring-black ring-opacity-10 p-2">
|
|
175
128
|
<BaseDatePicker v-model="date" :show-input="true" inline></BaseDatePicker>
|
|
176
129
|
</div>
|
|
177
130
|
</template>
|
|
@@ -180,31 +133,35 @@ export const WithDatePicker = (args) => ({
|
|
|
180
133
|
});
|
|
181
134
|
|
|
182
135
|
WithDatePicker.args = {
|
|
136
|
+
animated: true,
|
|
183
137
|
placement: 'bottom-start',
|
|
184
138
|
};
|
|
185
139
|
|
|
186
|
-
export const
|
|
187
|
-
components: { BaseDropdown,
|
|
140
|
+
export const ModalWithScroll = (args) => ({
|
|
141
|
+
components: { BaseDropdown, BaseModalCenter },
|
|
188
142
|
setup() {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
return { args, items, onClickOutside };
|
|
143
|
+
const open = ref(true);
|
|
144
|
+
return { args, items, open };
|
|
193
145
|
},
|
|
194
146
|
template: `
|
|
195
|
-
<
|
|
196
|
-
<div class="
|
|
147
|
+
<BaseModalCenter v-model="open">
|
|
148
|
+
<div class="p-10 bg-white">
|
|
197
149
|
<BaseDropdown v-bind="args">
|
|
198
150
|
<template #button>
|
|
199
151
|
<div class="btn btn-primary">Click me</div>
|
|
200
152
|
</template>
|
|
201
153
|
<template #dropdown>
|
|
202
|
-
<div
|
|
203
|
-
|
|
154
|
+
<div
|
|
155
|
+
class="bg-white shadow py-1 px-1 rounded"
|
|
156
|
+
style="max-height: 200px; overflow: auto;"
|
|
157
|
+
data-scroll-lock-scrollable>
|
|
158
|
+
<button type="button" v-for="item in items" :key="item.label" class="block text-sm px-4 py-1.5">{{ item.label }}</button>
|
|
204
159
|
</div>
|
|
205
160
|
</template>
|
|
206
161
|
</BaseDropdown>
|
|
162
|
+
|
|
163
|
+
<div style="height: 3000px;"></div>
|
|
207
164
|
</div>
|
|
208
|
-
</
|
|
165
|
+
</BaseModalCenter>
|
|
209
166
|
`,
|
|
210
167
|
});
|
|
@@ -1,280 +1,74 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
ref="
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
>
|
|
8
|
-
|
|
9
|
-
</button>
|
|
2
|
+
<Popover v-slot="{ open }">
|
|
3
|
+
<PopoverButton class="outline-none">
|
|
4
|
+
<div ref="buttonRef">
|
|
5
|
+
<slot name="button" />
|
|
6
|
+
</div>
|
|
7
|
+
</PopoverButton>
|
|
8
|
+
|
|
10
9
|
<Teleport to="body">
|
|
11
10
|
<div
|
|
12
|
-
ref="
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
ref="dropdownRef"
|
|
12
|
+
:style="floatingStyles"
|
|
13
|
+
class="fixed top-0 left-0 z-menu"
|
|
15
14
|
>
|
|
16
15
|
<Transition
|
|
17
|
-
:enter-active-class="
|
|
18
|
-
animated ? 'transition duration-200 ease-out' : ''
|
|
19
|
-
"
|
|
16
|
+
:enter-active-class="animated ? 'transition duration-200 ease-out' : ''"
|
|
20
17
|
enter-from-class="transform scale-95 opacity-0"
|
|
21
18
|
enter-to-class="transform scale-100 opacity-100"
|
|
22
19
|
:leave-active-class="animated ? 'transition duration-75 ease-in' : ''"
|
|
23
20
|
leave-from-class="transform scale-100 opacity-100"
|
|
24
21
|
leave-to-class="transform scale-95 opacity-0"
|
|
25
22
|
>
|
|
26
|
-
<
|
|
27
|
-
<
|
|
28
|
-
v-show="
|
|
29
|
-
|
|
23
|
+
<div v-if="open || keepAlive">
|
|
24
|
+
<PopoverPanel
|
|
25
|
+
v-show="open"
|
|
26
|
+
v-slot="{ close }"
|
|
27
|
+
static
|
|
30
28
|
>
|
|
31
29
|
<slot
|
|
32
30
|
name="dropdown"
|
|
33
|
-
:show-dropdown="showDropdown"
|
|
34
31
|
:close="close"
|
|
35
|
-
:
|
|
36
|
-
:toggle="toggle"
|
|
32
|
+
:opened="open"
|
|
37
33
|
/>
|
|
38
|
-
</
|
|
39
|
-
</
|
|
34
|
+
</PopoverPanel>
|
|
35
|
+
</div>
|
|
40
36
|
</Transition>
|
|
41
37
|
</div>
|
|
42
38
|
</Teleport>
|
|
43
|
-
</
|
|
39
|
+
</Popover>
|
|
44
40
|
</template>
|
|
45
41
|
|
|
46
42
|
<script lang="ts" setup>
|
|
47
|
-
import {
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
50
|
-
import { PropType
|
|
51
|
-
|
|
43
|
+
import { autoUpdate, offset, flip, shift, useFloating, Placement } from '@floating-ui/vue';
|
|
44
|
+
import { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue';
|
|
45
|
+
import { unrefElement } from '@vueuse/core';
|
|
46
|
+
import { PropType } from 'vue';
|
|
47
|
+
|
|
48
|
+
const buttonRef = ref<InstanceType<typeof PopoverButton> | null>(null);
|
|
49
|
+
const dropdownRef = ref<HTMLElement | null>(null);
|
|
52
50
|
|
|
53
|
-
const
|
|
54
|
-
const dropdown = ref<HTMLElement | null>(null);
|
|
51
|
+
const buttonRefEl = computed(() => unrefElement(buttonRef));
|
|
55
52
|
|
|
56
|
-
const showDropdown = ref(false);
|
|
57
53
|
const props = defineProps({
|
|
58
|
-
placement: {
|
|
59
|
-
type: String as PropType<
|
|
60
|
-
'bottom-start' | 'bottom-end' | 'top-start' | 'top-end'
|
|
61
|
-
>,
|
|
62
|
-
default() {
|
|
63
|
-
return 'bottom-start';
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
padding: {
|
|
67
|
-
default: 8,
|
|
68
|
-
type: Number,
|
|
69
|
-
},
|
|
70
54
|
animated: {
|
|
71
|
-
default:
|
|
55
|
+
default: true,
|
|
72
56
|
type: Boolean,
|
|
73
57
|
},
|
|
74
58
|
keepAlive: {
|
|
75
|
-
default:
|
|
59
|
+
default: false,
|
|
76
60
|
type: Boolean,
|
|
77
61
|
},
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const buttonX = ref(0);
|
|
83
|
-
const buttonY = ref(0);
|
|
84
|
-
const buttonWidth = ref(0);
|
|
85
|
-
const buttonHeight = ref(0);
|
|
86
|
-
|
|
87
|
-
const dropdownX = ref(0);
|
|
88
|
-
const dropdownY = ref(0);
|
|
89
|
-
const dropdownWidth = ref(0);
|
|
90
|
-
const dropdownHeight = ref(0);
|
|
91
|
-
|
|
92
|
-
function setBoundingBoxes() {
|
|
93
|
-
if (button.value) {
|
|
94
|
-
const { y, x, height, width } = button.value.getBoundingClientRect();
|
|
95
|
-
buttonX.value = x;
|
|
96
|
-
buttonY.value = y;
|
|
97
|
-
buttonWidth.value = width;
|
|
98
|
-
buttonHeight.value = height;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (dropdown.value) {
|
|
102
|
-
const { y, x, height, width } = dropdown.value.getBoundingClientRect();
|
|
103
|
-
dropdownX.value = x;
|
|
104
|
-
dropdownY.value = y;
|
|
105
|
-
dropdownWidth.value = width;
|
|
106
|
-
dropdownHeight.value = height;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function toggle() {
|
|
111
|
-
if (showDropdown.value) {
|
|
112
|
-
close();
|
|
113
|
-
} else {
|
|
114
|
-
open();
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function open() {
|
|
119
|
-
activate();
|
|
120
|
-
showDropdown.value = true;
|
|
121
|
-
nextTick(() => {
|
|
122
|
-
setBoundingBoxes();
|
|
123
|
-
disableScroll();
|
|
124
|
-
emit('open');
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function close() {
|
|
129
|
-
deactivate();
|
|
130
|
-
showDropdown.value = false;
|
|
131
|
-
enableScroll();
|
|
132
|
-
emit('close');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function onKeydown(event: KeyboardEvent) {
|
|
136
|
-
if (event.code == 'Escape') {
|
|
137
|
-
if (showDropdown.value) {
|
|
138
|
-
close();
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const setBoundingBoxesDebounced = throttle(() => {
|
|
144
|
-
setBoundingBoxes();
|
|
145
|
-
}, 10);
|
|
146
|
-
|
|
147
|
-
let buttonResizeObserver = null as any;
|
|
148
|
-
let dropdownResizeObserver = null as any;
|
|
149
|
-
|
|
150
|
-
function activate() {
|
|
151
|
-
buttonResizeObserver = useResizeObserver(button, setBoundingBoxesDebounced);
|
|
152
|
-
dropdownResizeObserver = useResizeObserver(
|
|
153
|
-
dropdown,
|
|
154
|
-
setBoundingBoxesDebounced
|
|
155
|
-
);
|
|
156
|
-
window.addEventListener('keydown', onKeydown);
|
|
157
|
-
window.addEventListener('resize', setBoundingBoxesDebounced);
|
|
158
|
-
window.addEventListener('scroll', setBoundingBoxesDebounced, true);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function deactivate() {
|
|
162
|
-
buttonResizeObserver?.stop();
|
|
163
|
-
dropdownResizeObserver?.stop();
|
|
164
|
-
window.removeEventListener('resize', setBoundingBoxesDebounced);
|
|
165
|
-
window.removeEventListener('scroll', setBoundingBoxesDebounced, true);
|
|
166
|
-
window.removeEventListener('keydown', onKeydown);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
useClickOutside(
|
|
170
|
-
dropdown,
|
|
171
|
-
() => {
|
|
172
|
-
if (showDropdown.value) {
|
|
173
|
-
close();
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
{ includes: () => [button] }
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
const placementInternal = computed(() => {
|
|
180
|
-
// vertical
|
|
181
|
-
const spaceTop = buttonY.value - props.padding;
|
|
182
|
-
const spaceBottom =
|
|
183
|
-
window.innerHeight - buttonY.value - buttonHeight.value - props.padding;
|
|
184
|
-
|
|
185
|
-
const tooTallForTop = spaceTop < dropdownHeight.value;
|
|
186
|
-
const tooTallForBottom = spaceBottom < dropdownHeight.value;
|
|
187
|
-
|
|
188
|
-
let verticalPreference = props.placement.split('-')[0];
|
|
189
|
-
|
|
190
|
-
if (tooTallForTop && !tooTallForBottom) {
|
|
191
|
-
verticalPreference = 'bottom';
|
|
192
|
-
} else if (!tooTallForTop && tooTallForBottom) {
|
|
193
|
-
verticalPreference = 'top';
|
|
194
|
-
} else if (tooTallForTop && tooTallForBottom) {
|
|
195
|
-
if (spaceTop > spaceBottom) {
|
|
196
|
-
verticalPreference = 'top';
|
|
197
|
-
} else {
|
|
198
|
-
verticalPreference = 'bottom';
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// horizontal
|
|
203
|
-
const spaceStart = buttonX.value + buttonWidth.value;
|
|
204
|
-
const spaceEnd = window.innerWidth - buttonX.value;
|
|
205
|
-
|
|
206
|
-
const tooLargeForStart = spaceStart < dropdownWidth.value;
|
|
207
|
-
const tooLargeForEnd = spaceEnd < dropdownWidth.value;
|
|
208
|
-
|
|
209
|
-
let horizontalPreference = props.placement.split('-')[1];
|
|
210
|
-
|
|
211
|
-
if (tooLargeForStart && !tooLargeForEnd) {
|
|
212
|
-
horizontalPreference = 'start';
|
|
213
|
-
} else if (!tooLargeForStart && tooLargeForEnd) {
|
|
214
|
-
horizontalPreference = 'end';
|
|
215
|
-
} else if (tooLargeForStart && tooLargeForEnd) {
|
|
216
|
-
if (spaceStart > spaceEnd) {
|
|
217
|
-
horizontalPreference = 'end';
|
|
218
|
-
} else {
|
|
219
|
-
horizontalPreference = 'start';
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
return `${verticalPreference}-${horizontalPreference}`;
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
const dropdownStyles = computed((): StyleValue => {
|
|
227
|
-
let top = buttonY.value;
|
|
228
|
-
|
|
229
|
-
if (
|
|
230
|
-
placementInternal.value == 'bottom-start' ||
|
|
231
|
-
placementInternal.value == 'bottom-end'
|
|
232
|
-
) {
|
|
233
|
-
top += buttonHeight.value;
|
|
234
|
-
top += props.padding;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (
|
|
238
|
-
placementInternal.value == 'top-start' ||
|
|
239
|
-
placementInternal.value == 'top-end'
|
|
240
|
-
) {
|
|
241
|
-
top -= dropdownHeight.value;
|
|
242
|
-
top -= props.padding;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
const styles = {
|
|
246
|
-
position: 'fixed',
|
|
247
|
-
top: `${top}px`,
|
|
248
|
-
} as any;
|
|
249
|
-
|
|
250
|
-
if (
|
|
251
|
-
placementInternal.value == 'bottom-end' ||
|
|
252
|
-
placementInternal.value == 'top-end'
|
|
253
|
-
) {
|
|
254
|
-
styles.left = `${
|
|
255
|
-
buttonX.value + buttonWidth.value - dropdownWidth.value
|
|
256
|
-
}px`;
|
|
257
|
-
} else {
|
|
258
|
-
styles.left = `${buttonX.value}px`;
|
|
62
|
+
placement: {
|
|
63
|
+
default: 'bottom-end',
|
|
64
|
+
type: String as PropType<Placement>,
|
|
259
65
|
}
|
|
260
|
-
|
|
261
|
-
return styles as StyleValue;
|
|
262
66
|
});
|
|
263
67
|
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
addClickOutsideInclude(dropdown);
|
|
269
|
-
|
|
270
|
-
onBeforeUnmount(() => {
|
|
271
|
-
close();
|
|
272
|
-
deactivate();
|
|
68
|
+
const { floatingStyles } = useFloating(buttonRefEl, dropdownRef, {
|
|
69
|
+
placement: props.placement,
|
|
70
|
+
middleware: [offset(6), flip(), shift()],
|
|
71
|
+
whileElementsMounted: autoUpdate,
|
|
273
72
|
});
|
|
274
73
|
|
|
275
|
-
defineExpose({
|
|
276
|
-
open,
|
|
277
|
-
close,
|
|
278
|
-
toggle,
|
|
279
|
-
});
|
|
280
74
|
</script>
|
|
@@ -3,9 +3,6 @@
|
|
|
3
3
|
:animated="true"
|
|
4
4
|
:keep-alive="false"
|
|
5
5
|
:placement="placement"
|
|
6
|
-
:padding="padding"
|
|
7
|
-
@open="onOpen"
|
|
8
|
-
@close="onClose"
|
|
9
6
|
>
|
|
10
7
|
<template #button="buttonProps">
|
|
11
8
|
<slot
|
|
@@ -16,7 +13,7 @@
|
|
|
16
13
|
</template>
|
|
17
14
|
<template #dropdown="{ close }">
|
|
18
15
|
<div
|
|
19
|
-
class="inline-block w-[320px] overflow-hidden rounded-md
|
|
16
|
+
class="inline-block w-[320px] overflow-hidden rounded-md ring-1 ring-black ring-opacity-10 bg-white px-2 pt-2 shadow-lg"
|
|
20
17
|
>
|
|
21
18
|
<component
|
|
22
19
|
:is="componentName"
|
|
@@ -29,6 +26,7 @@
|
|
|
29
26
|
:inline="true"
|
|
30
27
|
:required="required"
|
|
31
28
|
:select="select"
|
|
29
|
+
:focus-on-mount="true"
|
|
32
30
|
dropdown-show="always"
|
|
33
31
|
@update:model-value="onUpdate($event, close)"
|
|
34
32
|
>
|
|
@@ -69,6 +67,7 @@ import BaseAutocomplete from './BaseAutocomplete.vue';
|
|
|
69
67
|
import BaseAutocompleteFetch from './BaseAutocompleteFetch.vue';
|
|
70
68
|
import BaseTagAutocomplete from './BaseTagAutocomplete.vue';
|
|
71
69
|
import BaseTagAutocompleteFetch from './BaseTagAutocompleteFetch.vue';
|
|
70
|
+
import { Placement } from '@floating-ui/vue';
|
|
72
71
|
|
|
73
72
|
const props = defineProps({
|
|
74
73
|
modelValue: {
|
|
@@ -110,14 +109,8 @@ const props = defineProps({
|
|
|
110
109
|
type: String,
|
|
111
110
|
},
|
|
112
111
|
placement: {
|
|
113
|
-
type: String as PropType<
|
|
114
|
-
'bottom-start' | 'bottom-end' | 'top-start' | 'top-end'
|
|
115
|
-
>,
|
|
116
|
-
default: undefined,
|
|
117
|
-
},
|
|
118
|
-
padding: {
|
|
112
|
+
type: String as PropType<Placement>,
|
|
119
113
|
default: undefined,
|
|
120
|
-
type: Number,
|
|
121
114
|
},
|
|
122
115
|
select: {
|
|
123
116
|
default: undefined,
|
|
@@ -125,7 +118,7 @@ const props = defineProps({
|
|
|
125
118
|
},
|
|
126
119
|
});
|
|
127
120
|
|
|
128
|
-
const emit = defineEmits(['update:model-value'
|
|
121
|
+
const emit = defineEmits(['update:model-value']);
|
|
129
122
|
|
|
130
123
|
const componentName = computed<any>(() => {
|
|
131
124
|
if (props.multiple) {
|
|
@@ -180,24 +173,6 @@ watch(
|
|
|
180
173
|
{ immediate: true, deep: true }
|
|
181
174
|
);
|
|
182
175
|
|
|
183
|
-
function onOpen() {
|
|
184
|
-
nextTick(() => {
|
|
185
|
-
setTimeout(() => {
|
|
186
|
-
autocomplete.value?.open();
|
|
187
|
-
}, 1);
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function onClose() {
|
|
192
|
-
nextTick(() => {
|
|
193
|
-
setTimeout(() => {
|
|
194
|
-
autocomplete.value?.setKeywords('');
|
|
195
|
-
}, 1);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
emit('close');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
176
|
function onUpdate(
|
|
202
177
|
value: Option | Option[] | null | undefined,
|
|
203
178
|
close: () => void
|
|
@@ -160,7 +160,6 @@ const props = defineProps({
|
|
|
160
160
|
default: false,
|
|
161
161
|
type: Boolean,
|
|
162
162
|
},
|
|
163
|
-
|
|
164
163
|
max: {
|
|
165
164
|
default: undefined,
|
|
166
165
|
type: Number,
|
|
@@ -185,9 +184,13 @@ const props = defineProps({
|
|
|
185
184
|
default: 'focus',
|
|
186
185
|
type: String as PropType<'focus' | 'always'>,
|
|
187
186
|
},
|
|
187
|
+
focusOnMount: {
|
|
188
|
+
default: false,
|
|
189
|
+
type: Boolean,
|
|
190
|
+
},
|
|
188
191
|
twContainer: {
|
|
189
192
|
default: '',
|
|
190
|
-
type: [String, Array] as PropType<string|string[]>,
|
|
193
|
+
type: [String, Array] as PropType<string | string[]>,
|
|
191
194
|
},
|
|
192
195
|
});
|
|
193
196
|
|
|
@@ -214,6 +217,20 @@ const hasOptions = useHasOptions(
|
|
|
214
217
|
computed(() => true)
|
|
215
218
|
);
|
|
216
219
|
|
|
220
|
+
let openOfFocusTimeout = 0;
|
|
221
|
+
|
|
222
|
+
onMounted(() => {
|
|
223
|
+
openOfFocusTimeout = setTimeout(() => {
|
|
224
|
+
if (props.focusOnMount) {
|
|
225
|
+
open();
|
|
226
|
+
}
|
|
227
|
+
}, 10)
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
onBeforeUnmount(() => {
|
|
231
|
+
clearTimeout(openOfFocusTimeout);
|
|
232
|
+
});
|
|
233
|
+
|
|
217
234
|
const drawer = ref<InstanceType<typeof BaseAutocompleteDrawer> | null>(null);
|
|
218
235
|
|
|
219
236
|
const keywords = ref('');
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
:has-error="hasError"
|
|
13
13
|
:max="max"
|
|
14
14
|
:filter="() => true"
|
|
15
|
+
:focus-on-mount="focusOnMount"
|
|
15
16
|
@open="onOpen"
|
|
16
17
|
@typing="onTyping"
|
|
17
18
|
@scroll-bottom="scrollBottom"
|
|
@@ -111,6 +112,10 @@ const props = defineProps({
|
|
|
111
112
|
default: false,
|
|
112
113
|
type: Boolean,
|
|
113
114
|
},
|
|
115
|
+
focusOnMount: {
|
|
116
|
+
default: false,
|
|
117
|
+
type: Boolean,
|
|
118
|
+
},
|
|
114
119
|
});
|
|
115
120
|
|
|
116
121
|
defineEmits(['update:modelValue', 'typing', 'focus', 'scrollBottom']);
|
|
@@ -26,14 +26,10 @@
|
|
|
26
26
|
|
|
27
27
|
<script lang="ts" setup>
|
|
28
28
|
import { useTooltip } from '@/composables/tooltip';
|
|
29
|
-
import { PropType } from 'vue';
|
|
30
29
|
|
|
31
|
-
const props = defineProps
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
type: Object as PropType<HTMLElement | null>,
|
|
35
|
-
}
|
|
36
|
-
});
|
|
30
|
+
const props = defineProps<{
|
|
31
|
+
target: HTMLElement | null;
|
|
32
|
+
}>();
|
|
37
33
|
|
|
38
34
|
const targetInternal = computed(() => props.target ?? null);
|
|
39
35
|
|
package/src/components/index.ts
CHANGED
|
@@ -18,7 +18,6 @@ import BaseButtonGroup from './BaseButtonGroup.vue';
|
|
|
18
18
|
import BaseCard from './BaseCard.vue';
|
|
19
19
|
import BaseCardRow from './BaseCardRow.vue';
|
|
20
20
|
import BaseCharacterCounter from './BaseCharacterCounter.vue';
|
|
21
|
-
import BaseClickOutside from './BaseClickOutside.vue';
|
|
22
21
|
import BaseClipboard from './BaseClipboard.vue';
|
|
23
22
|
import BaseCalendar from './BaseCalendar.vue';
|
|
24
23
|
import BaseColor from './BaseColor.vue';
|
|
@@ -118,7 +117,6 @@ export {
|
|
|
118
117
|
BaseCard,
|
|
119
118
|
BaseCardRow,
|
|
120
119
|
BaseCharacterCounter,
|
|
121
|
-
BaseClickOutside,
|
|
122
120
|
BaseClipboard,
|
|
123
121
|
BaseCalendar,
|
|
124
122
|
BaseColor,
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { MaybeElement } from '@vueuse/core';
|
|
2
|
-
import { MaybeRef } from '@vueuse/shared';
|
|
3
|
-
import { PropType } from 'vue';
|
|
4
|
-
declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
5
|
-
includes: {
|
|
6
|
-
type: PropType<(string | MaybeRef<MaybeElement>)[]>;
|
|
7
|
-
default: () => never[];
|
|
8
|
-
};
|
|
9
|
-
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
|
-
clickOutside: (...args: any[]) => void;
|
|
11
|
-
}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
|
|
12
|
-
includes: {
|
|
13
|
-
type: PropType<(string | MaybeRef<MaybeElement>)[]>;
|
|
14
|
-
default: () => never[];
|
|
15
|
-
};
|
|
16
|
-
}>> & {
|
|
17
|
-
onClickOutside?: ((...args: any[]) => any) | undefined;
|
|
18
|
-
}, {
|
|
19
|
-
includes: (string | MaybeRef<MaybeElement>)[];
|
|
20
|
-
}, {}>, {
|
|
21
|
-
default?(_: {}): any;
|
|
22
|
-
}>;
|
|
23
|
-
export default _default;
|
|
24
|
-
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
25
|
-
new (): {
|
|
26
|
-
$slots: S;
|
|
27
|
-
};
|
|
28
|
-
};
|