@veritree/ui 0.22.3 → 0.23.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/mixins/floating-ui-content.js +0 -21
- package/mixins/floating-ui-item.js +88 -46
- package/mixins/floating-ui.js +4 -13
- package/mixins/form-control-icon.js +2 -2
- package/mixins/form-control.js +9 -5
- package/nuxt.js +1 -0
- package/package.json +1 -1
- package/src/components/Button/VTButton.vue +5 -5
- package/src/components/Dialog/VTDialog.vue +6 -15
- package/src/components/Dialog/VTDialogClose.vue +19 -25
- package/src/components/Dialog/VTDialogContent.vue +18 -21
- package/src/components/Dialog/VTDialogFooter.vue +7 -18
- package/src/components/Dialog/VTDialogHeader.vue +15 -18
- package/src/components/Dialog/VTDialogMain.vue +11 -18
- package/src/components/Dialog/VTDialogOverlay.vue +14 -18
- package/src/components/Dialog/VTDialogTitle.vue +10 -7
- package/src/components/Drawer/VTDrawerContent.vue +1 -1
- package/src/components/Drawer/VTDrawerFooter.vue +1 -1
- package/src/components/DropdownMenu/VTDropdownMenu.vue +19 -0
- package/src/components/DropdownMenu/VTDropdownMenuContent.vue +5 -6
- package/src/components/DropdownMenu/VTDropdownMenuItem.vue +2 -2
- package/src/components/Form/VTFormFeedback.vue +5 -5
- package/src/components/Form/VTInput.vue +5 -2
- package/src/components/Form/VTTextarea.vue +5 -2
- package/src/components/Listbox/VTListbox.vue +35 -11
- package/src/components/Listbox/VTListboxContent.vue +4 -7
- package/src/components/Listbox/VTListboxItem.vue +117 -6
- package/src/components/Listbox/VTListboxList.vue +1 -24
- package/src/components/Listbox/VTListboxSearch.vue +58 -52
- package/src/components/Listbox/VTListboxTrigger.vue +7 -4
- package/src/components/Modal/VTModal.vue +1 -1
- package/src/components/Popover/VTPopover.vue +19 -0
- package/src/components/Popover/VTPopoverContent.vue +3 -3
- package/src/components/Tooltip/VTTooltip.vue +65 -0
- package/src/components/Tooltip/VTTooltipContent.vue +59 -0
- package/src/components/Tooltip/VTTooltipTrigger.vue +100 -0
- package/src/components/Utils/FloatingUi.vue +27 -13
|
@@ -10,16 +10,11 @@ export const floatingUiContentMixin = {
|
|
|
10
10
|
type: Boolean,
|
|
11
11
|
default: false,
|
|
12
12
|
},
|
|
13
|
-
floatingUiClass: {
|
|
14
|
-
type: [String, Function],
|
|
15
|
-
default: null,
|
|
16
|
-
},
|
|
17
13
|
},
|
|
18
14
|
|
|
19
15
|
data() {
|
|
20
16
|
return {
|
|
21
17
|
el: null,
|
|
22
|
-
isMousemove: false,
|
|
23
18
|
visible: false,
|
|
24
19
|
};
|
|
25
20
|
},
|
|
@@ -79,22 +74,6 @@ export const floatingUiContentMixin = {
|
|
|
79
74
|
}
|
|
80
75
|
},
|
|
81
76
|
|
|
82
|
-
// Mousemove instead of mouseover to support keyboard navigation.
|
|
83
|
-
// The problem with mouseover is that when scrolling (scrollIntoView),
|
|
84
|
-
// mouseover event gets triggered.
|
|
85
|
-
setMousemove() {
|
|
86
|
-
this.isMousemove = true;
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
unsetMousemove() {
|
|
90
|
-
this.isMousemove = false;
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
getMousemove() {
|
|
94
|
-
return this.isMousemove;
|
|
95
|
-
},
|
|
96
|
-
|
|
97
|
-
//
|
|
98
77
|
setActiveDescedant(id) {
|
|
99
78
|
this.activeDescedant = id;
|
|
100
79
|
},
|
|
@@ -19,10 +19,6 @@ export const floatingUiItemMixin = {
|
|
|
19
19
|
return this.apiInjected().items;
|
|
20
20
|
},
|
|
21
21
|
|
|
22
|
-
el() {
|
|
23
|
-
return this.$el;
|
|
24
|
-
},
|
|
25
|
-
|
|
26
22
|
componentContent() {
|
|
27
23
|
return this.apiInjected().componentContent;
|
|
28
24
|
},
|
|
@@ -51,7 +47,7 @@ export const floatingUiItemMixin = {
|
|
|
51
47
|
? `${this.componentName}--selected`
|
|
52
48
|
: null
|
|
53
49
|
: this.selected
|
|
54
|
-
? 'bg-
|
|
50
|
+
? 'bg-gray-200'
|
|
55
51
|
: null,
|
|
56
52
|
];
|
|
57
53
|
},
|
|
@@ -62,20 +58,24 @@ export const floatingUiItemMixin = {
|
|
|
62
58
|
index: null,
|
|
63
59
|
selected: false,
|
|
64
60
|
tabIndex: 0,
|
|
61
|
+
eventType: null,
|
|
65
62
|
};
|
|
66
63
|
},
|
|
67
64
|
|
|
68
65
|
watch: {
|
|
69
66
|
selected(newValue) {
|
|
70
|
-
if (!newValue || !this.componentContent)
|
|
67
|
+
if (!newValue || !this.componentContent) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
71
70
|
|
|
72
71
|
this.componentContent.setActiveDescedant(this.id);
|
|
73
72
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.el.scrollIntoView({ block: 'nearest' });
|
|
73
|
+
// do not scroll into view if it's a mouse event
|
|
74
|
+
if (this.eventType && this.eventType.includes('mouse')) {
|
|
75
|
+
return;
|
|
78
76
|
}
|
|
77
|
+
|
|
78
|
+
this.$el.scrollIntoView({ block: 'nearest' });
|
|
79
79
|
},
|
|
80
80
|
},
|
|
81
81
|
|
|
@@ -91,30 +91,45 @@ export const floatingUiItemMixin = {
|
|
|
91
91
|
|
|
92
92
|
methods: {
|
|
93
93
|
init() {
|
|
94
|
+
this.index = this.items.length;
|
|
95
|
+
|
|
94
96
|
const item = {
|
|
95
97
|
id: this.id,
|
|
98
|
+
text: this.$slots.default[0].text,
|
|
96
99
|
select: this.select,
|
|
97
100
|
unselect: this.unselect,
|
|
101
|
+
isSelected: this.isSelected,
|
|
98
102
|
focus: this.focus,
|
|
99
103
|
onClick: this.onClick,
|
|
100
104
|
};
|
|
101
105
|
|
|
102
106
|
this.apiInjected().registerItem(item);
|
|
103
|
-
|
|
104
|
-
this.index = this.items.length - 1;
|
|
105
107
|
},
|
|
106
108
|
|
|
109
|
+
/**
|
|
110
|
+
* mousemove and mouseleave events will be attached to
|
|
111
|
+
* the element here instead of using vue @mousemove
|
|
112
|
+
* and @mouseleave in the element since they did
|
|
113
|
+
* not worker properly
|
|
114
|
+
*/
|
|
107
115
|
addMouseEventListeners() {
|
|
108
|
-
this
|
|
109
|
-
this
|
|
116
|
+
this.$el.addEventListener('mousemove', this.onMousemove);
|
|
117
|
+
this.$el.addEventListener('mouseleave', this.onMouseleave);
|
|
110
118
|
},
|
|
111
119
|
|
|
120
|
+
/**
|
|
121
|
+
* remove the mousemove and mouseleave added for
|
|
122
|
+
* avoiding memory leaks, if @mousemove and
|
|
123
|
+
* @mouseleave were in the element, this
|
|
124
|
+
* wound't be needed
|
|
125
|
+
*/
|
|
112
126
|
removeMouseEventListeners() {
|
|
113
|
-
this
|
|
114
|
-
this
|
|
127
|
+
this.$el.removeEventListener('mousemove', this.onMousemove);
|
|
128
|
+
this.$el.removeEventListener('mouseleave', this.onMouseleave);
|
|
115
129
|
},
|
|
116
130
|
|
|
117
|
-
select() {
|
|
131
|
+
select(eventType) {
|
|
132
|
+
this.eventType = eventType;
|
|
118
133
|
this.selected = true;
|
|
119
134
|
},
|
|
120
135
|
|
|
@@ -122,59 +137,82 @@ export const floatingUiItemMixin = {
|
|
|
122
137
|
this.selected = false;
|
|
123
138
|
},
|
|
124
139
|
|
|
140
|
+
isSelected() {
|
|
141
|
+
return this.selected;
|
|
142
|
+
},
|
|
143
|
+
|
|
125
144
|
focus() {
|
|
126
|
-
if (!this
|
|
145
|
+
if (!this.$el) return;
|
|
127
146
|
|
|
128
147
|
this.tabIndex = -1;
|
|
129
148
|
this.selected = true;
|
|
130
|
-
this
|
|
149
|
+
this.$el.focus();
|
|
131
150
|
},
|
|
132
151
|
|
|
133
152
|
focusFirstItem() {
|
|
134
|
-
this.
|
|
153
|
+
const selectedIndex = this.getItemSelectedIndex();
|
|
154
|
+
const newSelectedIndex = 0;
|
|
155
|
+
|
|
156
|
+
this.setFocusToItem(selectedIndex, newSelectedIndex);
|
|
135
157
|
},
|
|
136
158
|
|
|
137
159
|
focusLastItem() {
|
|
138
|
-
this.
|
|
160
|
+
const selectedIndex = this.getItemSelectedIndex();
|
|
161
|
+
const newSelectedIndex = this.items.length - 1;
|
|
162
|
+
|
|
163
|
+
this.setFocusToItem(selectedIndex, newSelectedIndex);
|
|
139
164
|
},
|
|
140
165
|
|
|
141
166
|
/**
|
|
142
|
-
* Focus the
|
|
143
|
-
* If is the
|
|
167
|
+
* Focus the next item in the menu.
|
|
168
|
+
* If is the last item, jump to the first item.
|
|
144
169
|
*/
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
const
|
|
170
|
+
focusNextItem() {
|
|
171
|
+
const selectedIndex = this.getItemSelectedIndex();
|
|
172
|
+
const isLast = selectedIndex === this.items.length - 1;
|
|
173
|
+
const firstItemIndex = 0;
|
|
174
|
+
const nextItemIndex = selectedIndex + 1;
|
|
175
|
+
const newSelectedIndex = isLast ? firstItemIndex : nextItemIndex;
|
|
148
176
|
|
|
149
|
-
this.setFocusToItem(
|
|
177
|
+
this.setFocusToItem(selectedIndex, newSelectedIndex);
|
|
150
178
|
},
|
|
151
179
|
|
|
152
180
|
/**
|
|
153
|
-
* Focus the
|
|
154
|
-
* If is the
|
|
181
|
+
* Focus the previous item in the menu.
|
|
182
|
+
* If is the first item, jump to the last item.
|
|
155
183
|
*/
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
const
|
|
184
|
+
focusPreviousItem() {
|
|
185
|
+
const selectedIndex = this.getItemSelectedIndex();
|
|
186
|
+
const isFirst = selectedIndex === 0;
|
|
187
|
+
const lastItemIndex = this.items.length - 1;
|
|
188
|
+
const previousItemIndex = selectedIndex - 1;
|
|
189
|
+
const newSelectedIndex = isFirst ? lastItemIndex : previousItemIndex;
|
|
159
190
|
|
|
160
|
-
this.setFocusToItem(
|
|
191
|
+
this.setFocusToItem(selectedIndex, newSelectedIndex);
|
|
161
192
|
},
|
|
162
193
|
|
|
163
194
|
/**
|
|
164
|
-
* Focus item by
|
|
195
|
+
* Focus/select item by removing its tabindex and calling
|
|
165
196
|
* focus to the element.
|
|
166
197
|
*
|
|
167
|
-
* @param {Number, String}
|
|
198
|
+
* @param {Number, String} selectedIndex
|
|
199
|
+
* @param {Number, String} newSelectedIndex
|
|
168
200
|
*/
|
|
169
|
-
setFocusToItem(
|
|
201
|
+
setFocusToItem(selectedIndex, newSelectedIndex) {
|
|
170
202
|
this.tabIndex = 0;
|
|
171
|
-
this.selected = false;
|
|
172
203
|
|
|
173
|
-
//
|
|
174
|
-
|
|
204
|
+
// before focusing, let's unselect selected
|
|
205
|
+
// item that were previously focused
|
|
206
|
+
if (selectedIndex >= 0) {
|
|
207
|
+
this.items[selectedIndex].unselect();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// focus new item
|
|
211
|
+
this.items[newSelectedIndex].focus();
|
|
212
|
+
},
|
|
175
213
|
|
|
176
|
-
|
|
177
|
-
this.items
|
|
214
|
+
getItemSelectedIndex() {
|
|
215
|
+
return this.items.findIndex((item) => item.isSelected());
|
|
178
216
|
},
|
|
179
217
|
|
|
180
218
|
leaveMenu() {
|
|
@@ -185,7 +223,6 @@ export const floatingUiItemMixin = {
|
|
|
185
223
|
},
|
|
186
224
|
|
|
187
225
|
onClick() {
|
|
188
|
-
console.log(this.value);
|
|
189
226
|
if (this.disabled) {
|
|
190
227
|
return;
|
|
191
228
|
}
|
|
@@ -201,20 +238,25 @@ export const floatingUiItemMixin = {
|
|
|
201
238
|
this.leaveMenu();
|
|
202
239
|
},
|
|
203
240
|
|
|
204
|
-
onMousemove() {
|
|
241
|
+
onMousemove(event) {
|
|
205
242
|
if (this.selected) {
|
|
206
243
|
return;
|
|
207
244
|
}
|
|
208
245
|
|
|
246
|
+
// unselect all items before selecting new item
|
|
209
247
|
this.items.forEach((item) => item.unselect());
|
|
210
248
|
|
|
211
|
-
|
|
212
|
-
|
|
249
|
+
/**
|
|
250
|
+
* Select item passing the event type to decide if
|
|
251
|
+
* scrolling will be disabled or not. It is
|
|
252
|
+
* expected that on mouse move event, the scroll
|
|
253
|
+
* doesn't happen automatically.
|
|
254
|
+
*/
|
|
255
|
+
this.select(event.type);
|
|
213
256
|
},
|
|
214
257
|
|
|
215
258
|
onMouseleave() {
|
|
216
259
|
this.unselect();
|
|
217
|
-
this.componentContent.unsetMousemove();
|
|
218
260
|
},
|
|
219
261
|
},
|
|
220
262
|
};
|
package/mixins/floating-ui.js
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { computePosition, flip, shift, offset, size } from '@floating-ui/dom';
|
|
2
2
|
|
|
3
3
|
export const floatingUiMixin = {
|
|
4
|
-
props: {
|
|
5
|
-
placement: {
|
|
6
|
-
type: String,
|
|
7
|
-
default: 'bottom-start',
|
|
8
|
-
},
|
|
9
|
-
},
|
|
10
|
-
|
|
11
4
|
data() {
|
|
12
5
|
return {
|
|
13
6
|
component: null,
|
|
@@ -40,22 +33,20 @@ export const floatingUiMixin = {
|
|
|
40
33
|
},
|
|
41
34
|
|
|
42
35
|
positionContentToTrigger() {
|
|
43
|
-
// console.log(window.innerWidth)
|
|
44
|
-
|
|
45
36
|
const trigger = document.getElementById(this.componentTrigger.id);
|
|
46
37
|
const content = document.getElementById(this.componentContent.id);
|
|
38
|
+
const minWidthLimit = Number(this.floatingUiMinWidth);
|
|
47
39
|
|
|
48
40
|
computePosition(trigger, content, {
|
|
49
41
|
placement: this.placement,
|
|
50
42
|
middleware: [
|
|
51
|
-
offset(
|
|
43
|
+
offset(5),
|
|
52
44
|
flip(),
|
|
53
45
|
shift({ padding: 5 }),
|
|
54
46
|
size({
|
|
55
47
|
apply({ rects }) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const minWidthLimit = 200;
|
|
48
|
+
if (!minWidthLimit) return;
|
|
49
|
+
|
|
59
50
|
const width = rects.reference.width;
|
|
60
51
|
const minWidth = width < minWidthLimit ? minWidthLimit : width;
|
|
61
52
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { formControlMixin } from '../mixins/form-control';
|
|
1
|
+
import { formControlMixin, formControlStyleMixin } from '../mixins/form-control';
|
|
2
2
|
|
|
3
3
|
export const formControlIconMixin = {
|
|
4
4
|
inheritAttrs: false,
|
|
5
5
|
|
|
6
|
-
mixins: [formControlMixin],
|
|
6
|
+
mixins: [formControlMixin, formControlStyleMixin],
|
|
7
7
|
|
|
8
8
|
data() {
|
|
9
9
|
return {
|
package/mixins/form-control.js
CHANGED
|
@@ -45,11 +45,19 @@ export const formControlMixin = {
|
|
|
45
45
|
);
|
|
46
46
|
},
|
|
47
47
|
|
|
48
|
+
isError() {
|
|
49
|
+
return this.variant === 'error';
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const formControlStyleMixin = {
|
|
55
|
+
computed: {
|
|
48
56
|
classComputed() {
|
|
49
57
|
return [
|
|
50
58
|
this.headless
|
|
51
59
|
? `${this.name}`
|
|
52
|
-
: 'leading-0 flex w-full max-w-full appearance-none items-center justify-between
|
|
60
|
+
: 'leading-0 flex w-full max-w-full appearance-none items-center justify-between rounded border border-solid px-3 py-2 font-inherit text-base text-inherit file:hidden focus:border-secondary-200',
|
|
53
61
|
// variant styles
|
|
54
62
|
this.headless
|
|
55
63
|
? `${this.name}--${this.variant}`
|
|
@@ -64,9 +72,5 @@ export const formControlMixin = {
|
|
|
64
72
|
: 'h-10',
|
|
65
73
|
];
|
|
66
74
|
},
|
|
67
|
-
|
|
68
|
-
isError() {
|
|
69
|
-
return this.variant === 'error';
|
|
70
|
-
},
|
|
71
75
|
},
|
|
72
76
|
};
|
package/nuxt.js
CHANGED
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<component
|
|
4
4
|
:is="tag"
|
|
5
5
|
:to="to"
|
|
6
|
-
:href="href"
|
|
6
|
+
:href="href || to"
|
|
7
7
|
:type="type"
|
|
8
8
|
:disabled="isDisabled"
|
|
9
9
|
:class="[
|
|
@@ -17,11 +17,11 @@
|
|
|
17
17
|
headless
|
|
18
18
|
? `button--${variant}`
|
|
19
19
|
: isPrimary
|
|
20
|
-
? '
|
|
20
|
+
? 'bg-secondary-400 hover:bg-secondary-500 focus:bg-secondary-600 active:bg-secondary-600 border-transparent text-white disabled:bg-gray-200 disabled:text-gray-400'
|
|
21
21
|
: isSecondary
|
|
22
|
-
? 'border-gray-400 bg-white text-gray-700 hover:bg-gray-100 active:bg-gray-200 disabled:border-gray-300 disabled:text-gray-400'
|
|
22
|
+
? 'border-gray-400 bg-white text-gray-700 hover:bg-gray-100 hover:bg-gray-200 active:bg-gray-200 disabled:border-gray-300 disabled:text-gray-400'
|
|
23
23
|
: isTertiary
|
|
24
|
-
? '
|
|
24
|
+
? 'text-secondary-400 hover:text-secondary-500 focus:text-secondary-600 active:text-secondary-600 border-transparent disabled:text-gray-400'
|
|
25
25
|
: isIcon
|
|
26
26
|
? 'text-primary-100 focus-within:bg-gray-200 hover:bg-gray-200 active:bg-gray-300'
|
|
27
27
|
: null,
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
<VTSpinner v-if="busy" class="absolute inset-0 m-auto" />
|
|
44
44
|
<span
|
|
45
45
|
:class="[
|
|
46
|
-
headless ? null : 'inline-flex items-center gap-2 self-center
|
|
46
|
+
headless ? null : 'mx-auto inline-flex items-center gap-2 self-center',
|
|
47
47
|
headless && busy ? 'button--busy' : busy ? 'invisible' : null,
|
|
48
48
|
]"
|
|
49
49
|
>
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
<div
|
|
4
4
|
v-if="visible"
|
|
5
5
|
:id="id"
|
|
6
|
-
:class="
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
:class="[
|
|
7
|
+
headless
|
|
8
|
+
? 'dialog'
|
|
9
|
+
: 'fixed inset-0 z-50 grid grid-cols-1 grid-rows-1 p-4 md:p-8',
|
|
10
|
+
]"
|
|
10
11
|
aria-modal="true"
|
|
11
12
|
@click="onClick"
|
|
12
13
|
>
|
|
@@ -28,11 +29,8 @@ export default {
|
|
|
28
29
|
|
|
29
30
|
provide() {
|
|
30
31
|
return {
|
|
31
|
-
|
|
32
|
-
const id = this.id;
|
|
32
|
+
apiDialog: () => {
|
|
33
33
|
const componentId = this.componentId;
|
|
34
|
-
const isDark = this.dark;
|
|
35
|
-
const isHeadless = this.headless;
|
|
36
34
|
|
|
37
35
|
const registerContent = (content) => {
|
|
38
36
|
if (!content) return;
|
|
@@ -49,10 +47,7 @@ export default {
|
|
|
49
47
|
const emit = () => this.emit();
|
|
50
48
|
|
|
51
49
|
return {
|
|
52
|
-
id,
|
|
53
50
|
componentId,
|
|
54
|
-
isDark,
|
|
55
|
-
isHeadless,
|
|
56
51
|
hide,
|
|
57
52
|
emit,
|
|
58
53
|
registerContent,
|
|
@@ -75,10 +70,6 @@ export default {
|
|
|
75
70
|
type: Boolean,
|
|
76
71
|
default: false,
|
|
77
72
|
},
|
|
78
|
-
dark: {
|
|
79
|
-
type: Boolean,
|
|
80
|
-
default: false,
|
|
81
|
-
},
|
|
82
73
|
},
|
|
83
74
|
|
|
84
75
|
data() {
|
|
@@ -2,48 +2,42 @@
|
|
|
2
2
|
<VTButton
|
|
3
3
|
variant="icon"
|
|
4
4
|
:id="id"
|
|
5
|
-
:class="
|
|
6
|
-
'Dialog-close': headless,
|
|
7
|
-
}"
|
|
8
|
-
:theme="theme"
|
|
5
|
+
:class="[headless ? 'dialog-close' : null]"
|
|
9
6
|
@click.prevent="hide"
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
>
|
|
8
|
+
<slot>
|
|
9
|
+
<IconClose class="h-5 w-5" />
|
|
10
|
+
</slot>
|
|
11
|
+
</VTButton>
|
|
12
12
|
</template>
|
|
13
13
|
|
|
14
14
|
<script>
|
|
15
|
-
import { IconClose } from
|
|
16
|
-
import VTButton from
|
|
15
|
+
import { IconClose } from '@veritree/icons';
|
|
16
|
+
import VTButton from '../Button/VTButton.vue';
|
|
17
17
|
|
|
18
18
|
export default {
|
|
19
|
-
name:
|
|
19
|
+
name: 'VTDialogClose',
|
|
20
20
|
|
|
21
21
|
components: { IconClose, VTButton },
|
|
22
22
|
|
|
23
|
-
inject: [
|
|
23
|
+
inject: ['apiDialog'],
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
dark() {
|
|
31
|
-
return this.api().isDark;
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
headless() {
|
|
35
|
-
return this.api().isHeadless;
|
|
25
|
+
props: {
|
|
26
|
+
headless: {
|
|
27
|
+
type: Boolean,
|
|
28
|
+
default: false,
|
|
36
29
|
},
|
|
30
|
+
},
|
|
37
31
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return this.
|
|
32
|
+
computed: {
|
|
33
|
+
id() {
|
|
34
|
+
return `dialog-close-${this.apiDialog().componentId}`;
|
|
41
35
|
},
|
|
42
36
|
},
|
|
43
37
|
|
|
44
38
|
methods: {
|
|
45
39
|
hide() {
|
|
46
|
-
this.
|
|
40
|
+
this.apiDialog().hide();
|
|
47
41
|
},
|
|
48
42
|
},
|
|
49
43
|
};
|
|
@@ -11,15 +11,13 @@
|
|
|
11
11
|
<div
|
|
12
12
|
v-show="visible"
|
|
13
13
|
:id="id"
|
|
14
|
-
:class="
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
'bg-fd-600': dark,
|
|
20
|
-
}"
|
|
14
|
+
:class="[
|
|
15
|
+
headless
|
|
16
|
+
? 'dialog-content'
|
|
17
|
+
: 'relative m-auto flex max-h-full max-w-full flex-col overflow-auto rounded bg-white p-6 focus:outline-none sm:p-10',
|
|
18
|
+
]"
|
|
21
19
|
tabindex="-1"
|
|
22
|
-
@
|
|
20
|
+
@keydown.esc.stop="hide"
|
|
23
21
|
>
|
|
24
22
|
<slot></slot>
|
|
25
23
|
</div>
|
|
@@ -28,9 +26,16 @@
|
|
|
28
26
|
|
|
29
27
|
<script>
|
|
30
28
|
export default {
|
|
31
|
-
name:
|
|
29
|
+
name: 'VTDialogContent',
|
|
32
30
|
|
|
33
|
-
inject: [
|
|
31
|
+
inject: ['apiDialog'],
|
|
32
|
+
|
|
33
|
+
props: {
|
|
34
|
+
headless: {
|
|
35
|
+
type: Boolean,
|
|
36
|
+
default: false,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
34
39
|
|
|
35
40
|
data() {
|
|
36
41
|
return {
|
|
@@ -40,20 +45,12 @@ export default {
|
|
|
40
45
|
|
|
41
46
|
computed: {
|
|
42
47
|
id() {
|
|
43
|
-
return `dialog-content-${this.
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
dark() {
|
|
47
|
-
return this.api().isDark;
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
headless() {
|
|
51
|
-
return this.api().isHeadless;
|
|
48
|
+
return `dialog-content-${this.apiDialog().componentId}`;
|
|
52
49
|
},
|
|
53
50
|
},
|
|
54
51
|
|
|
55
52
|
mounted() {
|
|
56
|
-
this.
|
|
53
|
+
this.apiDialog().registerContent(this);
|
|
57
54
|
this.show();
|
|
58
55
|
|
|
59
56
|
this.$nextTick(() => this.$el.focus());
|
|
@@ -69,7 +66,7 @@ export default {
|
|
|
69
66
|
},
|
|
70
67
|
|
|
71
68
|
hideDialog() {
|
|
72
|
-
this.
|
|
69
|
+
this.apiDialog().emit();
|
|
73
70
|
},
|
|
74
71
|
},
|
|
75
72
|
};
|
|
@@ -1,32 +1,21 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<component
|
|
3
|
-
:is="as"
|
|
4
|
-
:class="{ 'Dialog-footer': headless, 'w-full': !headless }"
|
|
5
|
-
>
|
|
2
|
+
<component :is="as" :class="[headless ? 'dialog-footer' : 'w-full']">
|
|
6
3
|
<slot></slot>
|
|
7
4
|
</component>
|
|
8
5
|
</template>
|
|
9
6
|
|
|
10
7
|
<script>
|
|
11
8
|
export default {
|
|
12
|
-
name:
|
|
13
|
-
|
|
14
|
-
inject: ["api"],
|
|
9
|
+
name: 'VTDialogFooter',
|
|
15
10
|
|
|
16
11
|
props: {
|
|
12
|
+
headless: {
|
|
13
|
+
type: Boolean,
|
|
14
|
+
default: false,
|
|
15
|
+
},
|
|
17
16
|
as: {
|
|
18
17
|
type: String,
|
|
19
|
-
default:
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
computed: {
|
|
24
|
-
dark() {
|
|
25
|
-
return this.api().isDark;
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
headless() {
|
|
29
|
-
return this.api().isHeadless;
|
|
18
|
+
default: 'footer',
|
|
30
19
|
},
|
|
31
20
|
},
|
|
32
21
|
};
|