@bagelink/vue 1.5.15 → 1.5.20

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 (135) hide show
  1. package/bin/experimentalGenTypedRoutes.ts +15 -15
  2. package/bin/generateFormSchema.ts +12 -12
  3. package/bin/utils.ts +4 -4
  4. package/dist/components/Dropdown.vue.d.ts.map +1 -1
  5. package/dist/components/RouterWrapper.vue.d.ts.map +1 -1
  6. package/dist/components/calendar/CalendarPopover.vue.d.ts.map +1 -1
  7. package/dist/components/form/BagelForm.vue.d.ts.map +1 -1
  8. package/dist/components/form/FieldArray.vue.d.ts +5 -4
  9. package/dist/components/form/FieldArray.vue.d.ts.map +1 -1
  10. package/dist/components/form/inputs/CheckInput.vue.d.ts.map +1 -1
  11. package/dist/components/form/inputs/RichText/index.vue.d.ts +1 -0
  12. package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
  13. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  14. package/dist/components/form/inputs/ToggleInput.vue.d.ts.map +1 -1
  15. package/dist/components/form/inputs/Upload/UploadInput.vue.d.ts.map +1 -1
  16. package/dist/composables/useFormField.d.ts.map +1 -1
  17. package/dist/composables/useSchemaField.d.ts.map +1 -1
  18. package/dist/index.cjs +68 -55
  19. package/dist/index.mjs +34035 -143
  20. package/dist/style.css +1 -1
  21. package/package.json +1 -1
  22. package/src/components/AccordionItem.vue +2 -2
  23. package/src/components/AddToCalendar.vue +1 -1
  24. package/src/components/BglVideo.vue +8 -8
  25. package/src/components/Btn.vue +9 -9
  26. package/src/components/Card.vue +4 -4
  27. package/src/components/Carousel.vue +44 -44
  28. package/src/components/DataPreview.vue +1 -1
  29. package/src/components/DragOver.vue +6 -6
  30. package/src/components/Dropdown.vue +14 -14
  31. package/src/components/Flag.vue +3 -3
  32. package/src/components/Icon/Icon.vue +13 -13
  33. package/src/components/Image.vue +4 -4
  34. package/src/components/ImportData.vue +79 -79
  35. package/src/components/ListItem.vue +7 -7
  36. package/src/components/MapEmbed/Index.vue +6 -6
  37. package/src/components/Modal.vue +10 -10
  38. package/src/components/ModalForm.vue +4 -4
  39. package/src/components/NavBar.vue +2 -2
  40. package/src/components/Pagination.vue +9 -9
  41. package/src/components/Pill.vue +1 -1
  42. package/src/components/Rating.vue +2 -2
  43. package/src/components/RouterWrapper.vue +3 -3
  44. package/src/components/Slider.vue +77 -77
  45. package/src/components/Spreadsheet/Index.vue +34 -34
  46. package/src/components/Spreadsheet/SpreadsheetTable.vue +3 -3
  47. package/src/components/Zoomer.vue +28 -28
  48. package/src/components/analytics/BarChart.vue +6 -6
  49. package/src/components/analytics/KpiCard.vue +2 -2
  50. package/src/components/analytics/LineChart.vue +14 -14
  51. package/src/components/analytics/PieChart.vue +11 -11
  52. package/src/components/calendar/CalendarPopover.vue +1 -1
  53. package/src/components/calendar/Index.vue +1 -1
  54. package/src/components/calendar/views/AgendaView.vue +2 -2
  55. package/src/components/calendar/views/DayView.vue +6 -6
  56. package/src/components/calendar/views/MonthView.vue +2 -2
  57. package/src/components/calendar/views/WeekView.vue +18 -18
  58. package/src/components/dataTable/DataTable.vue +3 -3
  59. package/src/components/dataTable/useSorting.ts +1 -1
  60. package/src/components/dataTable/useTableData.ts +15 -15
  61. package/src/components/dataTable/useTableSelection.ts +8 -8
  62. package/src/components/dataTable/useTableVirtualization.ts +1 -1
  63. package/src/components/draggable/useDraggable.ts +42 -42
  64. package/src/components/form/BagelForm.vue +66 -23
  65. package/src/components/form/BglMultiStepForm.vue +18 -18
  66. package/src/components/form/FieldArray.vue +177 -67
  67. package/src/components/form/inputs/CheckInput.vue +2 -1
  68. package/src/components/form/inputs/CodeEditor/Index.vue +1 -1
  69. package/src/components/form/inputs/CodeEditor/format.ts +7 -7
  70. package/src/components/form/inputs/CodeEditor/useHighlight.ts +6 -6
  71. package/src/components/form/inputs/DateInput.vue +6 -6
  72. package/src/components/form/inputs/DatePicker.vue +19 -19
  73. package/src/components/form/inputs/EmailInput.vue +14 -14
  74. package/src/components/form/inputs/NumberInput.vue +6 -6
  75. package/src/components/form/inputs/OTP.vue +3 -3
  76. package/src/components/form/inputs/RadioGroup.vue +1 -1
  77. package/src/components/form/inputs/RadioPillsInput.vue +8 -8
  78. package/src/components/form/inputs/RichText/components/EditorToolbar.vue +10 -10
  79. package/src/components/form/inputs/RichText/components/TableGridSelector.vue +1 -1
  80. package/src/components/form/inputs/RichText/composables/useCommands.ts +1 -1
  81. package/src/components/form/inputs/RichText/composables/useEditor.ts +12 -12
  82. package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +1 -1
  83. package/src/components/form/inputs/RichText/index.vue +300 -132
  84. package/src/components/form/inputs/RichText/utils/commands.ts +69 -69
  85. package/src/components/form/inputs/RichText/utils/debug.ts +1 -1
  86. package/src/components/form/inputs/RichText/utils/formatting.ts +39 -39
  87. package/src/components/form/inputs/RichText/utils/media.ts +6 -6
  88. package/src/components/form/inputs/RichText/utils/selection.ts +28 -28
  89. package/src/components/form/inputs/RichText/utils/table.ts +19 -19
  90. package/src/components/form/inputs/SelectBtn.vue +1 -1
  91. package/src/components/form/inputs/SelectInput.vue +50 -26
  92. package/src/components/form/inputs/SignaturePad.vue +15 -15
  93. package/src/components/form/inputs/TableField.vue +1 -1
  94. package/src/components/form/inputs/TelInput.vue +6 -6
  95. package/src/components/form/inputs/TextInput.vue +5 -5
  96. package/src/components/form/inputs/ToggleInput.vue +2 -1
  97. package/src/components/form/inputs/Upload/UploadInput.vue +155 -102
  98. package/src/components/form/inputs/Upload/upload.ts +1 -1
  99. package/src/components/form/inputs/Upload/useFileUpload.ts +6 -6
  100. package/src/components/form/useBagelFormState.ts +5 -5
  101. package/src/components/layout/AppContent.vue +1 -1
  102. package/src/components/layout/AppLayout.vue +1 -1
  103. package/src/components/layout/Layout.vue +4 -4
  104. package/src/components/layout/TabbedLayout.vue +1 -1
  105. package/src/components/layout/Tabs.vue +2 -2
  106. package/src/components/layout/TabsNav.vue +7 -7
  107. package/src/components/lightbox/Lightbox.vue +8 -8
  108. package/src/components/lightbox/index.ts +8 -8
  109. package/src/composables/index.ts +2 -2
  110. package/src/composables/useAddToCalendar.ts +13 -13
  111. package/src/composables/useDevice.ts +2 -2
  112. package/src/composables/useExcel.ts +6 -6
  113. package/src/composables/useFormField.ts +5 -9
  114. package/src/composables/usePolling.ts +8 -8
  115. package/src/composables/useSchemaField.ts +53 -38
  116. package/src/composables/useTheme.ts +9 -9
  117. package/src/composables/useValidateFieldValue.ts +2 -2
  118. package/src/directives/pattern.ts +25 -25
  119. package/src/directives/ripple.ts +4 -4
  120. package/src/directives/vResize.ts +6 -6
  121. package/src/plugins/bagel.ts +4 -4
  122. package/src/plugins/useModal.ts +3 -3
  123. package/src/styles/layout.css +7 -1
  124. package/src/utils/BagelFormUtils.ts +7 -7
  125. package/src/utils/calendar/Helpers.ts +8 -8
  126. package/src/utils/calendar/dateUtils.ts +22 -22
  127. package/src/utils/calendar/time.ts +25 -25
  128. package/src/utils/calendar/week.ts +25 -25
  129. package/src/utils/elementUtils.ts +27 -27
  130. package/src/utils/index.ts +22 -22
  131. package/src/utils/sizeParsing.ts +2 -2
  132. package/src/utils/strings.ts +5 -5
  133. package/src/utils/tapDetector.ts +11 -11
  134. package/src/utils/useSearch.ts +29 -29
  135. package/vite.config.ts +1 -1
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import type { ToolbarConfig } from './richTextTypes'
3
3
  import { CodeEditor, copyText, Btn, Modal, BglVideo, Icon, Card, ColorInput } from '@bagelink/vue'
