-
-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathSplide.svelte
More file actions
154 lines (134 loc) · 4.12 KB
/
Splide.svelte
File metadata and controls
154 lines (134 loc) · 4.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<script lang="ts">
import type { ArrowsEventDetail, EventDetail, MoveEventDetail, SlideEventDetail } from '$lib/types';
import { classNames, getSlides, isEqualDeep, isEqualShallow, merge } from '$lib/utils';
import type { ComponentConstructor, Options, PaginationData, PaginationItem, SlideComponent } from '@splidejs/splide';
import { Splide } from '@splidejs/splide';
import { afterUpdate, createEventDispatcher, onMount } from 'svelte';
import { bind } from './bind';
import { SplideTrack } from '$lib/components';
/**
* The class name for the root element.
*/
let className: string | undefined = undefined;
export { className as class };
/**
* Splide options. Do not change readonly options after mount.
*/
export let options: Options = {};
/**
* The splide instance.
*/
export let splide: Splide | undefined = undefined;
/**
* An object with extensions.
*/
export let extensions: Record<string, ComponentConstructor> | undefined = undefined;
/**
* A transition component.
*/
export let transition: ComponentConstructor | undefined = undefined;
/**
* Determines whether to render a track element or not.
*/
export let hasTrack = true;
/**
* A dispatcher function.
* The `createEventDispatcher` type assertion does not accept a type alias.
* If specified, the svelte kit fails to generate a type of `events` and it will be `CustomEvent<any>`.
* Also, the svelte action does not provide the way to specify event types.
*/
const dispatch = createEventDispatcher<{
mounted: EventDetail;
destroy: EventDetail;
active: SlideEventDetail;
arrowsMounted?: ArrowsEventDetail;
arrowsUpdated?: ArrowsEventDetail;
autoplayPause?: EventDetail;
autoplayPlay?: EventDetail;
autoplayPlaying?: EventDetail<{ rate: number }>;
click?: SlideEventDetail;
drag?: EventDetail;
dragged?: EventDetail;
dragging?: EventDetail;
hidden?: SlideEventDetail;
inactive?: SlideEventDetail;
lazyloadLoaded?: EventDetail<{ img: HTMLImageElement, Slide: SlideComponent }>;
move?: MoveEventDetail;
moved?: MoveEventDetail;
navigationMounted?: EventDetail<{ splides: Splide[] }>;
paginationMounted?: EventDetail<{ data: PaginationData, item: PaginationItem }>;
paginationUpdated?: EventDetail<{ data: PaginationData, prev: PaginationItem, curr: PaginationItem }>;
refresh?: EventDetail;
resize?: EventDetail;
resized?: EventDetail;
scroll?: EventDetail;
scrolled?: EventDetail;
updated?: EventDetail<{ options: Options }>;
visible?: SlideEventDetail;
}>();
/**
* The root element.
*/
let root: HTMLElement;
/**
* Holds the previous slide elements.
*/
let prevSlides: HTMLElement[];
/**
* Holds the previous options.
*/
let prevOptions = merge( {}, options );
/**
* Updates splide options only when they have difference with previous options.
*/
$: if ( splide && ! isEqualDeep( prevOptions, options ) ) {
splide.options = options;
prevOptions = merge( {}, prevOptions );
}
onMount( () => {
splide = new Splide( root, options );
bind<typeof dispatch>( splide, dispatch );
splide.mount( extensions, transition );
prevSlides = getSlides( splide );
return () => splide.destroy();
} );
afterUpdate( () => {
if ( splide ) {
const newSlides = getSlides( splide );
if ( ! isEqualShallow( prevSlides, newSlides ) ) {
splide.refresh();
prevSlides = newSlides.slice();
}
}
} );
/**
* Moves the slider by the specified control.
*
* @param control - A control pattern.
*/
export function go( control: number | string ): void {
splide?.go( control );
}
/**
* Syncs the slider with another Splide.
*
* @param target - A target splide instance to sync with.
*/
export function sync( target: Splide ): void {
splide?.sync( target );
}
</script>
<svelte:options accessors/>
<div
class={ classNames( 'splide', className ) }
bind:this={ root }
{ ...$$restProps }
>
{ #if hasTrack }
<SplideTrack>
<slot/>
</SplideTrack>
{ :else }
<slot/>
{ /if }
</div>