@zipify/wysiwyg 4.0.4-0 → 4.1.0-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/cli.js +1 -1
- package/dist/wysiwyg.css +12 -12
- package/dist/wysiwyg.mjs +1300 -227
- package/example/tooltip/Tooltip.js +69 -92
- package/example/tooltip/modifiers/TooltipCloseOnScrollModifier.js +5 -2
- package/example/tooltip/tooltip.css +31 -8
- package/lib/Wysiwyg.vue +1 -3
- package/lib/components/base/composables/__tests__/useModalToggler.test.js +2 -0
- package/lib/components/base/composables/useModalToggler.js +24 -30
- package/lib/components/toolbar/Toolbar.vue +1 -1
- package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +2 -0
- package/lib/composables/useToolbar.js +20 -24
- package/package.json +2 -1
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import './tooltip.css';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import arrow from '@popperjs/core/lib/modifiers/arrow';
|
|
5
|
-
import flip from '@popperjs/core/lib/modifiers/flip';
|
|
6
|
-
import offset from '@popperjs/core/lib/modifiers/offset';
|
|
7
|
-
import preventOverflow from '@popperjs/core/lib/modifiers/preventOverflow';
|
|
3
|
+
import { arrow, autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/dom';
|
|
8
4
|
import { TooltipCloseOnScrollModifier } from './modifiers';
|
|
9
5
|
|
|
10
6
|
export class Tooltip {
|
|
@@ -18,11 +14,11 @@ export class Tooltip {
|
|
|
18
14
|
static get animationOptions() {
|
|
19
15
|
return {
|
|
20
16
|
enterDuration: 150,
|
|
21
|
-
leaveDuration:
|
|
17
|
+
leaveDuration: 100
|
|
22
18
|
};
|
|
23
19
|
}
|
|
24
20
|
|
|
25
|
-
static get
|
|
21
|
+
static get tooltipStyles() {
|
|
26
22
|
return {
|
|
27
23
|
willChange: 'transform',
|
|
28
24
|
zIndex: 999999
|
|
@@ -35,17 +31,17 @@ export class Tooltip {
|
|
|
35
31
|
/** @type {string} tooltip's content */
|
|
36
32
|
message = '';
|
|
37
33
|
|
|
38
|
-
/** @type {object} options for
|
|
39
|
-
|
|
34
|
+
/** @type {object} options for FloatingUI instance */
|
|
35
|
+
tooltipOptions = {};
|
|
40
36
|
|
|
41
37
|
/** @type {object} styles for tooltip's wrapper element */
|
|
42
|
-
|
|
38
|
+
tooltipStyles = {};
|
|
43
39
|
|
|
44
40
|
/** @type {{ enterDuration: number, leaveDuration: number }} tooltip's fade in / fade out durations */
|
|
45
41
|
animationOptions = {};
|
|
46
42
|
|
|
47
|
-
/** @type {
|
|
48
|
-
|
|
43
|
+
/** @type {function | null} created FloatingUI instance */
|
|
44
|
+
floatingInstance = null;
|
|
49
45
|
|
|
50
46
|
/** @type {{ tooltip: HTMLElement, container: HTMLElement, contentEl: HTMLElement, arrow: HTMLElement }} elements of tooltip */
|
|
51
47
|
elements = {};
|
|
@@ -55,25 +51,25 @@ export class Tooltip {
|
|
|
55
51
|
* @param params {object}
|
|
56
52
|
* @param params.triggerEl {HTMLElement}
|
|
57
53
|
* @param params.message {string}
|
|
58
|
-
* @param [params.
|
|
59
|
-
* @param [params.
|
|
54
|
+
* @param [params.tooltipOptions] {{ placement: string, size: string }}
|
|
55
|
+
* @param [params.tooltipStyles] {object}
|
|
60
56
|
* @param [params.animationOptions] {{ enterDuration: number, leaveDuration: number }}
|
|
61
57
|
*/
|
|
62
|
-
constructor({ triggerEl, message,
|
|
58
|
+
constructor({ triggerEl, message, tooltipOptions, tooltipStyles, animationOptions }) {
|
|
63
59
|
this.triggerEl = triggerEl;
|
|
64
60
|
this.message = message;
|
|
65
61
|
|
|
66
|
-
this.
|
|
67
|
-
this.
|
|
62
|
+
this.tooltipOptions = Object.assign({}, Tooltip.defaultOptions, tooltipOptions);
|
|
63
|
+
this.tooltipStyles = Object.assign({}, Tooltip.tooltipStyles, tooltipStyles);
|
|
68
64
|
this.animationOptions = Object.assign({}, Tooltip.animationOptions, animationOptions);
|
|
69
65
|
|
|
70
66
|
this._isMacOS = window.navigator.userAgent.toLowerCase().includes('mac os');
|
|
71
67
|
|
|
72
|
-
this
|
|
68
|
+
this.#initialize();
|
|
73
69
|
}
|
|
74
70
|
|
|
75
|
-
|
|
76
|
-
let tooltip = this
|
|
71
|
+
#initialize() {
|
|
72
|
+
let tooltip = this.#createTooltip();
|
|
77
73
|
|
|
78
74
|
this.elements = {
|
|
79
75
|
tooltip,
|
|
@@ -83,13 +79,15 @@ export class Tooltip {
|
|
|
83
79
|
};
|
|
84
80
|
}
|
|
85
81
|
|
|
86
|
-
|
|
82
|
+
#createTooltip() {
|
|
87
83
|
let element = document.createElement('div');
|
|
88
84
|
|
|
89
|
-
Object.keys(this.
|
|
85
|
+
Object.keys(this.tooltipStyles).forEach((style) => (element.style[style] = this.tooltipStyles[style]));
|
|
86
|
+
|
|
87
|
+
element.classList.add('zpa-tooltip__wrapper');
|
|
90
88
|
|
|
91
89
|
element.innerHTML = `
|
|
92
|
-
<div class="zpa-tooltip zpa-tooltip--${this.
|
|
90
|
+
<div class="zpa-tooltip zpa-tooltip--${this.tooltipOptions.size}" data-container>
|
|
93
91
|
<div class="zpa-tooltip__content" data-content></div>
|
|
94
92
|
<div class="zpa-tooltip__arrow" data-arrow></div>
|
|
95
93
|
</div>`;
|
|
@@ -97,20 +95,20 @@ export class Tooltip {
|
|
|
97
95
|
return element;
|
|
98
96
|
}
|
|
99
97
|
|
|
100
|
-
|
|
98
|
+
#renderContent(message) {
|
|
101
99
|
// Do not use .innerHTML, it will break tooltips in Scripts section!
|
|
102
100
|
this.elements.contentEl.textContent = message;
|
|
103
101
|
|
|
104
102
|
this.elements.hotkey?.remove();
|
|
105
|
-
this
|
|
103
|
+
this.#renderHotkeyTip();
|
|
106
104
|
}
|
|
107
105
|
|
|
108
|
-
|
|
106
|
+
#renderHotkeyTip() {
|
|
109
107
|
const raw = this.triggerEl.dataset.tooltipHotkey;
|
|
110
108
|
|
|
111
109
|
if (!raw) return;
|
|
112
110
|
|
|
113
|
-
const parts = raw.split(' ').map(this.
|
|
111
|
+
const parts = raw.split(' ').map(this.#formatHotkeyPart.bind(this));
|
|
114
112
|
const tipEl = document.createElement('span');
|
|
115
113
|
|
|
116
114
|
tipEl.classList.add('zpa-tooltip__hotkey');
|
|
@@ -119,7 +117,7 @@ export class Tooltip {
|
|
|
119
117
|
this.elements.contentEl.append(tipEl);
|
|
120
118
|
}
|
|
121
119
|
|
|
122
|
-
|
|
120
|
+
#formatHotkeyPart(part) {
|
|
123
121
|
switch (part.toLowerCase()) {
|
|
124
122
|
case 'mod':
|
|
125
123
|
return this._isMacOS ? '⌘' : 'Ctrl';
|
|
@@ -131,111 +129,90 @@ export class Tooltip {
|
|
|
131
129
|
}
|
|
132
130
|
}
|
|
133
131
|
|
|
134
|
-
|
|
132
|
+
#getModifiers() {
|
|
135
133
|
return [
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
name: 'offset',
|
|
144
|
-
options: {
|
|
145
|
-
offset: [0, 8]
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
name: 'preventOverflow',
|
|
150
|
-
options: {
|
|
151
|
-
padding: {
|
|
152
|
-
top: 4,
|
|
153
|
-
bottom: 4,
|
|
154
|
-
left: 8,
|
|
155
|
-
right: 8
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
name: 'customAttributes',
|
|
161
|
-
enabled: true,
|
|
162
|
-
phase: 'beforeWrite',
|
|
163
|
-
requires: ['computeStyles'],
|
|
164
|
-
fn: ({ state }) => {
|
|
165
|
-
this.elements.arrow.classList.add(`zpa-tooltip__arrow--${state.placement}`);
|
|
166
|
-
state.attributes.popper = {};
|
|
167
|
-
}
|
|
168
|
-
},
|
|
134
|
+
flip(),
|
|
135
|
+
offset({ mainAxis: 8 }),
|
|
136
|
+
shift({ padding: 4 }),
|
|
137
|
+
arrow({ element: this.elements.arrow }),
|
|
169
138
|
TooltipCloseOnScrollModifier.init({ tooltip: this })
|
|
170
139
|
];
|
|
171
140
|
}
|
|
172
141
|
|
|
173
|
-
|
|
142
|
+
#setTooltipDuration(duration = 0) {
|
|
174
143
|
this.elements.container.style.transitionDuration = `${duration}ms`;
|
|
175
144
|
}
|
|
176
145
|
|
|
177
|
-
|
|
178
|
-
const modifiers = this
|
|
146
|
+
#renderPopper() {
|
|
147
|
+
const modifiers = this.#getModifiers();
|
|
179
148
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
149
|
+
this.floatingInstance = autoUpdate(this.triggerEl, this.elements.tooltip, async () => {
|
|
150
|
+
const positioning = await computePosition(this.triggerEl, this.elements.tooltip, {
|
|
151
|
+
placement: this.tooltipOptions.placement,
|
|
152
|
+
middleware: [...modifiers]
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const { x, y, middlewareData, placement } = positioning;
|
|
156
|
+
|
|
157
|
+
if (middlewareData.arrow) this.#renderArrow(placement, middlewareData.arrow);
|
|
183
158
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
159
|
+
Object.assign(this.elements.tooltip.style, {
|
|
160
|
+
left: `${x}px`,
|
|
161
|
+
top: `${y}px`
|
|
162
|
+
});
|
|
187
163
|
});
|
|
188
164
|
|
|
189
|
-
return this.
|
|
165
|
+
return this.floatingInstance;
|
|
190
166
|
}
|
|
191
167
|
|
|
192
|
-
|
|
168
|
+
#renderArrow(placement, { x, y }) {
|
|
169
|
+
this.elements.tooltip.classList.add(`zpa-tooltip--${placement}`);
|
|
170
|
+
|
|
171
|
+
Object.assign(this.elements.arrow.style, {
|
|
172
|
+
left: x != null ? `${x}px` : '',
|
|
173
|
+
top: y != null ? `${y}px` : ''
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
#toggle(makeVisible) {
|
|
193
178
|
const { enterDuration, leaveDuration } = this.animationOptions;
|
|
194
179
|
|
|
195
|
-
this
|
|
180
|
+
this.#setTooltipDuration(makeVisible ? enterDuration : leaveDuration);
|
|
196
181
|
this.elements.container.classList.toggle('zpa-tooltip--open', makeVisible);
|
|
197
182
|
}
|
|
198
183
|
|
|
199
184
|
open() {
|
|
200
|
-
if (this.
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
185
|
+
if (this.floatingInstance) return;
|
|
203
186
|
|
|
204
187
|
document.body.appendChild(this.elements.tooltip);
|
|
205
|
-
this.popperInstance = this
|
|
188
|
+
this.popperInstance = this.#renderPopper();
|
|
206
189
|
|
|
207
|
-
this
|
|
208
|
-
this
|
|
190
|
+
this.#renderContent(this.message);
|
|
191
|
+
this.#toggle(true);
|
|
209
192
|
}
|
|
210
193
|
|
|
211
194
|
close() {
|
|
212
|
-
if (!this.
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
195
|
+
if (!this.floatingInstance) return;
|
|
215
196
|
|
|
216
|
-
this
|
|
197
|
+
this.#toggle(false);
|
|
217
198
|
|
|
218
199
|
return setTimeout(() => {
|
|
219
200
|
this.destroy();
|
|
220
201
|
}, this.animationOptions.leaveDuration);
|
|
221
202
|
}
|
|
222
203
|
|
|
223
|
-
update() {
|
|
224
|
-
this.popperInstance?.update();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
204
|
updateContent(content) {
|
|
228
205
|
this.message = content;
|
|
229
|
-
this
|
|
230
|
-
this.update();
|
|
206
|
+
this.#renderContent(this.message);
|
|
231
207
|
}
|
|
232
208
|
|
|
233
209
|
destroy() {
|
|
234
210
|
this.elements.tooltip.remove();
|
|
235
211
|
|
|
236
212
|
if (this.popperInstance) {
|
|
237
|
-
|
|
238
|
-
this.
|
|
213
|
+
// destroy instance
|
|
214
|
+
this.floatingInstance();
|
|
215
|
+
this.floatingInstance = null;
|
|
239
216
|
}
|
|
240
217
|
}
|
|
241
218
|
}
|
|
@@ -21,7 +21,7 @@ export class TooltipCloseOnScrollModifier {
|
|
|
21
21
|
/**
|
|
22
22
|
* @param {Tooltip} tooltip - tooltip element
|
|
23
23
|
*
|
|
24
|
-
* @return {Partial<Modifier<any, any>>} -
|
|
24
|
+
* @return {Partial<Modifier<any, any>>} - Floating modifier
|
|
25
25
|
* */
|
|
26
26
|
static init({ tooltip }) {
|
|
27
27
|
const modifier = new TooltipCloseOnScrollModifier(tooltip);
|
|
@@ -30,7 +30,10 @@ export class TooltipCloseOnScrollModifier {
|
|
|
30
30
|
name: 'closeOnScroll',
|
|
31
31
|
enabled: true,
|
|
32
32
|
phase: 'main',
|
|
33
|
-
fn: () =>
|
|
33
|
+
fn: ({ x, y }) => {
|
|
34
|
+
modifier.closeOnScroll();
|
|
35
|
+
return { x, y };
|
|
36
|
+
}
|
|
34
37
|
};
|
|
35
38
|
}
|
|
36
39
|
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
.zpa-tooltip__wrapper {
|
|
2
|
+
position: absolute;
|
|
3
|
+
top: 0;
|
|
4
|
+
left: 0;
|
|
5
|
+
}
|
|
6
|
+
|
|
1
7
|
.zpa-tooltip {
|
|
2
8
|
position: relative;
|
|
3
9
|
background-color: #36404C;
|
|
@@ -31,6 +37,7 @@
|
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
.zpa-tooltip__arrow {
|
|
40
|
+
position: absolute;
|
|
34
41
|
width: 16px;
|
|
35
42
|
height: 16px;
|
|
36
43
|
color: #36404C;
|
|
@@ -43,11 +50,15 @@
|
|
|
43
50
|
border-style: solid;
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
.zpa-
|
|
53
|
+
.zpa-tooltip--top {
|
|
54
|
+
transform-origin: center bottom;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.zpa-tooltip--top .zpa-tooltip__arrow {
|
|
47
58
|
bottom: 0;
|
|
48
59
|
}
|
|
49
60
|
|
|
50
|
-
.zpa-
|
|
61
|
+
.zpa-tooltip--top .zpa-tooltip__arrow::before {
|
|
51
62
|
bottom: -7px;
|
|
52
63
|
left: 0;
|
|
53
64
|
border-width: 8px 8px 0;
|
|
@@ -55,11 +66,15 @@
|
|
|
55
66
|
transform-origin: center top;
|
|
56
67
|
}
|
|
57
68
|
|
|
58
|
-
.zpa-
|
|
69
|
+
.zpa-tooltip--bottom {
|
|
70
|
+
transform-origin: center top;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.zpa-tooltip--bottom .zpa-tooltip__arrow {
|
|
59
74
|
top: 0;
|
|
60
75
|
}
|
|
61
76
|
|
|
62
|
-
.zpa-
|
|
77
|
+
.zpa-tooltip--bottom .zpa-tooltip__arrow::before {
|
|
63
78
|
top: -7px;
|
|
64
79
|
left: 0;
|
|
65
80
|
border-width: 0 8px 8px;
|
|
@@ -67,22 +82,30 @@
|
|
|
67
82
|
transform-origin: center bottom;
|
|
68
83
|
}
|
|
69
84
|
|
|
70
|
-
.zpa-
|
|
85
|
+
.zpa-tooltip--left {
|
|
86
|
+
transform-origin: center right;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.zpa-tooltip--left .zpa-tooltip__arrow {
|
|
71
90
|
right: 0;
|
|
72
91
|
}
|
|
73
92
|
|
|
74
|
-
.zpa-
|
|
93
|
+
.zpa-tooltip--left .zpa-tooltip__arrow::before {
|
|
75
94
|
border-width: 8px 0 8px 8px;
|
|
76
95
|
border-left-color: initial;
|
|
77
96
|
right: -7px;
|
|
78
97
|
transform-origin: center left;
|
|
79
98
|
}
|
|
80
99
|
|
|
81
|
-
.zpa-
|
|
100
|
+
.zpa-tooltip--right {
|
|
101
|
+
transform-origin: center left;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.zpa-tooltip--right .zpa-tooltip__arrow {
|
|
82
105
|
left: 0;
|
|
83
106
|
}
|
|
84
107
|
|
|
85
|
-
.zpa-
|
|
108
|
+
.zpa-tooltip--right .zpa-tooltip__arrow::before {
|
|
86
109
|
left: -7px;
|
|
87
110
|
border-width: 8px 8px 8px 0;
|
|
88
111
|
border-right-color: initial;
|
package/lib/Wysiwyg.vue
CHANGED
|
@@ -148,11 +148,9 @@ const toolbar = useToolbar({
|
|
|
148
148
|
isActiveRef: isToolbarActiveRef,
|
|
149
149
|
offsets: props.toolbarOffsets
|
|
150
150
|
});
|
|
151
|
-
const updateToolbar = () => toolbar.update();
|
|
152
151
|
|
|
153
152
|
function onChange(content) {
|
|
154
153
|
emit('update:model-value', content);
|
|
155
|
-
updateToolbar();
|
|
156
154
|
}
|
|
157
155
|
|
|
158
156
|
const pageBlocks = toRef(props, 'pageBlocks');
|
|
@@ -196,7 +194,7 @@ provide(InjectionTokens.LOCAL_STORAGE, new Storage(localStorage));
|
|
|
196
194
|
provide(InjectionTokens.FAVORITE_COLORS, favoriteColors);
|
|
197
195
|
provide(InjectionTokens.PAGE_BLOCKS, pageBlocks);
|
|
198
196
|
|
|
199
|
-
defineExpose({ getContentCustomization, getContent,
|
|
197
|
+
defineExpose({ getContentCustomization, getContent, editor });
|
|
200
198
|
</script>
|
|
201
199
|
|
|
202
200
|
<style src="./styles/main.css" />
|
|
@@ -4,6 +4,8 @@ import { InjectionTokens } from '../../../../injectionTokens';
|
|
|
4
4
|
import { useModalToggler } from '../useModalToggler';
|
|
5
5
|
import { useElementRef } from '../useElementRef';
|
|
6
6
|
|
|
7
|
+
jest.mock('@floating-ui/dom');
|
|
8
|
+
|
|
7
9
|
const createEditor = () => ({
|
|
8
10
|
commands: {
|
|
9
11
|
storeSelection: jest.fn(),
|
|
@@ -1,61 +1,55 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { inject, nextTick, ref } from 'vue';
|
|
2
|
+
import { autoUpdate, computePosition, limitShift, offset, shift } from '@floating-ui/dom';
|
|
3
3
|
import { InjectionTokens } from '../../../injectionTokens';
|
|
4
4
|
import { useElementRef } from './useElementRef';
|
|
5
5
|
|
|
6
6
|
export function useModalToggler({ onBeforeOpened, onClosed, wrapperRef, modalRef } = {}) {
|
|
7
7
|
const editor = inject(InjectionTokens.EDITOR);
|
|
8
8
|
const isOpened = ref(false);
|
|
9
|
-
let
|
|
9
|
+
let floatingInstance;
|
|
10
10
|
|
|
11
|
-
function
|
|
11
|
+
function initModal() {
|
|
12
12
|
const wrapperEl = useElementRef(wrapperRef);
|
|
13
13
|
const modalEl = useElementRef(modalRef);
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
{
|
|
32
|
-
name: 'flip',
|
|
33
|
-
enabled: false
|
|
34
|
-
}
|
|
35
|
-
]
|
|
15
|
+
floatingInstance = autoUpdate(wrapperEl.value, modalEl.value, async () => {
|
|
16
|
+
const positioning = await computePosition(wrapperEl.value, modalEl.value, {
|
|
17
|
+
placement: 'bottom',
|
|
18
|
+
strategy: 'fixed',
|
|
19
|
+
middleware: [
|
|
20
|
+
shift({ padding: 16, crossAxis: true, limiter: limitShift() }),
|
|
21
|
+
offset({ mainAxis: 4 })
|
|
22
|
+
]
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const { x, y } = positioning;
|
|
26
|
+
|
|
27
|
+
Object.assign(modalEl.value, {
|
|
28
|
+
left: `${x}px`,
|
|
29
|
+
top: `${y}px`
|
|
30
|
+
});
|
|
36
31
|
});
|
|
37
32
|
}
|
|
38
33
|
|
|
39
34
|
async function open() {
|
|
35
|
+
if (isOpened.value) return;
|
|
36
|
+
|
|
40
37
|
onBeforeOpened?.();
|
|
41
38
|
editor.commands.storeSelection();
|
|
42
39
|
isOpened.value = true;
|
|
43
40
|
|
|
44
41
|
await nextTick();
|
|
45
42
|
|
|
46
|
-
|
|
43
|
+
initModal();
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
function close() {
|
|
50
47
|
isOpened.value = false;
|
|
48
|
+
floatingInstance?.();
|
|
51
49
|
editor.commands.restoreSelection();
|
|
52
50
|
onClosed?.();
|
|
53
51
|
}
|
|
54
52
|
|
|
55
|
-
onUnmounted(() => {
|
|
56
|
-
popper?.destroy();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
53
|
const toggle = (toOpen) => toOpen ? open() : close();
|
|
60
54
|
|
|
61
55
|
return { isOpened, open, close, toggle };
|
|
@@ -4,6 +4,8 @@ import { InjectionTokens } from '../../../../injectionTokens';
|
|
|
4
4
|
import { Button, Modal, NumberField, Range } from '../../../base';
|
|
5
5
|
import LineHeightControl from '../LineHeightControl';
|
|
6
6
|
|
|
7
|
+
jest.mock('@floating-ui/dom');
|
|
8
|
+
|
|
7
9
|
const SELECTORS = {
|
|
8
10
|
INDICATOR: '[data-test-selector="customizedIndicator"]'
|
|
9
11
|
};
|
|
@@ -1,38 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { onUnmounted } from 'vue';
|
|
2
|
+
import { autoUpdate, computePosition, limitShift, offset, shift } from '@floating-ui/dom';
|
|
2
3
|
import { useElementRef } from '../components/base';
|
|
3
4
|
|
|
4
5
|
export function useToolbar({ wrapperRef, offsets, isActiveRef, placementRef }) {
|
|
5
6
|
const wrapperEl = useElementRef(wrapperRef);
|
|
6
|
-
let
|
|
7
|
+
let floatingInstance;
|
|
7
8
|
|
|
8
9
|
function mount(element) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
name: 'flip',
|
|
26
|
-
enabled: false
|
|
27
|
-
}
|
|
28
|
-
]
|
|
10
|
+
floatingInstance = autoUpdate(wrapperEl.value, element, async () => {
|
|
11
|
+
const positioning = await computePosition(wrapperEl.value, element, {
|
|
12
|
+
placement: placementRef.value,
|
|
13
|
+
strategy: 'fixed',
|
|
14
|
+
middleware: [
|
|
15
|
+
shift({ padding: 16, crossAxis: true, limiter: limitShift() }),
|
|
16
|
+
offset({ crossAxis: offsets[0], mainAxis: offsets[1] })
|
|
17
|
+
]
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const { x, y } = positioning;
|
|
21
|
+
|
|
22
|
+
Object.assign(element.style, {
|
|
23
|
+
left: `${x}px`,
|
|
24
|
+
top: `${y}px`
|
|
25
|
+
});
|
|
29
26
|
});
|
|
30
27
|
}
|
|
31
28
|
|
|
32
|
-
|
|
29
|
+
onUnmounted(() => floatingInstance?.());
|
|
33
30
|
|
|
34
31
|
return {
|
|
35
|
-
update,
|
|
36
32
|
mount,
|
|
37
33
|
isActiveRef,
|
|
38
34
|
offsets
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zipify/wysiwyg",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.1.0-0",
|
|
4
4
|
"description": "Zipify modification of TipTap text editor",
|
|
5
5
|
"main": "dist/wysiwyg.mjs",
|
|
6
6
|
"bin": {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"prepare": "husky install"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
+
"@floating-ui/dom": "^1.5.3",
|
|
33
34
|
"@popperjs/core": "^2.11.7",
|
|
34
35
|
"@tiptap/core": "^2.0.0",
|
|
35
36
|
"@tiptap/extension-document": "^2.0.0",
|