@bagelink/vue 1.6.43 → 1.6.49
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/bin/experimentalGenTypedRoutes.ts +18 -19
- package/bin/utils.ts +4 -4
- package/dist/components/AddressSearch.vue.d.ts.map +1 -1
- package/dist/components/Alert.vue.d.ts.map +1 -1
- package/dist/components/BglVideo.vue.d.ts.map +1 -1
- package/dist/components/Card.vue.d.ts.map +1 -1
- package/dist/components/Carousel.vue.d.ts +2 -2
- package/dist/components/Carousel.vue.d.ts.map +1 -1
- package/dist/components/Dropdown.vue.d.ts.map +1 -1
- package/dist/components/Flag.vue.d.ts.map +1 -1
- package/dist/components/IframeVue.vue.d.ts.map +1 -1
- package/dist/components/ListItem.vue.d.ts.map +1 -1
- package/dist/components/Loading.vue.d.ts.map +1 -1
- package/dist/components/Modal.vue.d.ts.map +1 -1
- package/dist/components/ModalForm.vue.d.ts.map +1 -1
- package/dist/components/NavBar.vue.d.ts +1 -1
- package/dist/components/Pill.vue.d.ts.map +1 -1
- package/dist/components/Swiper.vue.d.ts +12 -4
- package/dist/components/Swiper.vue.d.ts.map +1 -1
- package/dist/components/Zoomer.vue.d.ts.map +1 -1
- package/dist/components/analytics/LineChart.vue.d.ts.map +1 -1
- package/dist/components/analytics/PieChart.vue.d.ts +2 -1
- package/dist/components/analytics/PieChart.vue.d.ts.map +1 -1
- package/dist/components/analytics/index.d.ts +1 -1
- package/dist/components/analytics/index.d.ts.map +1 -1
- package/dist/components/calendar/CalendarPopover.vue.d.ts.map +1 -1
- package/dist/components/form/BglMultiStepForm.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/ColorInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/PasswordInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RadioGroup.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RangeInput.vue.d.ts +11 -11
- package/dist/components/form/inputs/RichText/components/EditorToolbar.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/components/TableGridSelector.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/utils/commands.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/TelInput.vue.d.ts.map +1 -1
- package/dist/components/layout/AppContent.vue.d.ts.map +1 -1
- package/dist/components/layout/AppSidebar.vue.d.ts +1 -0
- package/dist/components/layout/AppSidebar.vue.d.ts.map +1 -1
- package/dist/components/layout/Layout.vue.d.ts.map +1 -1
- package/dist/components/layout/Tabs.vue.d.ts.map +1 -1
- package/dist/components/layout/index.d.ts +3 -3
- package/dist/components/layout/index.d.ts.map +1 -1
- package/dist/components/lightbox/Lightbox.vue.d.ts.map +1 -1
- package/dist/index.cjs +24 -15
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +1530 -1404
- package/dist/plugins/modalTypes.d.ts +1 -8
- package/dist/plugins/modalTypes.d.ts.map +1 -1
- package/dist/plugins/useModal.d.ts.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -2
- package/src/components/AccordionItem.vue +13 -13
- package/src/components/AddToCalendar.vue +1 -1
- package/src/components/AddressSearch.vue +9 -8
- package/src/components/Alert.vue +2 -1
- package/src/components/Badge.vue +5 -5
- package/src/components/BglVideo.vue +44 -45
- package/src/components/Btn.vue +15 -15
- package/src/components/Card.vue +10 -8
- package/src/components/Carousel.vue +159 -162
- package/src/components/DataPreview.vue +1 -1
- package/src/components/DragOver.vue +6 -6
- package/src/components/Dropdown.vue +39 -38
- package/src/components/Flag.vue +7 -6
- package/src/components/Icon/Icon.vue +22 -22
- package/src/components/IframeVue.vue +5 -5
- package/src/components/Image.vue +17 -17
- package/src/components/ImportData.vue +79 -79
- package/src/components/ListItem.vue +12 -11
- package/src/components/Loading.vue +10 -9
- package/src/components/MapEmbed/Index.vue +24 -24
- package/src/components/Modal.vue +11 -9
- package/src/components/ModalForm.vue +15 -11
- package/src/components/NavBar.vue +6 -6
- package/src/components/Pagination.vue +27 -27
- package/src/components/Pill.vue +11 -12
- package/src/components/Rating.vue +2 -2
- package/src/components/Slider.vue +75 -75
- package/src/components/Spreadsheet/Index.vue +34 -34
- package/src/components/Spreadsheet/SpreadsheetTable.vue +3 -3
- package/src/components/Swiper.vue +4 -4
- package/src/components/Zoomer.vue +282 -182
- package/src/components/analytics/BarChart.vue +6 -6
- package/src/components/analytics/KpiCard.vue +2 -2
- package/src/components/analytics/LineChart.vue +63 -61
- package/src/components/analytics/PieChart.vue +104 -90
- package/src/components/analytics/index.ts +2 -2
- package/src/components/calendar/CalendarPopover.vue +1 -1
- package/src/components/calendar/Index.vue +1 -1
- package/src/components/calendar/views/AgendaView.vue +3 -3
- package/src/components/calendar/views/DayView.vue +6 -6
- package/src/components/calendar/views/MonthView.vue +2 -2
- package/src/components/calendar/views/WeekView.vue +18 -18
- package/src/components/dataTable/DataTable.vue +4 -4
- package/src/components/dataTable/useSorting.ts +1 -1
- package/src/components/dataTable/useTableData.ts +15 -15
- package/src/components/dataTable/useTableSelection.ts +15 -15
- package/src/components/dataTable/useTableVirtualization.ts +1 -1
- package/src/components/draggable/useDraggable.ts +42 -42
- package/src/components/form/BagelForm.vue +15 -15
- package/src/components/form/BglFieldSet.vue +5 -3
- package/src/components/form/BglMultiStepForm.vue +20 -21
- package/src/components/form/inputs/CheckInput.vue +2 -2
- package/src/components/form/inputs/CodeEditor/format.ts +7 -7
- package/src/components/form/inputs/CodeEditor/useHighlight.ts +6 -6
- package/src/components/form/inputs/ColorInput.vue +5 -4
- package/src/components/form/inputs/DateInput.vue +8 -9
- package/src/components/form/inputs/DatePicker.vue +24 -24
- package/src/components/form/inputs/EmailInput.vue +24 -24
- package/src/components/form/inputs/NumberInput.vue +26 -26
- package/src/components/form/inputs/OTP.vue +7 -7
- package/src/components/form/inputs/PasswordInput.vue +3 -2
- package/src/components/form/inputs/RadioGroup.vue +28 -25
- package/src/components/form/inputs/RadioPillsInput.vue +12 -12
- package/src/components/form/inputs/RangeInput.vue +21 -21
- package/src/components/form/inputs/RichText/components/EditorToolbar.vue +107 -92
- package/src/components/form/inputs/RichText/components/TableGridSelector.vue +64 -64
- package/src/components/form/inputs/RichText/components/gridBox.vue +10 -8
- package/src/components/form/inputs/RichText/composables/useCommands.ts +1 -1
- package/src/components/form/inputs/RichText/composables/useEditor.ts +12 -12
- package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +1 -1
- package/src/components/form/inputs/RichText/index.vue +138 -138
- package/src/components/form/inputs/RichText/utils/commands.ts +84 -85
- package/src/components/form/inputs/RichText/utils/debug.ts +1 -1
- package/src/components/form/inputs/RichText/utils/formatting.ts +39 -39
- package/src/components/form/inputs/RichText/utils/media.ts +7 -7
- package/src/components/form/inputs/RichText/utils/selection.ts +28 -28
- package/src/components/form/inputs/RichText/utils/table.ts +19 -19
- package/src/components/form/inputs/SelectBtn.vue +1 -1
- package/src/components/form/inputs/SelectInput.vue +54 -54
- package/src/components/form/inputs/SignaturePad.vue +40 -40
- package/src/components/form/inputs/TableField.vue +1 -1
- package/src/components/form/inputs/TelInput.vue +54 -53
- package/src/components/form/inputs/TextInput.vue +19 -19
- package/src/components/form/inputs/ToggleInput.vue +2 -2
- package/src/components/form/inputs/Upload/useFileUpload.ts +6 -6
- package/src/components/form/useBagelFormState.ts +5 -5
- package/src/components/layout/AppContent.vue +6 -3
- package/src/components/layout/AppLayout.vue +2 -2
- package/src/components/layout/AppSidebar.vue +83 -16
- package/src/components/layout/Layout.vue +12 -10
- package/src/components/layout/SidebarMenu.vue +4 -4
- package/src/components/layout/TabbedLayout.vue +17 -17
- package/src/components/layout/Tabs.vue +4 -5
- package/src/components/layout/TabsNav.vue +14 -14
- package/src/components/layout/index.ts +3 -5
- package/src/components/lightbox/Lightbox.vue +276 -126
- package/src/components/lightbox/index.ts +8 -8
- package/src/composables/index.ts +8 -8
- package/src/composables/useAddToCalendar.ts +13 -13
- package/src/composables/useDevice.ts +2 -2
- package/src/composables/useFormField.ts +4 -4
- package/src/composables/usePolling.ts +8 -8
- package/src/composables/useSchemaField.ts +38 -38
- package/src/composables/useTheme.ts +9 -9
- package/src/composables/useValidateFieldValue.ts +2 -2
- package/src/directives/pattern.ts +25 -25
- package/src/directives/ripple.ts +4 -4
- package/src/directives/vResize.ts +6 -6
- package/src/index.ts +1 -0
- package/src/plugins/bagel.ts +4 -4
- package/src/plugins/modalTypes.ts +1 -8
- package/src/plugins/useModal.ts +43 -18
- package/src/styles/layout.css +1 -1
- package/src/types/index.ts +1 -1
- package/src/utils/BagelFormUtils.ts +7 -7
- package/src/utils/calendar/Helpers.ts +8 -8
- package/src/utils/calendar/dateUtils.ts +22 -22
- package/src/utils/calendar/time.ts +25 -25
- package/src/utils/calendar/week.ts +25 -25
- package/src/utils/elementUtils.ts +27 -27
- package/src/utils/sizeParsing.ts +2 -2
- package/src/utils/strings.ts +5 -5
- package/src/utils/tapDetector.ts +11 -11
- package/src/utils/useSearch.ts +29 -29
- package/vite.config.ts +0 -2
|
@@ -17,7 +17,7 @@ const isDragging = ref(false)
|
|
|
17
17
|
const dragCounter = ref(0)
|
|
18
18
|
|
|
19
19
|
function handleDragEnter(e: DragEvent) {
|
|
20
|
-
if (props.disabled) {return}
|
|
20
|
+
if (props.disabled) { return }
|
|
21
21
|
e.preventDefault()
|
|
22
22
|
e.stopPropagation()
|
|
23
23
|
dragCounter.value++
|
|
@@ -25,17 +25,17 @@ function handleDragEnter(e: DragEvent) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function handleDragOver(e: DragEvent) {
|
|
28
|
-
if (props.disabled) {return}
|
|
28
|
+
if (props.disabled) { return }
|
|
29
29
|
e.preventDefault()
|
|
30
30
|
e.stopPropagation()
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function handleDragLeave(e: DragEvent) {
|
|
34
|
-
if (props.disabled) {return}
|
|
34
|
+
if (props.disabled) { return }
|
|
35
35
|
e.preventDefault()
|
|
36
36
|
e.stopPropagation()
|
|
37
37
|
dragCounter.value--
|
|
38
|
-
if (
|
|
38
|
+
if (dragCounter.value === 0) {
|
|
39
39
|
isDragging.value = false
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -60,13 +60,13 @@ function handleClick(e: MouseEvent) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
function handleDrop(e: DragEvent) {
|
|
63
|
-
if (props.disabled) {return}
|
|
63
|
+
if (props.disabled) { return }
|
|
64
64
|
e.preventDefault()
|
|
65
65
|
e.stopPropagation()
|
|
66
66
|
dragCounter.value = 0
|
|
67
67
|
isDragging.value = false
|
|
68
68
|
|
|
69
|
-
if (!e.dataTransfer) {return}
|
|
69
|
+
if (!e.dataTransfer) { return }
|
|
70
70
|
emit('addFiles', e.dataTransfer.files)
|
|
71
71
|
}
|
|
72
72
|
</script>
|
|
@@ -4,6 +4,7 @@ import type { TriggerEvent } from 'floating-vue'
|
|
|
4
4
|
import type { ComponentExposed } from 'vue-component-type-helpers'
|
|
5
5
|
import { Btn, useDevice } from '@bagelink/vue'
|
|
6
6
|
import { Dropdown as DDown } from 'floating-vue'
|
|
7
|
+
import { computed, ref } from 'vue'
|
|
7
8
|
|
|
8
9
|
export type Side = 'top' | 'right' | 'bottom' | 'left' | 'auto'
|
|
9
10
|
export type Alignment = 'start' | 'end'
|
|
@@ -89,111 +90,111 @@ const {
|
|
|
89
90
|
|
|
90
91
|
const emit = defineEmits(['show', 'hide'])
|
|
91
92
|
|
|
92
|
-
const iconSet =
|
|
93
|
-
if (icon) {return icon}
|
|
94
|
-
if (
|
|
93
|
+
const iconSet = computed(() => {
|
|
94
|
+
if (icon !== undefined && icon !== '') { return icon }
|
|
95
|
+
if (value === undefined || value === '') { return 'more_vert' }
|
|
95
96
|
return undefined
|
|
96
97
|
})
|
|
97
98
|
|
|
98
|
-
const ddownRef =
|
|
99
|
-
const triggerRef =
|
|
99
|
+
const ddownRef = ref<ComponentExposed<typeof DDown>>()
|
|
100
|
+
const triggerRef = ref<HTMLElement>()
|
|
100
101
|
const shown = defineModel('shown', {
|
|
101
102
|
type: Boolean,
|
|
102
103
|
default: false,
|
|
103
104
|
})
|
|
104
105
|
|
|
105
|
-
const show = () => ddownRef?.show()
|
|
106
|
+
const show = () => ddownRef.value?.show()
|
|
106
107
|
function hide() {
|
|
107
108
|
// Return focus to trigger element before hiding
|
|
108
|
-
triggerRef?.focus()
|
|
109
|
-
ddownRef?.hide()
|
|
109
|
+
triggerRef.value?.focus()
|
|
110
|
+
ddownRef.value?.hide()
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
const { isMobile, innerWidth } = useDevice()
|
|
113
114
|
|
|
114
|
-
const shouldDisablePositioning =
|
|
115
|
+
const shouldDisablePositioning = computed(() => {
|
|
115
116
|
return disablePlacement && isMobile
|
|
116
117
|
})
|
|
117
118
|
|
|
118
119
|
// Convert hover triggers to click on small screens (tablets and mobile)
|
|
119
|
-
const isSmallScreen =
|
|
120
|
+
const isSmallScreen = computed(() => innerWidth.value < 910)
|
|
120
121
|
|
|
121
|
-
const computedTriggers =
|
|
122
|
-
if (isSmallScreen && triggers.includes('hover')) {
|
|
122
|
+
const computedTriggers = computed((): TriggerEvent[] => {
|
|
123
|
+
if (isSmallScreen.value && triggers.includes('hover')) {
|
|
123
124
|
// Replace hover with click on small screens
|
|
124
|
-
return triggers.map(trigger => 'hover'
|
|
125
|
+
return triggers.map(trigger => trigger === 'hover' ? 'click' : trigger) as TriggerEvent[]
|
|
125
126
|
}
|
|
126
127
|
return triggers
|
|
127
128
|
})
|
|
128
129
|
|
|
129
130
|
// Intelligent trigger configuration
|
|
130
|
-
const computedShowTriggers =
|
|
131
|
+
const computedShowTriggers = computed((): TriggerEvent[] => {
|
|
131
132
|
if (showTriggers !== undefined) {
|
|
132
133
|
// Also convert hover to click in showTriggers on small screens
|
|
133
|
-
if (isSmallScreen && showTriggers.includes('hover')) {
|
|
134
|
-
return showTriggers.map(trigger => 'hover'
|
|
134
|
+
if (isSmallScreen.value && showTriggers.includes('hover')) {
|
|
135
|
+
return showTriggers.map(trigger => trigger === 'hover' ? 'click' : trigger) as TriggerEvent[]
|
|
135
136
|
}
|
|
136
137
|
return showTriggers
|
|
137
138
|
}
|
|
138
|
-
return computedTriggers
|
|
139
|
+
return computedTriggers.value
|
|
139
140
|
})
|
|
140
141
|
|
|
141
|
-
const computedHideTriggers =
|
|
142
|
+
const computedHideTriggers = computed((): TriggerEvent[] => {
|
|
142
143
|
if (hideTriggers !== undefined) {
|
|
143
144
|
// Also convert hover to click in hideTriggers on small screens
|
|
144
|
-
if (isSmallScreen && hideTriggers.includes('hover')) {
|
|
145
|
-
return hideTriggers.map(trigger => 'hover'
|
|
145
|
+
if (isSmallScreen.value && hideTriggers.includes('hover')) {
|
|
146
|
+
return hideTriggers.map(trigger => trigger === 'hover' ? 'click' : trigger) as TriggerEvent[]
|
|
146
147
|
}
|
|
147
148
|
return hideTriggers
|
|
148
149
|
}
|
|
149
150
|
// For click-only dropdowns, only hide on click
|
|
150
|
-
if (
|
|
151
|
+
if (computedTriggers.value.length === 1 && computedTriggers.value[0] === 'click') {
|
|
151
152
|
return ['click'] as TriggerEvent[]
|
|
152
153
|
}
|
|
153
154
|
// For hover dropdowns, add click to hide triggers for better UX
|
|
154
155
|
// But on small screens, hover becomes click, so we handle it differently
|
|
155
156
|
if (triggers.includes('hover')) {
|
|
156
|
-
return [...computedTriggers, 'click'] as TriggerEvent[]
|
|
157
|
+
return [...computedTriggers.value, 'click'] as TriggerEvent[]
|
|
157
158
|
}
|
|
158
|
-
return computedTriggers
|
|
159
|
+
return computedTriggers.value
|
|
159
160
|
})
|
|
160
161
|
|
|
161
|
-
const computedPopperTriggers =
|
|
162
|
-
if (
|
|
162
|
+
const computedPopperTriggers = computed((): TriggerEvent[] => {
|
|
163
|
+
if (popperTriggers.length > 0) { return popperTriggers }
|
|
163
164
|
// For hover dropdowns, enable hover on popper to keep it open
|
|
164
165
|
// But on small screens, don't add hover triggers since we convert to click
|
|
165
|
-
if (triggers.includes('hover') && !isSmallScreen) {
|
|
166
|
+
if (triggers.includes('hover') && !isSmallScreen.value) {
|
|
166
167
|
return ['hover'] as TriggerEvent[]
|
|
167
168
|
}
|
|
168
169
|
return []
|
|
169
170
|
})
|
|
170
171
|
|
|
171
172
|
// Ensure we do not override popper show triggers with an empty array
|
|
172
|
-
const computedPopperShowTriggers =
|
|
173
|
-
const hasExplicitShowTriggers = Array.isArray(popperShowTriggers) &&
|
|
174
|
-
if (hasExplicitShowTriggers) {return popperShowTriggers}
|
|
173
|
+
const computedPopperShowTriggers = computed((): TriggerEvent[] | undefined => {
|
|
174
|
+
const hasExplicitShowTriggers = Array.isArray(popperShowTriggers) && popperShowTriggers.length > 0
|
|
175
|
+
if (hasExplicitShowTriggers) { return popperShowTriggers }
|
|
175
176
|
// Only add hover for popper on large screens
|
|
176
|
-
if (triggers.includes('hover') && !isSmallScreen) {return ['hover'] as TriggerEvent[]}
|
|
177
|
+
if (triggers.includes('hover') && !isSmallScreen.value) { return ['hover'] as TriggerEvent[] }
|
|
177
178
|
return undefined
|
|
178
179
|
})
|
|
179
180
|
|
|
180
|
-
const computedPopperHideTriggers =
|
|
181
|
-
const hasExplicitHideTriggers = Array.isArray(popperHideTriggers) &&
|
|
182
|
-
if (hasExplicitHideTriggers) {return popperHideTriggers}
|
|
181
|
+
const computedPopperHideTriggers = computed((): TriggerEvent[] => {
|
|
182
|
+
const hasExplicitHideTriggers = Array.isArray(popperHideTriggers) && popperHideTriggers.length > 0
|
|
183
|
+
if (hasExplicitHideTriggers) { return popperHideTriggers }
|
|
183
184
|
// For hover dropdowns, make sure popper hides on mouseout
|
|
184
185
|
// But only on large screens where hover is meaningful
|
|
185
|
-
if (triggers.includes('hover') && !isSmallScreen) {
|
|
186
|
+
if (triggers.includes('hover') && !isSmallScreen.value) {
|
|
186
187
|
return ['hover'] as TriggerEvent[]
|
|
187
188
|
}
|
|
188
189
|
return []
|
|
189
190
|
})
|
|
190
191
|
|
|
191
|
-
const computedAutoHide =
|
|
192
|
+
const computedAutoHide = computed(() => autoHide)
|
|
192
193
|
|
|
193
|
-
const computedDelay =
|
|
194
|
-
if (delay !== undefined) {return delay}
|
|
194
|
+
const computedDelay = computed((): number | { show: number, hide: number } | undefined => {
|
|
195
|
+
if (delay !== undefined) { return delay }
|
|
195
196
|
// For hover dropdowns, add a hide delay (but only on large screens)
|
|
196
|
-
if (triggers.includes('hover') && !isSmallScreen) {
|
|
197
|
+
if (triggers.includes('hover') && !isSmallScreen.value) {
|
|
197
198
|
return { show: 0, hide: 10 } // 10ms delay before hiding
|
|
198
199
|
}
|
|
199
200
|
// For click dropdowns (including small screens), no delay
|
package/src/components/Flag.vue
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import type { CountryCode } from 'libphonenumber-js'
|
|
3
|
+
import { computed } from 'vue'
|
|
3
4
|
|
|
4
5
|
interface FlagProps {
|
|
5
6
|
country: CountryCode
|
|
@@ -9,17 +10,17 @@ interface FlagProps {
|
|
|
9
10
|
}
|
|
10
11
|
const props = defineProps<FlagProps>()
|
|
11
12
|
|
|
12
|
-
const fis =
|
|
13
|
-
if (props.circle || props.square) {return true}
|
|
13
|
+
const fis = computed(() => {
|
|
14
|
+
if (props.circle || props.square) { return true }
|
|
14
15
|
return false
|
|
15
16
|
})
|
|
16
|
-
const height =
|
|
17
|
+
const height = computed(() => `${props.size ?? 1}rem`)
|
|
17
18
|
|
|
18
|
-
const backgroundImage =
|
|
19
|
+
const backgroundImage = computed(() => {
|
|
19
20
|
let country = props.country.toLowerCase()
|
|
20
|
-
if ('ac'
|
|
21
|
+
if (country === 'ac') { country = 'sh-ac' }
|
|
21
22
|
const baseURL = 'https://cdn.jsdelivr.net/gh/lipis/flag-icons@7.0.0/flags'
|
|
22
|
-
if (fis) {return `url(${baseURL}/1x1/${country.toLowerCase()}.svg)`}
|
|
23
|
+
if (fis.value) { return `url(${baseURL}/1x1/${country.toLowerCase()}.svg)` }
|
|
23
24
|
return `url(${baseURL}/4x3/${country.toLowerCase()}.svg)`
|
|
24
25
|
})
|
|
25
26
|
</script>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { IconType } from '@bagelink/vue'
|
|
3
3
|
import { useDevice } from '@bagelink/vue'
|
|
4
|
-
import { ref, onMounted, watchEffect } from 'vue'
|
|
4
|
+
import { computed, ref, onMounted, watchEffect } from 'vue'
|
|
5
5
|
import { FONT_AWESOME_ICONS, MATERIAL_ICONS, FONT_AWESOME_BRANDS_ICONS } from './constants'
|
|
6
6
|
|
|
7
7
|
const props = withDefaults(defineProps<{
|
|
@@ -18,25 +18,25 @@ const props = withDefaults(defineProps<{
|
|
|
18
18
|
size: 1
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
-
const iconRender =
|
|
21
|
+
const iconRender = computed(() => (props.icon ?? props.name) as IconType)
|
|
22
22
|
|
|
23
23
|
const { isMobile } = useDevice()
|
|
24
24
|
|
|
25
|
-
const computedSize =
|
|
25
|
+
const computedSize = computed(() => {
|
|
26
26
|
if (isMobile.value && props.mobileSize !== undefined) {
|
|
27
27
|
return props.mobileSize
|
|
28
28
|
}
|
|
29
29
|
return props.size
|
|
30
30
|
})
|
|
31
31
|
|
|
32
|
-
const iconRenderType =
|
|
33
|
-
if (props.fontAwesome && (FONT_AWESOME_ICONS.includes(iconRender) || FONT_AWESOME_BRANDS_ICONS.includes(iconRender))) {return 'font-awesome'}
|
|
34
|
-
if (MATERIAL_ICONS.includes(iconRender)) {return 'material'}
|
|
35
|
-
if (FONT_AWESOME_ICONS.includes(iconRender) || FONT_AWESOME_BRANDS_ICONS.includes(iconRender)) {return 'font-awesome'}
|
|
32
|
+
const iconRenderType = computed(() => {
|
|
33
|
+
if (props.fontAwesome && (FONT_AWESOME_ICONS.includes(iconRender.value) || FONT_AWESOME_BRANDS_ICONS.includes(iconRender.value))) { return 'font-awesome' }
|
|
34
|
+
if (MATERIAL_ICONS.includes(iconRender.value)) { return 'material' }
|
|
35
|
+
if (FONT_AWESOME_ICONS.includes(iconRender.value) || FONT_AWESOME_BRANDS_ICONS.includes(iconRender.value)) { return 'font-awesome' }
|
|
36
36
|
return 'material'
|
|
37
37
|
})
|
|
38
38
|
|
|
39
|
-
const isFaBrand =
|
|
39
|
+
const isFaBrand = computed(() => FONT_AWESOME_BRANDS_ICONS.includes(iconRender.value))
|
|
40
40
|
|
|
41
41
|
// Hide until required font is ready to avoid ligature text/fallback flash
|
|
42
42
|
const isMaterialReady = ref(true)
|
|
@@ -44,22 +44,22 @@ const isFAFreeReady = ref(true)
|
|
|
44
44
|
const isFABrandsReady = ref(true)
|
|
45
45
|
|
|
46
46
|
function getFontFaceSet(): FontFaceSet | null {
|
|
47
|
-
if ('undefined'
|
|
47
|
+
if (typeof document === 'undefined') { return null }
|
|
48
48
|
const maybeFonts = (document as unknown as { fonts?: FontFaceSet }).fonts
|
|
49
49
|
return maybeFonts ?? null
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function supportsFontLoading(): boolean {
|
|
53
53
|
const fonts = getFontFaceSet()
|
|
54
|
-
return
|
|
54
|
+
return fonts !== null && typeof fonts.load === 'function'
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
async function ensureFontLoaded(family: string): Promise<boolean> {
|
|
58
|
-
if (!supportsFontLoading()) {return true}
|
|
58
|
+
if (!supportsFontLoading()) { return true }
|
|
59
59
|
try {
|
|
60
60
|
const fonts = getFontFaceSet()
|
|
61
|
-
if (!fonts) {return true}
|
|
62
|
-
if (fonts.check(`1em "${family}"`)) {return true}
|
|
61
|
+
if (!fonts) { return true }
|
|
62
|
+
if (fonts.check(`1em "${family}"`)) { return true }
|
|
63
63
|
await fonts.load(`1em "${family}"`)
|
|
64
64
|
return fonts.check(`1em "${family}"`)
|
|
65
65
|
} catch {
|
|
@@ -83,12 +83,12 @@ async function loadFABrandsIfNeeded() {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
onMounted(() => {
|
|
86
|
-
if (!supportsFontLoading()) {return}
|
|
87
|
-
if ('material'
|
|
86
|
+
if (!supportsFontLoading()) { return }
|
|
87
|
+
if (iconRenderType.value === 'material') {
|
|
88
88
|
const fonts = getFontFaceSet()
|
|
89
89
|
isMaterialReady.value = fonts ? fonts.check('1em "Material Symbols Outlined"') : true
|
|
90
90
|
void loadMaterialIfNeeded()
|
|
91
|
-
} else if (isFaBrand) {
|
|
91
|
+
} else if (isFaBrand.value) {
|
|
92
92
|
const fonts = getFontFaceSet()
|
|
93
93
|
isFABrandsReady.value = fonts ? fonts.check('1em "Font Awesome 6 Brands"') : true
|
|
94
94
|
void loadFABrandsIfNeeded()
|
|
@@ -100,19 +100,19 @@ onMounted(() => {
|
|
|
100
100
|
})
|
|
101
101
|
|
|
102
102
|
watchEffect(() => {
|
|
103
|
-
if (!supportsFontLoading()) {return}
|
|
104
|
-
if ('material'
|
|
103
|
+
if (!supportsFontLoading()) { return }
|
|
104
|
+
if (iconRenderType.value === 'material') {
|
|
105
105
|
void loadMaterialIfNeeded()
|
|
106
|
-
} else if (isFaBrand) {
|
|
106
|
+
} else if (isFaBrand.value) {
|
|
107
107
|
void loadFABrandsIfNeeded()
|
|
108
108
|
} else {
|
|
109
109
|
void loadFAFreeIfNeeded()
|
|
110
110
|
}
|
|
111
111
|
})
|
|
112
112
|
|
|
113
|
-
const isCurrentFontReady =
|
|
114
|
-
if ('material'
|
|
115
|
-
return isFaBrand ? isFABrandsReady.value : isFAFreeReady.value
|
|
113
|
+
const isCurrentFontReady = computed(() => {
|
|
114
|
+
if (iconRenderType.value === 'material') { return isMaterialReady.value }
|
|
115
|
+
return isFaBrand.value ? isFABrandsReady.value : isFAFreeReady.value
|
|
116
116
|
})
|
|
117
117
|
</script>
|
|
118
118
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
|
3
|
+
|
|
2
4
|
interface Message {
|
|
3
5
|
mesage: string
|
|
4
6
|
type: string
|
|
@@ -26,16 +28,14 @@ const emit = defineEmits<{
|
|
|
26
28
|
(load: 'load', payload: Event): void
|
|
27
29
|
}>()
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const iframe = $ref<HTMLIFrameElement>()
|
|
31
|
+
const iframe = ref<HTMLIFrameElement>()
|
|
32
32
|
|
|
33
33
|
function handleMessage(event: MessageEvent) {
|
|
34
34
|
emit('message', event.data as Message)
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
function handleMessageWrapper(event: MessageEvent) {
|
|
38
|
-
if (event.source === iframe?.contentWindow) {
|
|
38
|
+
if (event.source === iframe.value?.contentWindow) {
|
|
39
39
|
handleMessage(event)
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -48,7 +48,7 @@ onBeforeUnmount(() => {
|
|
|
48
48
|
window.removeEventListener('message', handleMessageWrapper)
|
|
49
49
|
})
|
|
50
50
|
|
|
51
|
-
const contentWindow = () => iframe?.contentWindow as Window | null
|
|
51
|
+
const contentWindow = () => iframe.value?.contentWindow as Window | null
|
|
52
52
|
|
|
53
53
|
defineExpose({ contentWindow })
|
|
54
54
|
</script>
|
package/src/components/Image.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { Skeleton, normalizeDimension, appendScript, normalizeURL, Icon, pathKeyToURL } from '@bagelink/vue'
|
|
3
|
-
import { watch } from 'vue'
|
|
3
|
+
import { ref, watch } from 'vue'
|
|
4
4
|
|
|
5
5
|
interface ImageProps {
|
|
6
6
|
src?: string
|
|
@@ -20,16 +20,16 @@ declare global {
|
|
|
20
20
|
|
|
21
21
|
const props = defineProps<ImageProps>()
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const imageSrc = ref<string | undefined>(undefined)
|
|
24
|
+
const loadingError = ref(false)
|
|
25
25
|
|
|
26
26
|
function getImageUrl(): string | undefined {
|
|
27
|
-
if (
|
|
28
|
-
return pathKeyToURL(props.src
|
|
27
|
+
if ((props.src === undefined || props.src === '') && (props.pathKey === undefined || props.pathKey === '') && (props.modelValue === undefined || props.modelValue === '')) { return }
|
|
28
|
+
return pathKeyToURL(props.src ?? props.pathKey ?? props.modelValue)
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
async function getCachedImage(url: string): Promise<string | undefined> {
|
|
32
|
-
if (!('caches' in window)) {return undefined}
|
|
32
|
+
if (!('caches' in window)) { return undefined }
|
|
33
33
|
try {
|
|
34
34
|
const imgCache = await window.caches.open('img-cache')
|
|
35
35
|
const cachedResponse = await imgCache.match(url)
|
|
@@ -43,7 +43,7 @@ async function getCachedImage(url: string): Promise<string | undefined> {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
async function cacheImage(url: string, blob: Blob) {
|
|
46
|
-
if (!('caches' in window)) {return}
|
|
46
|
+
if (!('caches' in window)) { return }
|
|
47
47
|
try {
|
|
48
48
|
const imgCache = await window.caches.open('img-cache')
|
|
49
49
|
await imgCache.put(url, new Response(blob))
|
|
@@ -62,30 +62,30 @@ async function convertHeicImage(url: string): Promise<string> {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
async function loadImage() {
|
|
65
|
-
loadingError = false
|
|
65
|
+
loadingError.value = false
|
|
66
66
|
const url = getImageUrl()
|
|
67
|
-
if (
|
|
68
|
-
imageSrc = undefined
|
|
67
|
+
if (url === undefined || url === '') {
|
|
68
|
+
imageSrc.value = undefined
|
|
69
69
|
return
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
try {
|
|
73
73
|
const ext = url.split('.').pop()?.toLowerCase().split('?')[0]
|
|
74
74
|
|
|
75
|
-
if ('heic'
|
|
75
|
+
if (ext === 'heic') {
|
|
76
76
|
const cachedSrc = await getCachedImage(url)
|
|
77
|
-
if (cachedSrc) {
|
|
78
|
-
imageSrc = cachedSrc
|
|
77
|
+
if (cachedSrc !== undefined && cachedSrc !== '') {
|
|
78
|
+
imageSrc.value = cachedSrc
|
|
79
79
|
return
|
|
80
80
|
}
|
|
81
|
-
imageSrc = await convertHeicImage(url)
|
|
81
|
+
imageSrc.value = await convertHeicImage(url)
|
|
82
82
|
} else {
|
|
83
|
-
imageSrc = url
|
|
83
|
+
imageSrc.value = url
|
|
84
84
|
}
|
|
85
85
|
} catch (error) {
|
|
86
86
|
console.error('Image loading error:', error)
|
|
87
|
-
loadingError = true
|
|
88
|
-
imageSrc = undefined
|
|
87
|
+
loadingError.value = true
|
|
88
|
+
imageSrc.value = undefined
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|