@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.
Files changed (58) hide show
  1. package/README.md +73 -22
  2. package/dist/rich-editor.esm.js +2 -0
  3. package/dist/rich-editor.esm.js.map +1 -0
  4. package/dist/rich-editor.min.js +2 -0
  5. package/dist/rich-editor.min.js.map +1 -0
  6. package/package.json +12 -7
  7. package/index.js +0 -221
  8. package/lib/core/editor.js +0 -1175
  9. package/lib/core/format.js +0 -542
  10. package/lib/core/module.js +0 -81
  11. package/lib/core/registry.js +0 -152
  12. package/lib/formats/background.js +0 -212
  13. package/lib/formats/bold.js +0 -67
  14. package/lib/formats/capitalization.js +0 -563
  15. package/lib/formats/color.js +0 -165
  16. package/lib/formats/emoji.js +0 -282
  17. package/lib/formats/font-family.js +0 -547
  18. package/lib/formats/heading.js +0 -502
  19. package/lib/formats/image.js +0 -344
  20. package/lib/formats/import.js +0 -385
  21. package/lib/formats/indent.js +0 -297
  22. package/lib/formats/italic.js +0 -27
  23. package/lib/formats/line-height.js +0 -558
  24. package/lib/formats/link.js +0 -251
  25. package/lib/formats/list.js +0 -635
  26. package/lib/formats/strike.js +0 -31
  27. package/lib/formats/subscript.js +0 -36
  28. package/lib/formats/superscript.js +0 -35
  29. package/lib/formats/table.js +0 -288
  30. package/lib/formats/tag.js +0 -304
  31. package/lib/formats/text-align.js +0 -421
  32. package/lib/formats/text-size.js +0 -497
  33. package/lib/formats/underline.js +0 -30
  34. package/lib/formats/video.js +0 -372
  35. package/lib/modules/block-toolbar.js +0 -628
  36. package/lib/modules/code-view.js +0 -434
  37. package/lib/modules/history.js +0 -410
  38. package/lib/modules/resize-handles.js +0 -677
  39. package/lib/modules/table-toolbar.js +0 -618
  40. package/lib/modules/toolbar.js +0 -424
  41. package/lib/styles-loader.js +0 -144
  42. package/lib/styles.css +0 -2123
  43. package/lib/ui/color-picker.js +0 -296
  44. package/lib/ui/customselect.js +0 -319
  45. package/lib/ui/emoji-picker.js +0 -196
  46. package/lib/ui/icons.js +0 -413
  47. package/lib/ui/image-popup.js +0 -444
  48. package/lib/ui/import-popup.js +0 -288
  49. package/lib/ui/link-popup.js +0 -191
  50. package/lib/ui/list-picker.js +0 -307
  51. package/lib/ui/select-button.js +0 -61
  52. package/lib/ui/table-popup.js +0 -171
  53. package/lib/ui/tag-popup.js +0 -249
  54. package/lib/ui/text-align-picker.js +0 -281
  55. package/lib/ui/video-popup.js +0 -422
  56. package/lib/utils/history-helper.js +0 -50
  57. package/lib/utils/popup-helper.js +0 -219
  58. package/lib/utils/popup-positioning.js +0 -231
