@oix1987/yjd 1.0.0 → 1.0.2
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/README.md +73 -22
- package/dist/rich-editor.esm.js +2 -0
- package/dist/rich-editor.esm.js.map +1 -0
- package/dist/rich-editor.min.js +2 -0
- package/dist/rich-editor.min.js.map +1 -0
- package/package.json +12 -7
- package/index.js +0 -221
- package/lib/core/editor.js +0 -1175
- package/lib/core/format.js +0 -542
- package/lib/core/module.js +0 -81
- package/lib/core/registry.js +0 -152
- package/lib/formats/background.js +0 -212
- package/lib/formats/bold.js +0 -67
- package/lib/formats/capitalization.js +0 -563
- package/lib/formats/color.js +0 -165
- package/lib/formats/emoji.js +0 -282
- package/lib/formats/font-family.js +0 -547
- package/lib/formats/heading.js +0 -502
- package/lib/formats/image.js +0 -344
- package/lib/formats/import.js +0 -385
- package/lib/formats/indent.js +0 -297
- package/lib/formats/italic.js +0 -27
- package/lib/formats/line-height.js +0 -558
- package/lib/formats/link.js +0 -251
- package/lib/formats/list.js +0 -635
- package/lib/formats/strike.js +0 -31
- package/lib/formats/subscript.js +0 -36
- package/lib/formats/superscript.js +0 -35
- package/lib/formats/table.js +0 -288
- package/lib/formats/tag.js +0 -304
- package/lib/formats/text-align.js +0 -421
- package/lib/formats/text-size.js +0 -497
- package/lib/formats/underline.js +0 -30
- package/lib/formats/video.js +0 -372
- package/lib/modules/block-toolbar.js +0 -628
- package/lib/modules/code-view.js +0 -434
- package/lib/modules/history.js +0 -410
- package/lib/modules/resize-handles.js +0 -677
- package/lib/modules/table-toolbar.js +0 -618
- package/lib/modules/toolbar.js +0 -424
- package/lib/styles-loader.js +0 -144
- package/lib/styles.css +0 -2123
- package/lib/ui/color-picker.js +0 -296
- package/lib/ui/customselect.js +0 -319
- package/lib/ui/emoji-picker.js +0 -196
- package/lib/ui/icons.js +0 -413
- package/lib/ui/image-popup.js +0 -444
- package/lib/ui/import-popup.js +0 -288
- package/lib/ui/link-popup.js +0 -191
- package/lib/ui/list-picker.js +0 -307
- package/lib/ui/select-button.js +0 -61
- package/lib/ui/table-popup.js +0 -171
- package/lib/ui/tag-popup.js +0 -249
- package/lib/ui/text-align-picker.js +0 -281
- package/lib/ui/video-popup.js +0 -422
- package/lib/utils/history-helper.js +0 -50
- package/lib/utils/popup-helper.js +0 -219
- package/lib/utils/popup-positioning.js +0 -231
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Responsive Popup Positioning Utility
|
|
3
|
-
* Handles positioning of popups to ensure they stay within viewport on mobile devices
|
|
4
|
-
*/
|
|
5
|
-
export class PopupPositioning {
|
|
6
|
-
/**
|
|
7
|
-
* Calculate optimal position for popup to stay within viewport
|
|
8
|
-
* @param {HTMLElement} anchor - The anchor element
|
|
9
|
-
* @param {HTMLElement} popup - The popup element
|
|
10
|
-
* @param {Object} options - Positioning options
|
|
11
|
-
* @returns {Object} - Calculated position {top, left, transform}
|
|
12
|
-
*/
|
|
13
|
-
static calculatePosition(anchor, popup, options = {}) {
|
|
14
|
-
const {
|
|
15
|
-
offsetX = 0,
|
|
16
|
-
offsetY = 5,
|
|
17
|
-
preferredPosition = 'bottom-right', // 'bottom-right', 'bottom-left', 'top-right', 'top-left'
|
|
18
|
-
maxWidth = null,
|
|
19
|
-
maxHeight = null
|
|
20
|
-
} = options;
|
|
21
|
-
|
|
22
|
-
// Get viewport dimensions
|
|
23
|
-
const viewportWidth = window.innerWidth;
|
|
24
|
-
const viewportHeight = window.innerHeight;
|
|
25
|
-
const scrollX = window.scrollX;
|
|
26
|
-
const scrollY = window.scrollY;
|
|
27
|
-
|
|
28
|
-
// Get anchor dimensions
|
|
29
|
-
const anchorRect = anchor.getBoundingClientRect();
|
|
30
|
-
|
|
31
|
-
// Get popup dimensions (measure if not already rendered)
|
|
32
|
-
let popupWidth = popup.offsetWidth;
|
|
33
|
-
let popupHeight = popup.offsetHeight;
|
|
34
|
-
|
|
35
|
-
// If popup is not yet visible, temporarily show it to measure
|
|
36
|
-
let wasVisible = popup.classList.contains('visible');
|
|
37
|
-
if (!wasVisible) {
|
|
38
|
-
popup.style.visibility = 'hidden';
|
|
39
|
-
popup.style.position = 'absolute';
|
|
40
|
-
popup.style.top = '0';
|
|
41
|
-
popup.style.left = '0';
|
|
42
|
-
popup.classList.add('visible');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Measure popup dimensions
|
|
46
|
-
popupWidth = popup.offsetWidth;
|
|
47
|
-
popupHeight = popup.offsetHeight;
|
|
48
|
-
|
|
49
|
-
// Apply max constraints
|
|
50
|
-
if (maxWidth && popupWidth > maxWidth) {
|
|
51
|
-
popupWidth = maxWidth;
|
|
52
|
-
}
|
|
53
|
-
if (maxHeight && popupHeight > maxHeight) {
|
|
54
|
-
popupHeight = maxHeight;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Hide popup if it was hidden before
|
|
58
|
-
if (!wasVisible) {
|
|
59
|
-
popup.classList.remove('visible');
|
|
60
|
-
popup.style.visibility = '';
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Calculate base positions for different orientations
|
|
64
|
-
const positions = {
|
|
65
|
-
'bottom-right': {
|
|
66
|
-
top: anchorRect.bottom + scrollY + offsetY,
|
|
67
|
-
left: anchorRect.left + scrollX + offsetX
|
|
68
|
-
},
|
|
69
|
-
'bottom-left': {
|
|
70
|
-
top: anchorRect.bottom + scrollY + offsetY,
|
|
71
|
-
left: anchorRect.right + scrollX - popupWidth - offsetX
|
|
72
|
-
},
|
|
73
|
-
'top-right': {
|
|
74
|
-
top: anchorRect.top + scrollY - popupHeight - offsetY,
|
|
75
|
-
left: anchorRect.left + scrollX + offsetX
|
|
76
|
-
},
|
|
77
|
-
'top-left': {
|
|
78
|
-
top: anchorRect.top + scrollY - popupHeight - offsetY,
|
|
79
|
-
left: anchorRect.right + scrollX - popupWidth - offsetX
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
// Start with preferred position
|
|
84
|
-
let position = positions[preferredPosition];
|
|
85
|
-
let transform = '';
|
|
86
|
-
|
|
87
|
-
// Check if popup fits in preferred position
|
|
88
|
-
const fitsInPreferred = this.checkFitsInViewport(position, popupWidth, popupHeight, viewportWidth, viewportHeight, scrollX, scrollY);
|
|
89
|
-
|
|
90
|
-
if (!fitsInPreferred) {
|
|
91
|
-
// Try alternative positions
|
|
92
|
-
const alternativePositions = this.getAlternativePositions(preferredPosition);
|
|
93
|
-
|
|
94
|
-
for (const altPosition of alternativePositions) {
|
|
95
|
-
const testPosition = positions[altPosition];
|
|
96
|
-
if (this.checkFitsInViewport(testPosition, popupWidth, popupHeight, viewportWidth, viewportHeight, scrollX, scrollY)) {
|
|
97
|
-
position = testPosition;
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// If no position fits, use the best available with adjustments
|
|
103
|
-
if (!this.checkFitsInViewport(position, popupWidth, popupHeight, viewportWidth, viewportHeight, scrollX, scrollY)) {
|
|
104
|
-
position = this.adjustToFitViewport(position, popupWidth, popupHeight, viewportWidth, viewportHeight, scrollX, scrollY);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// For mobile devices, add additional constraints
|
|
109
|
-
if (viewportWidth <= 768) {
|
|
110
|
-
position = this.applyMobileConstraints(position, popupWidth, popupHeight, viewportWidth, viewportHeight, scrollX, scrollY);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
top: position.top,
|
|
115
|
-
left: position.left,
|
|
116
|
-
transform: transform
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Check if position fits within viewport
|
|
122
|
-
*/
|
|
123
|
-
static checkFitsInViewport(position, width, height, viewportWidth, viewportHeight, scrollX, scrollY) {
|
|
124
|
-
const right = position.left + width;
|
|
125
|
-
const bottom = position.top + height;
|
|
126
|
-
|
|
127
|
-
return position.left >= scrollX &&
|
|
128
|
-
position.top >= scrollY &&
|
|
129
|
-
right <= scrollX + viewportWidth &&
|
|
130
|
-
bottom <= scrollY + viewportHeight;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Get alternative positions to try
|
|
135
|
-
*/
|
|
136
|
-
static getAlternativePositions(preferredPosition) {
|
|
137
|
-
const alternatives = {
|
|
138
|
-
'bottom-right': ['bottom-left', 'top-right', 'top-left'],
|
|
139
|
-
'bottom-left': ['bottom-right', 'top-left', 'top-right'],
|
|
140
|
-
'top-right': ['top-left', 'bottom-right', 'bottom-left'],
|
|
141
|
-
'top-left': ['top-right', 'bottom-left', 'bottom-right']
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
return alternatives[preferredPosition] || ['bottom-right', 'bottom-left', 'top-right', 'top-left'];
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Adjust position to fit within viewport
|
|
149
|
-
*/
|
|
150
|
-
static adjustToFitViewport(position, width, height, viewportWidth, viewportHeight, scrollX, scrollY) {
|
|
151
|
-
let { top, left } = position;
|
|
152
|
-
|
|
153
|
-
// Adjust horizontal position
|
|
154
|
-
if (left < scrollX) {
|
|
155
|
-
left = scrollX + 10;
|
|
156
|
-
} else if (left + width > scrollX + viewportWidth) {
|
|
157
|
-
left = scrollX + viewportWidth - width - 10;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Adjust vertical position
|
|
161
|
-
if (top < scrollY) {
|
|
162
|
-
top = scrollY + 10;
|
|
163
|
-
} else if (top + height > scrollY + viewportHeight) {
|
|
164
|
-
top = scrollY + viewportHeight - height - 10;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return { top, left };
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Apply mobile-specific constraints
|
|
172
|
-
*/
|
|
173
|
-
static applyMobileConstraints(position, width, height, viewportWidth, viewportHeight, scrollX, scrollY) {
|
|
174
|
-
let { top, left } = position;
|
|
175
|
-
|
|
176
|
-
// On mobile, prefer center positioning if popup is too large
|
|
177
|
-
if (width > viewportWidth * 0.9) {
|
|
178
|
-
left = scrollX + (viewportWidth - width) / 2;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (height > viewportHeight * 0.8) {
|
|
182
|
-
top = scrollY + (viewportHeight - height) / 2;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Ensure minimum margins
|
|
186
|
-
const minMargin = 10;
|
|
187
|
-
if (left < scrollX + minMargin) left = scrollX + minMargin;
|
|
188
|
-
if (top < scrollY + minMargin) top = scrollY + minMargin;
|
|
189
|
-
if (left + width > scrollX + viewportWidth - minMargin) {
|
|
190
|
-
left = scrollX + viewportWidth - width - minMargin;
|
|
191
|
-
}
|
|
192
|
-
if (top + height > scrollY + viewportHeight - minMargin) {
|
|
193
|
-
top = scrollY + viewportHeight - height - minMargin;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return { top, left };
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Apply calculated position to popup element
|
|
201
|
-
*/
|
|
202
|
-
static applyPosition(popup, position) {
|
|
203
|
-
popup.style.position = 'absolute';
|
|
204
|
-
popup.style.top = `${position.top}px`;
|
|
205
|
-
popup.style.left = `${position.left}px`;
|
|
206
|
-
|
|
207
|
-
if (position.transform) {
|
|
208
|
-
popup.style.transform = position.transform;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Check if device is mobile
|
|
214
|
-
*/
|
|
215
|
-
static isMobile() {
|
|
216
|
-
return window.innerWidth <= 768;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Get recommended max dimensions for mobile
|
|
221
|
-
*/
|
|
222
|
-
static getMobileMaxDimensions() {
|
|
223
|
-
const viewportWidth = window.innerWidth;
|
|
224
|
-
const viewportHeight = window.innerHeight;
|
|
225
|
-
|
|
226
|
-
return {
|
|
227
|
-
maxWidth: Math.min(viewportWidth * 0.95, 350),
|
|
228
|
-
maxHeight: Math.min(viewportHeight * 0.8, 400)
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
}
|