@bagelink/vue 1.6.4 → 1.6.9
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/dist/components/Swiper.vue.d.ts +2405 -0
- package/dist/components/Swiper.vue.d.ts.map +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/index.cjs +8 -8
- package/dist/index.mjs +7682 -4155
- package/dist/style.css +1 -1
- package/package.json +2 -1
- package/src/components/Carousel.vue +43 -43
- package/src/components/Swiper.vue +511 -0
- package/src/components/index.ts +1 -0
- package/src/styles/layout.css +57 -1
- package/src/styles/mobilLayout.css +59 -1
- package/src/styles/text.css +45 -0
- package/vite.config.ts +1 -1
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
<script setup lang="ts" generic="T = any">
|
|
2
|
+
import type { Swiper as SwiperType } from 'swiper'
|
|
3
|
+
import type { AutoplayOptions, CoverflowEffectOptions, PaginationOptions, SwiperOptions } from 'swiper/types'
|
|
4
|
+
import { Icon } from '@bagelink/vue'
|
|
5
|
+
import { Autoplay, EffectCoverflow, EffectCube, EffectFade, EffectFlip, Navigation, Pagination } from 'swiper/modules'
|
|
6
|
+
import { Swiper, SwiperSlide } from 'swiper/vue'
|
|
7
|
+
import { computed, ref, watch } from 'vue'
|
|
8
|
+
import 'swiper/css'
|
|
9
|
+
import 'swiper/css/navigation'
|
|
10
|
+
import 'swiper/css/pagination'
|
|
11
|
+
import 'swiper/css/effect-fade'
|
|
12
|
+
import 'swiper/css/effect-coverflow'
|
|
13
|
+
import 'swiper/css/effect-cube'
|
|
14
|
+
import 'swiper/css/effect-flip'
|
|
15
|
+
|
|
16
|
+
type SwiperEffect = 'slide' | 'fade' | 'cube' | 'coverflow' | 'flip'
|
|
17
|
+
type SwiperDirection = 'horizontal' | 'vertical'
|
|
18
|
+
type SwiperVariant = 'default' | 'testimonial' | 'gallery' | 'cards' | 'coverflow' | 'hero'
|
|
19
|
+
|
|
20
|
+
interface VariantConfig {
|
|
21
|
+
slidesPerView?: number | 'auto'
|
|
22
|
+
spaceBetween?: number
|
|
23
|
+
effect?: SwiperEffect
|
|
24
|
+
loop?: boolean
|
|
25
|
+
autoplay?: boolean | AutoplayOptions
|
|
26
|
+
pagination?: boolean | PaginationOptions
|
|
27
|
+
navigation?: boolean
|
|
28
|
+
speed?: number
|
|
29
|
+
centeredSlides?: boolean
|
|
30
|
+
coverflowEffect?: Partial<CoverflowEffectOptions>
|
|
31
|
+
breakpoints?: SwiperOptions['breakpoints']
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const props = withDefaults(
|
|
35
|
+
defineProps<{
|
|
36
|
+
// Items to render
|
|
37
|
+
items?: T[]
|
|
38
|
+
|
|
39
|
+
// Active index (v-model support)
|
|
40
|
+
index?: number
|
|
41
|
+
|
|
42
|
+
// Preset variant
|
|
43
|
+
variant?: SwiperVariant
|
|
44
|
+
|
|
45
|
+
// Slide dimensions
|
|
46
|
+
slideWidth?: number | string
|
|
47
|
+
|
|
48
|
+
// Basic swiper options
|
|
49
|
+
effect?: SwiperEffect
|
|
50
|
+
direction?: SwiperDirection
|
|
51
|
+
speed?: number
|
|
52
|
+
loop?: boolean
|
|
53
|
+
initialSlide?: number
|
|
54
|
+
|
|
55
|
+
// Slides display
|
|
56
|
+
slidesPerView?: number | 'auto'
|
|
57
|
+
spaceBetween?: number
|
|
58
|
+
centeredSlides?: boolean
|
|
59
|
+
|
|
60
|
+
// Interaction
|
|
61
|
+
grabCursor?: boolean
|
|
62
|
+
keyboard?: boolean
|
|
63
|
+
mousewheel?: boolean
|
|
64
|
+
|
|
65
|
+
// Auto height
|
|
66
|
+
autoHeight?: boolean
|
|
67
|
+
|
|
68
|
+
// Navigation
|
|
69
|
+
navigation?: boolean
|
|
70
|
+
|
|
71
|
+
// Pagination
|
|
72
|
+
pagination?: boolean | PaginationOptions
|
|
73
|
+
|
|
74
|
+
// Autoplay
|
|
75
|
+
autoplay?: boolean | AutoplayOptions
|
|
76
|
+
|
|
77
|
+
// Effect-specific options
|
|
78
|
+
coverflowEffect?: Partial<CoverflowEffectOptions>
|
|
79
|
+
|
|
80
|
+
// Responsive breakpoints
|
|
81
|
+
breakpoints?: SwiperOptions['breakpoints']
|
|
82
|
+
|
|
83
|
+
// Advanced: allow override with raw options
|
|
84
|
+
advancedOptions?: SwiperOptions
|
|
85
|
+
}>(),
|
|
86
|
+
{
|
|
87
|
+
items: undefined,
|
|
88
|
+
index: undefined,
|
|
89
|
+
variant: 'default',
|
|
90
|
+
slideWidth: undefined,
|
|
91
|
+
effect: undefined,
|
|
92
|
+
direction: 'horizontal',
|
|
93
|
+
speed: undefined,
|
|
94
|
+
loop: undefined,
|
|
95
|
+
initialSlide: 0,
|
|
96
|
+
slidesPerView: undefined,
|
|
97
|
+
spaceBetween: undefined,
|
|
98
|
+
centeredSlides: undefined,
|
|
99
|
+
grabCursor: true,
|
|
100
|
+
keyboard: true,
|
|
101
|
+
mousewheel: false,
|
|
102
|
+
autoHeight: false,
|
|
103
|
+
navigation: undefined,
|
|
104
|
+
pagination: undefined,
|
|
105
|
+
autoplay: undefined,
|
|
106
|
+
coverflowEffect: undefined,
|
|
107
|
+
breakpoints: undefined,
|
|
108
|
+
advancedOptions: undefined,
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
const emit = defineEmits<{
|
|
113
|
+
'update:index': [index: number]
|
|
114
|
+
}>()
|
|
115
|
+
|
|
116
|
+
defineSlots<{
|
|
117
|
+
'default'?: (props: { item: T, index: number, currentIndex: number }) => any
|
|
118
|
+
'prev-button'?: () => any
|
|
119
|
+
'next-button'?: () => any
|
|
120
|
+
'navigation'?: (props: {
|
|
121
|
+
items: T[]
|
|
122
|
+
currentIndex: number
|
|
123
|
+
slideTo: (index: number) => void
|
|
124
|
+
prev: () => void
|
|
125
|
+
next: () => void
|
|
126
|
+
isFirst: boolean
|
|
127
|
+
isLast: boolean
|
|
128
|
+
}) => any
|
|
129
|
+
'pagination'?: () => any
|
|
130
|
+
}>()
|
|
131
|
+
|
|
132
|
+
const variantPresets: Record<SwiperVariant, VariantConfig> = {
|
|
133
|
+
default: {},
|
|
134
|
+
testimonial: {
|
|
135
|
+
slidesPerView: 1,
|
|
136
|
+
autoplay: { delay: 5000, disableOnInteraction: false },
|
|
137
|
+
pagination: { clickable: true },
|
|
138
|
+
loop: true,
|
|
139
|
+
speed: 600,
|
|
140
|
+
},
|
|
141
|
+
gallery: {
|
|
142
|
+
slidesPerView: 1,
|
|
143
|
+
spaceBetween: 0,
|
|
144
|
+
navigation: true,
|
|
145
|
+
loop: true,
|
|
146
|
+
},
|
|
147
|
+
cards: {
|
|
148
|
+
slidesPerView: 3,
|
|
149
|
+
spaceBetween: 20,
|
|
150
|
+
navigation: true,
|
|
151
|
+
breakpoints: {
|
|
152
|
+
320: { slidesPerView: 1, spaceBetween: 10 },
|
|
153
|
+
768: { slidesPerView: 2, spaceBetween: 15 },
|
|
154
|
+
1024: { slidesPerView: 3, spaceBetween: 20 },
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
coverflow: {
|
|
158
|
+
effect: 'coverflow',
|
|
159
|
+
slidesPerView: 'auto',
|
|
160
|
+
centeredSlides: true,
|
|
161
|
+
loop: true,
|
|
162
|
+
navigation: true,
|
|
163
|
+
coverflowEffect: {
|
|
164
|
+
rotate: -2,
|
|
165
|
+
stretch: 0,
|
|
166
|
+
depth: 100,
|
|
167
|
+
slideShadows: true,
|
|
168
|
+
modifier: 1,
|
|
169
|
+
scale: 0.98,
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
hero: {
|
|
173
|
+
slidesPerView: 1,
|
|
174
|
+
autoplay: { delay: 4000 },
|
|
175
|
+
pagination: { clickable: true },
|
|
176
|
+
loop: true,
|
|
177
|
+
speed: 800,
|
|
178
|
+
effect: 'fade',
|
|
179
|
+
},
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const swiperEl = ref<SwiperType | null>(null)
|
|
183
|
+
const isFirstSlide = ref(true)
|
|
184
|
+
const isLastSlide = ref(false)
|
|
185
|
+
const currentIndex = ref(props.index ?? props.initialSlide ?? 0)
|
|
186
|
+
let isUpdatingFromExternal = false // Guard to prevent update loops
|
|
187
|
+
|
|
188
|
+
const slideStyles = computed(() => {
|
|
189
|
+
const styles: Record<string, string> = {}
|
|
190
|
+
|
|
191
|
+
if (props.slideWidth !== undefined) {
|
|
192
|
+
styles.width = typeof props.slideWidth === 'number' ? `${props.slideWidth}px` : props.slideWidth
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return styles
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
// Apply variant preset configuration
|
|
199
|
+
const variantConfig = computed(() => variantPresets[props.variant])
|
|
200
|
+
|
|
201
|
+
// Smart default: if slideWidth is set and slidesPerView wasn't set,
|
|
202
|
+
// automatically use 'auto' to let slides determine their own width
|
|
203
|
+
const effectiveSlidesPerView = computed(() => {
|
|
204
|
+
// Priority: explicit prop > variant config > smart default
|
|
205
|
+
if (props.slidesPerView !== undefined) {
|
|
206
|
+
return props.slidesPerView
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (variantConfig.value.slidesPerView !== undefined) {
|
|
210
|
+
return variantConfig.value.slidesPerView
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Smart default: if slideWidth is provided, use 'auto'
|
|
214
|
+
if (props.slideWidth !== undefined) {
|
|
215
|
+
return 'auto'
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Final fallback
|
|
219
|
+
return 1
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
const swiperParams = computed((): SwiperOptions => {
|
|
223
|
+
// Helper to get value with priority: prop > variant > default
|
|
224
|
+
const getValue = <K extends keyof VariantConfig>(
|
|
225
|
+
propValue: any,
|
|
226
|
+
variantKey: K,
|
|
227
|
+
defaultValue: any
|
|
228
|
+
) => {
|
|
229
|
+
if (propValue !== undefined) return propValue
|
|
230
|
+
if (variantConfig.value[variantKey] !== undefined) return variantConfig.value[variantKey]
|
|
231
|
+
return defaultValue
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const params: SwiperOptions = {
|
|
235
|
+
modules: [Navigation, Pagination, Autoplay, EffectFade, EffectCoverflow, EffectCube, EffectFlip],
|
|
236
|
+
effect: getValue(props.effect, 'effect', 'slide'),
|
|
237
|
+
direction: props.direction ?? 'horizontal',
|
|
238
|
+
speed: getValue(props.speed, 'speed', 300),
|
|
239
|
+
loop: getValue(props.loop, 'loop', false),
|
|
240
|
+
initialSlide: props.index ?? props.initialSlide,
|
|
241
|
+
slidesPerView: effectiveSlidesPerView.value,
|
|
242
|
+
spaceBetween: getValue(props.spaceBetween, 'spaceBetween', 0),
|
|
243
|
+
centeredSlides: getValue(props.centeredSlides, 'centeredSlides', false),
|
|
244
|
+
grabCursor: props.grabCursor,
|
|
245
|
+
keyboard: props.keyboard,
|
|
246
|
+
mousewheel: props.mousewheel,
|
|
247
|
+
autoHeight: props.autoHeight,
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Navigation (priority: prop > variant > default)
|
|
251
|
+
const navigationEnabled = getValue(props.navigation, 'navigation', false)
|
|
252
|
+
params.navigation = !!navigationEnabled
|
|
253
|
+
|
|
254
|
+
// Pagination (priority: prop > variant > default)
|
|
255
|
+
const paginationConfig = getValue(props.pagination, 'pagination', false)
|
|
256
|
+
params.pagination = paginationConfig
|
|
257
|
+
? (typeof paginationConfig === 'boolean' ? { clickable: true } : paginationConfig)
|
|
258
|
+
: false
|
|
259
|
+
|
|
260
|
+
// Autoplay (priority: prop > variant > default)
|
|
261
|
+
const autoplayConfig = getValue(props.autoplay, 'autoplay', false)
|
|
262
|
+
params.autoplay = autoplayConfig
|
|
263
|
+
? (typeof autoplayConfig === 'boolean' ? { delay: 3000 } : autoplayConfig)
|
|
264
|
+
: false
|
|
265
|
+
|
|
266
|
+
// Effect-specific options (merge variant and explicit)
|
|
267
|
+
const effectType = params.effect || 'slide'
|
|
268
|
+
if (effectType === 'coverflow') {
|
|
269
|
+
const baseCoverflowEffect = {
|
|
270
|
+
rotate: 0,
|
|
271
|
+
stretch: 0,
|
|
272
|
+
depth: 100,
|
|
273
|
+
modifier: 1,
|
|
274
|
+
slideShadows: true,
|
|
275
|
+
}
|
|
276
|
+
params.coverflowEffect = {
|
|
277
|
+
...baseCoverflowEffect,
|
|
278
|
+
...variantConfig.value.coverflowEffect,
|
|
279
|
+
...props.coverflowEffect,
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Breakpoints (priority: prop > variant)
|
|
284
|
+
const breakpointsConfig = getValue(props.breakpoints, 'breakpoints', undefined)
|
|
285
|
+
if (breakpointsConfig) {
|
|
286
|
+
params.breakpoints = breakpointsConfig
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Advanced options override
|
|
290
|
+
if (props.advancedOptions) {
|
|
291
|
+
return { ...params, ...props.advancedOptions }
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return params
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
// Format params for Swiper Vue component with proper types
|
|
298
|
+
const swiperVueProps = computed(() => ({
|
|
299
|
+
modules: swiperParams.value.modules,
|
|
300
|
+
effect: swiperParams.value.effect as 'slide' | 'fade' | 'cube' | 'coverflow' | 'flip',
|
|
301
|
+
direction: swiperParams.value.direction,
|
|
302
|
+
speed: swiperParams.value.speed,
|
|
303
|
+
loop: swiperParams.value.loop,
|
|
304
|
+
initialSlide: swiperParams.value.initialSlide,
|
|
305
|
+
slidesPerView: swiperParams.value.slidesPerView,
|
|
306
|
+
spaceBetween: swiperParams.value.spaceBetween as number,
|
|
307
|
+
centeredSlides: swiperParams.value.centeredSlides,
|
|
308
|
+
grabCursor: swiperParams.value.grabCursor,
|
|
309
|
+
keyboard: swiperParams.value.keyboard as boolean | undefined,
|
|
310
|
+
mousewheel: swiperParams.value.mousewheel as boolean | undefined,
|
|
311
|
+
autoHeight: swiperParams.value.autoHeight,
|
|
312
|
+
navigation: swiperParams.value.navigation as boolean | undefined,
|
|
313
|
+
pagination: swiperParams.value.pagination,
|
|
314
|
+
autoplay: swiperParams.value.autoplay,
|
|
315
|
+
coverflowEffect: swiperParams.value.coverflowEffect,
|
|
316
|
+
breakpoints: swiperParams.value.breakpoints,
|
|
317
|
+
}))
|
|
318
|
+
|
|
319
|
+
const swiperInstance = computed(() => swiperEl.value)
|
|
320
|
+
|
|
321
|
+
function updateNavigationState() {
|
|
322
|
+
if (swiperEl.value && !isUpdatingFromExternal) {
|
|
323
|
+
isFirstSlide.value = swiperEl.value.isBeginning
|
|
324
|
+
isLastSlide.value = swiperEl.value.isEnd
|
|
325
|
+
|
|
326
|
+
// Emit index update for v-model support
|
|
327
|
+
// Use activeIndex for non-loop mode, realIndex for loop mode
|
|
328
|
+
const newIndex = props.loop ? swiperEl.value.realIndex : swiperEl.value.activeIndex
|
|
329
|
+
currentIndex.value = newIndex
|
|
330
|
+
|
|
331
|
+
// Emit to keep external state in sync
|
|
332
|
+
emit('update:index', newIndex)
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function slideTo(index: number) {
|
|
337
|
+
if (!swiperEl.value) return
|
|
338
|
+
swiperEl.value.slideTo(index)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function handleSlideNav(dir: 'prev' | 'next') {
|
|
342
|
+
if (!swiperEl.value) return
|
|
343
|
+
|
|
344
|
+
if (dir === 'next') {
|
|
345
|
+
swiperEl.value.slideNext()
|
|
346
|
+
} else {
|
|
347
|
+
swiperEl.value.slidePrev()
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function onSwiper(swiper: SwiperType) {
|
|
352
|
+
swiperEl.value = swiper
|
|
353
|
+
updateNavigationState()
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
watch(
|
|
357
|
+
() => props.initialSlide,
|
|
358
|
+
(index) => {
|
|
359
|
+
if (index !== undefined && swiperEl.value) {
|
|
360
|
+
setTimeout(() => {
|
|
361
|
+
if (swiperEl.value) swiperEl.value.slideTo(index)
|
|
362
|
+
}, 1)
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
{ immediate: true },
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
// Watch for external index changes (v-model support)
|
|
369
|
+
watch(
|
|
370
|
+
() => props.index,
|
|
371
|
+
(newIndex) => {
|
|
372
|
+
if (newIndex !== undefined) {
|
|
373
|
+
currentIndex.value = newIndex
|
|
374
|
+
|
|
375
|
+
if (swiperEl.value) {
|
|
376
|
+
const activeIndex = props.loop ? swiperEl.value.realIndex : swiperEl.value.activeIndex
|
|
377
|
+
if (newIndex !== activeIndex) {
|
|
378
|
+
isUpdatingFromExternal = true
|
|
379
|
+
swiperEl.value.slideTo(newIndex)
|
|
380
|
+
// Reset guard after a short delay to allow transition
|
|
381
|
+
setTimeout(() => {
|
|
382
|
+
isUpdatingFromExternal = false
|
|
383
|
+
}, 50)
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
// Watch for param changes and update swiper
|
|
391
|
+
watch(
|
|
392
|
+
swiperParams,
|
|
393
|
+
(newParams) => {
|
|
394
|
+
if (swiperEl.value) {
|
|
395
|
+
Object.assign(swiperEl.value.params, newParams)
|
|
396
|
+
swiperEl.value.update()
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
{ deep: true },
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
defineExpose({
|
|
403
|
+
swiper: swiperInstance,
|
|
404
|
+
slideNext: () => { handleSlideNav('next') },
|
|
405
|
+
slidePrev: () => { handleSlideNav('prev') },
|
|
406
|
+
slideTo,
|
|
407
|
+
update: () => swiperEl.value?.update(),
|
|
408
|
+
isFirst: isFirstSlide,
|
|
409
|
+
isLast: isLastSlide,
|
|
410
|
+
currentIndex,
|
|
411
|
+
})
|
|
412
|
+
</script>
|
|
413
|
+
|
|
414
|
+
<template>
|
|
415
|
+
<div class="swi-wrap">
|
|
416
|
+
<Swiper
|
|
417
|
+
v-bind="swiperVueProps" class="swiper" @swiper="onSwiper" @slide-change="updateNavigationState"
|
|
418
|
+
@reach-beginning="updateNavigationState" @reach-end="updateNavigationState"
|
|
419
|
+
@from-edge="updateNavigationState"
|
|
420
|
+
>
|
|
421
|
+
<SwiperSlide v-for="(item, idx) in items" :key="idx" :style="slideStyles">
|
|
422
|
+
<slot :item="item" :index="idx" :currentIndex="currentIndex" />
|
|
423
|
+
</SwiperSlide>
|
|
424
|
+
</Swiper>
|
|
425
|
+
|
|
426
|
+
<!-- Custom Navigation Slot -->
|
|
427
|
+
<slot
|
|
428
|
+
name="navigation" :items="items || []" :currentIndex="currentIndex" :slide-to="slideTo"
|
|
429
|
+
:prev="() => handleSlideNav('prev')" :next="() => handleSlideNav('next')" :is-first="isFirstSlide"
|
|
430
|
+
:is-last="isLastSlide"
|
|
431
|
+
>
|
|
432
|
+
<!-- Default Navigation -->
|
|
433
|
+
<div v-if="navigation" class="swi-ctrl">
|
|
434
|
+
<div class="swi-prev hover" @click="handleSlideNav('prev')">
|
|
435
|
+
<slot name="prev-button">
|
|
436
|
+
<Icon name="chevron_left" />
|
|
437
|
+
</slot>
|
|
438
|
+
</div>
|
|
439
|
+
<div class="swi-next hover" @click="handleSlideNav('next')">
|
|
440
|
+
<slot name="next-button">
|
|
441
|
+
<Icon name="chevron_right" />
|
|
442
|
+
</slot>
|
|
443
|
+
</div>
|
|
444
|
+
</div>
|
|
445
|
+
</slot>
|
|
446
|
+
|
|
447
|
+
<!-- Custom Pagination Slot -->
|
|
448
|
+
<slot v-if="pagination" name="pagination" />
|
|
449
|
+
</div>
|
|
450
|
+
</template>
|
|
451
|
+
|
|
452
|
+
<style>
|
|
453
|
+
.swiper {
|
|
454
|
+
width: 100%;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
:root {
|
|
458
|
+
--swiper-navigation-color: white;
|
|
459
|
+
--swiper-pagination-color: white;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.swi-ctrl {
|
|
463
|
+
position: absolute;
|
|
464
|
+
top: 50%;
|
|
465
|
+
transform: translateY(-50%);
|
|
466
|
+
width: 100%;
|
|
467
|
+
z-index: 99;
|
|
468
|
+
display: flex;
|
|
469
|
+
justify-content: space-between;
|
|
470
|
+
padding: 0rem 4rem;
|
|
471
|
+
height: 0;
|
|
472
|
+
pointer-events: none;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
.swi-ctrl>* {
|
|
476
|
+
pointer-events: auto;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.swi-ctrl img {
|
|
480
|
+
height: 20px;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
.swi-wrap {
|
|
484
|
+
position: relative;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
.swi-prev,
|
|
488
|
+
.swi-next {
|
|
489
|
+
background: var(--blue);
|
|
490
|
+
height: 40px;
|
|
491
|
+
width: 40px;
|
|
492
|
+
border-radius: 100%;
|
|
493
|
+
padding: 10px;
|
|
494
|
+
display: flex;
|
|
495
|
+
justify-content: center;
|
|
496
|
+
align-items: center;
|
|
497
|
+
cursor: pointer;
|
|
498
|
+
transition: opacity 0.3s ease;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
.swi-prev:hover,
|
|
502
|
+
.swi-next:hover {
|
|
503
|
+
opacity: 0.8;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
@media screen and (max-width: 900px) {
|
|
507
|
+
.swi-ctrl {
|
|
508
|
+
padding: 0rem 0.5rem;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
</style>
|
package/src/components/index.ts
CHANGED
|
@@ -41,6 +41,7 @@ export { default as Rating } from './Rating.vue'
|
|
|
41
41
|
export { default as RouterWrapper } from './RouterWrapper.vue'
|
|
42
42
|
export { default as Slider } from './Slider.vue'
|
|
43
43
|
export { default as Spreadsheet } from './Spreadsheet/Index.vue'
|
|
44
|
+
export { default as Swiper } from './Swiper.vue'
|
|
44
45
|
export { default as Title } from './Title.vue'
|
|
45
46
|
export { default as ToolBar } from './ToolBar.vue'
|
|
46
47
|
export { default as TopBar } from './TopBar.vue'
|
package/src/styles/layout.css
CHANGED
|
@@ -55,10 +55,66 @@
|
|
|
55
55
|
border-radius: 100%;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
.aspect-ratio-1
|
|
58
|
+
.aspect-ratio-1,
|
|
59
|
+
.ratio-1 {
|
|
59
60
|
aspect-ratio: 1;
|
|
60
61
|
}
|
|
61
62
|
|
|
63
|
+
.aspect-ratio-4-3,
|
|
64
|
+
.ratio-4-3 {
|
|
65
|
+
aspect-ratio: 4 / 3;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.aspect-ratio-3-4,
|
|
69
|
+
.ratio-3-4 {
|
|
70
|
+
aspect-ratio: 3 / 4;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.aspect-ratio-16-9,
|
|
74
|
+
.ratio-16-9 {
|
|
75
|
+
aspect-ratio: 16 / 9;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.aspect-ratio-9-16,
|
|
79
|
+
.ratio-9-16 {
|
|
80
|
+
aspect-ratio: 9 / 16;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.aspect-ratio-3-2,
|
|
84
|
+
.ratio-3-2 {
|
|
85
|
+
aspect-ratio: 3 / 2;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.aspect-ratio-2-3,
|
|
89
|
+
.ratio-2-3 {
|
|
90
|
+
aspect-ratio: 2 / 3;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.aspect-ratio-5-4,
|
|
94
|
+
.ratio-5-4 {
|
|
95
|
+
aspect-ratio: 5 / 4;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.aspect-ratio-4-5,
|
|
99
|
+
.ratio-4-5 {
|
|
100
|
+
aspect-ratio: 4 / 5;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.aspect-ratio-2-1,
|
|
104
|
+
.ratio-2-1 {
|
|
105
|
+
aspect-ratio: 2 / 1;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.aspect-ratio-1-2,
|
|
109
|
+
.ratio-1-2 {
|
|
110
|
+
aspect-ratio: 1 / 2;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.aspect-ratio-21-9,
|
|
114
|
+
.ratio-21-9 {
|
|
115
|
+
aspect-ratio: 21 / 9;
|
|
116
|
+
}
|
|
117
|
+
|
|
62
118
|
.vertical-align-middle,
|
|
63
119
|
.vertical-middle {
|
|
64
120
|
vertical-align: middle;
|
|
@@ -91,10 +91,68 @@
|
|
|
91
91
|
border-radius: 100%;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
|
|
95
|
+
.m_aspect-ratio-1,
|
|
96
|
+
.m_ratio-1 {
|
|
95
97
|
aspect-ratio: 1;
|
|
96
98
|
}
|
|
97
99
|
|
|
100
|
+
.m_aspect-ratio-4-3,
|
|
101
|
+
.m_ratio-4-3 {
|
|
102
|
+
aspect-ratio: 4 / 3;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.m_aspect-ratio-3-4,
|
|
106
|
+
.m_ratio-3-4 {
|
|
107
|
+
aspect-ratio: 3 / 4;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.m_aspect-ratio-16-9,
|
|
111
|
+
.m_ratio-16-9 {
|
|
112
|
+
aspect-ratio: 16 / 9;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.m_aspect-ratio-9-16,
|
|
116
|
+
.m_ratio-9-16 {
|
|
117
|
+
aspect-ratio: 9 / 16;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.m_aspect-ratio-3-2,
|
|
121
|
+
.m_ratio-3-2 {
|
|
122
|
+
aspect-ratio: 3 / 2;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.m_aspect-ratio-2-3,
|
|
126
|
+
.m_ratio-2-3 {
|
|
127
|
+
aspect-ratio: 2 / 3;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.m_aspect-ratio-5-4,
|
|
131
|
+
.m_ratio-5-4 {
|
|
132
|
+
aspect-ratio: 5 / 4;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.m_aspect-ratio-4-5,
|
|
136
|
+
.m_ratio-4-5 {
|
|
137
|
+
aspect-ratio: 4 / 5;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.m_aspect-ratio-2-1,
|
|
141
|
+
.m_ratio-2-1 {
|
|
142
|
+
aspect-ratio: 2 / 1;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.m_aspect-ratio-1-2,
|
|
146
|
+
.m_ratio-1-2 {
|
|
147
|
+
aspect-ratio: 1 / 2;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.m_aspect-ratio-21-9,
|
|
151
|
+
.m_ratio-21-9 {
|
|
152
|
+
aspect-ratio: 21 / 9;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
98
156
|
.m_vertical-align-middle,
|
|
99
157
|
.m_vertical-middle {
|
|
100
158
|
vertical-align: middle;
|