@shelamkoff/rector 1.0.2 → 1.0.3
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/plugins/gallery/README.md +92 -92
- package/dist/plugins/gallery/README.ru.md +17 -17
- package/dist/plugins/gallery/gallery.css +38 -18
- package/dist/plugins/gallery/settings.js +15 -10
- package/dist/plugins/gallery/view-filled.js +26 -19
- package/dist/renderer/renderers/gallery/README.md +41 -41
- package/dist/renderer/renderers/gallery/README.ru.md +41 -41
- package/dist/renderer/renderers/gallery/index.js +100 -85
- package/dist/renderer/renderers/gallery/styles.css +417 -401
- package/dist/shared/galleryMasonry.d.ts +34 -0
- package/dist/shared/galleryMasonry.js +152 -0
- package/package.json +7 -6
|
@@ -9,10 +9,11 @@ import {
|
|
|
9
9
|
createDownload,
|
|
10
10
|
createFullscreen,
|
|
11
11
|
exposeStylesUrl,
|
|
12
|
-
} from '@shelamkoff/expose'
|
|
13
|
-
import { setSafeUrlAttribute } from '../../../shared/sanitize/sanitizeUrl.js'
|
|
12
|
+
} from '@shelamkoff/expose'
|
|
13
|
+
import { setSafeUrlAttribute } from '../../../shared/sanitize/sanitizeUrl.js'
|
|
14
|
+
import { mountGalleryMasonry } from '../../../shared/galleryMasonry.js'
|
|
14
15
|
|
|
15
|
-
const styles = new URL('./styles.css', import.meta.url).href
|
|
16
|
+
const styles = new URL('./styles.css', import.meta.url).href
|
|
16
17
|
const exposeStyles = exposeStylesUrl
|
|
17
18
|
|
|
18
19
|
const MAX_VISIBLE = 6
|
|
@@ -85,16 +86,18 @@ function selectAutoTemplate(count, orientations) {
|
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
/**
|
|
89
|
-
* Create the gallery renderer and own every opened Expose instance.
|
|
90
|
-
* @param {string} classPrefix
|
|
91
|
-
* @param {Record<string, import('../../../shared/localeTypes').LocaleValue>} locale
|
|
92
|
-
* @returns {import('../../types').BlockRenderer<import('../../types').GalleryBlock>}
|
|
89
|
+
/**
|
|
90
|
+
* Create the gallery renderer and own every opened Expose instance.
|
|
91
|
+
* @param {string} classPrefix
|
|
92
|
+
* @param {Record<string, import('../../../shared/localeTypes').LocaleValue>} locale
|
|
93
|
+
* @returns {import('../../types').BlockRenderer<import('../../types').GalleryBlock>}
|
|
93
94
|
*/
|
|
94
95
|
export function createGalleryRenderer(classPrefix, locale) {
|
|
95
|
-
/** @type {WeakMap<HTMLElement, Set<import('@shelamkoff/expose').Expose>>} */
|
|
96
|
-
const activeInstances = new WeakMap()
|
|
97
|
-
|
|
96
|
+
/** @type {WeakMap<HTMLElement, Set<import('@shelamkoff/expose').Expose>>} */
|
|
97
|
+
const activeInstances = new WeakMap()
|
|
98
|
+
/** @type {WeakMap<HTMLElement, ReturnType<typeof mountGalleryMasonry>>} */
|
|
99
|
+
const masonryMounts = new WeakMap()
|
|
100
|
+
return {
|
|
98
101
|
type: 'gallery',
|
|
99
102
|
styles: [styles, exposeStyles],
|
|
100
103
|
|
|
@@ -112,7 +115,7 @@ export function createGalleryRenderer(classPrefix, locale) {
|
|
|
112
115
|
? 'auto'
|
|
113
116
|
: rawLayout
|
|
114
117
|
|
|
115
|
-
const container = document.createElement('div')
|
|
118
|
+
const container = document.createElement('div')
|
|
116
119
|
/** @type {Set<import('@shelamkoff/expose').Expose>} */
|
|
117
120
|
const instances = new Set()
|
|
118
121
|
activeInstances.set(container, instances)
|
|
@@ -121,10 +124,12 @@ export function createGalleryRenderer(classPrefix, locale) {
|
|
|
121
124
|
const slots = getSlotsCount(layout)
|
|
122
125
|
const visibleCount = Math.min(images.length, layout === 'auto' ? MAX_VISIBLE : slots)
|
|
123
126
|
const visibleImages = images.slice(0, visibleCount)
|
|
124
|
-
const overflowCount = images.length - visibleCount
|
|
127
|
+
const overflowCount = images.length - visibleCount
|
|
125
128
|
const openLabel = typeof locale['renderer.gallery.open'] === 'string'
|
|
126
129
|
? locale['renderer.gallery.open']
|
|
127
130
|
: 'Open image'
|
|
131
|
+
/** @type {HTMLElement[] | null} */
|
|
132
|
+
let masonryItems = null
|
|
128
133
|
|
|
129
134
|
if (layout === 'auto') {
|
|
130
135
|
// Set initial template class, refine after images load
|
|
@@ -146,42 +151,46 @@ export function createGalleryRenderer(classPrefix, locale) {
|
|
|
146
151
|
}
|
|
147
152
|
|
|
148
153
|
visibleImages.forEach((image, i) => {
|
|
149
|
-
const item = createItem(image, classPrefix, openLabel)
|
|
150
|
-
const img = item.querySelector('img')
|
|
151
|
-
if (img) {
|
|
152
|
-
let settled = false
|
|
153
|
-
const onImgReady = () => {
|
|
154
|
-
if (settled) return
|
|
155
|
-
settled = true
|
|
156
|
-
orientations[i] = img.naturalWidth ? detectOrientation(img) : 'S'
|
|
157
|
-
loadedCount++
|
|
158
|
-
if (loadedCount >= visibleImages.length) onAllLoaded()
|
|
159
|
-
}
|
|
160
|
-
img.addEventListener('load', onImgReady, { once: true })
|
|
161
|
-
img.addEventListener('error', onImgReady, { once: true })
|
|
162
|
-
// A cached image can become complete between assigning `src` in
|
|
163
|
-
// createItem() and registering these listeners. Account for that
|
|
164
|
-
// path without counting a later load/error event twice.
|
|
165
|
-
if (img.complete) queueMicrotask(onImgReady)
|
|
166
|
-
}
|
|
154
|
+
const item = createItem(image, classPrefix, openLabel)
|
|
155
|
+
const img = item.querySelector('img')
|
|
156
|
+
if (img) {
|
|
157
|
+
let settled = false
|
|
158
|
+
const onImgReady = () => {
|
|
159
|
+
if (settled) return
|
|
160
|
+
settled = true
|
|
161
|
+
orientations[i] = img.naturalWidth ? detectOrientation(img) : 'S'
|
|
162
|
+
loadedCount++
|
|
163
|
+
if (loadedCount >= visibleImages.length) onAllLoaded()
|
|
164
|
+
}
|
|
165
|
+
img.addEventListener('load', onImgReady, { once: true })
|
|
166
|
+
img.addEventListener('error', onImgReady, { once: true })
|
|
167
|
+
// A cached image can become complete between assigning `src` in
|
|
168
|
+
// createItem() and registering these listeners. Account for that
|
|
169
|
+
// path without counting a later load/error event twice.
|
|
170
|
+
if (img.complete) queueMicrotask(onImgReady)
|
|
171
|
+
}
|
|
167
172
|
if (overflowCount > 0 && i === visibleImages.length - 1) {
|
|
168
173
|
item.appendChild(createOverflow(overflowCount, classPrefix))
|
|
169
174
|
}
|
|
170
175
|
container.appendChild(item)
|
|
171
176
|
})
|
|
172
|
-
} else if (layout === 'masonry') {
|
|
173
|
-
container.classList.add('eg--masonry')
|
|
174
|
-
|
|
175
|
-
|
|
177
|
+
} else if (layout === 'masonry') {
|
|
178
|
+
container.classList.add('eg--masonry')
|
|
179
|
+
masonryItems = []
|
|
180
|
+
|
|
181
|
+
images.forEach((image) => {
|
|
176
182
|
const item = createItem(image, classPrefix, openLabel)
|
|
177
|
-
|
|
178
|
-
|
|
183
|
+
const img = item.querySelector('img')
|
|
184
|
+
if (img) img.loading = 'eager'
|
|
185
|
+
masonryItems?.push(item)
|
|
186
|
+
container.appendChild(item)
|
|
187
|
+
})
|
|
179
188
|
} else {
|
|
180
189
|
// Specific template: 1, 2, 3a-6c, triptych, poly-*
|
|
181
190
|
container.classList.add(`eg--${layout}`)
|
|
182
191
|
|
|
183
192
|
visibleImages.forEach((image, i) => {
|
|
184
|
-
const item = createItem(image, classPrefix, openLabel)
|
|
193
|
+
const item = createItem(image, classPrefix, openLabel)
|
|
185
194
|
if (overflowCount > 0 && i === visibleImages.length - 1) {
|
|
186
195
|
item.appendChild(createOverflow(overflowCount, classPrefix))
|
|
187
196
|
}
|
|
@@ -190,9 +199,12 @@ export function createGalleryRenderer(classPrefix, locale) {
|
|
|
190
199
|
}
|
|
191
200
|
|
|
192
201
|
// Apply gallery inline styles
|
|
193
|
-
if (styles) {
|
|
194
|
-
applyGalleryStyles(container, styles, classPrefix)
|
|
195
|
-
}
|
|
202
|
+
if (styles) {
|
|
203
|
+
applyGalleryStyles(container, styles, classPrefix)
|
|
204
|
+
}
|
|
205
|
+
if (masonryItems) {
|
|
206
|
+
masonryMounts.set(container, mountGalleryMasonry(container, masonryItems))
|
|
207
|
+
}
|
|
196
208
|
|
|
197
209
|
// Expose lightbox on click
|
|
198
210
|
container.addEventListener('click', (e) => {
|
|
@@ -221,8 +233,8 @@ export function createGalleryRenderer(classPrefix, locale) {
|
|
|
221
233
|
if (o.captions ?? true) plugins.push(createCaptions())
|
|
222
234
|
if (o.thumbnails) plugins.push(createThumbnails())
|
|
223
235
|
if (o.fullscreen ?? true) plugins.push(createFullscreen())
|
|
224
|
-
const autoplay = o.autoplayInterval ? createAutoplay({ interval: o.autoplayInterval }) : null
|
|
225
|
-
if (autoplay) plugins.push(autoplay)
|
|
236
|
+
const autoplay = o.autoplayInterval ? createAutoplay({ interval: o.autoplayInterval }) : null
|
|
237
|
+
if (autoplay) plugins.push(autoplay)
|
|
226
238
|
plugins.push(createTransform())
|
|
227
239
|
plugins.push(createDownload())
|
|
228
240
|
|
|
@@ -231,23 +243,23 @@ export function createGalleryRenderer(classPrefix, locale) {
|
|
|
231
243
|
|
|
232
244
|
const expose = new Expose(slides, {
|
|
233
245
|
startIndex: idx,
|
|
234
|
-
animation: 'fade',
|
|
235
|
-
loop,
|
|
236
|
-
navigation: o.navigation ?? true,
|
|
237
|
-
toolbar,
|
|
238
|
-
plugins,
|
|
239
|
-
})
|
|
240
|
-
instances.add(expose)
|
|
241
|
-
expose.on('close:complete', () => {
|
|
242
|
-
expose.destroy()
|
|
243
|
-
instances.delete(expose)
|
|
244
|
-
})
|
|
245
|
-
void expose.open(idx).then(() => {
|
|
246
|
-
autoplay?.start()
|
|
247
|
-
}).catch(() => {
|
|
248
|
-
expose.destroy()
|
|
249
|
-
instances.delete(expose)
|
|
250
|
-
})
|
|
246
|
+
animation: 'fade',
|
|
247
|
+
loop,
|
|
248
|
+
navigation: o.navigation ?? true,
|
|
249
|
+
toolbar,
|
|
250
|
+
plugins,
|
|
251
|
+
})
|
|
252
|
+
instances.add(expose)
|
|
253
|
+
expose.on('close:complete', () => {
|
|
254
|
+
expose.destroy()
|
|
255
|
+
instances.delete(expose)
|
|
256
|
+
})
|
|
257
|
+
void expose.open(idx).then(() => {
|
|
258
|
+
autoplay?.start()
|
|
259
|
+
}).catch(() => {
|
|
260
|
+
expose.destroy()
|
|
261
|
+
instances.delete(expose)
|
|
262
|
+
})
|
|
251
263
|
})
|
|
252
264
|
|
|
253
265
|
return container
|
|
@@ -257,35 +269,38 @@ export function createGalleryRenderer(classPrefix, locale) {
|
|
|
257
269
|
* Dispose lightboxes that are still open when rendered content is replaced.
|
|
258
270
|
* @param {HTMLElement} element
|
|
259
271
|
*/
|
|
260
|
-
destroy(element) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
272
|
+
destroy(element) {
|
|
273
|
+
masonryMounts.get(element)?.destroy()
|
|
274
|
+
masonryMounts.delete(element)
|
|
275
|
+
const instances = activeInstances.get(element)
|
|
276
|
+
if (instances) {
|
|
277
|
+
for (const expose of instances) {
|
|
278
|
+
expose.destroy()
|
|
279
|
+
}
|
|
280
|
+
instances.clear()
|
|
281
|
+
activeInstances.delete(element)
|
|
282
|
+
}
|
|
283
|
+
},
|
|
269
284
|
}
|
|
270
285
|
}
|
|
271
286
|
|
|
272
287
|
/**
|
|
273
|
-
* @param {{ url: string; caption?: string }} image
|
|
274
|
-
* @param {string} classPrefix
|
|
275
|
-
* @param {string} openLabel
|
|
276
|
-
* @returns {HTMLElement}
|
|
277
|
-
*/
|
|
278
|
-
function createItem(image, classPrefix, openLabel) {
|
|
279
|
-
const figure = document.createElement('figure')
|
|
280
|
-
figure.className = `${classPrefix}-gallery__item`
|
|
281
|
-
figure.tabIndex = 0
|
|
282
|
-
figure.setAttribute('role', 'button')
|
|
283
|
-
figure.setAttribute('aria-label', image.caption ? `${openLabel}: ${image.caption}` : openLabel)
|
|
284
|
-
figure.addEventListener('keydown', (event) => {
|
|
285
|
-
if (event.key !== 'Enter' && event.key !== ' ') return
|
|
286
|
-
event.preventDefault()
|
|
287
|
-
figure.click()
|
|
288
|
-
})
|
|
288
|
+
* @param {{ url: string; caption?: string }} image
|
|
289
|
+
* @param {string} classPrefix
|
|
290
|
+
* @param {string} openLabel
|
|
291
|
+
* @returns {HTMLElement}
|
|
292
|
+
*/
|
|
293
|
+
function createItem(image, classPrefix, openLabel) {
|
|
294
|
+
const figure = document.createElement('figure')
|
|
295
|
+
figure.className = `${classPrefix}-gallery__item`
|
|
296
|
+
figure.tabIndex = 0
|
|
297
|
+
figure.setAttribute('role', 'button')
|
|
298
|
+
figure.setAttribute('aria-label', image.caption ? `${openLabel}: ${image.caption}` : openLabel)
|
|
299
|
+
figure.addEventListener('keydown', (event) => {
|
|
300
|
+
if (event.key !== 'Enter' && event.key !== ' ') return
|
|
301
|
+
event.preventDefault()
|
|
302
|
+
figure.click()
|
|
303
|
+
})
|
|
289
304
|
|
|
290
305
|
const img = document.createElement('img')
|
|
291
306
|
img.className = `${classPrefix}-gallery__image`
|