@bagelink/vue 1.6.47 → 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/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/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/index.cjs +24 -15
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +4863 -4781
- package/dist/style.css +1 -1
- package/package.json +1 -2
- package/src/components/AccordionItem.vue +11 -11
- 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 +9 -8
- 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/Zoomer.vue +165 -168
- 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/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/AppLayout.vue +2 -2
- package/src/components/layout/AppSidebar.vue +77 -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 +22 -22
- 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/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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { useDebounceFn } from '@bagelink/vue'
|
|
3
|
-
import { onMounted
|
|
3
|
+
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
4
4
|
import TapDetector from '../utils/tapDetector'
|
|
5
5
|
|
|
6
6
|
// Props interface
|
|
@@ -34,87 +34,84 @@ const {
|
|
|
34
34
|
} = defineProps<Props>()
|
|
35
35
|
|
|
36
36
|
const emit = defineEmits(['update:zoom'])
|
|
37
|
-
// Reactive state using
|
|
38
|
-
const zoomElement =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
get: () => zoom ?? _zoom,
|
|
37
|
+
// Reactive state using standard Vue composition API
|
|
38
|
+
const zoomElement = ref<HTMLElement | undefined>()
|
|
39
|
+
const containerWidth = ref(1)
|
|
40
|
+
const containerHeight = ref(1)
|
|
41
|
+
const containerLeft = ref(0)
|
|
42
|
+
const containerTop = ref(0)
|
|
43
|
+
const translateX = ref(0)
|
|
44
|
+
const animTranslateX = ref(0)
|
|
45
|
+
const translateY = ref(0)
|
|
46
|
+
const animTranslateY = ref(0)
|
|
47
|
+
const _zoom = ref(zoom ?? 1)
|
|
48
|
+
const scale = computed({
|
|
49
|
+
get: () => zoom ?? _zoom.value,
|
|
50
50
|
set: (val) => {
|
|
51
|
-
_zoom = val
|
|
52
|
-
emit('update:zoom', _zoom)
|
|
51
|
+
_zoom.value = val
|
|
52
|
+
emit('update:zoom', _zoom.value)
|
|
53
53
|
},
|
|
54
54
|
})
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
let translateXValue = $ref(0)
|
|
69
|
-
let translateYValue = $ref(0)
|
|
56
|
+
const animScale = ref(1)
|
|
57
|
+
const lastFullWheelTime = ref(0)
|
|
58
|
+
const lastWheelTime = ref(0)
|
|
59
|
+
const lastWheelDirection = ref<'x' | 'y'>('y')
|
|
60
|
+
const isPointerDown = ref(false)
|
|
61
|
+
const pointerPosX = ref(-1)
|
|
62
|
+
const pointerPosY = ref(-1)
|
|
63
|
+
const twoFingerInitDist = ref(0)
|
|
64
|
+
const panLocked = ref(true)
|
|
65
|
+
const raf = ref<number | undefined>()
|
|
66
|
+
const tapDetector = ref<TapDetector | undefined>()
|
|
70
67
|
|
|
71
68
|
// Momentum/inertia tracking
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
69
|
+
const velocityX = ref(0)
|
|
70
|
+
const velocityY = ref(0)
|
|
71
|
+
const lastMoveTime = ref(0)
|
|
72
|
+
const momentumRaf = ref<number | undefined>()
|
|
76
73
|
|
|
77
|
-
const wrapperStyle =
|
|
74
|
+
const wrapperStyle = computed(() => {
|
|
78
75
|
// Translation is in normalized coordinates (0.5 = half container)
|
|
79
76
|
// Convert to pixels
|
|
80
|
-
translateXValue = containerWidth * animTranslateX
|
|
81
|
-
translateYValue = containerHeight * animTranslateY
|
|
77
|
+
const translateXValue = containerWidth.value * animTranslateX.value
|
|
78
|
+
const translateYValue = containerHeight.value * animTranslateY.value
|
|
82
79
|
return {
|
|
83
80
|
transform: [
|
|
84
81
|
`translate(${translateXValue}px, ${translateYValue}px)`,
|
|
85
|
-
`scale(${animScale})`,
|
|
82
|
+
`scale(${animScale.value})`,
|
|
86
83
|
].join(' '),
|
|
87
84
|
transformOrigin: '50% 50%',
|
|
88
85
|
}
|
|
89
86
|
})
|
|
90
87
|
|
|
91
|
-
|
|
88
|
+
watch(() => scale.value, (newScale) => {
|
|
92
89
|
const { x, y } = calcTranslateLimit()
|
|
93
|
-
translateX = Math.max(-x, Math.min(x, translateX))
|
|
94
|
-
translateY = Math.max(-y, Math.min(y, translateY))
|
|
90
|
+
translateX.value = Math.max(-x, Math.min(x, translateX.value))
|
|
91
|
+
translateY.value = Math.max(-y, Math.min(y, translateY.value))
|
|
95
92
|
if (newScale !== 1) {
|
|
96
|
-
panLocked = false
|
|
93
|
+
panLocked.value = false
|
|
97
94
|
}
|
|
98
95
|
})
|
|
99
96
|
|
|
100
97
|
function reset() {
|
|
101
|
-
scale = 1
|
|
102
|
-
panLocked = true
|
|
103
|
-
translateX = 0
|
|
104
|
-
translateY = 0
|
|
98
|
+
scale.value = 1
|
|
99
|
+
panLocked.value = true
|
|
100
|
+
translateX.value = 0
|
|
101
|
+
translateY.value = 0
|
|
105
102
|
}
|
|
106
103
|
|
|
107
104
|
defineExpose({ reset })
|
|
108
105
|
|
|
109
106
|
function tryToScale(scaleDelta: number) {
|
|
110
107
|
if (disabled) { return }
|
|
111
|
-
let newScale = scale * scaleDelta
|
|
108
|
+
let newScale = scale.value * scaleDelta
|
|
112
109
|
if (zoomingElastic) {
|
|
113
110
|
if (newScale < minScale || newScale > maxScale) {
|
|
114
111
|
let log = Math.log2(scaleDelta)
|
|
115
112
|
log *= 0.2
|
|
116
113
|
scaleDelta = 2 ** log
|
|
117
|
-
newScale = scale * scaleDelta
|
|
114
|
+
newScale = scale.value * scaleDelta
|
|
118
115
|
}
|
|
119
116
|
} else {
|
|
120
117
|
if (newScale < minScale) {
|
|
@@ -123,104 +120,104 @@ function tryToScale(scaleDelta: number) {
|
|
|
123
120
|
newScale = maxScale
|
|
124
121
|
}
|
|
125
122
|
}
|
|
126
|
-
scaleDelta = newScale / scale
|
|
127
|
-
scale = newScale
|
|
123
|
+
scaleDelta = newScale / scale.value
|
|
124
|
+
scale.value = newScale
|
|
128
125
|
if (pivot !== 'image-center') {
|
|
129
|
-
const normMousePosX = (pointerPosX - containerLeft) / containerWidth
|
|
130
|
-
const normMousePosY = (pointerPosY - containerTop) / containerHeight
|
|
131
|
-
translateX = (0.5 + translateX - normMousePosX) * scaleDelta + normMousePosX - 0.5
|
|
132
|
-
translateY = (0.5 + translateY - normMousePosY) * scaleDelta + normMousePosY - 0.5
|
|
126
|
+
const normMousePosX = (pointerPosX.value - containerLeft.value) / containerWidth.value
|
|
127
|
+
const normMousePosY = (pointerPosY.value - containerTop.value) / containerHeight.value
|
|
128
|
+
translateX.value = (0.5 + translateX.value - normMousePosX) * scaleDelta + normMousePosX - 0.5
|
|
129
|
+
translateY.value = (0.5 + translateY.value - normMousePosY) * scaleDelta + normMousePosY - 0.5
|
|
133
130
|
}
|
|
134
131
|
}
|
|
135
132
|
|
|
136
133
|
function setPointerPosCenter() {
|
|
137
|
-
pointerPosX = containerLeft + containerWidth / 2
|
|
138
|
-
pointerPosY = containerTop + containerHeight / 2
|
|
134
|
+
pointerPosX.value = containerLeft.value + containerWidth.value / 2
|
|
135
|
+
pointerPosY.value = containerTop.value + containerHeight.value / 2
|
|
139
136
|
}
|
|
140
137
|
|
|
141
138
|
function onPointerMove(newMousePosX: number, newMousePosY: number) {
|
|
142
|
-
if (isPointerDown) {
|
|
139
|
+
if (isPointerDown.value) {
|
|
143
140
|
const currentTime = Date.now()
|
|
144
|
-
const pixelDeltaX = newMousePosX - pointerPosX
|
|
145
|
-
const pixelDeltaY = newMousePosY - pointerPosY
|
|
141
|
+
const pixelDeltaX = newMousePosX - pointerPosX.value
|
|
142
|
+
const pixelDeltaY = newMousePosY - pointerPosY.value
|
|
146
143
|
|
|
147
|
-
if (!panLocked) {
|
|
144
|
+
if (!panLocked.value) {
|
|
148
145
|
// Calculate velocity for momentum
|
|
149
|
-
const timeDelta = currentTime - lastMoveTime
|
|
146
|
+
const timeDelta = currentTime - lastMoveTime.value
|
|
150
147
|
if (timeDelta > 0) {
|
|
151
|
-
velocityX = pixelDeltaX / timeDelta
|
|
152
|
-
velocityY = pixelDeltaY / timeDelta
|
|
148
|
+
velocityX.value = pixelDeltaX / timeDelta
|
|
149
|
+
velocityY.value = pixelDeltaY / timeDelta
|
|
153
150
|
}
|
|
154
151
|
|
|
155
152
|
const translateLimit = calcTranslateLimit()
|
|
156
153
|
const maxTranslateX = translateLimit.x
|
|
157
154
|
const maxTranslateY = translateLimit.y
|
|
158
|
-
const newTranslateX = translateX + pixelDeltaX / containerWidth
|
|
159
|
-
const newTranslateY = translateY + pixelDeltaY / containerHeight
|
|
155
|
+
const newTranslateX = translateX.value + pixelDeltaX / containerWidth.value
|
|
156
|
+
const newTranslateY = translateY.value + pixelDeltaY / containerHeight.value
|
|
160
157
|
|
|
161
|
-
translateX = Math.max(-maxTranslateX, Math.min(maxTranslateX, newTranslateX))
|
|
162
|
-
translateY = Math.max(-maxTranslateY, Math.min(maxTranslateY, newTranslateY))
|
|
158
|
+
translateX.value = Math.max(-maxTranslateX, Math.min(maxTranslateX, newTranslateX))
|
|
159
|
+
translateY.value = Math.max(-maxTranslateY, Math.min(maxTranslateY, newTranslateY))
|
|
163
160
|
|
|
164
|
-
lastMoveTime = currentTime
|
|
161
|
+
lastMoveTime.value = currentTime
|
|
165
162
|
}
|
|
166
163
|
}
|
|
167
|
-
pointerPosX = newMousePosX
|
|
168
|
-
pointerPosY = newMousePosY
|
|
164
|
+
pointerPosX.value = newMousePosX
|
|
165
|
+
pointerPosY.value = newMousePosY
|
|
169
166
|
}
|
|
170
167
|
|
|
171
168
|
function applyMomentum() {
|
|
172
|
-
if (Math.abs(velocityX) < 0.01 && Math.abs(velocityY) < 0.01) {
|
|
173
|
-
velocityX = 0
|
|
174
|
-
velocityY = 0
|
|
175
|
-
if (momentumRaf) {
|
|
176
|
-
cancelAnimationFrame(momentumRaf)
|
|
177
|
-
momentumRaf = undefined
|
|
169
|
+
if (Math.abs(velocityX.value) < 0.01 && Math.abs(velocityY.value) < 0.01) {
|
|
170
|
+
velocityX.value = 0
|
|
171
|
+
velocityY.value = 0
|
|
172
|
+
if (momentumRaf.value) {
|
|
173
|
+
cancelAnimationFrame(momentumRaf.value)
|
|
174
|
+
momentumRaf.value = undefined
|
|
178
175
|
}
|
|
179
176
|
return
|
|
180
177
|
}
|
|
181
178
|
|
|
182
179
|
const translateLimit = calcTranslateLimit()
|
|
183
|
-
const newTranslateX = translateX + velocityX * 16 / containerWidth
|
|
184
|
-
const newTranslateY = translateY + velocityY * 16 / containerHeight
|
|
180
|
+
const newTranslateX = translateX.value + velocityX.value * 16 / containerWidth.value
|
|
181
|
+
const newTranslateY = translateY.value + velocityY.value * 16 / containerHeight.value
|
|
185
182
|
|
|
186
|
-
translateX = Math.max(-translateLimit.x, Math.min(translateLimit.x, newTranslateX))
|
|
187
|
-
translateY = Math.max(-translateLimit.y, Math.min(translateLimit.y, newTranslateY))
|
|
183
|
+
translateX.value = Math.max(-translateLimit.x, Math.min(translateLimit.x, newTranslateX))
|
|
184
|
+
translateY.value = Math.max(-translateLimit.y, Math.min(translateLimit.y, newTranslateY))
|
|
188
185
|
|
|
189
186
|
// Apply friction
|
|
190
|
-
velocityX *= 0.95
|
|
191
|
-
velocityY *= 0.95
|
|
187
|
+
velocityX.value *= 0.95
|
|
188
|
+
velocityY.value *= 0.95
|
|
192
189
|
|
|
193
|
-
momentumRaf = requestAnimationFrame(applyMomentum)
|
|
190
|
+
momentumRaf.value = requestAnimationFrame(applyMomentum)
|
|
194
191
|
}
|
|
195
192
|
|
|
196
193
|
const onInteractionEnd = useDebounceFn(() => {
|
|
197
194
|
limit()
|
|
198
|
-
panLocked = scale === 1
|
|
195
|
+
panLocked.value = scale.value === 1
|
|
199
196
|
|
|
200
197
|
// Start momentum animation if there's significant velocity
|
|
201
|
-
if (!panLocked && (Math.abs(velocityX) > 0.1 || Math.abs(velocityY) > 0.1)) {
|
|
202
|
-
if (momentumRaf) cancelAnimationFrame(momentumRaf)
|
|
198
|
+
if (!panLocked.value && (Math.abs(velocityX.value) > 0.1 || Math.abs(velocityY.value) > 0.1)) {
|
|
199
|
+
if (momentumRaf.value) cancelAnimationFrame(momentumRaf.value)
|
|
203
200
|
applyMomentum()
|
|
204
201
|
} else {
|
|
205
|
-
velocityX = 0
|
|
206
|
-
velocityY = 0
|
|
202
|
+
velocityX.value = 0
|
|
203
|
+
velocityY.value = 0
|
|
207
204
|
}
|
|
208
205
|
}, 50)
|
|
209
206
|
|
|
210
207
|
function limit() {
|
|
211
|
-
if (scale < minScale) {
|
|
212
|
-
scale = minScale
|
|
213
|
-
} else if (scale > maxScale) {
|
|
214
|
-
tryToScale(maxScale / scale)
|
|
208
|
+
if (scale.value < minScale) {
|
|
209
|
+
scale.value = minScale
|
|
210
|
+
} else if (scale.value > maxScale) {
|
|
211
|
+
tryToScale(maxScale / scale.value)
|
|
215
212
|
}
|
|
216
213
|
|
|
217
214
|
if (limitTranslation) {
|
|
218
215
|
const translateLimit = calcTranslateLimit()
|
|
219
|
-
if (Math.abs(translateX) > translateLimit.x) {
|
|
220
|
-
translateX *= translateLimit.x / Math.abs(translateX)
|
|
216
|
+
if (Math.abs(translateX.value) > translateLimit.x) {
|
|
217
|
+
translateX.value *= translateLimit.x / Math.abs(translateX.value)
|
|
221
218
|
}
|
|
222
|
-
if (Math.abs(translateY) > translateLimit.y) {
|
|
223
|
-
translateY *= translateLimit.y / Math.abs(translateY)
|
|
219
|
+
if (Math.abs(translateY.value) > translateLimit.y) {
|
|
220
|
+
translateY.value *= translateLimit.y / Math.abs(translateY.value)
|
|
224
221
|
}
|
|
225
222
|
}
|
|
226
223
|
}
|
|
@@ -238,7 +235,7 @@ function calcTranslateLimit() {
|
|
|
238
235
|
// Max pan distance in normalized coords = (scale - 1) / 2
|
|
239
236
|
// This works for both X and Y directions regardless of aspect ratio
|
|
240
237
|
|
|
241
|
-
const basePanLimit = Math.max(0, (scale - 1) / 2)
|
|
238
|
+
const basePanLimit = Math.max(0, (scale.value - 1) / 2)
|
|
242
239
|
|
|
243
240
|
return {
|
|
244
241
|
x: basePanLimit,
|
|
@@ -251,18 +248,18 @@ function onMouseWheel(ev: WheelEvent) {
|
|
|
251
248
|
ev.preventDefault()
|
|
252
249
|
const currTime = Date.now()
|
|
253
250
|
if (Math.abs(ev.deltaY) === 120) {
|
|
254
|
-
if (currTime - lastFullWheelTime > 50) {
|
|
251
|
+
if (currTime - lastFullWheelTime.value > 50) {
|
|
255
252
|
onMouseWheelDo(ev.deltaY)
|
|
256
|
-
lastFullWheelTime = currTime
|
|
253
|
+
lastFullWheelTime.value = currTime
|
|
257
254
|
}
|
|
258
255
|
} else {
|
|
259
|
-
if (currTime - lastWheelTime > 50) {
|
|
260
|
-
lastWheelDirection = ev.deltaX > ev.deltaY ? 'x' : 'y'
|
|
261
|
-
if (lastWheelDirection === 'y') {
|
|
256
|
+
if (currTime - lastWheelTime.value > 50) {
|
|
257
|
+
lastWheelDirection.value = ev.deltaX > ev.deltaY ? 'x' : 'y'
|
|
258
|
+
if (lastWheelDirection.value === 'y') {
|
|
262
259
|
onMouseWheelDo(ev.deltaY)
|
|
263
260
|
}
|
|
264
261
|
}
|
|
265
|
-
lastWheelTime = currTime
|
|
262
|
+
lastWheelTime.value = currTime
|
|
266
263
|
}
|
|
267
264
|
}
|
|
268
265
|
|
|
@@ -275,22 +272,22 @@ function onMouseWheelDo(wheelDelta: number) {
|
|
|
275
272
|
|
|
276
273
|
function onMouseDown(ev: MouseEvent) {
|
|
277
274
|
refreshContainerPos()
|
|
278
|
-
isPointerDown = true
|
|
279
|
-
pointerPosX = ev.clientX
|
|
280
|
-
pointerPosY = ev.clientY
|
|
281
|
-
lastMoveTime = Date.now()
|
|
282
|
-
velocityX = 0
|
|
283
|
-
velocityY = 0
|
|
284
|
-
if (momentumRaf) {
|
|
285
|
-
cancelAnimationFrame(momentumRaf)
|
|
286
|
-
momentumRaf = undefined
|
|
275
|
+
isPointerDown.value = true
|
|
276
|
+
pointerPosX.value = ev.clientX
|
|
277
|
+
pointerPosY.value = ev.clientY
|
|
278
|
+
lastMoveTime.value = Date.now()
|
|
279
|
+
velocityX.value = 0
|
|
280
|
+
velocityY.value = 0
|
|
281
|
+
if (momentumRaf.value) {
|
|
282
|
+
cancelAnimationFrame(momentumRaf.value)
|
|
283
|
+
momentumRaf.value = undefined
|
|
287
284
|
}
|
|
288
285
|
document.addEventListener('mousemove', onMouseMove)
|
|
289
286
|
document.addEventListener('mouseup', onMouseUp)
|
|
290
287
|
}
|
|
291
288
|
|
|
292
289
|
function onMouseUp() {
|
|
293
|
-
isPointerDown = false
|
|
290
|
+
isPointerDown.value = false
|
|
294
291
|
onInteractionEnd()
|
|
295
292
|
document.removeEventListener('mouseup', onMouseUp)
|
|
296
293
|
document.removeEventListener('mousemove', onMouseMove)
|
|
@@ -298,7 +295,7 @@ function onMouseUp() {
|
|
|
298
295
|
|
|
299
296
|
function onMouseMove(ev: MouseEvent) {
|
|
300
297
|
// Prevent swiper from handling mouse drag when panning zoomed image
|
|
301
|
-
if (!panLocked && scale > 1) {
|
|
298
|
+
if (!panLocked.value && scale.value > 1) {
|
|
302
299
|
ev.stopPropagation()
|
|
303
300
|
}
|
|
304
301
|
onPointerMove(ev.clientX, ev.clientY)
|
|
@@ -307,41 +304,41 @@ function onMouseMove(ev: MouseEvent) {
|
|
|
307
304
|
function onTouchStart(ev: TouchEvent) {
|
|
308
305
|
if (ev.touches.length === 1) {
|
|
309
306
|
refreshContainerPos()
|
|
310
|
-
pointerPosX = ev.touches[0].clientX
|
|
311
|
-
pointerPosY = ev.touches[0].clientY
|
|
312
|
-
lastMoveTime = Date.now()
|
|
313
|
-
velocityX = 0
|
|
314
|
-
velocityY = 0
|
|
315
|
-
if (momentumRaf) {
|
|
316
|
-
cancelAnimationFrame(momentumRaf)
|
|
317
|
-
momentumRaf = undefined
|
|
307
|
+
pointerPosX.value = ev.touches[0].clientX
|
|
308
|
+
pointerPosY.value = ev.touches[0].clientY
|
|
309
|
+
lastMoveTime.value = Date.now()
|
|
310
|
+
velocityX.value = 0
|
|
311
|
+
velocityY.value = 0
|
|
312
|
+
if (momentumRaf.value) {
|
|
313
|
+
cancelAnimationFrame(momentumRaf.value)
|
|
314
|
+
momentumRaf.value = undefined
|
|
318
315
|
}
|
|
319
|
-
isPointerDown = true
|
|
316
|
+
isPointerDown.value = true
|
|
320
317
|
} else if (ev.touches.length === 2) {
|
|
321
|
-
if (momentumRaf) {
|
|
322
|
-
cancelAnimationFrame(momentumRaf)
|
|
323
|
-
momentumRaf = undefined
|
|
318
|
+
if (momentumRaf.value) {
|
|
319
|
+
cancelAnimationFrame(momentumRaf.value)
|
|
320
|
+
momentumRaf.value = undefined
|
|
324
321
|
}
|
|
325
|
-
velocityX = 0
|
|
326
|
-
velocityY = 0
|
|
327
|
-
isPointerDown = true
|
|
328
|
-
pointerPosX = (ev.touches[0].clientX + ev.touches[1].clientX) / 2
|
|
329
|
-
pointerPosY = (ev.touches[0].clientY + ev.touches[1].clientY) / 2
|
|
322
|
+
velocityX.value = 0
|
|
323
|
+
velocityY.value = 0
|
|
324
|
+
isPointerDown.value = true
|
|
325
|
+
pointerPosX.value = (ev.touches[0].clientX + ev.touches[1].clientX) / 2
|
|
326
|
+
pointerPosY.value = (ev.touches[0].clientY + ev.touches[1].clientY) / 2
|
|
330
327
|
const distX = ev.touches[0].clientX - ev.touches[1].clientX
|
|
331
328
|
const distY = ev.touches[0].clientY - ev.touches[1].clientY
|
|
332
|
-
twoFingerInitDist = Math.sqrt(distX * distX + distY * distY)
|
|
329
|
+
twoFingerInitDist.value = Math.sqrt(distX * distX + distY * distY)
|
|
333
330
|
}
|
|
334
331
|
document.addEventListener('touchend', onTouchEnd)
|
|
335
332
|
}
|
|
336
333
|
|
|
337
334
|
function onTouchEnd(ev: TouchEvent) {
|
|
338
335
|
if (ev.touches.length === 0) {
|
|
339
|
-
isPointerDown = false
|
|
340
|
-
if (Math.abs(scale - 1) < 0.1) { scale = 1 }
|
|
336
|
+
isPointerDown.value = false
|
|
337
|
+
if (Math.abs(scale.value - 1) < 0.1) { scale.value = 1 }
|
|
341
338
|
onInteractionEnd()
|
|
342
339
|
} else if (ev.touches.length === 1) {
|
|
343
|
-
pointerPosX = ev.touches[0].clientX
|
|
344
|
-
pointerPosY = ev.touches[0].clientY
|
|
340
|
+
pointerPosX.value = ev.touches[0].clientX
|
|
341
|
+
pointerPosY.value = ev.touches[0].clientY
|
|
345
342
|
}
|
|
346
343
|
document.removeEventListener('touchend', onTouchEnd)
|
|
347
344
|
}
|
|
@@ -349,7 +346,7 @@ function onTouchEnd(ev: TouchEvent) {
|
|
|
349
346
|
function onTouchMove(ev: TouchEvent) {
|
|
350
347
|
if (ev.touches.length === 1) {
|
|
351
348
|
// Prevent swiper from handling touch when panning zoomed image
|
|
352
|
-
if (!panLocked && scale > 1) {
|
|
349
|
+
if (!panLocked.value && scale.value > 1) {
|
|
353
350
|
ev.stopPropagation()
|
|
354
351
|
}
|
|
355
352
|
onPointerMove(ev.touches[0].clientX, ev.touches[0].clientY)
|
|
@@ -359,24 +356,24 @@ function onTouchMove(ev: TouchEvent) {
|
|
|
359
356
|
const distX = ev.touches[0].clientX - ev.touches[1].clientX
|
|
360
357
|
const distY = ev.touches[0].clientY - ev.touches[1].clientY
|
|
361
358
|
const newTwoFingerDist = Math.sqrt(distX * distX + distY * distY)
|
|
362
|
-
tryToScale(newTwoFingerDist / twoFingerInitDist)
|
|
363
|
-
twoFingerInitDist = newTwoFingerDist
|
|
359
|
+
tryToScale(newTwoFingerDist / twoFingerInitDist.value)
|
|
360
|
+
twoFingerInitDist.value = newTwoFingerDist
|
|
364
361
|
}
|
|
365
362
|
}
|
|
366
363
|
|
|
367
364
|
function refreshContainerPos() {
|
|
368
|
-
if (zoomElement) {
|
|
369
|
-
const rect = zoomElement.getBoundingClientRect()
|
|
370
|
-
containerLeft = rect.left
|
|
371
|
-
containerTop = rect.top
|
|
365
|
+
if (zoomElement.value) {
|
|
366
|
+
const rect = zoomElement.value.getBoundingClientRect()
|
|
367
|
+
containerLeft.value = rect.left
|
|
368
|
+
containerTop.value = rect.top
|
|
372
369
|
}
|
|
373
370
|
}
|
|
374
371
|
|
|
375
372
|
function loop() {
|
|
376
|
-
animScale = gainOn(animScale, scale)
|
|
377
|
-
animTranslateX = gainOn(animTranslateX, translateX)
|
|
378
|
-
animTranslateY = gainOn(animTranslateY, translateY)
|
|
379
|
-
raf = window.requestAnimationFrame(loop)
|
|
373
|
+
animScale.value = gainOn(animScale.value, scale.value)
|
|
374
|
+
animTranslateX.value = gainOn(animTranslateX.value, translateX.value)
|
|
375
|
+
animTranslateY.value = gainOn(animTranslateY.value, translateY.value)
|
|
376
|
+
raf.value = window.requestAnimationFrame(loop)
|
|
380
377
|
}
|
|
381
378
|
|
|
382
379
|
function gainOn(from: number, to: number) {
|
|
@@ -386,14 +383,14 @@ function gainOn(from: number, to: number) {
|
|
|
386
383
|
}
|
|
387
384
|
|
|
388
385
|
// Lifecycle hooks
|
|
389
|
-
|
|
390
|
-
tapDetector = new TapDetector()
|
|
391
|
-
if (zoomElement) { tapDetector.attach(zoomElement) }
|
|
386
|
+
onMounted(() => {
|
|
387
|
+
tapDetector.value = new TapDetector()
|
|
388
|
+
if (zoomElement.value) { tapDetector.value.attach(zoomElement.value) }
|
|
392
389
|
if (doubleClickToZoom) {
|
|
393
|
-
tapDetector.onDoubleTap(onDoubleTap as any)
|
|
390
|
+
tapDetector.value.onDoubleTap(onDoubleTap as any)
|
|
394
391
|
// Also add native dblclick event for mouse
|
|
395
|
-
if (zoomElement) {
|
|
396
|
-
zoomElement.addEventListener('dblclick', onDoubleTap as any)
|
|
392
|
+
if (zoomElement.value) {
|
|
393
|
+
zoomElement.value.addEventListener('dblclick', onDoubleTap as any)
|
|
397
394
|
}
|
|
398
395
|
}
|
|
399
396
|
window.addEventListener('resize', onWindowResize)
|
|
@@ -402,23 +399,23 @@ vueOnMounted(() => {
|
|
|
402
399
|
loop()
|
|
403
400
|
})
|
|
404
401
|
|
|
405
|
-
|
|
406
|
-
if (zoomElement) {
|
|
407
|
-
tapDetector?.detach(zoomElement)
|
|
402
|
+
onUnmounted(() => {
|
|
403
|
+
if (zoomElement.value) {
|
|
404
|
+
tapDetector.value?.detach(zoomElement.value)
|
|
408
405
|
if (doubleClickToZoom) {
|
|
409
|
-
zoomElement.removeEventListener('dblclick', onDoubleTap as any)
|
|
406
|
+
zoomElement.value.removeEventListener('dblclick', onDoubleTap as any)
|
|
410
407
|
}
|
|
411
408
|
}
|
|
412
409
|
window.removeEventListener('resize', onWindowResize)
|
|
413
|
-
if (raf) { window.cancelAnimationFrame(raf) }
|
|
414
|
-
if (momentumRaf) { window.cancelAnimationFrame(momentumRaf) }
|
|
410
|
+
if (raf.value) { window.cancelAnimationFrame(raf.value) }
|
|
411
|
+
if (momentumRaf.value) { window.cancelAnimationFrame(momentumRaf.value) }
|
|
415
412
|
})
|
|
416
413
|
|
|
417
414
|
function onDoubleTap(ev: MouseEvent) {
|
|
418
415
|
// Update pointer position if available
|
|
419
416
|
if (ev.clientX > 0) {
|
|
420
|
-
pointerPosX = ev.clientX
|
|
421
|
-
pointerPosY = ev.clientY
|
|
417
|
+
pointerPosX.value = ev.clientX
|
|
418
|
+
pointerPosY.value = ev.clientY
|
|
422
419
|
}
|
|
423
420
|
|
|
424
421
|
// Calculate zoom levels
|
|
@@ -426,12 +423,12 @@ function onDoubleTap(ev: MouseEvent) {
|
|
|
426
423
|
const highZoom = maxScale
|
|
427
424
|
|
|
428
425
|
// Cycle through three states: 1x -> medium -> max -> 1x
|
|
429
|
-
if (scale === 1) {
|
|
426
|
+
if (scale.value === 1) {
|
|
430
427
|
// From no zoom -> medium zoom
|
|
431
428
|
tryToScale(mediumZoom)
|
|
432
|
-
} else if (scale < highZoom - 0.1) {
|
|
429
|
+
} else if (scale.value < highZoom - 0.1) {
|
|
433
430
|
// From medium zoom -> max zoom
|
|
434
|
-
tryToScale(highZoom / scale)
|
|
431
|
+
tryToScale(highZoom / scale.value)
|
|
435
432
|
} else {
|
|
436
433
|
// From max zoom -> no zoom (reset)
|
|
437
434
|
reset()
|
|
@@ -439,10 +436,10 @@ function onDoubleTap(ev: MouseEvent) {
|
|
|
439
436
|
}
|
|
440
437
|
|
|
441
438
|
function onWindowResize() {
|
|
442
|
-
if (zoomElement) {
|
|
443
|
-
const styles = window.getComputedStyle(zoomElement)
|
|
444
|
-
containerWidth = Number.parseFloat(styles.width)
|
|
445
|
-
containerHeight = Number.parseFloat(styles.height)
|
|
439
|
+
if (zoomElement.value) {
|
|
440
|
+
const styles = window.getComputedStyle(zoomElement.value)
|
|
441
|
+
containerWidth.value = Number.parseFloat(styles.width)
|
|
442
|
+
containerHeight.value = Number.parseFloat(styles.height)
|
|
446
443
|
setPointerPosCenter()
|
|
447
444
|
limit()
|
|
448
445
|
}
|
|
@@ -57,7 +57,7 @@ const observer = ref<IntersectionObserver | null>(null)
|
|
|
57
57
|
const chartRef = ref<HTMLElement | null>(null)
|
|
58
58
|
|
|
59
59
|
const chartData = computed(() => {
|
|
60
|
-
if (!props.data ||
|
|
60
|
+
if (!props.data || props.data.length === 0) { return [] }
|
|
61
61
|
|
|
62
62
|
// Use all data without limiting to maxBars
|
|
63
63
|
const maxValue = Math.max(...props.data.map(d => d.value), 1)
|
|
@@ -71,8 +71,8 @@ const chartData = computed(() => {
|
|
|
71
71
|
// Animation computed properties
|
|
72
72
|
const getBarOpacity = computed(() => {
|
|
73
73
|
return (index: number) => {
|
|
74
|
-
if (!props.animated) {return 1}
|
|
75
|
-
if (!isInView.value) {return 0}
|
|
74
|
+
if (!props.animated) { return 1 }
|
|
75
|
+
if (!isInView.value) { return 0 }
|
|
76
76
|
|
|
77
77
|
const totalBars = chartData.value.length
|
|
78
78
|
|
|
@@ -90,7 +90,7 @@ function easeOutCubic(t: number): number {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
function startAnimation() {
|
|
93
|
-
if (isAnimating.value || !props.animated) {return}
|
|
93
|
+
if (isAnimating.value || !props.animated) { return }
|
|
94
94
|
|
|
95
95
|
console.log(`🎯 TrendChart: Starting animation with ${props.animationDuration}ms duration`)
|
|
96
96
|
isAnimating.value = true
|
|
@@ -105,7 +105,7 @@ function startAnimation() {
|
|
|
105
105
|
|
|
106
106
|
animatedProgress.value = easedProgress
|
|
107
107
|
|
|
108
|
-
if (
|
|
108
|
+
if (progress < 1) {
|
|
109
109
|
requestAnimationFrame(animate)
|
|
110
110
|
} else {
|
|
111
111
|
isAnimating.value = false
|
|
@@ -117,7 +117,7 @@ function startAnimation() {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
function setupIntersectionObserver() {
|
|
120
|
-
if (!chartRef.value || observer.value) {return}
|
|
120
|
+
if (!chartRef.value || observer.value) { return }
|
|
121
121
|
|
|
122
122
|
observer.value = new IntersectionObserver(
|
|
123
123
|
(entries) => {
|
|
@@ -27,10 +27,10 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
27
27
|
subtitle: ''
|
|
28
28
|
})
|
|
29
29
|
|
|
30
|
-
const isIncreasing = computed(() =>
|
|
30
|
+
const isIncreasing = computed(() => props.percentageChange >= 0)
|
|
31
31
|
|
|
32
32
|
const formattedValue = computed(() => {
|
|
33
|
-
if (
|
|
33
|
+
if (typeof props.value === 'string') { return props.value }
|
|
34
34
|
|
|
35
35
|
if (props.currency) {
|
|
36
36
|
return new Intl.NumberFormat('he-IL', {
|