@bagelink/vue 1.5.13 โ†’ 1.5.17

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "1.5.13",
4
+ "version": "1.5.17",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Neveh Allon",
@@ -1,12 +1,12 @@
1
1
  <script setup lang="ts">
2
- import { Icon } from '@bagelink/vue'
2
+ import Loading from './Loading.vue'
3
3
  </script>
4
4
 
5
5
  <template>
6
6
  <RouterView v-slot="{ Component, route }">
7
7
  <slot v-if="!Component">
8
- <div class="w-100p h-100p flex justify-content-center">
9
- <Icon name="border_clear" size="4" />
8
+ <div class="w-100p h-100vh flex justify-content-center">
9
+ <Loading />
10
10
  </div>
11
11
  </slot>
12
12
  <transition v-else :duration="300" name="slide-fade" mode="out-in" appear>
@@ -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'
@@ -52,6 +52,102 @@ const editor = useEditor()
52
52
  const isInitializing = ref(false)
53
53
  const hasInitialized = ref(false)
54
54
  const commands = useCommands(editor.state, editor.state.debug)
55
+
56
+ // Reactive theme colors with forced reactivity
57
+ const forceUpdate = ref(0)
58
+ const currentInputColor = computed(() => {
59
+ // Force reactivity by using forceUpdate
60
+ void forceUpdate.value
61
+
62
+ if (typeof document !== 'undefined') {
63
+ const computedStyle = getComputedStyle(document.documentElement)
64
+ const color = computedStyle.getPropertyValue('--input-color').trim()
65
+ console.log('๐ŸŽจ currentInputColor computed:', color, 'forceUpdate:', forceUpdate.value)
66
+ return color || '#000'
67
+ }
68
+ return '#000'
69
+ })
70
+
71
+ const currentTextColor = computed(() => {
72
+ const inputColor = currentInputColor.value
73
+ const textColor = props.textColor || (inputColor && inputColor.length > 0 && inputColor !== '#000' ? inputColor : 'inherit')
74
+ console.log('๐ŸŽจ currentTextColor computed:', textColor, 'from inputColor:', inputColor)
75
+ return textColor
76
+ })
77
+
78
+ // Set up theme observation with MutationObserver
79
+ let themeObserver: MutationObserver | null = null
80
+
81
+ onMounted(() => {
82
+ if (typeof document !== 'undefined') {
83
+ themeObserver = new MutationObserver((mutations) => {
84
+ let shouldUpdate = false
85
+ mutations.forEach((mutation) => {
86
+ if (mutation.type === 'attributes') {
87
+ const { attributeName } = mutation
88
+ if (attributeName === 'data-theme'
89
+ || attributeName === 'class'
90
+ || attributeName === 'style') {
91
+ shouldUpdate = true
92
+ }
93
+ }
94
+ })
95
+
96
+ if (shouldUpdate) {
97
+ console.log('๐Ÿ”„ Theme change detected, forcing update')
98
+ forceUpdate.value++
99
+
100
+ // Also directly update iframe if initialized
101
+ if (hasInitialized.value) {
102
+ setTimeout(() => {
103
+ updateIframeColors()
104
+ }, 50)
105
+ }
106
+ }
107
+ })
108
+
109
+ // Watch for attribute changes on document element
110
+ themeObserver.observe(document.documentElement, {
111
+ attributes: true,
112
+ attributeFilter: ['data-theme', 'class', 'style']
113
+ })
114
+
115
+ // Also watch body for theme class changes
116
+ if (document.body) {
117
+ themeObserver.observe(document.body, {
118
+ attributes: true,
119
+ attributeFilter: ['class', 'data-theme']
120
+ })
121
+ }
122
+ }
123
+ })
124
+
125
+ onBeforeUnmount(() => {
126
+ themeObserver?.disconnect()
127
+ })
128
+
129
+ // Global testing functions
130
+ if (typeof window !== 'undefined') {
131
+ (window as any).testRichTextTheme = () => {
132
+ console.log('๐Ÿงช Testing RichText theme:', {
133
+ currentInputColor: currentInputColor.value,
134
+ currentTextColor: currentTextColor.value,
135
+ hasInitialized: hasInitialized.value,
136
+ hasIframe: !!iframe.value,
137
+ cssVar: getComputedStyle(document.documentElement).getPropertyValue('--input-color')
138
+ })
139
+
140
+ if (hasInitialized.value) {
141
+ updateIframeColors()
142
+ }
143
+ }
144
+
145
+ (window as any).forceRichTextUpdate = () => {
146
+ console.log('๐Ÿ”„ Forcing RichText update')
147
+ forceUpdate.value++
148
+ }
149
+ }
150
+
55
151
  // Computed properties for UI control
