@bagelink/vue 0.0.827 → 0.0.833

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.
@@ -2,221 +2,184 @@
2
2
  import { onMounted, onUnmounted, watch } from 'vue'
3
3
 
4
4
  const props = defineProps({
5
- autoHeight: {
6
- type: Boolean,
7
- default: false,
8
- },
9
- allowScroll: {
10
- type: Boolean,
11
- default: true,
12
- },
13
- freeDrag: {
14
- type: Boolean,
15
- default: true,
16
- },
17
- items: {
18
- type: Number,
19
- default: 4,
20
- },
21
- index: {
22
- type: Number,
23
- default: 0,
24
- },
5
+ autoHeight: { type: Boolean, default: false },
6
+ allowScroll: { type: Boolean, default: true },
7
+ freeDrag: { type: Boolean, default: true },
8
+ items: { type: Number, default: 4 },
9
+ index: { type: Number, default: 0 },
10
+ rtl: { type: Boolean, default: false },
11
+ autoplay: { type: Boolean, default: false },
12
+ autoPlaySpeed: { type: Number, default: 4000 },
25
13
  })
14
+
26
15
  const emit = defineEmits(['update:index'])
27
16
  const bglSlider = $ref<HTMLElement>()
17
+
28
18
  let itemCount = $ref(props.items)
29
- let activeSlideIndex = $ref(0)
19
+ let activeSlideIndex = $ref(props.index)
30
20
  let isDragging = $ref(false)
31
- let startX = $ref(0)
32
- let scrollLeft = $ref(0)
33
21
  let isPressed = $ref(false)
22
+ let startX = $ref(0)
23
+ let scrollStart = $ref(0)
24
+ let yHeight = $ref('auto')
25
+ let timeout: NodeJS.Timeout
26
+ let autoPlayInterval: NodeJS.Timeout
34
27
 
