@oix1987/yjd 1.0.1 → 1.0.3
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 +9 -1
- 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 +13 -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/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
- /package/{lib → dist}/styles.css +0 -0
package/lib/ui/list-picker.js
DELETED
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
import IconUtils from './icons.js';
|
|
2
|
-
import { appendPopup, calculatePopupPosition, setPopupPosition } from '../utils/popup-helper.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* List Picker Component - Popup for selecting list types
|
|
6
|
-
*/
|
|
7
|
-
class ListPicker {
|
|
8
|
-
constructor(options = {}) {
|
|
9
|
-
this.options = {
|
|
10
|
-
listTypes: [
|
|
11
|
-
{ value: 'bullet', label: 'Bullet List', icon: 'list-bullet' },
|
|
12
|
-
{ value: 'ordered', label: 'Numbered List', icon: 'list-ordered' },
|
|
13
|
-
{ value: 'roman', label: 'Roman Numerals List', icon: 'list-roman' },
|
|
14
|
-
{ value: 'alpha', label: 'Alphabetical List', icon: 'list-alpha' }
|
|
15
|
-
],
|
|
16
|
-
onListSelect: null,
|
|
17
|
-
...options
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
this.popup = null;
|
|
21
|
-
this.isVisible = false;
|
|
22
|
-
this.currentListType = null;
|
|
23
|
-
this.clickOutsideHandler = null;
|
|
24
|
-
|
|
25
|
-
this.createListPicker();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Create list picker popup
|
|
30
|
-
*/
|
|
31
|
-
createListPicker() {
|
|
32
|
-
// Create popup
|
|
33
|
-
this.popup = document.createElement('div');
|
|
34
|
-
this.popup.className = 'list-picker-popup';
|
|
35
|
-
|
|
36
|
-
// Create list type buttons
|
|
37
|
-
this.createListTypeButtons();
|
|
38
|
-
|
|
39
|
-
// Add popup to container
|
|
40
|
-
appendPopup(this.popup);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Create list type buttons
|
|
45
|
-
*/
|
|
46
|
-
async createListTypeButtons() {
|
|
47
|
-
const buttonContainer = document.createElement('div');
|
|
48
|
-
buttonContainer.className = 'list-button-container';
|
|
49
|
-
|
|
50
|
-
// Icons are now inline, no need to preload
|
|
51
|
-
|
|
52
|
-
// Create buttons
|
|
53
|
-
for (const listType of this.options.listTypes) {
|
|
54
|
-
const listButton = document.createElement('button');
|
|
55
|
-
listButton.type = 'button';
|
|
56
|
-
listButton.className = 'list-button';
|
|
57
|
-
listButton.dataset.listType = listType.value;
|
|
58
|
-
listButton.title = listType.label;
|
|
59
|
-
|
|
60
|
-
// Add icon
|
|
61
|
-
const iconSvg = IconUtils.getIcon(listType.icon);
|
|
62
|
-
if (iconSvg) {
|
|
63
|
-
listButton.innerHTML = iconSvg;
|
|
64
|
-
} else {
|
|
65
|
-
listButton.textContent = listType.label.charAt(0);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
listButton.addEventListener('click', (e) => {
|
|
69
|
-
e.preventDefault();
|
|
70
|
-
e.stopPropagation();
|
|
71
|
-
this.selectListType(listType.value);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
buttonContainer.appendChild(listButton);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
this.popup.appendChild(buttonContainer);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Setup click outside handler
|
|
82
|
-
*/
|
|
83
|
-
setupClickOutside() {
|
|
84
|
-
if (this.clickOutsideHandler) {
|
|
85
|
-
document.removeEventListener('click', this.clickOutsideHandler);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
this.clickOutsideHandler = (e) => {
|
|
89
|
-
if (!this.popup.contains(e.target)) {
|
|
90
|
-
this.hide();
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
// Add slight delay to avoid immediate close
|
|
95
|
-
setTimeout(() => {
|
|
96
|
-
document.addEventListener('click', this.clickOutsideHandler);
|
|
97
|
-
}, 100);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Remove click outside handler
|
|
102
|
-
*/
|
|
103
|
-
removeClickOutside() {
|
|
104
|
-
if (this.clickOutsideHandler) {
|
|
105
|
-
document.removeEventListener('click', this.clickOutsideHandler);
|
|
106
|
-
this.clickOutsideHandler = null;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Show list picker popup
|
|
112
|
-
* @param {HTMLElement} anchor - Element to position popup relative to
|
|
113
|
-
*/
|
|
114
|
-
show(anchor) {
|
|
115
|
-
if (!anchor) return;
|
|
116
|
-
|
|
117
|
-
// Ensure popup is in DOM
|
|
118
|
-
if (!document.body.contains(this.popup)) {
|
|
119
|
-
appendPopup(this.popup);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Update current list type state
|
|
123
|
-
this.updateCurrentListType();
|
|
124
|
-
|
|
125
|
-
// Calculate and set popup position
|
|
126
|
-
const position = calculatePopupPosition(anchor, this.popup, {
|
|
127
|
-
offsetY: 5,
|
|
128
|
-
offsetX: 0
|
|
129
|
-
});
|
|
130
|
-
setPopupPosition(this.popup, position);
|
|
131
|
-
|
|
132
|
-
// Show popup by adding visible class
|
|
133
|
-
this.popup.classList.add('visible');
|
|
134
|
-
this.isVisible = true;
|
|
135
|
-
|
|
136
|
-
// Setup click outside handler
|
|
137
|
-
this.setupClickOutside();
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Hide list picker popup
|
|
142
|
-
*/
|
|
143
|
-
hide() {
|
|
144
|
-
this.popup.classList.remove('visible');
|
|
145
|
-
this.isVisible = false;
|
|
146
|
-
this.removeClickOutside();
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Select list type and trigger callback
|
|
151
|
-
* @param {string} listType - Selected list type
|
|
152
|
-
*/
|
|
153
|
-
selectListType(listType) {
|
|
154
|
-
this.currentListType = listType;
|
|
155
|
-
|
|
156
|
-
if (this.options.onListSelect) {
|
|
157
|
-
this.options.onListSelect(listType);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
this.hide();
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Update current list type state based on selection
|
|
165
|
-
*/
|
|
166
|
-
updateCurrentListType() {
|
|
167
|
-
try {
|
|
168
|
-
const listType = this.getCurrentListType();
|
|
169
|
-
this.currentListType = listType;
|
|
170
|
-
|
|
171
|
-
// Update button states
|
|
172
|
-
this.updateButtonStates(listType);
|
|
173
|
-
} catch (error) {
|
|
174
|
-
console.warn('Error updating current list type:', error);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Update button states based on current list type
|
|
180
|
-
* @param {string|null} currentListType - Current active list type
|
|
181
|
-
*/
|
|
182
|
-
updateButtonStates(currentListType) {
|
|
183
|
-
const buttons = this.popup.querySelectorAll('.list-button');
|
|
184
|
-
buttons.forEach(button => {
|
|
185
|
-
button.classList.remove('active');
|
|
186
|
-
if (currentListType && button.dataset.listType === currentListType) {
|
|
187
|
-
button.classList.add('active');
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Update toolbar button icon based on selection
|
|
194
|
-
* @param {string} listType - Current list type
|
|
195
|
-
*/
|
|
196
|
-
updateToolbarButtonIcon(listType) {
|
|
197
|
-
const button = document.querySelector('.rich-editor-toolbar-btn.list-btn');
|
|
198
|
-
if (!button) return;
|
|
199
|
-
|
|
200
|
-
const iconMap = {
|
|
201
|
-
'bullet': 'list-bullet',
|
|
202
|
-
'ordered': 'list-ordered',
|
|
203
|
-
'roman': 'list-roman',
|
|
204
|
-
'alpha': 'list-alpha'
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
const titleMap = {
|
|
208
|
-
'bullet': 'Bullet List',
|
|
209
|
-
'ordered': 'Numbered List',
|
|
210
|
-
'roman': 'Roman Numerals List',
|
|
211
|
-
'alpha': 'Alphabetical List'
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
const iconName = iconMap[listType] || 'list-bullet';
|
|
215
|
-
|
|
216
|
-
// Update button title
|
|
217
|
-
button.title = titleMap[listType] || 'List';
|
|
218
|
-
|
|
219
|
-
// Update icon
|
|
220
|
-
const svgContent = IconUtils.getIcon(iconName);
|
|
221
|
-
if (svgContent) {
|
|
222
|
-
const iconSpan = button.querySelector('.icon');
|
|
223
|
-
if (iconSpan) {
|
|
224
|
-
iconSpan.innerHTML = svgContent;
|
|
225
|
-
} else {
|
|
226
|
-
button.innerHTML = `<span class="icon">${svgContent}</span>`;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Get parent list of an element
|
|
233
|
-
*/
|
|
234
|
-
getParentList(element) {
|
|
235
|
-
let current = element;
|
|
236
|
-
while (current && current !== document.body) {
|
|
237
|
-
if (current.tagName === 'UL' || current.tagName === 'OL') {
|
|
238
|
-
return current;
|
|
239
|
-
}
|
|
240
|
-
current = current.parentElement;
|
|
241
|
-
}
|
|
242
|
-
return null;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Get list type from list element
|
|
247
|
-
*/
|
|
248
|
-
getListType(listElement) {
|
|
249
|
-
if (listElement.tagName === 'OL') {
|
|
250
|
-
const type = listElement.style.listStyleType;
|
|
251
|
-
if (type === 'upper-roman') return 'roman';
|
|
252
|
-
if (type === 'lower-alpha') return 'alpha';
|
|
253
|
-
return 'ordered';
|
|
254
|
-
}
|
|
255
|
-
return 'bullet';
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Get block element containing the given node
|
|
260
|
-
*/
|
|
261
|
-
getBlockElement(node) {
|
|
262
|
-
if (!node) return null;
|
|
263
|
-
|
|
264
|
-
let currentNode = node;
|
|
265
|
-
while (currentNode && currentNode !== document.body) {
|
|
266
|
-
if (currentNode.nodeType === Node.ELEMENT_NODE) {
|
|
267
|
-
const tagName = currentNode.tagName;
|
|
268
|
-
if (['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE', 'LI', 'UL', 'OL'].includes(tagName)) {
|
|
269
|
-
return currentNode;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
currentNode = currentNode.parentNode;
|
|
273
|
-
}
|
|
274
|
-
return null;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Get current list type
|
|
279
|
-
* @returns {string|null}
|
|
280
|
-
*/
|
|
281
|
-
getCurrentListType() {
|
|
282
|
-
const selection = window.getSelection();
|
|
283
|
-
if (!selection || !selection.rangeCount) return null;
|
|
284
|
-
|
|
285
|
-
const range = selection.getRangeAt(0);
|
|
286
|
-
const listElement = this.getParentList(range.commonAncestorContainer);
|
|
287
|
-
|
|
288
|
-
return listElement ? this.getListType(listElement) : null;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Destroy the list picker
|
|
293
|
-
*/
|
|
294
|
-
destroy() {
|
|
295
|
-
this.removeClickOutside();
|
|
296
|
-
|
|
297
|
-
if (this.popup && this.popup.parentNode) {
|
|
298
|
-
this.popup.parentNode.removeChild(this.popup);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
this.popup = null;
|
|
302
|
-
this.isVisible = false;
|
|
303
|
-
this.currentListType = null;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
export default ListPicker;
|
package/lib/ui/select-button.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import IconUtils from './icons.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Create Custom Button - Simple utility to create styled button
|
|
5
|
-
* @param {string} text - Button text content
|
|
6
|
-
* @param {Object} options - Button options
|
|
7
|
-
* @param {string} options.width - Button width (e.g., '120px', 'auto')
|
|
8
|
-
* @returns {HTMLElement} Button element
|
|
9
|
-
*/
|
|
10
|
-
function createCustomButton(text = 'Button', options = {}) {
|
|
11
|
-
const { width = 'auto' } = options;
|
|
12
|
-
|
|
13
|
-
// Create button
|
|
14
|
-
const button = document.createElement('button');
|
|
15
|
-
button.type = 'button';
|
|
16
|
-
button.className = 'custom-select-button';
|
|
17
|
-
|
|
18
|
-
// Create text span
|
|
19
|
-
const textSpan = document.createElement('span');
|
|
20
|
-
textSpan.textContent = text;
|
|
21
|
-
textSpan.className = 'button-text';
|
|
22
|
-
|
|
23
|
-
// Create dropdown icon
|
|
24
|
-
const dropdownIcon = IconUtils.createIconElement('dropdown');
|
|
25
|
-
dropdownIcon.className = 'dropdown-icon';
|
|
26
|
-
|
|
27
|
-
// Add text and icon to button
|
|
28
|
-
button.appendChild(textSpan);
|
|
29
|
-
button.appendChild(dropdownIcon);
|
|
30
|
-
|
|
31
|
-
// Apply styles
|
|
32
|
-
button.style.width = width;
|
|
33
|
-
button.style.padding = '0px 5px 0px 8px';
|
|
34
|
-
button.style.setProperty('height', '32px', 'important');
|
|
35
|
-
button.style.setProperty('borderRadius', '6px', 'important');
|
|
36
|
-
button.style.setProperty('alignItems', 'center', 'important');
|
|
37
|
-
button.style.fontSize = '14px';
|
|
38
|
-
button.style.fontWeight = '400';
|
|
39
|
-
button.style.color = '#374151';
|
|
40
|
-
button.style.background = '#FFFFFF';
|
|
41
|
-
button.style.cursor = 'pointer';
|
|
42
|
-
button.style.border = '1px solid #d1d5db';
|
|
43
|
-
button.style.display = 'flex';
|
|
44
|
-
button.style.justifyContent = 'space-between';
|
|
45
|
-
button.style.alignItems = 'center';
|
|
46
|
-
|
|
47
|
-
// Style the text span to take available space
|
|
48
|
-
textSpan.style.flex = '1';
|
|
49
|
-
textSpan.style.textAlign = 'left';
|
|
50
|
-
|
|
51
|
-
// Style the dropdown icon
|
|
52
|
-
|
|
53
|
-
// Add method to update button text
|
|
54
|
-
button.updateText = function(newText) {
|
|
55
|
-
textSpan.textContent = newText;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
return button;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export default createCustomButton;
|
package/lib/ui/table-popup.js
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Table Popup Component - Interactive table size picker
|
|
3
|
-
*/
|
|
4
|
-
import { PopupPositioning } from '../utils/popup-positioning.js';
|
|
5
|
-
import { appendPopup, calculatePopupPosition, setPopupPosition } from '../utils/popup-helper.js';
|
|
6
|
-
|
|
7
|
-
class TablePopup {
|
|
8
|
-
constructor(options = {}) {
|
|
9
|
-
this.options = {
|
|
10
|
-
maxRows: 8,
|
|
11
|
-
maxCols: 8,
|
|
12
|
-
onTableSelect: null,
|
|
13
|
-
...options
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
this.popup = null;
|
|
17
|
-
this.isVisible = false;
|
|
18
|
-
this.selectedRows = 1;
|
|
19
|
-
this.selectedCols = 1;
|
|
20
|
-
this.grid = null;
|
|
21
|
-
this.sizeDisplay = null;
|
|
22
|
-
|
|
23
|
-
this.createPopup();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
createPopup() {
|
|
27
|
-
this.popup = document.createElement('div');
|
|
28
|
-
this.popup.className = 'table-popup';
|
|
29
|
-
|
|
30
|
-
const content = document.createElement('div');
|
|
31
|
-
content.className = 'table-popup-content';
|
|
32
|
-
|
|
33
|
-
// Create size display text
|
|
34
|
-
this.createSizeDisplay();
|
|
35
|
-
|
|
36
|
-
// Create grid selector
|
|
37
|
-
this.createGridSelector();
|
|
38
|
-
|
|
39
|
-
content.appendChild(this.grid);
|
|
40
|
-
content.appendChild(this.sizeDisplay);
|
|
41
|
-
this.popup.appendChild(content);
|
|
42
|
-
appendPopup(this.popup);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
createSizeDisplay() {
|
|
46
|
-
this.sizeDisplay = document.createElement('div');
|
|
47
|
-
this.sizeDisplay.className = 'table-size-display';
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
createGridSelector() {
|
|
51
|
-
this.grid = document.createElement('div');
|
|
52
|
-
this.grid.className = 'table-grid-selector';
|
|
53
|
-
|
|
54
|
-
// Create grid of cells
|
|
55
|
-
for (let row = 1; row <= this.options.maxRows; row++) {
|
|
56
|
-
for (let col = 1; col <= this.options.maxCols; col++) {
|
|
57
|
-
const cell = document.createElement('div');
|
|
58
|
-
cell.className = 'table-grid-cell';
|
|
59
|
-
cell.dataset.row = row;
|
|
60
|
-
cell.dataset.col = col;
|
|
61
|
-
|
|
62
|
-
// Mouse events
|
|
63
|
-
cell.addEventListener('mouseenter', () => {
|
|
64
|
-
this.highlightGrid(row, col);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
cell.addEventListener('click', () => {
|
|
68
|
-
this.selectSize(row, col);
|
|
69
|
-
this.handleInsert();
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
this.grid.appendChild(cell);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Reset hover when leaving grid
|
|
77
|
-
this.grid.addEventListener('mouseleave', () => {
|
|
78
|
-
this.highlightGrid(1, 1);
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
highlightGrid(rows, cols) {
|
|
83
|
-
this.selectedRows = rows;
|
|
84
|
-
this.selectedCols = cols;
|
|
85
|
-
|
|
86
|
-
// Update size display text
|
|
87
|
-
this.updateSizeDisplay(rows, cols);
|
|
88
|
-
|
|
89
|
-
// Update grid visual
|
|
90
|
-
const cells = this.grid.querySelectorAll('.table-grid-cell');
|
|
91
|
-
cells.forEach(cell => {
|
|
92
|
-
const cellRow = parseInt(cell.dataset.row);
|
|
93
|
-
const cellCol = parseInt(cell.dataset.col);
|
|
94
|
-
|
|
95
|
-
if (cellRow <= rows && cellCol <= cols) {
|
|
96
|
-
cell.classList.add('highlighted');
|
|
97
|
-
} else {
|
|
98
|
-
cell.classList.remove('highlighted');
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
updateSizeDisplay(rows, cols) {
|
|
104
|
-
if (this.sizeDisplay) {
|
|
105
|
-
this.sizeDisplay.textContent = `${rows}x${cols}`;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
selectSize(rows, cols) {
|
|
110
|
-
this.selectedRows = rows;
|
|
111
|
-
this.selectedCols = cols;
|
|
112
|
-
this.updateSizeDisplay(rows, cols);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
handleInsert() {
|
|
116
|
-
if (this.options.onTableSelect) {
|
|
117
|
-
this.options.onTableSelect({
|
|
118
|
-
rows: this.selectedRows,
|
|
119
|
-
cols: this.selectedCols
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
this.hide();
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
show(anchor) {
|
|
127
|
-
if (!anchor) return;
|
|
128
|
-
|
|
129
|
-
// Reset selection
|
|
130
|
-
this.selectedRows = 1;
|
|
131
|
-
this.selectedCols = 1;
|
|
132
|
-
this.highlightGrid(1, 1);
|
|
133
|
-
|
|
134
|
-
// Calculate and set popup position
|
|
135
|
-
const position = calculatePopupPosition(anchor, this.popup, {
|
|
136
|
-
offsetY: 5,
|
|
137
|
-
offsetX: 0
|
|
138
|
-
});
|
|
139
|
-
setPopupPosition(this.popup, position);
|
|
140
|
-
|
|
141
|
-
// Show popup
|
|
142
|
-
this.popup.classList.add('visible');
|
|
143
|
-
this.isVisible = true;
|
|
144
|
-
|
|
145
|
-
// Click outside to close
|
|
146
|
-
setTimeout(() => {
|
|
147
|
-
document.addEventListener('click', this.closeOnClickOutside);
|
|
148
|
-
}, 100);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
hide() {
|
|
152
|
-
this.popup.classList.remove('visible');
|
|
153
|
-
this.isVisible = false;
|
|
154
|
-
document.removeEventListener('click', this.closeOnClickOutside);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
closeOnClickOutside = (e) => {
|
|
158
|
-
if (!this.popup.contains(e.target)) {
|
|
159
|
-
this.hide();
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
destroy() {
|
|
164
|
-
document.removeEventListener('click', this.closeOnClickOutside);
|
|
165
|
-
if (this.popup && this.popup.parentNode) {
|
|
166
|
-
this.popup.parentNode.removeChild(this.popup);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
export default TablePopup;
|