@@ -3,11 +3,13 @@ import { EventStore } from './EventStore'
3
3
import { WatchHandler , WatchHandlerType } from './WatchHandler'
4
4
import { EventHandler , EventHandlerType } from './EventHandler'
5
5
import { defaultOptions , EmblaOptionsType , OptionsType } from './Options'
6
+ import { NodeHandler , NodeHandlerType } from './NodeHandler'
6
7
import { OptionsHandler } from './OptionsHandler'
7
8
import { PluginsHandler } from './PluginsHandler'
8
9
import { EmblaPluginsType , EmblaPluginType } from './Plugins'
9
- import { isNumber , isString , WindowType } from './utils'
10
10
import { ScrollToDirectionType } from './ScrollTo'
11
+ import { isNumber } from './utils'
12
+ import { SsrHandler , SsrHandlerType } from './SsrHandler'
11
13
12
14
export type EmblaCarouselType = {
13
15
canScrollNext : ( ) => boolean
@@ -43,16 +45,17 @@ export type EmblaCarouselType = {
43
45
jump ?: boolean ,
44
46
direction ?: ScrollToDirectionType
45
47
) => void
48
+ ssrStyles : ( ) => string
46
49
}
47
50
48
51
function EmblaCarousel (
49
52
root : HTMLElement ,
50
53
userOptions ?: EmblaOptionsType ,
51
- userPlugins ?: EmblaPluginType [ ]
54
+ userPlugins ?: EmblaPluginType [ ] ,
55
+ headless ?: boolean
52
56
) : EmblaCarouselType {
53
- const ownerDocument = root . ownerDocument
54
- const ownerWindow = < WindowType > ownerDocument . defaultView
55
- const optionsHandler = OptionsHandler ( ownerWindow )
57
+ const isSsr = ! ! headless
58
+ const optionsHandler = OptionsHandler ( )
56
59
const pluginsHandler = PluginsHandler ( optionsHandler )
57
60
const mediaHandlers = EventStore ( )
58
61
const watchHandler = WatchHandler ( )
@@ -64,43 +67,33 @@ function EmblaCarousel(
64
67
65
68
let destroyed = false
66
69
let engine : EngineType
70
+ let nodeHandler : NodeHandlerType
71
+ let ssrHandler : SsrHandlerType
67
72
let optionsBase = mergeOptions ( defaultOptions , EmblaCarousel . globalOptions )
68
73
let options = mergeOptions ( optionsBase )
69
74
let pluginList : EmblaPluginType [ ] = [ ]
70
75
let pluginApis : EmblaPluginsType
71
-
72
76
let container : HTMLElement
73
77
let slides : HTMLElement [ ]
74
78
75
- function storeElements ( ) : void {
76
- const { container : userContainer , slides : userSlides } = options
77
-
78
- const customContainer = isString ( userContainer )
79
- ? root . querySelector ( userContainer )
80
- : userContainer
81
- container = < HTMLElement > ( customContainer || root . children [ 0 ] )
82
-
83
- const customSlides = isString ( userSlides )
84
- ? container . querySelectorAll ( userSlides )
85
- : userSlides
86
- slides = < HTMLElement [ ] > [ ] . slice . call ( customSlides || container . children )
87
- }
88
-
89
- function createEngine ( options : OptionsType ) : EngineType {
79
+ function createEngine (
80
+ options : OptionsType ,
81
+ container : HTMLElement ,
82
+ slides : HTMLElement [ ]
83
+ ) : EngineType {
90
84
const engine = Engine (
91
85
root ,
92
86
container ,
93
87
slides ,
94
- ownerDocument ,
95
- ownerWindow ,
96
88
options ,
89
+ nodeHandler ,
97
90
eventHandler ,
98
91
watchHandler
99
92
)
100
93
101
94
if ( options . loop && ! engine . slideLooper . canLoop ( ) ) {
102
95
const optionsWithoutLoop = Object . assign ( { } , options , { loop : false } )
103
- return createEngine ( optionsWithoutLoop )
96
+ return createEngine ( optionsWithoutLoop , container , slides )
104
97
}
105
98
return engine
106
99
}
@@ -111,32 +104,51 @@ function EmblaCarousel(
111
104
) : void {
112
105
if ( destroyed ) return
113
106
107
+ nodeHandler = NodeHandler ( root , isSsr )
108
+ const { ownerWindow } = nodeHandler
109
+
110
+ optionsHandler . init ( ownerWindow )
114
111
optionsBase = mergeOptions ( optionsBase , withOptions )
115
112
options = optionsAtMedia ( optionsBase )
116
113
pluginList = withPlugins || pluginList
117
114
118
- storeElements ( )
115
+ const nodes = nodeHandler . getNodes ( options )
116
+ container = nodes . container
117
+ slides = nodes . slides
118
+ engine = createEngine ( options , container , slides )
119
119
120
- engine = createEngine ( options )
120
+ ssrHandler = SsrHandler (
121
+ isSsr ,
122
+ container ,
123
+ engine . axis ,
124
+ nodeHandler ,
125
+ optionsBase ,
126
+ mergeOptions ,
127
+ createEngine
128
+ )
121
129
122
130
optionsMediaQueries ( [
123
131
optionsBase ,
124
132
...pluginList . map ( ( { options } ) => options )
125
133
] ) . forEach ( ( query ) => mediaHandlers . add ( query , 'change' , reActivate ) )
126
134
127
135
if ( ! options . active ) return
136
+ if ( ! ownerWindow ) return
137
+ if ( isSsr ) return
128
138
129
139
engine . translate . to ( engine . location . get ( ) )
130
- engine . animation . init ( )
131
- engine . slidesInView . init ( )
132
- engine . slideFocus . init ( )
133
- engine . resizeHandler . init ( )
134
- engine . slidesHandler . init ( )
140
+ engine . animation . init ( ownerWindow )
141
+ engine . resizeHandler . init ( ownerWindow )
142
+ engine . slidesInView . init ( ownerWindow )
143
+ engine . slidesHandler . init ( ownerWindow )
135
144
engine . eventHandler . init ( self )
136
145
engine . watchHandler . init ( self )
146
+ engine . slideFocus . init ( )
137
147
138
148
if ( engine . options . loop ) engine . slideLooper . loop ( )
139
- if ( container . offsetParent && slides . length ) engine . dragHandler . init ( )
149
+ if ( container . offsetParent && slides . length ) {
150
+ engine . dragHandler . init ( ownerWindow )
151
+ }
140
152
141
153
pluginApis = pluginsHandler . init ( self , pluginList )
142
154
}
@@ -180,6 +192,7 @@ function EmblaCarousel(
180
192
direction ?: ScrollToDirectionType
181
193
) : void {
182
194
if ( ! options . active || destroyed ) return
195
+
183
196
engine . scrollBody
184
197
. useBaseFriction ( )
185
198
. useDuration ( jump === true ? 0 : options . duration )
@@ -245,6 +258,10 @@ function EmblaCarousel(
245
258
return pluginApis
246
259
}
247
260
261
+ function ssrStyles ( ) : string {
262
+ return ssrHandler . getStyles ( )
263
+ }
264
+
248
265
function internalEngine ( ) : EngineType {
249
266
return engine
250
267
}
@@ -286,11 +303,12 @@ function EmblaCarousel(
286
303
slideNodes,
287
304
slidesInView,
288
305
slidesNotInView,
289
- snapList
306
+ snapList,
307
+ ssrStyles
290
308
}
291
309
292
310
activate ( userOptions , userPlugins )
293
- setTimeout ( ( ) => eventHandler . emit ( 'init' , null ) , 0 )
311
+ setTimeout ( ( ) => eventHandler . emit ( 'init' , null ) , 0 ) // TODO: Won't work in SSR
294
312
return self
295
313
}
296
314
0 commit comments