@bagelink/vue 1.4.103 → 1.4.105

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.4.103",
4
+ "version": "1.4.105",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Neveh Allon",
@@ -1,7 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  import type { IconType } from '@bagelink/vue'
3
+ import { useDevice } from '@bagelink/vue'
4
+ import { ref, onMounted, watchEffect } from 'vue'
3
5
  import { FONT_AWESOME_ICONS, MATERIAL_ICONS, FONT_AWESOME_BRANDS_ICONS } from './constants'
4
- import { ref, onMounted, onUnmounted } from 'vue'
5
6
 
6
7
  const props = withDefaults(defineProps<{
7
8
  icon?: IconType
@@ -17,22 +18,9 @@ const props = withDefaults(defineProps<{
17
18
  size: 1
18
19
  })
19
20
 
20
- const iconRender = $computed(() => props.icon || props.name) as IconType
21
+ const iconRender = $computed(() => (props.icon ?? props.name) as IconType)
21
22
 
22
- const isMobile = ref(false)
23
-
24
- const checkMobile = () => {
25
- isMobile.value = window.innerWidth <= 910
26
- }
27
-
28
- onMounted(() => {
29
- checkMobile()
30
- window.addEventListener('resize', checkMobile)
31
- })
32
-
33
- onUnmounted(() => {
34
- window.removeEventListener('resize', checkMobile)
35
- })
23
+ const { isMobile } = useDevice()
36
24
 
37
25
  const computedSize = $computed(() => {
38
26
  if (isMobile.value && props.mobileSize !== undefined) {
@@ -49,36 +37,108 @@ const iconRenderType = $computed(() => {
49
37
  })
50
38
 
51
39
  const isFaBrand = $computed(() => FONT_AWESOME_BRANDS_ICONS.includes(iconRender))
40
+
41
+ // Hide until required font is ready to avoid ligature text/fallback flash
42
+ const isMaterialReady = ref(true)
43
+ const isFAFreeReady = ref(true)
44
+ const isFABrandsReady = ref(true)
45
+
46
+ function getFontFaceSet(): FontFaceSet | null {
47
+ if (typeof document === 'undefined') return null
48
+ const maybeFonts = (document as unknown as { fonts?: FontFaceSet }).fonts
49
+ return maybeFonts ?? null
50
+ }
51
+
52
+ function supportsFontLoading(): boolean {
53
+ const fonts = getFontFaceSet()
54
+ return fonts !== null && typeof fonts.load === 'function'
55
+ }
56
+
57
+ async function ensureFontLoaded(family: string): Promise<boolean> {
58
+ if (!supportsFontLoading()) return true
59
+ try {
60
+ const fonts = getFontFaceSet()
61
+ if (!fonts) return true
62
+ if (fonts.check(`1em "${family}"`)) return true
63
+ await fonts.load(`1em "${family}"`)
64
+ return fonts.check(`1em "${family}"`)
65
+ } catch {
66
+ return false
67
+ }
68
+ }
69
+
70
+ async function loadMaterialIfNeeded() {
71
+ const ok = await ensureFontLoaded('Material Symbols Outlined')
72
+ isMaterialReady.value = ok
73
+ }
74
+
75
+ async function loadFAFreeIfNeeded() {
76
+ const ok = await ensureFontLoaded('Font Awesome 6 Free')
77
+ isFAFreeReady.value = ok
78
+ }
79
+
80
+ async function loadFABrandsIfNeeded() {
81
+ const ok = await ensureFontLoaded('Font Awesome 6 Brands')
82
+ isFABrandsReady.value = ok
83
+ }
84
+
85
+ onMounted(() => {
86
+ if (!supportsFontLoading()) return
87
+ if (iconRenderType === 'material') {
88
+ const fonts = getFontFaceSet()
89
+ isMaterialReady.value = fonts ? fonts.check('1em "Material Symbols Outlined"') : true
90
+ void loadMaterialIfNeeded()
91
+ } else if (isFaBrand) {
92
+ const fonts = getFontFaceSet()
93
+ isFABrandsReady.value = fonts ? fonts.check('1em "Font Awesome 6 Brands"') : true
94
+ void loadFABrandsIfNeeded()
95
+ } else {
96
+ const fonts = getFontFaceSet()
97
+ isFAFreeReady.value = fonts ? fonts.check('1em "Font Awesome 6 Free"') : true
98
+ void loadFAFreeIfNeeded()
99
+ }
100
+ })
101
+
102
+ watchEffect(() => {
103
+ if (!supportsFontLoading()) return
104
+ if (iconRenderType === 'material') {
105
+ void loadMaterialIfNeeded()
106
+ } else if (isFaBrand) {
107
+ void loadFABrandsIfNeeded()
108
+ } else {
109
+ void loadFAFreeIfNeeded()
110
+ }
111
+ })
112
+
113
+ const isCurrentFontReady = $computed(() => {
114
+ if (iconRenderType === 'material') return isMaterialReady.value
115
+ return isFaBrand ? isFABrandsReady.value : isFAFreeReady.value
116
+ })
52
117
  </script>
53
118
 
54
119
  <template>
55
120
  <span
56
- v-if="iconRenderType === 'material'"
57
- class="bgl_icon-font notranslate"
58
- :class="{ 'round flex aspect-ratio-1 justify-content-center': round }"
59
- :style="{
121
+ v-if="iconRenderType === 'material'" class="bgl_icon-font notranslate"
122
+ :class="{ 'round flex aspect-ratio-1 justify-content-center': round }" :style="{
60
123
  'fontSize': `${computedSize}rem`,
61
124
  color,
62
125
  'font-variation-settings': `'FILL' ${fill ? 1 : 0}, 'wght' ${weight || 400}`,
63
- 'width': round ? `calc(${computedSize}rem * 2)` : 'auto',
64
- 'height': round ? `calc(${computedSize}rem * 2)` : 'auto',
65
- }"
66
- translate="no"
126
+ 'width': round ? `calc(${computedSize}rem * 2)` : 'auto',
127
+ 'height': round ? `calc(${computedSize}rem * 2)` : 'auto',
128
+ 'visibility': isCurrentFontReady ? 'visible' : 'hidden',
129
+ }" translate="no"
67
130
  >
68
131
  {{ iconRender }}
69
132
  </span>
70
133
  <span
71
- v-else-if="iconRenderType === 'font-awesome'"
72
- class="fa bgl_icon-font notranslate"
73
- :class="[
134
+ v-else-if="iconRenderType === 'font-awesome'" class="fa bgl_icon-font notranslate" :class="[
74
135
  `fa-${iconRender}`,
75
136
  {
76
137
  'fa-brands': isFaBrand,
77
138
  'fa-solid': fill,
78
139
  'far': !fill && !isFaBrand,
79
140
  },
80
- ]"
81
- :style="{ 'fontSize': `${computedSize}rem`, color, 'font-variation-settings': `'wght' ${weight || 400}` }"
141
+ ]" :style="{ 'fontSize': `${computedSize}rem`, color, 'font-variation-settings': `'wght' ${weight || 400}`, 'visibility': isCurrentFontReady ? 'visible' : 'hidden' }"
82
142
  translate="no"
83
143
  />
84
144
  </template>
@@ -86,6 +146,7 @@ const isFaBrand = $computed(() => FONT_AWESOME_BRANDS_ICONS.includes(iconRender)
86
146
  <style>
87
147
  @import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200');
88
148
  @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css');
149
+
89
150
  [dir='rtl'] .data-row .bgl_icon-font,
90
151
  [dir='rtl'] .embedded-field .bgl_icon-font,
91
152
  [dir='rtl'] .rich-text-editor .toolbar .bgl_icon-font {