4
- import { watch, onUnmounted, onBeforeUnmount, ref, computed, useAttrs } from 'vue'
4
+ import { watch, onUnmounted, onBeforeUnmount, onMounted, ref, computed, useAttrs } from 'vue'
5
5
  import CheckInput from '../CheckInput.vue'
6
6
  import NumberInput from '../NumberInput.vue'
7
7
  import SelectInput from '../SelectInput.vue'
@@ -41,6 +41,8 @@ const props = defineProps<{
41
41
  autofocus?: boolean
42
42
  // Text color
43
43
  textColor?: string
44
+ // Font size
45
+ fontSize?: number | string
44
46
  }>()
45
47
 
46
48
  const emit = defineEmits(['update:modelValue'])
@@ -52,15 +54,111 @@ const editor = useEditor()
52
54
  const isInitializing = ref(false)
53
55
  const hasInitialized = ref(false)
54
56
  const commands = useCommands(editor.state, editor.state.debug)
57
+
58
+ // Reactive theme colors with forced reactivity
59
+ const forceUpdate = ref(0)
60
+ const currentInputColor = computed(() => {
61
+ // Force reactivity by using forceUpdate
62
+ void forceUpdate.value
63
+
64
+ if ('undefined' !== typeof document) {
65
+ const computedStyle = getComputedStyle(document.documentElement)
66
+ const color = computedStyle.getPropertyValue('--input-color').trim()
67
+ console.log('🎨 currentInputColor computed:', color, 'forceUpdate:', forceUpdate.value)
68
+ return color || '#000'
69
+ }
70
+ return '#000'
71
+ })
72
+
73
+ const currentTextColor = computed(() => {
74
+ const inputColor = currentInputColor.value
75
+ const textColor = props.textColor || (inputColor && 0 < inputColor.length && '#000' !== inputColor ? inputColor : 'inherit')
76
+ console.log('🎨 currentTextColor computed:', textColor, 'from inputColor:', inputColor)
77
+ return textColor
78
+ })
79
+
80
+ // Set up theme observation with MutationObserver
81
+ let themeObserver: MutationObserver | null = null
82
+
83
+ onMounted(() => {
84
+ if ('undefined' !== typeof document) {
85
+ themeObserver = new MutationObserver((mutations) => {
86
+ let shouldUpdate = false
87
+ mutations.forEach((mutation) => {
88
+ if ('attributes' === mutation.type) {
89
+ const { attributeName } = mutation
90
+ if ('data-theme' === attributeName
91
+ || 'class' === attributeName
92
+ || 'style' === attributeName) {
93
+ shouldUpdate = true
94
+ }
95
+ }
96
+ })
97
+
98
+ if (shouldUpdate) {
99
+ console.log('🔄 Theme change detected, forcing update')
100
+ forceUpdate.value++
101
+
102
+ // Also directly update iframe if initialized
103
+ if (hasInitialized.value) {
104
+ setTimeout(() => {
105
+ updateIframeColors()
106
+ }, 50)
107
+ }
108
+ }
109
+ })
110
+
111
+ // Watch for attribute changes on document element
112
+ themeObserver.observe(document.documentElement, {
113
+ attributes: true,
114
+ attributeFilter: ['data-theme', 'class', 'style']
115
+ })
116
+
117
+ // Also watch body for theme class changes
118
+ if (document.body) {
119
+ themeObserver.observe(document.body, {
120
+ attributes: true,
121
+ attributeFilter: ['class', 'data-theme']
122
+ })
123
+ }
124
+ }
125
+ })
126
+
127
+ onBeforeUnmount(() => {
128
+ themeObserver?.disconnect()
129
+ })
130
+
131
+ // Global testing functions
132
+ if ('undefined' !== typeof window) {
133
+ (window as any).testRichTextTheme = () => {
134
+ console.log('🧪 Testing RichText theme:', {
135
+ currentInputColor: currentInputColor.value,
136
+ currentTextColor: currentTextColor.value,
137
+ hasInitialized: hasInitialized.value,
138
+ hasIframe: !!iframe.value,
139
+ cssVar: getComputedStyle(document.documentElement).getPropertyValue('--input-color')
140
+ })
141
+
142
+ if (hasInitialized.value) {
143
+ updateIframeColors()
144
+ }
145
+ }
146
+
147
+ (window as any).forceRichTextUpdate = () => {
148
+ console.log('🔄 Forcing RichText update')
149
+ forceUpdate.value++
150
+ }
151
+ }
152
+
55
153
  // Computed properties for UI control
56
154
  const shouldShowToolbar = computed(() => {
57
- if (props.hideToolbar) return false
58
- if (props.basic) return false
155
+ if (props.hideToolbar) {return false}
156
+ if (props.basic) {return false}
59
157
  return true
60
158
  })
61
159
 
62
160
  const shouldShowInlineToolbar = computed(() => {
63
- if (props.hideInlineToolbar) return false
161
+ if (props.hideInlineToolbar) {return false}
64
162
  return true
65
163
  })
66
164
 