56
152
  const shouldShowToolbar = computed(() => {
57
153
  if (props.hideToolbar) return false
@@ -2509,16 +2605,11 @@ async function initEditor() {
2509
2605
  isInitializing.value = true
2510
2606
 
2511
2607
  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
2608
  // Use basic embedded styles for better compatibility
2518
2609
  // We copy CSS variables to the iframe so it can use them
2519
2610
  const editorStylesContent = `
2520
2611
  :root {
2521
- --input-color: ${inputColor || '#000'};
2612
+ --input-color: ${currentInputColor.value || '#000'};
2522
2613
  }
2523
2614
  body {
2524
2615
  margin: 0;
@@ -2526,11 +2617,16 @@ async function initEditor() {
2526
2617
  min-height: 200px;
2527
2618
  font-family: sans-serif !important;
2528
2619
  line-height: 1.5;
2529
- color: ${props.textColor || (inputColor ? 'var(--input-color)' : 'inherit')};
2620
+ color: ${currentTextColor.value};
2530
2621
  background: transparent;
2531
2622
  max-width: 1060px;
2532
2623
  margin: 0 auto;
2533
2624
  }
2625
+
2626
+ /* Ensure all text elements inherit the theme color */
2627
+ p, h1, h2, h3, h4, h5, h6, div, span, li, td, th {
2628
+ color: inherit !important;
2629
+ }
2534
2630
  table {
2535
2631
  border-collapse: collapse;
2536
2632
  margin-bottom: 1rem;
@@ -2823,6 +2919,11 @@ async function initEditor() {
2823
2919
  }
2824
2920
 
2825
2921
  hasInitialized.value = true
2922
+
2923
+ // Update colors after initialization
2924
+ setTimeout(() => {
2925
+ updateIframeColors()
2926
+ }, 100)
2826
2927
  } catch (error) {
2827
2928
  // Keep only this error log for debugging critical issues
2828
2929
  console.error('Error during editor initialization:', error)
@@ -2831,6 +2932,64 @@ async function initEditor() {
2831
2932
  }
2832
2933
  }
2833
2934
 
2935
+ // Function to update CSS colors in the iframe
2936
+ function updateIframeColors() {
2937
+ console.log('๐ŸŽฏ updateIframeColors called', {
2938
+ hasIframe: !!iframe.value,
2939
+ hasContentDocument: !!iframe.value?.contentDocument,
2940
+ hasInitialized: hasInitialized.value
2941
+ })
2942
+
2943
+ if (!iframe.value?.contentDocument || iframe.value.contentDocument === null) {
2944
+ console.warn('โŒ No iframe or contentDocument')
2945
+ return
2946
+ }
2947
+
2948
+ const doc = iframe.value.contentDocument
2949
+ let styleElement = doc.getElementById('editor-theme-styles') as HTMLStyleElement
2950
+
2951
+ if (!styleElement) {
2952
+ styleElement = doc.createElement('style')
2953
+ styleElement.id = 'editor-theme-styles'
2954
+ doc.head.appendChild(styleElement)
2955
+ console.log('โœ… Created new style element')
2956
+ }
2957
+
2958
+ const css = `
2959
+ :root {
2960
+ --input-color: ${currentInputColor.value || '#000'};
2961
+ }
2962
+ body {
2963
+ color: ${currentTextColor.value} !important;
2964
+ }
2965
+
2966
+ /* Ensure all text elements inherit the color */
2967
+ p, h1, h2, h3, h4, h5, h6, div, span, li, td, th {
2968
+ color: inherit !important;
2969
+ }
2970
+ `
2971
+
2972
+ styleElement.textContent = css
2973
+ console.log('๐ŸŽจ Updated iframe colors:', {
2974
+ inputColor: currentInputColor.value,
2975
+ textColor: currentTextColor.value,
2976
+ css: css.trim()
2977
+ })
2978
+ }
2979
+
2980
+ // Watch for theme changes and update iframe colors
2981
+ watch([currentInputColor, currentTextColor], (newValues, oldValues) => {
2982
+ console.log('๐Ÿ”„ Colors changed:', {
2983
+ newValues,
2984
+ oldValues,
2985
+ hasInitialized: hasInitialized.value
2986
+ })
2987
+
2988
+ if (hasInitialized.value) {
2989
+ updateIframeColors()
2990
+ }
2991
+ }, { flush: 'post' })
2992
+
2834
2993
  // Reset initialization state when content changes significantly
2835
2994
  watch(() => props.modelValue, (newValue, oldValue) => {
2836
2995
  if (newValue !== editor.state.content) {
@@ -72,7 +72,7 @@ function autoResizeTextarea() {
72
72
 
73
73
  const textarea = input as HTMLTextAreaElement
74
74
  textarea.style.height = 'auto'
75
- textarea.style.height = (textarea.scrollHeight + 1) + 'px'
75
+ textarea.style.height = `${textarea.scrollHeight + 1}px`
76
76
  }
77
77
 
78
78
  function updateInputVal() {
@@ -81,17 +81,17 @@ function updateInputVal() {
81
81
  debouncedEmit()
82
82
 
83
83
  if (props.autoheight) {
84
- nextTick(() => autoResizeTextarea())
84
+ nextTick(() => { autoResizeTextarea() })
85
85
  }
86
86
  }
87
87
 
88
88
  watch(
89
89
  () => props.modelValue,
90
- newVal => {
90
+ (newVal) => {
91
91
  if (newVal !== inputVal) {
92
92
  inputVal = newVal
93
93
  if (props.autoheight) {
94
- nextTick(() => autoResizeTextarea())
94
+ nextTick(() => { autoResizeTextarea() })
95
95
  }
96
96
  }
97
97
  },
@@ -119,55 +119,27 @@ onMounted(async () => {
119
119
 
120
120
  <template>
121
121
  <div
122
- class="bagel-input text-input"
123
- :class="{
122
+ class="bagel-input text-input" :class="{
124
123
  dense,
125
124
  small,
126
125
  shrink,
127
126
  code,
128
127
  textInputIconWrap: icon,
129
128
  txtInputIconStart: iconStart,
130
- }"
131
- :title="title"
129
+ }" :title="title"
132
130
  >
133
131
  <label :for="id">
134
132
  {{ label }} <span v-if="required && label">*</span>
135
133
 
136
134
  <input
137
- v-if="!multiline && !autoheight && !code && inputRows < 2"
138
- :id
139
- ref="input"
140
- v-model.trim="inputVal"
141
- :name
142
- :title
143
- :autocomplete
144
- :type
145
- :rows="1"
146
- :placeholder="placeholder || label"
147
- :disabled
148
- :required
149
- :pattern
150
- v-bind="nativeInputAttrs"
151
- @focusout="onFocusout"
152
- @focus="onFocus"
153
- @input="updateInputVal"
154
- />
135
+ v-if="!multiline && !autoheight && !code && inputRows < 2" :id ref="input" v-model.trim="inputVal"
136
+ :name :title :autocomplete :type :rows="1" :placeholder="placeholder || label" :disabled :required
137
+ :pattern v-bind="nativeInputAttrs" @focusout="onFocusout" @focus="onFocus" @input="updateInputVal"
138
+ >
155
139
  <textarea
156
- v-else
157
- :id
158
- ref="input"
159
- v-model="inputVal"
160
- :name
161
- :title
162
- :type
163
- :rows="inputRows"
164
- :placeholder="placeholder || label"
165
- :disabled
166
- :required
167
- :pattern
168
- v-bind="nativeInputAttrs"
169
- @input="updateInputVal"
170
- @focusout="onFocusout"
140
+ v-else :id ref="input" v-model="inputVal" :name :title :type :rows="inputRows"
141
+ :placeholder="placeholder || label" :disabled :required :pattern v-bind="nativeInputAttrs"
142
+ @input="updateInputVal" @focusout="onFocusout"
171
143
  />
172
144
  <p v-if="helptext" class="opacity-7 light">{{ helptext }}</p>
173
145
  <Icon v-if="iconStart" class="iconStart" :icon="iconStart" />
@@ -236,7 +208,8 @@ onMounted(async () => {
236
208
  line-height: 0;
237
209
  }
238
210
 
239
- .textInputIconWrap input {
211
+ .textInputIconWrap input,
212
+ .textInputIconWrap textarea {
240
213
  padding-inline-end: calc(var(--input-height) / 3 + 1.5rem);
241
214
  }
242
215