35
- function disableDrag() {
36
- bglSlider
37
- ?.querySelectorAll('img')
38
- .forEach((e) => { e.setAttribute('draggable', 'false') })
28
+ // Helper Functions
29
+ function preventDefaultClick(e: MouseEvent) {
30
+ e.preventDefault()
31
+ }
39
32
 
40
- for (const e of (bglSlider?.children as any[] | undefined) || []) {
41
- e.setAttribute('draggable', 'false')
42
- e.addEventListener('click', (e: any) => e.preventDefault())
43
- }
33
+ function disableDrag() {
34
+ bglSlider?.querySelectorAll('img').forEach((img) => { img.setAttribute('draggable', 'false') })
35
+ Array.from(bglSlider?.children || []).forEach((child) => {
36
+ child.setAttribute('draggable', 'false');
37
+ (child as HTMLElement).addEventListener('click', preventDefaultClick)
38
+ })
44
39
  }
45
40
 
46
- let yHeight = $ref('auto')
47
- function evalHeight() {
41
+ function updateHeight() {
48
42
  if (!props.autoHeight || !bglSlider) return
49
- const slidChildren = bglSlider.children[activeSlideIndex].children
50
- const height = Array.from(slidChildren)
51
- .map(el => el.clientHeight)
52
- .reduce((a, b) => a + b, 0)
53
-
54
- yHeight = `${height}px`
43
+ const children = Array.from(bglSlider.children[activeSlideIndex].children)
44
+ const totalHeight = children.reduce((sum, el) => sum + el.clientHeight, 0)
45
+ yHeight = `${totalHeight}px`
55
46
  }
56
47
 
57
- function scrollEase(target: number, duration: number = 500) {
58
- if (!bglSlider) return
59
- if (isPressed) return
48
+ function easeScroll(target: number, duration = 500) {
49
+ if (!bglSlider || isPressed) return
60
50
  const start = bglSlider.scrollLeft
61
51
  const change = target - start
62
52
  const startTime = performance.now()
63
53
 
64
- function animateScroll(currentTime: number) {
54
+ function animate(currentTime: number) {
65
55
  if (!bglSlider) return
66
56
  const timeElapsed = currentTime - startTime
67
57
  const progress = Math.min(timeElapsed / duration, 1)
68
58
  bglSlider.scrollLeft = start + change * easeInOutQuad(progress)
69
- if (progress < 1) {
70
- requestAnimationFrame(animateScroll)
71
- }
59
+ if (progress < 1) requestAnimationFrame(animate)
72
60
  }
73
61
 
74
62
  function easeInOutQuad(t: number) {
75
63
  return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
76
64
  }
77
65
 
78
- requestAnimationFrame(animateScroll)
66
+ requestAnimationFrame(animate)
79
67
  }
80
68
 
81
69
  function goToSlide(index: number) {
82
- if (!bglSlider || index < 0 || index > bglSlider.children.length - 1) return
83
- const isRTL = getComputedStyle(bglSlider).direction === 'rtl'
84
- const scrollX = bglSlider.offsetWidth * index * (isRTL ? -1 : 1)
85
- const screenWidth = window.innerWidth
86
- let duration = 700
87
-
88
- if (screenWidth < 600) {
89
- duration = 400
90
- } else if (screenWidth < 991) {
91
- duration = 500
92
- }
93
-
94
- scrollEase(scrollX, duration)
70
+ if (!bglSlider || index < 0 || index >= bglSlider.children.length) return
71
+ const offset = bglSlider.offsetWidth * index * (props.rtl ? -1 : 1)
72
+ const duration = window.innerWidth < 600 ? 400 : window.innerWidth < 991 ? 500 : 700
73
+ easeScroll(offset, duration)
95
74
  activeSlideIndex = index
96
- evalHeight()
75
+ updateHeight()
97
76
  }
98
77
 
99
- watch(() => props.index, goToSlide)
100
-
101
- watch(
102
- () => activeSlideIndex,
103
- () => {
104
- if (props.index === activeSlideIndex) return
105
- emit('update:index', activeSlideIndex) }
106
- )
78
+ function handleSlideChange() {
79
+ if (props.index !== activeSlideIndex) emit('update:index', activeSlideIndex)
80
+ }
107
81
 
108
- function goToSlideScrollEnd() {
82
+ function handleResize() {
109
83
  if (!bglSlider) return
110
- const isDragForward = startX > bglSlider.offsetLeft
111
- if (itemCount === 1) {
112
- if (isDragForward) activeSlideIndex = Math.ceil(bglSlider.scrollLeft / bglSlider.offsetWidth)
113
- else activeSlideIndex = Math.floor(bglSlider.scrollLeft / bglSlider.offsetWidth)
114
- } else {
115
- activeSlideIndex = Math.round(bglSlider.scrollLeft / bglSlider.offsetWidth)
116
- }
117
- startX = 0
118
- const nextSlide = Math.round(bglSlider.scrollLeft / bglSlider.offsetWidth)
119
- goToSlide(nextSlide)
84
+ itemCount = window.innerWidth < 600 ? 1 : window.innerWidth < 991 ? Math.min(props.items, 2) : Math.min(props.items, 3)
85
+ goToSlide(activeSlideIndex)
120
86
  }
121
87
 
122
- let timeout: any = null
123
-
124
- function scrollEnd() {
88
+ function onScrollEnd() {
89
+ if ((!props.freeDrag && !props.allowScroll) || !bglSlider) return
90
+ if (autoPlayInterval) clearInterval(autoPlayInterval)
125
91
  if (timeout) clearTimeout(timeout)
126
- timeout = setTimeout(goToSlideScrollEnd, 400)
127
- }
128
-
129
- function stopDragging(e: MouseEvent) {
130
- isPressed = false
131
- document.removeEventListener('mousemove', move)
132
- document.removeEventListener('mouseup', stopDragging)
133
- document.removeEventListener('dragend', stopDragging)
134
- setTimeout(() => (isDragging = false), 100)
92
+ timeout = setTimeout(() => { finalizeScroll() }, 400)
135
93
  }
136
94
 
137
- function move(e: MouseEvent) {
95
+ function finalizeScroll() {
138
96
  if (!bglSlider) return
139
- const x = e.pageX - bglSlider.offsetLeft
140
- const walk = x - startX
141
- if (walk > 20 || walk < -20) isDragging = true
142
- if (!isDragging) return
143
- const scroll = x - startX
144
- bglSlider.scrollLeft = scrollLeft - scroll
97
+ if (props.autoplay) autoPlayInterval = setInterval(next, props.autoPlaySpeed)
98
+ scrollStart = props.rtl ? -bglSlider.scrollLeft : bglSlider.scrollLeft
99
+ activeSlideIndex = Math.round(scrollStart / bglSlider.offsetWidth)
100
+ goToSlide(activeSlideIndex)
145
101
  }
146
102
 
147
- function startDragging(e: MouseEvent) {
103
+ function startDrag(e: MouseEvent) {
148
104
  if (e.button !== 0 || !props.freeDrag || !bglSlider) return
105
+ if (autoPlayInterval) clearInterval(autoPlayInterval)
149
106
  startX = e.pageX - bglSlider.offsetLeft
150
- scrollLeft = bglSlider.scrollLeft
107
+ scrollStart = bglSlider.scrollLeft
151
108
  isPressed = true
152
- document.addEventListener('mousemove', move)
153
- document.addEventListener('mouseup', stopDragging)
154
- // document.addEventListener('dragend', stopDragging)
109
+ document.addEventListener('mousemove', onDrag)
110
+ document.addEventListener('mouseup', endDrag)
155
111
  }
156
112
 
157
- function next() {
113
+ function onDrag(e: MouseEvent) {
158
114
  if (!bglSlider) return
159
- const slideCount = bglSlider.children.length
160
- const isLastSlide = activeSlideIndex >= slideCount - 1
161
- if (isLastSlide) goToSlide(0)
162
- else goToSlide(activeSlideIndex + 1)
115
+ const x = e.pageX - bglSlider.offsetLeft
116
+ const distance = x - startX
117
+ if (Math.abs(distance) > 20) isDragging = true
118
+ if (isDragging) bglSlider.scrollLeft = scrollStart - distance
163
119
  }
164
120
 
165
- function prev() {
121
+ function endDrag() {
122
+ isPressed = false
123
+ document.removeEventListener('mousemove', onDrag)
124
+ document.removeEventListener('mouseup', endDrag)
125
+ setTimeout(() => (isDragging = false), 100)
126
+ }
127
+
128
+ // Navigation Functions
129
+ function next() {
166
130
  if (!bglSlider) return
167
131
  const slideCount = bglSlider.children.length
168
- if (activeSlideIndex === 0) goToSlide(slideCount - 1)
169
- else goToSlide(activeSlideIndex - 1)
132
+ goToSlide((activeSlideIndex + 1) % slideCount)
170
133
  }
171
134
 
172
- function evalWidth() {
135
+ function prev() {
173
136
  if (!bglSlider) return
174
- if (window.innerWidth < 600) itemCount = 1
175
- else if (window.innerWidth < 991) itemCount = Math.min(props.items, 2)
176
- else if (window.innerWidth < 1280) itemCount = Math.min(props.items, 3)
177
- else itemCount = props.items
178
- console.log(itemCount, window.innerWidth)
179
- goToSlide(activeSlideIndex)
137
+ const slideCount = bglSlider.children.length
138
+ goToSlide((activeSlideIndex - 1 + slideCount) % slideCount)
180
139
  }
181
140
 
141
+ // Lifecycle Hooks
182
142
  onMounted(() => {
183
- window.addEventListener('resize', evalWidth)
184
- evalHeight()
185
- evalWidth()
143
+ window.addEventListener('resize', handleResize)
186
144
  disableDrag()
145
+ updateHeight()
146
+ handleResize()
147
+ if (props.autoplay) {
148
+ autoPlayInterval = setInterval(next, props.autoPlaySpeed)
149
+ }
187
150
  })
188
151
 
189
- onUnmounted(() => { window.removeEventListener('resize', evalWidth) })
152
+ function clearAutoplay() {
153
+ if (autoPlayInterval) clearInterval(autoPlayInterval)
154
+ }
155
+
156
+ onUnmounted(() => {
157
+ window.removeEventListener('resize', handleResize)
158
+ })
159
+
160
+ // Watchers
161
+ watch(() => props.index, goToSlide)
162
+ watch(() => activeSlideIndex, handleSlideChange)
190
163
  </script>
191
164
 
192
165
  <template>
193
- <div class="BglCarousel" :style="{ height: yHeight }" :class="{ autoHeight }">
166
+ <div class="BglCarousel" :style="{ height: yHeight }" :class="{ autoHeight }" :dir="rtl ? 'rtl' : 'ltr'">
194
167
  <div
195
168
  ref="bglSlider"
196
- :class="{
197
- dragging: isDragging,
198
- clicking: isPressed,
199
- allowScroll,
200
- odd: itemCount % 2 !== 0,
201
- [`slides-${itemCount}`]: itemCount === 1,
202
- }"
203
169
  class="bgl-slider"
204
- :style="{
205
- '--item-count': itemCount,
206
- }"
207
- @scroll.active="scrollEnd"
208
- @mousedown="startDragging"
170
+ :class="{ dragging: isDragging, clicking: isPressed, allowScroll, odd: itemCount % 2 !== 0, [`slides-${itemCount}`]: itemCount === 1 }"
171
+ :style="{ '--item-count': itemCount }"
172
+ @scroll="onScrollEnd"
173
+ @mousedown="startDrag"
174
+ @mouseover="clearAutoplay"
175
+ @focusin="clearAutoplay"
209
176
  >
210
177
  <div v-if="isDragging" class="blocker" />
211
178
  <slot />
212
179
  </div>
213
180
  <div class="Handlers">
214
- <span @click="prev">
215
- <slot :prev :index="activeSlideIndex" name="prev" />
216
- </span>
217
- <span @click="next">
218
- <slot :next :index="activeSlideIndex" name="next" />
219
- </span>
181
+ <span @click="prev"><slot name="prev" :index="activeSlideIndex" /></span>
182
+ <span @click="next"><slot name="next" :index="activeSlideIndex" /></span>
220
183
  </div>
221
184
  </div>
222
185
  </template>
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
+ import type { MaterialIcons, ThemeType } from '@bagelink/vue'
2
3
  import { Btn, MaterialIcon } from '@bagelink/vue'
3
4
  import { useSlots } from 'vue'
4
- import type { MaterialIcons, ThemeType } from '@bagelink/vue'
5
5
 
6
6
  interface BtnProp {
7
7
  icon: MaterialIcons
@@ -12,7 +12,7 @@ interface BtnProp {
12
12
  const props = defineProps<{
13
13
  disabled?: boolean
14
14
  icon?: MaterialIcons
15
- iconEnd: MaterialIcons
15
+ iconEnd?: MaterialIcons
16
16
  color?: ThemeType
17
17
  theme?: ThemeType
18
18
  flat?: boolean
@@ -21,8 +21,8 @@ const props = defineProps<{
21
21
  loading?: boolean
22
22
  value?: string
23
23
  round?: boolean
24
- btn: BtnProp
25
- btnEnd: BtnProp
24
+ btn?: BtnProp
25
+ btnEnd?: BtnProp
26
26
  }>()
27
27
 
28
28
  const slots = useSlots()