@@ -239,7 +337,7 @@ const tablePreviewHtml = computed(() => {
239
337
  border: ${form.borderWidth}px solid ${form.borderColor};
240
338
  text-align: ${form.alignment};
241
339
  ${form.fixedLayout ? `width: ${100 / form.cols}%;` : ''}
242
- ${form.alternateRows && i % 2 === 1
340
+ ${form.alternateRows && 1 === i % 2
243
341
  ? `background-color: ${form.alternateRowBgColor}; color: ${form.alternateRowTextColor};`
244
342
  : `background-color: ${form.cellBgColor}; color: ${form.cellTextColor};`}
245
343
  `
@@ -301,7 +399,7 @@ function detectAndSetDirection() {
301
399
  // Function to get current direction based on content
302
400
  function getCurrentDirection() {
303
401
  const { doc } = editor.state
304
- if (!doc?.body) return 'ltr'
402
+ if (!doc?.body) {return 'ltr'}
305
403
 
306
404
  const allText = doc.body.textContent || ''
307
405
  const firstChars = allText.trim().substring(0, 10)
@@ -312,7 +410,7 @@ function getCurrentDirection() {
312
410
 
313
411
  // Helper function to update content with history tracking
314
412
  function updateContentWithHistory(doc: Document, skipHistory = false) {
315
- if (!doc) return
413
+ if (!doc) {return}
316
414
 
317
415
  const newContent = doc.body.innerHTML
318
416
  if (newContent !== editor.state.content) {
@@ -322,7 +420,7 @@ function updateContentWithHistory(doc: Document, skipHistory = false) {
322
420
  // Clear redo stack when new content is added
323
421
  editor.state.redoStack = []
324
422
  // Limit undo stack size to prevent memory issues
325
- if (editor.state.undoStack.length > 50) {
423
+ if (50 < editor.state.undoStack.length) {
326
424
  editor.state.undoStack.shift()
327
425
  }
328
426
  }
@@ -374,10 +472,10 @@ function showInlineToolbarForSelection() {
374
472
  }
375
473
 
376
474
  const { doc } = editor.state
377
- if (!doc) return
475
+ if (!doc) {return}
378
476
 
379
477
  const selection = doc.getSelection()
380
- if (!selection || selection.rangeCount === 0) {
478
+ if (!selection || 0 === selection.rangeCount) {
381
479
  hideInlineToolbar()
382
480
  return
383
481
  }
@@ -431,14 +529,14 @@ function hideInlineToolbar() {
431
529
 
432
530
  // Function to run inline toolbar action
433
531
  function runInlineAction(actionName: string) {
434
- if (!inlineToolbarSelection.value) return
532
+ if (!inlineToolbarSelection.value) {return}
435
533
 
436
534
  const { doc } = editor.state
437
- if (!doc) return
535
+ if (!doc) {return}
438
536
 
439
537
  // Get the stored range
440
538
  const storedRange = (inlineToolbarSelection.value as any)._storedRange as Range
441
- if (!storedRange) return
539
+ if (!storedRange) {return}
442
540
 
443
541
  // Restore selection using the stored range
444
542
  const selection = doc.getSelection()
@@ -453,7 +551,7 @@ function runInlineAction(actionName: string) {
453
551
  // Keep the toolbar visible but update the stored selection
454
552
  setTimeout(() => {
455
553
  const newSelection = doc.getSelection()
456
- if (newSelection && newSelection.rangeCount > 0) {
554
+ if (newSelection && 0 < newSelection.rangeCount) {
457
555
  const newRange = newSelection.getRangeAt(0)
458
556
  if (!newRange.collapsed) {
459
557
  ; (inlineToolbarSelection.value as any)._storedRange = newRange.cloneRange()
@@ -474,7 +572,7 @@ function showTooltipMessage(message: string, x?: number, y?: number) {
474
572
  // If coordinates not provided, try to get cursor position
475
573
  if (x === undefined || y === undefined) {
476
574
  const selection = editor.state.doc?.getSelection()
477
- if (selection && selection.rangeCount > 0) {
575
+ if (selection && 0 < selection.rangeCount) {
478
576
  const range = selection.getRangeAt(0)
479
577
  const rect = range.getBoundingClientRect()
480
578
  // Get iframe offset
@@ -510,20 +608,20 @@ function openLinkModal(selection: Selection, range: Range, existingLink: HTMLAnc
510
608
  pendingLinkData = { selection, range, existingLink }
511
609
  linkForm.value = {
512
610
  url: existingLink?.href || '',
513
- openInNewTab: existingLink?.target !== '_self'
611
+ openInNewTab: '_self' !== existingLink?.target
514
612
  }
515
613
  showLinkModal.value = true
516
614
  }
517
615
 
518
616
  // Function to submit link
519
617
  function submitLink() {
520
- if (!pendingLinkData || !linkForm.value.url) return
618
+ if (!pendingLinkData || !linkForm.value.url) {return}
521
619
 
522
620
  const { selection, range, existingLink } = pendingLinkData
523
621
  const { url, openInNewTab } = linkForm.value
524
622
  const { doc } = editor.state
525
623
 
526
- if (!doc) return
624
+ if (!doc) {return}
527
625
 
528
626
  if (existingLink) {
529
627
  // Update existing link
@@ -570,7 +668,7 @@ function submitLink() {
570
668
 
571
669
  // Function to visit link
572
670
  function visitLink() {
573
- if (!linkForm.value.url || !isValidUrl(linkForm.value.url)) return
671
+ if (!linkForm.value.url || !isValidUrl(linkForm.value.url)) {return}
574
672
 
575
673
  let url = linkForm.value.url.trim()
576
674
 
@@ -588,7 +686,7 @@ function visitLink() {
588
686
 
589
687
  // Function to validate URL
590
688
  function isValidUrl(url: string): boolean {
591
- if (!url || url.trim() === '') return false
689
+ if (!url || '' === url.trim()) {return false}
592
690
 
593
691
  try {
594
692
  URL.canParse(url)
@@ -607,12 +705,12 @@ function isValidUrl(url: string): boolean {
607
705
  // Function to open image modal
608
706
  function openImageModal(existingImage: HTMLElement | null = null) {
609
707
  const { doc } = editor.state
610
- if (!doc) return
708
+ if (!doc) {return}
611
709
 
612
710
  // Get current selection for new images
613
711
  if (!existingImage) {
614
712
  const selection = doc.getSelection()
615
- if (!selection || !selection.rangeCount) return
713
+ if (!selection || !selection.rangeCount) {return}
616
714
  const range = selection.getRangeAt(0)
617
715
  pendingImageData = { selection, range, existingImage: null }
618
716
  } else {
@@ -656,10 +754,10 @@ function openImageModal(existingImage: HTMLElement | null = null) {
656
754
 
657
755
  // Function to submit image
658
756
  function submitImage() {
659
- if (!imageForm.value.src || !pendingImageData) return
757
+ if (!imageForm.value.src || !pendingImageData) {return}
660
758
 
661
759
  const { doc } = editor.state
662
- if (!doc) return
760
+ if (!doc) {return}
663
761
 
664
762
  const { existingImage } = pendingImageData
665
763
 
@@ -682,7 +780,7 @@ function submitImage() {
682
780
 
683
781
  if (imageForm.value.height) {
684
782
  img.setAttribute('data-height', imageForm.value.height)
685
- if (imageForm.value.height.includes('%') || imageForm.value.height.includes('px') || imageForm.value.height.includes('vh') || imageForm.value.height.includes('rem') || imageForm.value.height.includes('em') || imageForm.value.height === 'auto') {
783
+ if (imageForm.value.height.includes('%') || imageForm.value.height.includes('px') || imageForm.value.height.includes('vh') || imageForm.value.height.includes('rem') || imageForm.value.height.includes('em') || 'auto' === imageForm.value.height) {
686
784
  img.style.height = imageForm.value.height
687
785
  } else {
688
786
  img.style.height = `${imageForm.value.height}px`
@@ -713,7 +811,7 @@ function submitImage() {
713
811
  // Create or update figure/image - always wrap in figure
714
812
  let elementToUpdate: HTMLElement
715
813
  if (existingImage) {
716
- if (existingImage.tagName.toLowerCase() === 'img') {
814
+ if ('img' === existingImage.tagName.toLowerCase()) {
717
815
  // Converting standalone image to figure (always)
718
816
  const figure = doc.createElement('figure')
719
817
  figure.className = 'image-figure'
@@ -778,12 +876,12 @@ function submitImage() {
778
876
  // Function to open embed modal
779
877
  function openEmbedModal(existingEmbed: HTMLElement | null = null) {
780
878
  const { doc } = editor.state
781
- if (!doc) return
879
+ if (!doc) {return}
782
880
 
783
881
  // Get current selection for new embeds
784
882
  if (!existingEmbed) {
785
883
  const selection = doc.getSelection()
786
- if (!selection || !selection.rangeCount) return
884
+ if (!selection || !selection.rangeCount) {return}
787
885
  const range = selection.getRangeAt(0)
788
886
  pendingEmbedData = { selection, range, existingEmbed: null }
789
887
  } else {
@@ -837,10 +935,10 @@ function extractEmbedUrl(input: string): string {
837
935
 
838
936
  // Function to submit embed
839
937
  function submitEmbed() {
840
- if (!embedForm.value.src || !pendingEmbedData) return
938
+ if (!embedForm.value.src || !pendingEmbedData) {return}
841
939
 
842
940
  const { doc } = editor.state
843
- if (!doc) return
941
+ if (!doc) {return}
844
942
 
845
943
  const { existingEmbed } = pendingEmbedData
846
944
 
@@ -917,12 +1015,12 @@ function submitEmbed() {
917
1015
  // Function to open video modal
918
1016
  function openVideoModal(existingVideo: HTMLElement | null = null) {
919
1017
  const { doc } = editor.state
920
- if (!doc) return
1018
+ if (!doc) {return}
921
1019
 
922
1020
  // Get current selection for new videos
923
1021
  if (!existingVideo) {
924
1022
  const selection = doc.getSelection()
925
- if (!selection || !selection.rangeCount) return
1023
+ if (!selection || !selection.rangeCount) {return}
926
1024
  const range = selection.getRangeAt(0)
927
1025
  pendingVideoData = { selection, range, existingVideo: null }
928
1026
  } else {
@@ -937,14 +1035,14 @@ function openVideoModal(existingVideo: HTMLElement | null = null) {
937
1035
  if (existingVideo) {
938
1036
  // Populate form with existing video data
939
1037
  const container = existingVideo.querySelector('.video-container')
940
- const isCustom = container?.getAttribute('data-custom-aspect-ratio') === 'true'
1038
+ const isCustom = 'true' === container?.getAttribute('data-custom-aspect-ratio')
941
1039
  videoForm.value = {
942
1040
  src: container?.getAttribute('data-video-src') || '',
943
1041
  width: container?.getAttribute('data-width') || '',
944
- autoplay: container?.getAttribute('data-autoplay') === 'true',
945
- mute: container?.getAttribute('data-mute') === 'true',
946
- controls: container?.getAttribute('data-controls') === 'true',
947
- loop: container?.getAttribute('data-loop') === 'true',
1042
+ autoplay: 'true' === container?.getAttribute('data-autoplay'),
1043
+ mute: 'true' === container?.getAttribute('data-mute'),
1044
+ controls: 'true' === container?.getAttribute('data-controls'),
1045
+ loop: 'true' === container?.getAttribute('data-loop'),
948
1046
  aspectRatio: isCustom ? 'custom' : (container?.getAttribute('data-aspect-ratio') || '16:9'),
949
1047
  customWidth: container?.getAttribute('data-custom-width') || '',
950
1048
  customHeight: container?.getAttribute('data-custom-height') || '',
@@ -973,7 +1071,7 @@ function openVideoModal(existingVideo: HTMLElement | null = null) {
973
1071
 
974
1072
  // Function to validate video URL
975
1073
  function isValidVideoUrl(url: string): boolean {
976
- if (!url || url.trim() === '') return false
1074
+ if (!url || '' === url.trim()) {return false}
977
1075
 
978
1076
  try {
979
1077
  // Check for iframe tags
@@ -1008,23 +1106,23 @@ function isValidVideoUrl(url: string): boolean {
1008
1106
  }
1009
1107
  }
1010
1108
  function submitVideo() {
1011
- if (!videoForm.value.src || !pendingVideoData) return
1109
+ if (!videoForm.value.src || !pendingVideoData) {return}
1012
1110
 
1013
1111
  const { doc } = editor.state
1014
- if (!doc) return
1112
+ if (!doc) {return}
1015
1113
 
1016
1114
  const { existingVideo } = pendingVideoData
1017
1115
 
1018
1116
  // Calculate aspect ratio
1019
1117
  let { aspectRatio } = videoForm.value
1020
- const isCustom = videoForm.value.aspectRatio === 'custom'
1118
+ const isCustom = 'custom' === videoForm.value.aspectRatio
1021
1119
  if (isCustom && videoForm.value.customWidth && videoForm.value.customHeight) {
1022
1120
  aspectRatio = `${videoForm.value.customWidth}:${videoForm.value.customHeight}`
1023
1121
  }
1024
1122
 
1025
1123
  // Auto-adjust aspect ratio for YouTube Shorts
1026
1124
  const isYoutubeShort = videoForm.value.src.includes('youtube.com/shorts/')
1027
- if (isYoutubeShort && aspectRatio === '16:9') {
1125
+ if (isYoutubeShort && '16:9' === aspectRatio) {
1028
1126
  aspectRatio = '9:16'
1029
1127
  }
1030
1128
 
@@ -1072,8 +1170,8 @@ function submitVideo() {
1072
1170
  const description = doc.createElement('div')
1073
1171
  description.className = 'video-placeholder-description'
1074
1172
  let platformText = 'video'
1075
- if (isYoutube) platformText = 'YouTube video'
1076
- else if (isVimeo) platformText = 'Vimeo video'
1173
+ if (isYoutube) {platformText = 'YouTube video'}
1174
+ else if (isVimeo) {platformText = 'Vimeo video'}
1077
1175
  description.textContent = platformText
1078
1176
 
1079
1177
  // Try to get YouTube thumbnail if possible
@@ -1162,7 +1260,7 @@ function submitVideo() {
1162
1260
 
1163
1261
  // Function to delete video
1164
1262
  function deleteVideo() {
1165
- if (!pendingVideoData?.existingVideo) return
1263
+ if (!pendingVideoData?.existingVideo) {return}
1166
1264
 
1167
1265
  const { existingVideo } = pendingVideoData
1168
1266
  existingVideo.remove()
@@ -1181,9 +1279,9 @@ function detectTableAlignment(table: HTMLTableElement): 'left' | 'center' | 'rig
1181
1279
 
1182
1280
  console.log('Table margins:', { marginLeft, marginRight })
1183
1281
 
1184
- if (marginLeft === 'auto' && marginRight === 'auto') {
1282
+ if ('auto' === marginLeft && 'auto' === marginRight) {
1185
1283
  return 'center'
1186
- } else if (marginLeft === 'auto' && marginRight === '0') {
1284
+ }if (marginLeft === 'auto' && marginRight === '0') {
1187
1285
  return 'right'
1188
1286
  } else {
1189
1287
  return 'left'
@@ -1192,12 +1290,12 @@ function detectTableAlignment(table: HTMLTableElement): 'left' | 'center' | 'rig
1192
1290
 
1193
1291
  function openTableEditor(existingTable: HTMLTableElement | null = null) {
1194
1292
  const { doc } = editor.state
1195
- if (!doc) return
1293
+ if (!doc) {return}
1196
1294
 
1197
1295
  // Get current selection for new tables
1198
1296
  if (!existingTable) {
1199
1297
  const selection = doc.getSelection()
1200
- if (!selection || !selection.rangeCount) return
1298
+ if (!selection || !selection.rangeCount) {return}
1201
1299
  const range = selection.getRangeAt(0)
1202
1300
  pendingTableData = { selection, range, existingTable: null }
1203
1301
  } else {
@@ -1219,11 +1317,11 @@ function openTableEditor(existingTable: HTMLTableElement | null = null) {
1219
1317
  let alternateRowBg = '#f9f9f9'
1220
1318
  let alternateRowTextColor = '#333333'
1221
1319
 
1222
- if (tbody && tbody.rows.length >= 2) {
1320
+ if (tbody && 2 <= tbody.rows.length) {
1223
1321
  const firstRow = tbody.rows[0]
1224
1322
  const secondRow = tbody.rows[1]
1225
1323
 
1226
- if (firstRow.cells.length > 0 && secondRow.cells.length > 0) {
1324
+ if (0 < firstRow.cells.length && 0 < secondRow.cells.length) {
1227
1325
  const firstCell = firstRow.cells[0] as HTMLElement
1228
1326
  const secondCell = secondRow.cells[0] as HTMLElement
1229
1327
 
@@ -1241,7 +1339,7 @@ function openTableEditor(existingTable: HTMLTableElement | null = null) {
1241
1339
 
1242
1340
  tableForm.value = {
1243
1341
  rows: tbody ? tbody.rows.length : 3,
1244
- cols: tbody && tbody.rows.length > 0 ? tbody.rows[0].cells.length : 3,
1342
+ cols: tbody && 0 < tbody.rows.length ? tbody.rows[0].cells.length : 3,
1245
1343
  width: Number.parseInt(existingTable.style.width) || 100,
1246
1344
  borderWidth: Number.parseInt(existingTable.style.borderWidth) || 1,
1247
1345
  borderColor: existingTable.style.borderColor || '#dddddd',
@@ -1254,7 +1352,7 @@ function openTableEditor(existingTable: HTMLTableElement | null = null) {
1254
1352
  alternateRows: hasAlternatingRows,
1255
1353
  alternateRowBgColor: alternateRowBg,
1256
1354
  alternateRowTextColor,
1257
- fixedLayout: existingTable.style.tableLayout === 'fixed' || true, // ברירת מחדל true
1355
+ fixedLayout: 'fixed' === existingTable.style.tableLayout || true, // ברירת מחדל true
1258
1356
  alignment: detectTableAlignment(existingTable),
1259
1357
  direction: existingTable.dir || 'ltr'
1260
1358
  }
@@ -1284,10 +1382,10 @@ function openTableEditor(existingTable: HTMLTableElement | null = null) {
1284
1382
 
1285
1383
  // Function to submit table changes
1286
1384
  function submitTable() {
1287
- if (!pendingTableData) return
1385
+ if (!pendingTableData) {return}
1288
1386
 
1289
1387
  const { doc } = editor.state
1290
- if (!doc) return
1388
+ if (!doc) {return}
1291
1389
 
1292
1390
  if (pendingTableData.existingTable) {
1293
1391
  // Update existing table instead of creating new one
@@ -1347,7 +1445,7 @@ function submitTable() {
1347
1445
  const cells = row.querySelectorAll('td')
1348
1446
  cells.forEach((cell) => {
1349
1447
  const cellEl = cell as HTMLElement
1350
- if (tableForm.value.alternateRows && i % 2 === 1) {
1448
+ if (tableForm.value.alternateRows && 1 === i % 2) {
1351
1449
  // Alternate rows: use special colors
1352
1450
  cellEl.style.backgroundColor = tableForm.value.alternateRowBgColor
1353
1451
  cellEl.style.color = tableForm.value.alternateRowTextColor
@@ -1372,7 +1470,7 @@ function submitTable() {
1372
1470
 
1373
1471
  // Function to create new table (moved from submitTable)
1374
1472
  function createNewTable(doc: Document) {
1375
- if (!pendingTableData) return
1473
+ if (!pendingTableData) {return}
1376
1474
 
1377
1475
  // Create new table with current settings
1378
1476
  const table = doc.createElement('table')
@@ -1392,10 +1490,10 @@ function createNewTable(doc: Document) {
1392
1490
  // Don't set textAlign on table - let it inherit from document direction
1393
1491
  // table.style.textAlign = tableForm.value.alignment
1394
1492
 
1395
- if (tableForm.value.alignment === 'center') {
1493
+ if ('center' === tableForm.value.alignment) {
1396
1494
  table.style.marginLeft = 'auto'
1397
1495
  table.style.marginRight = 'auto'
1398
- } else if (tableForm.value.alignment === 'right') {
1496
+ } else if ('right' === tableForm.value.alignment) {
1399
1497
  table.style.marginLeft = 'auto'
1400
1498
  table.style.marginRight = '0'
1401
1499
  } else {
@@ -1448,7 +1546,7 @@ function createNewTable(doc: Document) {
1448
1546
  }
1449
1547
 
1450
1548
  // Apply background and text colors
1451
- if (tableForm.value.alternateRows && i % 2 === 1) {
1549
+ if (tableForm.value.alternateRows && 1 === i % 2) {
1452
1550
  // Alternate rows: use special colors
1453
1551
  cell.style.backgroundColor = tableForm.value.alternateRowBgColor
1454
1552
  cell.style.color = tableForm.value.alternateRowTextColor
@@ -1492,7 +1590,7 @@ function createNewTable(doc: Document) {
1492
1590
 
1493
1591
  // Function to delete table
1494
1592
  function deleteTable() {
1495
- if (!pendingTableData?.existingTable) return
1593
+ if (!pendingTableData?.existingTable) {return}
1496
1594
 
1497
1595
  const { existingTable } = pendingTableData
1498
1596
  existingTable.remove()
@@ -1521,7 +1619,7 @@ function applyDefaultTableSettings(table: HTMLTableElement) {
1521
1619
  const headers = table.querySelectorAll('th')
1522
1620
  const cells = table.querySelectorAll('td')
1523
1621
 
1524
- if (headers.length > 0) {
1622
+ if (0 < headers.length) {
1525
1623
  const colWidth = `${100 / headers.length}%`
1526
1624
  headers.forEach((th) => {
1527
1625
  if (!(th as HTMLElement).style.width) {
@@ -1530,7 +1628,7 @@ function applyDefaultTableSettings(table: HTMLTableElement) {
1530
1628
  })
1531
1629
  }
1532
1630
 
1533
- if (cells.length > 0 && headers.length === 0) {
1631
+ if (0 < cells.length && 0 === headers.length) {
1534
1632
  // If no headers, use first row to determine column count
1535
1633
  const firstRow = table.querySelector('tr')
1536
1634
  if (firstRow) {
@@ -1560,7 +1658,7 @@ function applyDefaultTableSettings(table: HTMLTableElement) {
1560
1658
 
1561
1659
  // Function to delete image
1562
1660
  function deleteImage() {
1563
- if (!pendingImageData?.existingImage) return
1661
+ if (!pendingImageData?.existingImage) {return}
1564
1662
 
1565
1663
  const { existingImage } = pendingImageData
1566
1664
  existingImage.remove()
@@ -1572,7 +1670,7 @@ function deleteImage() {
1572
1670
 
1573
1671
  // Function to delete embed
1574
1672
  function deleteEmbed() {
1575
- if (!pendingEmbedData?.existingEmbed) return
1673
+ if (!pendingEmbedData?.existingEmbed) {return}
1576
1674
 
1577
1675
  const { existingEmbed } = pendingEmbedData
1578
1676
  existingEmbed.remove()
@@ -1595,19 +1693,19 @@ function deleteEmbed() {
1595
1693
  // Table manipulation functions
1596
1694
  function mergeCellRight() {
1597
1695
  const { doc } = editor.state
1598
- if (!doc || !contextMenuCell.value) return
1696
+ if (!doc || !contextMenuCell.value) {return}
1599
1697
 
1600
1698
  const cell = contextMenuCell.value
1601
1699
  const row = cell.parentElement as HTMLTableRowElement
1602
1700
  const cellIndex = Array.from(row.cells).indexOf(cell)
1603
1701
  const table = cell.closest('table') as HTMLTableElement
1604
- const isRTL = table?.dir === 'rtl'
1702
+ const isRTL = 'rtl' === table?.dir
1605
1703
 
1606
1704
  // In RTL, "right" means the previous cell, in LTR it means the next cell
1607
1705
  const targetIndex = isRTL ? cellIndex - 1 : cellIndex + 1
1608
1706
  const targetCell = row.cells[targetIndex]
1609
1707
 
1610
- if (targetCell && targetIndex >= 0 && targetIndex < row.cells.length) {
1708
+ if (targetCell && 0 <= targetIndex && targetIndex < row.cells.length) {
1611
1709
  // Combine content
1612
1710
  if (targetCell.innerHTML.trim()) {
1613
1711
  cell.innerHTML += ` ${targetCell.innerHTML}`
@@ -1627,7 +1725,7 @@ function mergeCellRight() {
1627
1725
 
1628
1726
  function mergeCellDown() {
1629
1727
  const { doc } = editor.state
1630
- if (!doc || !contextMenuCell.value) return
1728
+ if (!doc || !contextMenuCell.value) {return}
1631
1729
 
1632
1730
  const cell = contextMenuCell.value
1633
1731
  const table = cell.closest('table') as HTMLTableElement
@@ -1663,15 +1761,15 @@ function mergeCellDown() {
1663
1761
 
1664
1762
  function splitCell() {
1665
1763
  const { doc } = editor.state
1666
- if (!doc || !contextMenuCell.value) return
1764
+ if (!doc || !contextMenuCell.value) {return}
1667
1765
 
1668
1766
  const cell = contextMenuCell.value
1669
1767
  const table = cell.closest('table') as HTMLTableElement
1670
- const isRTL = table?.dir === 'rtl'
1768
+ const isRTL = 'rtl' === table?.dir
1671
1769
  const colspan = Number.parseInt(cell.getAttribute('colspan') || '1')
1672
1770
  const rowspan = Number.parseInt(cell.getAttribute('rowspan') || '1')
1673
1771
 
1674
- if (colspan > 1) {
1772
+ if (1 < colspan) {
1675
1773
  // Split horizontally
1676
1774
  cell.setAttribute('colspan', '1')
1677
1775
  const row = cell.parentElement as HTMLTableRowElement
@@ -1692,7 +1790,7 @@ function splitCell() {
1692
1790
  }
1693
1791
  }
1694
1792
  }
1695
- } else if (rowspan > 1) {
1793
+ } else if (1 < rowspan) {
1696
1794
  // Split vertically
1697
1795
  cell.setAttribute('rowspan', '1')
1698
1796
  const row = cell.parentElement as HTMLTableRowElement
@@ -1724,7 +1822,7 @@ function splitCell() {
1724
1822
 
1725
1823
  function insertRowAbove() {
1726
1824
  const { doc } = editor.state
1727
- if (!doc || !contextMenuCell.value) return
1825
+ if (!doc || !contextMenuCell.value) {return}
1728
1826
 
1729
1827
  const cell = contextMenuCell.value
1730
1828
  const row = cell.parentElement as HTMLTableRowElement
@@ -1751,7 +1849,7 @@ function insertRowAbove() {
1751
1849
 
1752
1850
  function insertRowBelow() {
1753
1851
  const { doc } = editor.state
1754
- if (!doc || !contextMenuCell.value) return
1852
+ if (!doc || !contextMenuCell.value) {return}
1755
1853
 
1756
1854
  const cell = contextMenuCell.value
1757
1855
  const row = cell.parentElement as HTMLTableRowElement
@@ -1778,7 +1876,7 @@ function insertRowBelow() {
1778
1876
 
1779
1877
  function deleteRow() {
1780
1878
  const { doc } = editor.state
1781
- if (!doc || !contextMenuCell.value) return
1879
+ if (!doc || !contextMenuCell.value) {return}
1782
1880
 
1783
1881
  const cell = contextMenuCell.value
1784
1882
  const row = cell.parentElement as HTMLTableRowElement
@@ -1788,7 +1886,7 @@ function deleteRow() {
1788
1886
  const tbody = table.querySelector('tbody') || table
1789
1887
  const rows = tbody.querySelectorAll('tr')
1790
1888
 
1791
- if (rows.length <= 1) {
1889
+ if (1 >= rows.length) {
1792
1890
  alert('Cannot delete the last row')
1793
1891
  return
1794
1892
  }
@@ -1799,7 +1897,7 @@ function deleteRow() {
1799
1897
 
1800
1898
  function insertColumnLeft() {
1801
1899
  const { doc } = editor.state
1802
- if (!doc || !contextMenuCell.value) return
1900
+ if (!doc || !contextMenuCell.value) {return}
1803
1901
 
1804
1902
  const cell = contextMenuCell.value
1805
1903
  const table = cell.closest('table') as HTMLTableElement
@@ -1808,7 +1906,7 @@ function insertColumnLeft() {
1808
1906
  // Add new cell to each row at the same index
1809
1907
  const rows = table.querySelectorAll('tr')
1810
1908
  rows.forEach((row) => {
1811
- const newCell = doc.createElement(row.parentElement?.tagName === 'THEAD' ? 'th' : 'td')
1909
+ const newCell = doc.createElement('THEAD' === row.parentElement?.tagName ? 'th' : 'td')
1812
1910
  newCell.innerHTML = '&nbsp;'
1813
1911
  newCell.style.padding = '8px'
1814
1912
  newCell.style.border = '1px solid #ddd'
@@ -1825,7 +1923,7 @@ function insertColumnLeft() {
1825
1923
 
1826
1924
  function insertColumnRight() {
1827
1925
  const { doc } = editor.state
1828
- if (!doc || !contextMenuCell.value) return
1926
+ if (!doc || !contextMenuCell.value) {return}
1829
1927
 
1830
1928
  const cell = contextMenuCell.value
1831
1929
  const table = cell.closest('table') as HTMLTableElement
@@ -1834,7 +1932,7 @@ function insertColumnRight() {
1834
1932
  // Add new cell to each row after the current index
1835
1933
  const rows = table.querySelectorAll('tr')
1836
1934
  rows.forEach((row) => {
1837
- const newCell = doc.createElement(row.parentElement?.tagName === 'THEAD' ? 'th' : 'td')
1935
+ const newCell = doc.createElement('THEAD' === row.parentElement?.tagName ? 'th' : 'td')
1838
1936
  newCell.innerHTML = '&nbsp;'
1839
1937
  newCell.style.padding = '8px'
1840
1938
  newCell.style.border = '1px solid #ddd'
@@ -1852,7 +1950,7 @@ function insertColumnRight() {
1852
1950
 
1853
1951
  function deleteColumn() {
1854
1952
  const { doc } = editor.state
1855
- if (!doc || !contextMenuCell.value) return
1953
+ if (!doc || !contextMenuCell.value) {return}
1856
1954
 
1857
1955
  const cell = contextMenuCell.value
1858
1956
  const table = cell.closest('table') as HTMLTableElement
@@ -1860,7 +1958,7 @@ function deleteColumn() {
1860
1958
 
1861
1959
  // Check if this is the only column
1862
1960
  const firstRow = table.querySelector('tr')
1863
- if (firstRow && firstRow.cells.length <= 1) {
1961
+ if (firstRow && 1 >= firstRow.cells.length) {
1864
1962
  alert('Cannot delete the last column')
1865
1963
  return
1866
1964
  }
@@ -1878,18 +1976,18 @@ function deleteColumn() {
1878
1976
 
1879
1977
  // Table context menu functions
1880
1978
  const canMergeRight = computed(() => {
1881
- if (!contextMenuCell.value) return false
1979
+ if (!contextMenuCell.value) {return false}
1882
1980
  const cell = contextMenuCell.value
1883
1981
  const row = cell.parentElement as HTMLTableRowElement
1884
1982
  const cellIndex = Array.from(row.cells).indexOf(cell)
1885
1983
  const table = cell.closest('table') as HTMLTableElement
1886
- const isRTL = table?.dir === 'rtl'
1984
+ const isRTL = 'rtl' === table?.dir
1887
1985
  const targetIndex = isRTL ? cellIndex - 1 : cellIndex + 1
1888
- return targetIndex >= 0 && targetIndex < row.cells.length
1986
+ return 0 <= targetIndex && targetIndex < row.cells.length
1889
1987
  })
1890
1988
 
1891
1989
  const canMergeDown = computed(() => {
1892
- if (!contextMenuCell.value) return false
1990
+ if (!contextMenuCell.value) {return false}
1893
1991
  const cell = contextMenuCell.value
1894
1992
  const table = cell.closest('table') as HTMLTableElement
1895
1993
  const rows = Array.from(table.rows)
@@ -1899,11 +1997,11 @@ const canMergeDown = computed(() => {
1899
1997
  })
1900
1998
 
1901
1999
  const canSplit = computed(() => {
1902
- if (!contextMenuCell.value) return false
2000
+ if (!contextMenuCell.value) {return false}
1903
2001
  const cell = contextMenuCell.value
1904
2002
  const colspan = Number.parseInt(cell.getAttribute('colspan') || '1')
1905
2003
  const rowspan = Number.parseInt(cell.getAttribute('rowspan') || '1')
1906
- return colspan > 1 || rowspan > 1
2004
+ return 1 < colspan || 1 < rowspan
1907
2005
  })
1908
2006
 
1909
2007
  function handleTableContextMenu(event: MouseEvent) {
@@ -1935,9 +2033,9 @@ const hasRTL = $computed(() => /[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/.test(
1935
2033
 
1936
2034
  // Computed property to handle height prop
1937
2035
  const editorHeight = $computed(() => {
1938
- if (typeof props.height === 'number') {
2036
+ if ('number' === typeof props.height) {
1939
2037
  return `${props.height}px`
1940
- } else if (typeof props.height === 'string') {
2038
+ }if (typeof props.height === 'string') {
1941
2039
  return props.height
1942
2040
  }
1943
2041
  return '240px' // default height
@@ -2005,16 +2103,16 @@ function setupTableEditButtons(doc: Document) {
2005
2103
  if (table.style.marginLeft && table.style.marginRight) {
2006
2104
  // Detect current alignment
2007
2105
  let alignment = 'left'
2008
- if (table.style.marginLeft === 'auto' && table.style.marginRight === 'auto') {
2106
+ if ('auto' === table.style.marginLeft && 'auto' === table.style.marginRight) {
2009
2107
  alignment = 'center'
2010
- } else if (table.style.marginLeft === 'auto') {
2108
+ } else if ('auto' === table.style.marginLeft) {
2011
2109
  alignment = 'right'
2012
2110
  }
2013
2111
 
2014
2112
  // Apply flex alignment to wrapper
2015
- if (alignment === 'center') {
2113
+ if ('center' === alignment) {
2016
2114
  wrapper.style.alignItems = 'center'
2017
- } else if (alignment === 'right') {
2115
+ } else if ('right' === alignment) {
2018
2116
  wrapper.style.alignItems = 'flex-end'
2019
2117
  } else {
2020
2118
  wrapper.style.alignItems = 'flex-start'
@@ -2092,14 +2190,14 @@ function setupAutoWrapping(doc: Document) {
2092
2190
  }
2093
2191
 
2094
2192
  // If body is completely empty, add a paragraph and return
2095
- if (!doc.body.innerHTML.trim() || doc.body.innerHTML === '') {
2193
+ if (!doc.body.innerHTML.trim() || '' === doc.body.innerHTML) {
2096
2194
  const direction = getCurrentDirection()
2097
2195
  doc.body.innerHTML = `<p dir="${direction}"><br></p>`
2098
2196
  return
2099
2197
  }
2100
2198
 
2101
2199
  // Mark body as being normalized to prevent recursive processing
2102
- if (doc.body.dataset.normalizing === 'true') {
2200
+ if ('true' === doc.body.dataset.normalizing) {
2103
2201
  return
2104
2202
  }
2105
2203
  doc.body.dataset.normalizing = 'true'
@@ -2115,7 +2213,7 @@ function setupAutoWrapping(doc: Document) {
2115
2213
  const parent = node.parentNode as HTMLElement
2116
2214
  return (parent === doc.body
2117
2215
  && node.textContent?.trim()
2118
- && node.textContent.trim().length > 0)
2216
+ && 0 < node.textContent.trim().length)
2119
2217
  ? NodeFilter.FILTER_ACCEPT
2120
2218
  : NodeFilter.FILTER_REJECT
2121
2219
  }
@@ -2164,13 +2262,13 @@ function setupAutoWrapping(doc: Document) {
2164
2262
  const paras = Array.from(doc.body.querySelectorAll('p'))
2165
2263
  for (let i = 0; i < paras.length; i++) {
2166
2264
  const current = paras[i]
2167
- const isEmpty = !current.textContent?.trim() || current.innerHTML === '<br>'
2265
+ const isEmpty = !current.textContent?.trim() || '<br>' === current.innerHTML
2168
2266
 
2169
2267
  if (isEmpty) {
2170
2268
  // Only remove if we have consecutive empty paragraphs at the end
2171
2269
  const isLastPara = i === paras.length - 1
2172
- const prevPara = i > 0 ? paras[i - 1] : null
2173
- const isPrevEmpty = prevPara && (!prevPara.textContent?.trim() || prevPara.innerHTML === '<br>')
2270
+ const prevPara = 0 < i ? paras[i - 1] : null
2271
+ const isPrevEmpty = prevPara && (!prevPara.textContent?.trim() || '<br>' === prevPara.innerHTML)
2174
2272
 
2175
2273
  // Keep at least one empty paragraph for cursor placement
2176
2274
  if (isPrevEmpty && !isLastPara) {
@@ -2193,7 +2291,7 @@ function setupAutoWrapping(doc: Document) {
2193
2291
  detectAndSetDirection()
2194
2292
 
2195
2293
  // Handle complete content deletion immediately
2196
- if (!doc.body.innerHTML.trim() || doc.body.innerHTML === '') {
2294
+ if (!doc.body.innerHTML.trim() || '' === doc.body.innerHTML) {
2197
2295
  if (props.placeholder) {
2198
2296
  addPlaceholder()
2199
2297
  } else {
@@ -2220,9 +2318,9 @@ function setupAutoWrapping(doc: Document) {
2220
2318
 
2221
2319
  // Handle Enter key
2222
2320
  doc.addEventListener('keydown', (e) => {
2223
- if (e.key === 'Enter') {
2321
+ if ('Enter' === e.key) {
2224
2322
  const selection = doc.getSelection()
2225
- if (!selection || !selection.rangeCount) return
2323
+ if (!selection || !selection.rangeCount) {return}
2226
2324
 
2227
2325
  const range = selection.getRangeAt(0)
2228
2326
 
@@ -2248,13 +2346,13 @@ function setupAutoWrapping(doc: Document) {
2248
2346
  }
2249
2347
  paragraph = (paragraph as Element).closest('p,h1,h2,h3,h4,h5,h6') as HTMLElement
2250
2348
 
2251
- if (!paragraph) return
2349
+ if (!paragraph) {return}
2252
2350
 
2253
2351
  // Check if current paragraph is empty and previous paragraph is also empty
2254
2352
  const currentIsEmpty = !paragraph.textContent?.trim()
2255
2353
  const prevSibling = (paragraph as Element).previousElementSibling as HTMLElement
2256
2354
  const prevIsEmpty = prevSibling
2257
- && (prevSibling.tagName === 'P')
2355
+ && ('P' === prevSibling.tagName)
2258
2356
  && !prevSibling.textContent?.trim()
2259
2357
 
2260
2358
  // If both current and previous paragraphs are empty, don't create another empty paragraph
@@ -2344,7 +2442,7 @@ function setupAutoWrapping(doc: Document) {
2344
2442
  }) // Add a MutationObserver to catch structural changes that might create loose text
2345
2443
  const observer = new MutationObserver((mutations) => {
2346
2444
  for (const mutation of mutations) {
2347
- if (mutation.type === 'childList') {
2445
+ if ('childList' === mutation.type) {
2348
2446
  // Check if any loose text nodes were added to body
2349
2447
  Array.from(mutation.addedNodes).forEach((addedNode) => {
2350
2448
  if (addedNode.nodeType === Node.TEXT_NODE
@@ -2360,7 +2458,7 @@ function setupAutoWrapping(doc: Document) {
2360
2458
  // Check if a table was added
2361
2459
  else if (addedNode.nodeType === Node.ELEMENT_NODE) {
2362
2460
  const element = addedNode as HTMLElement
2363
- if (element.tagName === 'TABLE') {
2461
+ if ('TABLE' === element.tagName) {
2364
2462
  console.log('MutationObserver detected new table:', element)
2365
2463
  setTimeout(() => {
2366
2464
  console.log('Applying default table settings...')
@@ -2378,7 +2476,7 @@ function setupAutoWrapping(doc: Document) {
2378
2476
  }
2379
2477
 
2380
2478
  // Also apply direction to list items if it's a list
2381
- if (element.tagName === 'UL' || element.tagName === 'OL') {
2479
+ if ('UL' === element.tagName || 'OL' === element.tagName) {
2382
2480
  const listItems = element.querySelectorAll('li')
2383
2481
  listItems.forEach((li) => {
2384
2482
  if (!li.dir) {
@@ -2445,7 +2543,7 @@ function setupAutoWrapping(doc: Document) {
2445
2543
 
2446
2544
  // Get current selection
2447
2545
  const selection = doc.getSelection()
2448
- if (!selection) return
2546
+ if (!selection) {return}
2449
2547
 
2450
2548
  // Create a range that selects the entire link
2451
2549
  const range = doc.createRange()
@@ -2455,7 +2553,7 @@ function setupAutoWrapping(doc: Document) {
2455
2553
 
2456
2554
  // Populate the form with existing link data
2457
2555
  linkForm.value.url = link.href
2458
- linkForm.value.openInNewTab = link.target === '_blank'
2556
+ linkForm.value.openInNewTab = '_blank' === link.target
2459
2557
 
2460
2558
  // Store the link data for editing
2461
2559
  pendingLinkData = {
@@ -2509,16 +2607,11 @@ async function initEditor() {
2509
2607
  isInitializing.value = true
2510
2608
 
2511
2609
  try {
2512
- // Get the --input-color CSS variable from the parent page
2513
- const computedStyle = getComputedStyle(document.documentElement)
2514
- const inputColor = computedStyle.getPropertyValue('--input-color').trim()
2515
- const defaultTextColor = inputColor || 'inherit'
2516
-
2517
2610
  // Use basic embedded styles for better compatibility
2518
2611
  // We copy CSS variables to the iframe so it can use them
2519
2612
  const editorStylesContent = `
2520
2613
  :root {
2521
- --input-color: ${inputColor || '#000'};
2614
+ --input-color: ${currentInputColor.value || '#000'};
2522
2615
  }
2523
2616
  body {
2524
2617
  margin: 0;
@@ -2526,11 +2619,16 @@ async function initEditor() {
2526
2619
  min-height: 200px;
2527
2620
  font-family: sans-serif !important;
2528
2621
  line-height: 1.5;
2529
- color: ${props.textColor || (inputColor ? 'var(--input-color)' : 'inherit')};
2622
+ color: ${currentTextColor.value};
2530
2623
  background: transparent;
2531
2624
  max-width: 1060px;
2532
2625
  margin: 0 auto;
2533
2626
  }
2627
+
2628
+ /* Ensure all text elements inherit the theme color */
2629
+ p, h1, h2, h3, h4, h5, h6, div, span, li, td, th {
2630
+ color: inherit !important;
2631
+ }
2534
2632
  table {
2535
2633
  border-collapse: collapse;
2536
2634
  margin-bottom: 1rem;
@@ -2624,7 +2722,7 @@ async function initEditor() {
2624
2722
 
2625
2723
  // Write the complete HTML document to the iframe
2626
2724
  const doc = iframe.value.contentDocument || iframe.value.contentWindow?.document
2627
- if (!doc) return
2725
+ if (!doc) {return}
2628
2726
 
2629
2727
  // First write the content
2630
2728
  doc.open()
@@ -2653,7 +2751,7 @@ async function initEditor() {
2653
2751
  }
2654
2752
 
2655
2753
  // Also apply direction to list items
2656
- if (htmlElement.tagName === 'UL' || htmlElement.tagName === 'OL') {
2754
+ if ('UL' === htmlElement.tagName || 'OL' === htmlElement.tagName) {
2657
2755
  const listItems = htmlElement.querySelectorAll('li')
2658
2756
  listItems.forEach((li) => {
2659
2757
  const listItem = li as HTMLElement
@@ -2677,7 +2775,7 @@ async function initEditor() {
2677
2775
  // Clear all formatting by removing styles and replacing with plain text
2678
2776
  const elements = doc.body.querySelectorAll('*')
2679
2777
  elements.forEach((el) => {
2680
- if (el.tagName !== 'P' && el.tagName !== 'BR') {
2778
+ if ('P' !== el.tagName && 'BR' !== el.tagName) {
2681
2779
  const textContent = el.textContent || ''
2682
2780
  if (textContent.trim()) {
2683
2781
  const p = doc.createElement('p')
@@ -2686,10 +2784,10 @@ async function initEditor() {
2686
2784
  } else {
2687
2785
  el.remove()
2688
2786
  }
2689
- } else if (el.tagName === 'P') {
2787
+ } else if ('P' === el.tagName) {
2690
2788
  // Remove all attributes from paragraphs
2691
2789
  Array.from(el.attributes).forEach((attr) => {
2692
- if (attr.name !== 'dir') {
2790
+ if ('dir' !== attr.name) {
2693
2791
  el.removeAttribute(attr.name)
2694
2792
  }
2695
2793
  })
@@ -2713,7 +2811,7 @@ async function initEditor() {
2713
2811
  doc.addEventListener('click', (e) => {
2714
2812
  setTimeout(() => {
2715
2813
  const selection = doc.getSelection()
2716
- if (!selection || selection.rangeCount === 0 || selection.getRangeAt(0).collapsed) {
2814
+ if (!selection || 0 === selection.rangeCount || selection.getRangeAt(0).collapsed) {
2717
2815
  hideInlineToolbar()
2718
2816
  }
2719
2817
  }, 10)
@@ -2724,7 +2822,7 @@ async function initEditor() {
2724
2822
  if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Escape'].includes(e.key)) {
2725
2823
  setTimeout(() => {
2726
2824
  const selection = doc.getSelection()
2727
- if (!selection || selection.rangeCount === 0 || selection.getRangeAt(0).collapsed) {
2825
+ if (!selection || 0 === selection.rangeCount || selection.getRangeAt(0).collapsed) {
2728
2826
  hideInlineToolbar()
2729
2827
  }
2730
2828
  }, 10)
@@ -2818,11 +2916,16 @@ async function initEditor() {
2818
2916
  }
2819
2917
 
2820
2918
  // Only focus if autofocus is explicitly set to true
2821
- if (props.autofocus === true) {
2919
+ if (true === props.autofocus) {
2822
2920
  doc.body.focus()
2823
2921
  }
2824
2922
 
2825
2923
  hasInitialized.value = true
2924
+
2925
+ // Update colors after initialization
2926
+ setTimeout(() => {
2927
+ updateIframeColors()
2928
+ }, 100)
2826
2929
  } catch (error) {
2827
2930
  // Keep only this error log for debugging critical issues
2828
2931
  console.error('Error during editor initialization:', error)
@@ -2831,11 +2934,74 @@ async function initEditor() {
2831
2934
  }
2832
2935
  }
2833
2936
 
2937
+ // Function to update CSS colors in the iframe
2938
+ function updateIframeColors() {
2939
+ console.log('🎯 updateIframeColors called', {
2940
+ hasIframe: !!iframe.value,
2941
+ hasContentDocument: !!iframe.value?.contentDocument,
2942
+ hasInitialized: hasInitialized.value
2943
+ })
2944
+
2945
+ if (!iframe.value?.contentDocument || null === iframe.value.contentDocument) {
2946
+ console.warn('❌ No iframe or contentDocument')
2947
+ return
2948
+ }
2949
+
2950
+ const doc = iframe.value.contentDocument
2951
+ let styleElement = doc.getElementById('editor-theme-styles') as HTMLStyleElement
2952
+
2953
+ if (!styleElement) {
2954
+ styleElement = doc.createElement('style')
2955
+ styleElement.id = 'editor-theme-styles'
2956
+ doc.head.appendChild(styleElement)
2957
+ console.log('✅ Created new style element')
2958
+ }
2959
+
2960
+ const fontSize = props.fontSize ? ('number' === typeof props.fontSize ? `${props.fontSize}px` : props.fontSize) : '16px'
2961
+
2962
+ const css = `
2963
+ :root {
2964
+ --input-color: ${currentInputColor.value || '#000'};
2965
+ --richtext-font-size: ${fontSize};
2966
+ }
2967
+ body {
2968
+ color: ${currentTextColor.value} !important;
2969
+ font-size: ${fontSize} !important;
2970
+ }
2971
+
2972
+ /* Ensure all text elements inherit the color and font size */
2973
+ p, h1, h2, h3, h4, h5, h6, div, span, li, td, th {
2974
+ color: inherit !important;
2975
+ font-size: inherit !important;
2976
+ }
2977
+ `
2978
+
2979
+ styleElement.textContent = css
2980
+ console.log('🎨 Updated iframe colors:', {
2981
+ inputColor: currentInputColor.value,
2982
+ textColor: currentTextColor.value,
2983
+ css: css.trim()
2984
+ })
2985
+ }
2986
+
2987
+ // Watch for theme changes and update iframe colors
2988
+ watch([currentInputColor, currentTextColor], (newValues, oldValues) => {
2989
+ console.log('🔄 Colors changed:', {
2990
+ newValues,
2991
+ oldValues,
2992
+ hasInitialized: hasInitialized.value
2993
+ })
2994
+
2995
+ if (hasInitialized.value) {
2996
+ updateIframeColors()
2997
+ }
2998
+ }, { flush: 'post' })
2999
+
2834
3000
  // Reset initialization state when content changes significantly
2835
3001
  watch(() => props.modelValue, (newValue, oldValue) => {
2836
3002
  if (newValue !== editor.state.content) {
2837
3003
  // Only reset if content change is significant (not just minor edits)
2838
- if (!oldValue || Math.abs(newValue.length - oldValue.length) > 50) {
3004
+ if (!oldValue || 50 < Math.abs(newValue.length - oldValue.length)) {
2839
3005
  hasInitialized.value = false
2840
3006
  // For external changes, update content directly but then push to history
2841
3007
  editor.state.content = newValue
@@ -2870,10 +3036,10 @@ watch(() => editor.state.content, (newValue) => {
2870
3036
  watch(() => tableForm.value.alignment, (newAlignment) => {
2871
3037
  if (pendingTableData?.existingTable) {
2872
3038
  const table = pendingTableData.existingTable
2873
- if (newAlignment === 'center') {
3039
+ if ('center' === newAlignment) {
2874
3040
  table.style.marginLeft = 'auto'
2875
3041
  table.style.marginRight = 'auto'
2876
- } else if (newAlignment === 'right') {
3042
+ } else if ('right' === newAlignment) {
2877
3043
  table.style.marginLeft = 'auto'
2878
3044
  table.style.marginRight = '0'
2879
3045
  } else {
@@ -2894,13 +3060,13 @@ function handleGlobalClick() {
2894
3060
  }
2895
3061
 
2896
3062
  // Add event listener when component mounts
2897
- if (typeof window !== 'undefined') {
3063
+ if ('undefined' !== typeof window) {
2898
3064
  window.addEventListener('click', handleGlobalClick)
2899
3065
  }
2900
3066
 
2901
3067
  // Cleanup event listener
2902
3068
  onBeforeUnmount(() => {
2903
- if (typeof window !== 'undefined') {
3069
+ if ('undefined' !== typeof window) {
2904
3070
  window.removeEventListener('click', handleGlobalClick)
2905
3071
  }
2906
3072
  })
@@ -3412,7 +3578,6 @@ defineExpose({
3412
3578
  min-width: calc(var(--input-height) * 3);
3413
3579
  width: 100%;
3414
3580
  }
3415
-
3416
3581
  .rich-text-editor--basic .content-area:hover {
3417
3582
  outline-color: rgba(0, 0, 0, 0.05);
3418
3583
  box-shadow: inset 0 0 8px #00000018;
@@ -3423,6 +3588,7 @@ defineExpose({
3423
3588
  .content-area span,
3424
3589
  .content-area li {
3425
3590
  line-height: 1.65;
3591
+ font-size: var(--richtext-font-size, 16px);
3426
3592
  }
3427
3593
  </style>
3428
3594
 
@@ -3452,6 +3618,7 @@ defineExpose({
3452
3618
  .preview-area {
3453
3619
  flex: 1;
3454
3620
  background: var(--bgl-richtext-color);
3621
+ font-size: var(--richtext-font-size, 16px);
3455
3622
  }
3456
3623
 
3457
3624
  .split-view {
@@ -3465,6 +3632,7 @@ defineExpose({
3465
3632
  border: none;
3466
3633
  outline: none;
3467
3634
  background: transparent;
3635
+ font-size: var(--richtext-font-size, 16px);
3468
3636
  }
3469
3637
 
3470
3638
  .html-editor {