@@ -1,677 +0,0 @@
1
- import Module from '../core/module.js';
2
-
3
- /**
4
- * Resize Handles Module - Adds resize functionality to images, videos, and tables
5
- * Creates 4 corner handles for dragging to resize elements
6
- */
7
- class ResizeHandles extends Module {
8
- static DEFAULTS = {
9
- minWidth: 50,
10
- minHeight: 50,
11
- maxWidth: 800,
12
- maxHeight: 600,
13
- maintainAspectRatio: true, // For images and videos
14
- snapToGrid: false,
15
- gridSize: 10
16
- };
17
-
18
- constructor(editor, options = {}) {
19
- super(editor, options);
20
- this.activeElement = null;
21
- this.handles = [];
22
- this.isResizing = false;
23
- this.startX = 0;
24
- this.startY = 0;
25
- this.startWidth = 0;
26
- this.startHeight = 0;
27
- this.currentHandle = null;
28
- this.aspectRatio = 1;
29
-
30
- this.init();
31
- }
32
-
33
- init() {
34
- this.createHandles();
35
- this.setupEventListeners();
36
- }
37
-
38
- /**
39
- * Create resize handles container
40
- */
41
- createHandles() {
42
- this.handlesContainer = document.createElement('div');
43
- this.handlesContainer.className = 'resize-handles-container';
44
- this.handlesContainer.style.position = 'absolute';
45
- this.handlesContainer.style.pointerEvents = 'none';
46
- this.handlesContainer.style.zIndex = '997'; // Lower than all toolbar elements
47
- this.handlesContainer.style.display = 'none';
48
-
49
- // Create 4 corner handles
50
- const handlePositions = [
51
- { name: 'nw', cursor: 'nw-resize', position: { top: -4, left: -4 } },
52
- { name: 'ne', cursor: 'ne-resize', position: { top: -4, right: -4 } },
53
- { name: 'sw', cursor: 'sw-resize', position: { bottom: -4, left: -4 } },
54
- { name: 'se', cursor: 'se-resize', position: { bottom: -4, right: -4 } }
55
- ];
56
-
57
- handlePositions.forEach(config => {
58
- const handle = this.createHandle(config);
59
- this.handles.push(handle);
60
- this.handlesContainer.appendChild(handle);
61
- });
62
-
63
- // Add to editor wrapper but ensure it's behind toolbars
64
- this.editor.wrapper.appendChild(this.handlesContainer);
65
- }
66
-
67
- /**
68
- * Create individual resize handle
69
- */
70
- createHandle(config) {
71
- const handle = document.createElement('div');
72
- handle.className = `resize-handle resize-handle-${config.name}`;
73
- handle.style.position = 'absolute';
74
- handle.style.width = '8px';
75
- handle.style.height = '8px';
76
- handle.style.backgroundColor = '#3b82f6';
77
- handle.style.border = '1px solid #fff';
78
- handle.style.borderRadius = '50%';
79
- handle.style.cursor = config.cursor;
80
- handle.style.pointerEvents = 'auto';
81
- handle.style.boxShadow = '0 2px 4px rgba(0,0,0,0.2)';
82
- handle.style.zIndex = '999'; // Lower than toolbars
83
- handle.dataset.handle = config.name;
84
-
85
- // Position handle
86
- Object.entries(config.position).forEach(([key, value]) => {
87
- handle.style[key] = value + 'px';
88
- });
89
-
90
- // Add event listeners
91
- handle.addEventListener('mousedown', (e) => this.handleMouseDown(e, config.name));
92
-
93
- return handle;
94
- }
95
-
96
- /**
97
- * Setup event listeners
98
- */
99
- setupEventListeners() {
100
- // Listen for clicks on resizable elements
101
- this.editor.editor.addEventListener('click', (e) => {
102
- this.handleElementClick(e);
103
- });
104
-
105
- // Listen for clicks outside to hide handles
106
- document.addEventListener('click', (e) => {
107
- if (!this.isClickOnResizableElement(e) && !this.isClickOnHandle(e)) {
108
- this.hideHandles();
109
- }
110
- });
111
-
112
- // Global mouse events for dragging
113
- document.addEventListener('mousemove', (e) => this.handleMouseMove(e));
114
- document.addEventListener('mouseup', (e) => this.handleMouseUp(e));
115
-
116
- // Hide handles when scrolling
117
- window.addEventListener('scroll', () => {
118
- if (this.activeElement) {
119
- this.updateHandlePosition();
120
- }
121
- });
122
-
123
- // Hide handles on editor scroll
124
- this.editor.editor.addEventListener('scroll', () => {
125
- if (this.activeElement) {
126
- this.updateHandlePosition();
127
- }
128
- });
129
-
130
- // Listen for DOM changes to update handles
131
- this.setupMutationObserver();
132
- }
133
-
134
- /**
135
- * Handle click on resizable elements
136
- */
137
- handleElementClick(e) {
138
- const target = e.target;
139
-
140
- // Debug logging
141
-
142
-
143
- // Find the actual resizable element
144
- let resizableElement = this.findResizableElement(target);
145
-
146
- if (resizableElement) {
147
- e.preventDefault();
148
- e.stopPropagation();
149
- this.showHandles(resizableElement);
150
- }
151
- }
152
-
153
- /**
154
- * Find the actual resizable element from a clicked target
155
- */
156
- findResizableElement(target) {
157
- // If target is already resizable, return it
158
- if (this.isResizableElement(target)) {
159
- return target;
160
- }
161
-
162
- // If target is inside a table (td, th, tr, tbody), find the table
163
- if (target.tagName === 'TD' || target.tagName === 'TH' ||
164
- target.tagName === 'TR' || target.tagName === 'TBODY') {
165
- let parent = target.parentElement;
166
- while (parent && parent.tagName !== 'TABLE') {
167
- parent = parent.parentElement;
168
- }
169
- if (parent && this.isResizableElement(parent)) {
170
- return parent;
171
- }
172
- }
173
-
174
- // Check if any parent is resizable
175
- let parent = target.parentElement;
176
- while (parent && parent !== this.editor.wrapper) {
177
- if (this.isResizableElement(parent)) {
178
- return parent;
179
- }
180
- parent = parent.parentElement;
181
- }
182
-
183
- return null;
184
- }
185
-
186
- /**
187
- * Check if element is resizable
188
- */
189
- isResizableElement(element) {
190
- // Debug logging
191
-
192
-
193
- const isImage = element.classList.contains('inserted-image');
194
- const isVideo = element.classList.contains('inserted-video');
195
- const isTable = element.classList.contains('rich-editor-table');
196
-
197
-
198
-
199
- return isImage || isVideo || isTable;
200
- }
201
-
202
- /**
203
- * Check if click is on resizable element
204
- */
205
- isClickOnResizableElement(e) {
206
- return this.isResizableElement(e.target);
207
- }
208
-
209
- /**
210
- * Check if click is on resize handle
211
- */
212
- isClickOnHandle(e) {
213
- return e.target.classList.contains('resize-handle');
214
- }
215
-
216
- /**
217
- * Show resize handles for element
218
- */
219
- showHandles(element) {
220
-
221
-
222
- this.activeElement = element;
223
- this.updateHandlePosition();
224
- this.handlesContainer.style.display = 'block';
225
-
226
- // Store aspect ratio for images and videos
227
- if (element.classList.contains('inserted-image') || element.classList.contains('inserted-video')) {
228
- this.aspectRatio = element.offsetWidth / element.offsetHeight;
229
- }
230
-
231
- // For tables, ensure they have proper positioning and setup size monitoring
232
- if (element.classList.contains('rich-editor-table')) {
233
- element.style.position = 'relative';
234
- element.style.display = 'table';
235
-
236
- // Store initial dimensions for comparison
237
- this.lastTableWidth = element.offsetWidth;
238
- this.lastTableHeight = element.offsetHeight;
239
-
240
- // Setup periodic size checking for tables
241
- this.setupTableSizeMonitoring(element);
242
- }
243
-
244
-
245
- }
246
-
247
- /**
248
- * Hide resize handles
249
- */
250
- hideHandles() {
251
- // Clear table size monitoring
252
- if (this.tableSizeInterval) {
253
- clearInterval(this.tableSizeInterval);
254
- this.tableSizeInterval = null;
255
- }
256
-
257
- this.activeElement = null;
258
- this.handlesContainer.style.display = 'none';
259
- }
260
-
261
- /**
262
- * Update handle position based on active element
263
- */
264
- updateHandlePosition() {
265
- if (!this.activeElement) return;
266
-
267
- // Check if element still exists in DOM
268
- if (!document.body.contains(this.activeElement)) {
269
- this.hideHandles();
270
- return;
271
- }
272
-
273
- const elementRect = this.activeElement.getBoundingClientRect();
274
- const editorRect = this.editor.wrapper.getBoundingClientRect();
275
- const scrollTop = this.editor.wrapper.scrollTop || 0;
276
- const scrollLeft = this.editor.wrapper.scrollLeft || 0;
277
-
278
- // Position handles container
279
- const top = elementRect.top - editorRect.top + scrollTop;
280
- const left = elementRect.left - editorRect.left + scrollLeft;
281
- const width = elementRect.width;
282
- const height = elementRect.height;
283
- const bottom = top + height;
284
- this.handlesContainer.style.top = top + 'px';
285
- this.handlesContainer.style.left = left + 'px';
286
- this.handlesContainer.style.width = width + 'px';
287
- this.handlesContainer.style.height = height + 'px';
288
-
289
- if(bottom < 0){
290
- this.hideHandles();
291
- return;
292
- }
293
- if(top > editorRect.height){
294
- this.hideHandles();
295
- return;
296
- }
297
- }
298
-
299
- /**
300
- * Handle mouse down on resize handle
301
- */
302
- handleMouseDown(e, handleName) {
303
- e.preventDefault();
304
- e.stopPropagation();
305
-
306
- this.isResizing = true;
307
- this.currentHandle = handleName;
308
- this.startX = e.clientX;
309
- this.startY = e.clientY;
310
- this.startWidth = this.activeElement.offsetWidth;
311
- this.startHeight = this.activeElement.offsetHeight;
312
-
313
- // Store initial position
314
- const elementRect = this.activeElement.getBoundingClientRect();
315
- this.startLeft = elementRect.left;
316
- this.startTop = elementRect.top;
317
-
318
- // Add resizing class for styling
319
- this.activeElement.classList.add('resizing');
320
- document.body.style.cursor = e.target.style.cursor;
321
- document.body.style.userSelect = 'none';
322
- }
323
-
324
- /**
325
- * Handle mouse move during resize
326
- */
327
- handleMouseMove(e) {
328
- if (!this.isResizing || !this.activeElement) return;
329
-
330
- const deltaX = e.clientX - this.startX;
331
- const deltaY = e.clientY - this.startY;
332
-
333
- let newWidth = this.startWidth;
334
- let newHeight = this.startHeight;
335
-
336
- // Calculate new dimensions based on handle position
337
- switch (this.currentHandle) {
338
- case 'nw':
339
- newWidth = this.startWidth - deltaX;
340
- newHeight = this.startHeight - deltaY;
341
- break;
342
- case 'ne':
343
- newWidth = this.startWidth + deltaX;
344
- newHeight = this.startHeight - deltaY;
345
- break;
346
- case 'sw':
347
- newWidth = this.startWidth - deltaX;
348
- newHeight = this.startHeight + deltaY;
349
- break;
350
- case 'se':
351
- newWidth = this.startWidth + deltaX;
352
- newHeight = this.startHeight + deltaY;
353
- break;
354
- }
355
-
356
- // Apply constraints
357
- newWidth = Math.max(this.options.minWidth, Math.min(this.options.maxWidth, newWidth));
358
- newHeight = Math.max(this.options.minHeight, Math.min(this.options.maxHeight, newHeight));
359
-
360
- // Maintain aspect ratio for images and videos
361
- if ((this.activeElement.classList.contains('inserted-image') ||
362
- this.activeElement.classList.contains('inserted-video')) &&
363
- this.options.maintainAspectRatio) {
364
-
365
- const ratioByWidth = newWidth / this.aspectRatio;
366
- const ratioByHeight = newHeight * this.aspectRatio;
367
-
368
- if (Math.abs(newWidth - ratioByHeight) < Math.abs(newHeight - ratioByWidth)) {
369
- newWidth = ratioByHeight;
370
- } else {
371
- newHeight = ratioByWidth;
372
- }
373
- }
374
-
375
- // Snap to grid if enabled
376
- if (this.options.snapToGrid) {
377
- newWidth = Math.round(newWidth / this.options.gridSize) * this.options.gridSize;
378
- newHeight = Math.round(newHeight / this.options.gridSize) * this.options.gridSize;
379
- }
380
-
381
- // Apply new dimensions
382
- this.applyDimensions(newWidth, newHeight);
383
- this.updateHandlePosition();
384
-
385
- // Emit resize event
386
- this.emit('element-resize', {
387
- element: this.activeElement,
388
- width: newWidth,
389
- height: newHeight,
390
- handle: this.currentHandle
391
- });
392
- }
393
-
394
- /**
395
- * Handle mouse up - end resize
396
- */
397
- handleMouseUp(e) {
398
- if (!this.isResizing) return;
399
-
400
- this.isResizing = false;
401
- this.currentHandle = null;
402
-
403
- // Remove resizing class
404
- if (this.activeElement) {
405
- this.activeElement.classList.remove('resizing');
406
- }
407
-
408
- // Reset cursor
409
- document.body.style.cursor = '';
410
- document.body.style.userSelect = '';
411
-
412
- // Emit resize complete event
413
- this.emit('element-resize-complete', {
414
- element: this.activeElement,
415
- width: this.activeElement.offsetWidth,
416
- height: this.activeElement.offsetHeight
417
- });
418
- }
419
-
420
- /**
421
- * Apply dimensions to element
422
- */
423
- applyDimensions(width, height) {
424
- if (!this.activeElement) return;
425
-
426
- if (this.activeElement.classList.contains('rich-editor-table')) {
427
- // For tables, set both width and height
428
- this.activeElement.style.width = width + 'px';
429
- this.activeElement.style.minWidth = width + 'px';
430
- this.activeElement.style.height = height + 'px';
431
- this.activeElement.style.minHeight = height + 'px';
432
-
433
- // Calculate cell dimensions
434
- const rows = this.activeElement.querySelectorAll('tr');
435
- const cols = rows.length > 0 ? rows[0].querySelectorAll('td, th').length : 0;
436
-
437
- if (rows.length > 0 && cols > 0) {
438
- const cellWidth = Math.floor(width / cols);
439
- const cellHeight = Math.floor(height / rows.length);
440
-
441
- // Apply dimensions to all cells
442
- const cells = this.activeElement.querySelectorAll('td, th');
443
- cells.forEach(cell => {
444
- cell.style.minWidth = cellWidth + 'px';
445
- cell.style.minHeight = cellHeight + 'px';
446
- cell.style.height = cellHeight + 'px';
447
- });
448
- }
449
- } else {
450
- // For images and videos (including iframes)
451
- this.activeElement.style.width = width + 'px';
452
- this.activeElement.style.height = height + 'px';
453
-
454
- // If it's an iframe, update its attributes too
455
- if (this.activeElement.tagName === 'IFRAME') {
456
- this.activeElement.width = width;
457
- this.activeElement.height = height;
458
- }
459
- }
460
- }
461
-
462
- /**
463
- * Get current active element
464
- */
465
- getActiveElement() {
466
- return this.activeElement;
467
- }
468
-
469
- /**
470
- * Set active element programmatically
471
- */
472
- setActiveElement(element) {
473
- if (this.isResizableElement(element)) {
474
- this.showHandles(element);
475
- }
476
- }
477
-
478
- /**
479
- * Check and update handles if active element has changed
480
- */
481
- checkAndUpdateHandles() {
482
- if (this.activeElement) {
483
- // Check if element still exists and is still resizable
484
- if (!document.body.contains(this.activeElement) || !this.isResizableElement(this.activeElement)) {
485
- this.hideHandles();
486
- return;
487
- }
488
-
489
- // Update position if element still exists
490
- this.updateHandlePosition();
491
-
492
- // For tables, also check if size has changed due to content
493
- if (this.activeElement.classList.contains('rich-editor-table')) {
494
- this.checkTableSizeChange();
495
- }
496
- }
497
- }
498
-
499
- /**
500
- * Force refresh handles for current active element
501
- */
502
- refreshHandles() {
503
- if (this.activeElement && document.body.contains(this.activeElement)) {
504
- this.updateHandlePosition();
505
- }
506
- }
507
-
508
- /**
509
- * Setup periodic monitoring for table size changes
510
- */
511
- setupTableSizeMonitoring(tableElement) {
512
- // Clear any existing interval
513
- if (this.tableSizeInterval) {
514
- clearInterval(this.tableSizeInterval);
515
- }
516
-
517
- // Check table size every 100ms
518
- this.tableSizeInterval = setInterval(() => {
519
- if (this.activeElement && this.activeElement.classList.contains('rich-editor-table')) {
520
- this.checkTableSizeChange();
521
- } else {
522
- // Clear interval if no longer monitoring a table
523
- clearInterval(this.tableSizeInterval);
524
- this.tableSizeInterval = null;
525
- }
526
- }, 100);
527
- }
528
-
529
- /**
530
- * Check if table size has changed and update handles accordingly
531
- */
532
- checkTableSizeChange() {
533
- if (!this.activeElement || !this.activeElement.classList.contains('rich-editor-table')) {
534
- return;
535
- }
536
-
537
- const currentWidth = this.activeElement.offsetWidth;
538
- const currentHeight = this.activeElement.offsetHeight;
539
-
540
- // Check if dimensions have changed significantly (more than 1px to avoid floating point issues)
541
- if (Math.abs(currentWidth - this.lastTableWidth) > 1 ||
542
- Math.abs(currentHeight - this.lastTableHeight) > 1) {
543
-
544
- // Update stored dimensions
545
- this.lastTableWidth = currentWidth;
546
- this.lastTableHeight = currentHeight;
547
-
548
- // Update handle positions
549
- this.updateHandlePosition();
550
-
551
- // Emit size change event
552
- this.emit('table-size-changed', {
553
- element: this.activeElement,
554
- width: currentWidth,
555
- height: currentHeight,
556
- previousWidth: this.lastTableWidth,
557
- previousHeight: this.lastTableHeight
558
- });
559
- }
560
- }
561
-
562
- /**
563
- * Setup mutation observer to watch for DOM changes
564
- */
565
- setupMutationObserver() {
566
- if (typeof MutationObserver !== 'undefined') {
567
- this.mutationObserver = new MutationObserver((mutations) => {
568
- let shouldUpdate = false;
569
-
570
- mutations.forEach((mutation) => {
571
- // Check if active element was removed or modified
572
- if (this.activeElement) {
573
- if (mutation.type === 'childList') {
574
- // Check if active element was removed
575
- if (mutation.removedNodes) {
576
- for (let node of mutation.removedNodes) {
577
- if (node === this.activeElement || node.contains(this.activeElement)) {
578
- shouldUpdate = true;
579
- break;
580
- }
581
- }
582
- }
583
-
584
- // Check if active element was modified
585
- if (mutation.target === this.activeElement ||
586
- (mutation.target.nodeType === Node.ELEMENT_NODE &&
587
- this.activeElement.contains(mutation.target))) {
588
- shouldUpdate = true;
589
- }
590
- }
591
-
592
- // Check for text content changes that might affect table size
593
- if (mutation.type === 'characterData' && this.activeElement.classList.contains('rich-editor-table')) {
594
- // Check if the text change is within the active table
595
- let target = mutation.target;
596
- while (target && target !== this.activeElement) {
597
- target = target.parentNode;
598
- }
599
- if (target === this.activeElement) {
600
- shouldUpdate = true;
601
- }
602
- }
603
-
604
- // Check for attribute changes that might affect size
605
- if (mutation.type === 'attributes' && this.activeElement.classList.contains('rich-editor-table')) {
606
- const attributeName = mutation.attributeName;
607
- // Monitor changes to style attributes that affect size
608
- if (attributeName === 'style' || attributeName === 'class') {
609
- shouldUpdate = true;
610
- }
611
- }
612
- }
613
- });
614
-
615
- if (shouldUpdate) {
616
- // Use setTimeout to ensure DOM is fully updated
617
- setTimeout(() => {
618
- this.checkAndUpdateHandles();
619
- }, 0);
620
- }
621
- });
622
-
623
- // Start observing the editor content with more comprehensive monitoring
624
- this.mutationObserver.observe(this.editor.editor, {
625
- childList: true,
626
- subtree: true,
627
- attributes: true,
628
- attributeFilter: ['style', 'class'],
629
- characterData: true, // Monitor text content changes
630
- characterDataOldValue: true
631
- });
632
- }
633
- }
634
-
635
- /**
636
- * Enable/disable aspect ratio maintenance
637
- */
638
- setMaintainAspectRatio(maintain) {
639
- this.options.maintainAspectRatio = maintain;
640
- }
641
-
642
- /**
643
- * Set resize constraints
644
- */
645
- setConstraints(minWidth, minHeight, maxWidth, maxHeight) {
646
- this.options.minWidth = minWidth || this.options.minWidth;
647
- this.options.minHeight = minHeight || this.options.minHeight;
648
- this.options.maxWidth = maxWidth || this.options.maxWidth;
649
- this.options.maxHeight = maxHeight || this.options.maxHeight;
650
- }
651
-
652
- /**
653
- * Destroy module
654
- */
655
- destroy() {
656
- this.hideHandles();
657
- if (this.handlesContainer) {
658
- this.handlesContainer.remove();
659
- }
660
-
661
- // Clear table size monitoring
662
- if (this.tableSizeInterval) {
663
- clearInterval(this.tableSizeInterval);
664
- this.tableSizeInterval = null;
665
- }
666
-
667
- // Disconnect mutation observer
668
- if (this.mutationObserver) {
669
- this.mutationObserver.disconnect();
670
- this.mutationObserver = null;
671
- }
672
-
673
- super.destroy();
674
- }
675
- }
676
-
677
- export default ResizeHandles;