@frybynite/image-cloud 0.6.5 → 0.7.0
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/README.md +1 -28
- package/dist/image-cloud-auto-init.js +759 -345
- package/dist/image-cloud-auto-init.js.map +1 -1
- package/dist/image-cloud.js +1040 -1085
- package/dist/image-cloud.js.map +1 -1
- package/dist/image-cloud.umd.js +5 -5
- package/dist/image-cloud.umd.js.map +1 -1
- package/dist/index.d.ts +0 -31
- package/dist/react.d.ts +0 -31
- package/dist/react.js +848 -434
- package/dist/react.js.map +1 -1
- package/dist/vue.d.ts +0 -31
- package/dist/vue.js +856 -442
- package/dist/vue.js.map +1 -1
- package/dist/web-component.d.ts +0 -31
- package/dist/web-component.js +843 -429
- package/dist/web-component.js.map +1 -1
- package/package.json +14 -27
- package/dist/composite-BSJXKGwG.js +0 -63
- package/dist/composite-BSJXKGwG.js.map +0 -1
- package/dist/google-drive-DK2v0Xay.js +0 -227
- package/dist/google-drive-DK2v0Xay.js.map +0 -1
- package/dist/image-cloud-CO9PMUGK.js +0 -38
- package/dist/image-cloud-CO9PMUGK.js.map +0 -1
- package/dist/loaders/all.d.ts +0 -1683
- package/dist/loaders/all.js +0 -463
- package/dist/loaders/all.js.map +0 -1
- package/dist/loaders/composite.d.ts +0 -1683
- package/dist/loaders/composite.js +0 -63
- package/dist/loaders/composite.js.map +0 -1
- package/dist/loaders/google-drive.d.ts +0 -1683
- package/dist/loaders/google-drive.js +0 -227
- package/dist/loaders/google-drive.js.map +0 -1
- package/dist/loaders/static.d.ts +0 -1683
- package/dist/loaders/static.js +0 -186
- package/dist/loaders/static.js.map +0 -1
- package/dist/static-D9YjTesh.js +0 -186
- package/dist/static-D9YjTesh.js.map +0 -1
package/dist/image-cloud.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
const
|
|
1
|
+
const mt = Object.freeze({
|
|
2
2
|
none: "none",
|
|
3
3
|
sm: "0 2px 4px rgba(0,0,0,0.1)",
|
|
4
4
|
md: "0 4px 16px rgba(0,0,0,0.4)",
|
|
5
5
|
lg: "0 8px 32px rgba(0,0,0,0.5)",
|
|
6
6
|
glow: "0 0 30px rgba(255,255,255,0.6)"
|
|
7
|
-
}),
|
|
7
|
+
}), wt = Object.freeze({
|
|
8
8
|
energetic: Object.freeze({ overshoot: 0.25, bounces: 2, decayRatio: 0.5 }),
|
|
9
9
|
playful: Object.freeze({ overshoot: 0.15, bounces: 1, decayRatio: 0.5 }),
|
|
10
10
|
subtle: Object.freeze({ overshoot: 0.08, bounces: 1, decayRatio: 0.5 })
|
|
11
|
-
}),
|
|
11
|
+
}), xt = Object.freeze({
|
|
12
12
|
gentle: Object.freeze({ stiffness: 150, damping: 30, mass: 1, oscillations: 2 }),
|
|
13
13
|
bouncy: Object.freeze({ stiffness: 300, damping: 15, mass: 1, oscillations: 4 }),
|
|
14
14
|
wobbly: Object.freeze({ stiffness: 180, damping: 12, mass: 1.5, oscillations: 5 }),
|
|
15
15
|
snappy: Object.freeze({ stiffness: 400, damping: 25, mass: 0.8, oscillations: 2 })
|
|
16
|
-
}),
|
|
16
|
+
}), St = Object.freeze({
|
|
17
17
|
gentle: Object.freeze({ amplitude: 30, frequency: 1.5, decay: !0, decayRate: 0.9, phase: 0 }),
|
|
18
18
|
playful: Object.freeze({ amplitude: 50, frequency: 2.5, decay: !0, decayRate: 0.7, phase: 0 }),
|
|
19
19
|
serpentine: Object.freeze({ amplitude: 60, frequency: 3, decay: !1, decayRate: 1, phase: 0 }),
|
|
20
20
|
flutter: Object.freeze({ amplitude: 20, frequency: 4, decay: !0, decayRate: 0.5, phase: 0 })
|
|
21
|
-
}),
|
|
21
|
+
}), pt = Object.freeze({
|
|
22
22
|
type: "linear"
|
|
23
|
-
}),
|
|
23
|
+
}), bt = Object.freeze({
|
|
24
24
|
mode: "none"
|
|
25
|
-
}),
|
|
25
|
+
}), yt = Object.freeze({
|
|
26
26
|
mode: "none"
|
|
27
|
-
}),
|
|
27
|
+
}), At = Object.freeze({
|
|
28
28
|
default: Object.freeze({
|
|
29
29
|
border: Object.freeze({
|
|
30
30
|
width: 0,
|
|
@@ -49,17 +49,17 @@ const pt = Object.freeze({
|
|
|
49
49
|
focused: Object.freeze({
|
|
50
50
|
shadow: "none"
|
|
51
51
|
})
|
|
52
|
-
}),
|
|
52
|
+
}), Dt = Object.freeze({
|
|
53
53
|
rows: 1,
|
|
54
54
|
amplitude: 100,
|
|
55
55
|
frequency: 2,
|
|
56
56
|
phaseShift: 0,
|
|
57
57
|
synchronization: "offset"
|
|
58
58
|
// Note: Image rotation along wave is now controlled via image.rotation.mode = 'tangent'
|
|
59
|
-
}),
|
|
59
|
+
}), Ot = Object.freeze({
|
|
60
60
|
mobile: Object.freeze({ maxWidth: 767 }),
|
|
61
61
|
tablet: Object.freeze({ maxWidth: 1199 })
|
|
62
|
-
}),
|
|
62
|
+
}), $t = Object.freeze({
|
|
63
63
|
mode: "adaptive",
|
|
64
64
|
// Default to adaptive sizing
|
|
65
65
|
minSize: 50,
|
|
@@ -71,21 +71,21 @@ const pt = Object.freeze({
|
|
|
71
71
|
// No variance by default
|
|
72
72
|
max: 1
|
|
73
73
|
})
|
|
74
|
-
}),
|
|
74
|
+
}), Ut = Object.freeze({
|
|
75
75
|
mode: "none",
|
|
76
76
|
range: Object.freeze({
|
|
77
77
|
min: -15,
|
|
78
78
|
max: 15
|
|
79
79
|
})
|
|
80
|
-
}),
|
|
81
|
-
sizing:
|
|
82
|
-
rotation:
|
|
83
|
-
}),
|
|
80
|
+
}), Tt = Object.freeze({
|
|
81
|
+
sizing: $t,
|
|
82
|
+
rotation: Ut
|
|
83
|
+
}), Ct = Object.freeze({
|
|
84
84
|
validateUrls: !0,
|
|
85
85
|
validationTimeout: 5e3,
|
|
86
86
|
validationMethod: "head",
|
|
87
87
|
allowedExtensions: ["jpg", "jpeg", "png", "gif", "webp", "bmp"]
|
|
88
|
-
}),
|
|
88
|
+
}), Rt = Object.freeze({
|
|
89
89
|
enabled: !1,
|
|
90
90
|
centers: !1,
|
|
91
91
|
loaders: !1
|
|
@@ -94,17 +94,17 @@ const pt = Object.freeze({
|
|
|
94
94
|
loaders: [],
|
|
95
95
|
// Shared loader settings and debug config
|
|
96
96
|
config: Object.freeze({
|
|
97
|
-
loaders:
|
|
98
|
-
debug:
|
|
97
|
+
loaders: Ct,
|
|
98
|
+
debug: Rt
|
|
99
99
|
}),
|
|
100
100
|
// Image sizing and rotation configuration
|
|
101
|
-
image:
|
|
101
|
+
image: Tt,
|
|
102
102
|
// Pattern-based layout configuration
|
|
103
103
|
layout: Object.freeze({
|
|
104
104
|
algorithm: "radial",
|
|
105
105
|
scaleDecay: 0,
|
|
106
106
|
// No decay by default (0-1 for radial/spiral)
|
|
107
|
-
responsive:
|
|
107
|
+
responsive: Ot,
|
|
108
108
|
targetCoverage: 0.6,
|
|
109
109
|
// Target 60% of container area
|
|
110
110
|
densityFactor: 1,
|
|
@@ -160,9 +160,9 @@ const pt = Object.freeze({
|
|
|
160
160
|
}),
|
|
161
161
|
easing: "cubic-bezier(0.25, 1, 0.5, 1)",
|
|
162
162
|
// smooth deceleration
|
|
163
|
-
path:
|
|
164
|
-
rotation:
|
|
165
|
-
scale:
|
|
163
|
+
path: pt,
|
|
164
|
+
rotation: bt,
|
|
165
|
+
scale: yt
|
|
166
166
|
})
|
|
167
167
|
}),
|
|
168
168
|
// Pattern-based interaction configuration
|
|
@@ -219,50 +219,50 @@ const pt = Object.freeze({
|
|
|
219
219
|
})
|
|
220
220
|
}),
|
|
221
221
|
// Image styling
|
|
222
|
-
styling:
|
|
222
|
+
styling: At
|
|
223
223
|
});
|
|
224
|
-
function
|
|
225
|
-
if (!
|
|
226
|
-
if (!t) return { ...
|
|
227
|
-
const e = { ...
|
|
228
|
-
return t.border !== void 0 && (e.border = { ...
|
|
224
|
+
function Z(n, t) {
|
|
225
|
+
if (!n) return t || {};
|
|
226
|
+
if (!t) return { ...n };
|
|
227
|
+
const e = { ...n };
|
|
228
|
+
return t.border !== void 0 && (e.border = { ...n.border, ...t.border }), t.borderTop !== void 0 && (e.borderTop = { ...n.borderTop, ...t.borderTop }), t.borderRight !== void 0 && (e.borderRight = { ...n.borderRight, ...t.borderRight }), t.borderBottom !== void 0 && (e.borderBottom = { ...n.borderBottom, ...t.borderBottom }), t.borderLeft !== void 0 && (e.borderLeft = { ...n.borderLeft, ...t.borderLeft }), t.filter !== void 0 && (e.filter = { ...n.filter, ...t.filter }), t.outline !== void 0 && (e.outline = { ...n.outline, ...t.outline }), t.shadow !== void 0 && (e.shadow = t.shadow), t.opacity !== void 0 && (e.opacity = t.opacity), t.cursor !== void 0 && (e.cursor = t.cursor), t.className !== void 0 && (e.className = t.className), t.objectFit !== void 0 && (e.objectFit = t.objectFit), t.aspectRatio !== void 0 && (e.aspectRatio = t.aspectRatio), t.borderRadiusTopLeft !== void 0 && (e.borderRadiusTopLeft = t.borderRadiusTopLeft), t.borderRadiusTopRight !== void 0 && (e.borderRadiusTopRight = t.borderRadiusTopRight), t.borderRadiusBottomRight !== void 0 && (e.borderRadiusBottomRight = t.borderRadiusBottomRight), t.borderRadiusBottomLeft !== void 0 && (e.borderRadiusBottomLeft = t.borderRadiusBottomLeft), e;
|
|
229
229
|
}
|
|
230
|
-
function
|
|
231
|
-
if (!t) return { ...
|
|
232
|
-
const e =
|
|
233
|
-
|
|
230
|
+
function Pt(n, t) {
|
|
231
|
+
if (!t) return { ...n };
|
|
232
|
+
const e = Z(n.default, t.default), i = Z(
|
|
233
|
+
Z(e, n.hover),
|
|
234
234
|
t.hover
|
|
235
|
-
),
|
|
236
|
-
|
|
235
|
+
), o = Z(
|
|
236
|
+
Z(e, n.focused),
|
|
237
237
|
t.focused
|
|
238
238
|
);
|
|
239
239
|
return {
|
|
240
240
|
default: e,
|
|
241
241
|
hover: i,
|
|
242
|
-
focused:
|
|
242
|
+
focused: o
|
|
243
243
|
};
|
|
244
244
|
}
|
|
245
|
-
function
|
|
246
|
-
if (!t) return { ...
|
|
247
|
-
const e = { ...
|
|
245
|
+
function _t(n, t) {
|
|
246
|
+
if (!t) return { ...n };
|
|
247
|
+
const e = { ...n };
|
|
248
248
|
if (t.sizing !== void 0 && (e.sizing = {
|
|
249
|
-
...
|
|
249
|
+
...n.sizing,
|
|
250
250
|
...t.sizing
|
|
251
251
|
}, t.sizing.variance)) {
|
|
252
|
-
const i = t.sizing.variance,
|
|
253
|
-
e.sizing.variance = { min:
|
|
252
|
+
const i = t.sizing.variance, o = i.min !== void 0 && i.min >= 0.25 && i.min <= 1 ? i.min : n.sizing?.variance?.min ?? 1, s = i.max !== void 0 && i.max >= 1 && i.max <= 1.75 ? i.max : n.sizing?.variance?.max ?? 1;
|
|
253
|
+
e.sizing.variance = { min: o, max: s };
|
|
254
254
|
}
|
|
255
255
|
if (t.rotation !== void 0 && (e.rotation = {
|
|
256
|
-
...
|
|
256
|
+
...n.rotation,
|
|
257
257
|
...t.rotation
|
|
258
258
|
}, t.rotation.range)) {
|
|
259
|
-
const i = t.rotation.range,
|
|
260
|
-
e.rotation.range = { min:
|
|
259
|
+
const i = t.rotation.range, o = i.min !== void 0 && i.min >= -180 && i.min <= 0 ? i.min : n.rotation?.range?.min ?? -15, s = i.max !== void 0 && i.max >= 0 && i.max <= 180 ? i.max : n.rotation?.range?.max ?? 15;
|
|
260
|
+
e.rotation.range = { min: o, max: s };
|
|
261
261
|
}
|
|
262
262
|
return e;
|
|
263
263
|
}
|
|
264
|
-
function
|
|
265
|
-
const t =
|
|
264
|
+
function Ht(n) {
|
|
265
|
+
const t = n.layout?.rotation;
|
|
266
266
|
if (t && "enabled" in t)
|
|
267
267
|
return {
|
|
268
268
|
rotation: {
|
|
@@ -271,8 +271,8 @@ function jt(o) {
|
|
|
271
271
|
}
|
|
272
272
|
};
|
|
273
273
|
}
|
|
274
|
-
function
|
|
275
|
-
const t =
|
|
274
|
+
function Nt(n) {
|
|
275
|
+
const t = n.layout?.sizing?.variance;
|
|
276
276
|
if (t)
|
|
277
277
|
return {
|
|
278
278
|
sizing: {
|
|
@@ -282,113 +282,113 @@ function kt(o) {
|
|
|
282
282
|
}
|
|
283
283
|
};
|
|
284
284
|
}
|
|
285
|
-
function
|
|
286
|
-
const t =
|
|
287
|
-
let i =
|
|
285
|
+
function jt(n = {}) {
|
|
286
|
+
const t = Ht(n), e = Nt(n);
|
|
287
|
+
let i = n.image;
|
|
288
288
|
(t || e) && (i = {
|
|
289
289
|
...e || {},
|
|
290
290
|
...t || {},
|
|
291
291
|
...i
|
|
292
|
-
}, i.rotation && t?.rotation &&
|
|
292
|
+
}, i.rotation && t?.rotation && n.image?.rotation && (i.rotation = {
|
|
293
293
|
...t.rotation,
|
|
294
|
-
...
|
|
294
|
+
...n.image.rotation
|
|
295
295
|
}));
|
|
296
|
-
const
|
|
297
|
-
|
|
296
|
+
const o = [...n.loaders ?? []];
|
|
297
|
+
n.images && n.images.length > 0 && o.unshift({
|
|
298
298
|
static: {
|
|
299
|
-
sources: [{ urls:
|
|
299
|
+
sources: [{ urls: n.images }]
|
|
300
300
|
}
|
|
301
301
|
});
|
|
302
302
|
const r = {
|
|
303
303
|
loaders: {
|
|
304
|
-
...
|
|
305
|
-
...
|
|
304
|
+
...Ct,
|
|
305
|
+
...n.config?.loaders ?? {}
|
|
306
306
|
}
|
|
307
307
|
}, a = {
|
|
308
|
-
loaders:
|
|
308
|
+
loaders: o,
|
|
309
309
|
config: r,
|
|
310
|
-
image:
|
|
310
|
+
image: _t(Tt, i),
|
|
311
311
|
layout: { ...y.layout },
|
|
312
312
|
animation: { ...y.animation },
|
|
313
313
|
interaction: { ...y.interaction },
|
|
314
314
|
rendering: { ...y.rendering },
|
|
315
|
-
styling:
|
|
315
|
+
styling: Pt(At, n.styling)
|
|
316
316
|
};
|
|
317
|
-
return
|
|
317
|
+
return n.layout && (a.layout = {
|
|
318
318
|
...y.layout,
|
|
319
|
-
...
|
|
320
|
-
},
|
|
319
|
+
...n.layout
|
|
320
|
+
}, n.layout.responsive && (a.layout.responsive = {
|
|
321
321
|
...y.layout.responsive,
|
|
322
|
-
mobile:
|
|
323
|
-
tablet:
|
|
324
|
-
}),
|
|
322
|
+
mobile: n.layout.responsive.mobile ? { ...y.layout.responsive.mobile, ...n.layout.responsive.mobile } : y.layout.responsive.mobile,
|
|
323
|
+
tablet: n.layout.responsive.tablet ? { ...y.layout.responsive.tablet, ...n.layout.responsive.tablet } : y.layout.responsive.tablet
|
|
324
|
+
}), n.layout.spacing && (a.layout.spacing = {
|
|
325
325
|
...y.layout.spacing,
|
|
326
|
-
...
|
|
327
|
-
})),
|
|
326
|
+
...n.layout.spacing
|
|
327
|
+
})), n.animation && (a.animation = {
|
|
328
328
|
...y.animation,
|
|
329
|
-
...
|
|
330
|
-
},
|
|
329
|
+
...n.animation
|
|
330
|
+
}, n.animation.easing && (a.animation.easing = {
|
|
331
331
|
...y.animation.easing,
|
|
332
|
-
...
|
|
333
|
-
}),
|
|
332
|
+
...n.animation.easing
|
|
333
|
+
}), n.animation.queue && (a.animation.queue = {
|
|
334
334
|
...y.animation.queue,
|
|
335
|
-
...
|
|
336
|
-
}),
|
|
335
|
+
...n.animation.queue
|
|
336
|
+
}), n.animation.performance && (a.animation.performance = {
|
|
337
337
|
...y.animation.performance,
|
|
338
|
-
...
|
|
339
|
-
}),
|
|
338
|
+
...n.animation.performance
|
|
339
|
+
}), n.animation.entry && (a.animation.entry = {
|
|
340
340
|
...y.animation.entry,
|
|
341
|
-
...
|
|
342
|
-
start:
|
|
341
|
+
...n.animation.entry,
|
|
342
|
+
start: n.animation.entry.start ? {
|
|
343
343
|
...y.animation.entry.start,
|
|
344
|
-
...
|
|
345
|
-
circular:
|
|
344
|
+
...n.animation.entry.start,
|
|
345
|
+
circular: n.animation.entry.start.circular ? { ...y.animation.entry.start.circular, ...n.animation.entry.start.circular } : y.animation.entry.start.circular
|
|
346
346
|
} : y.animation.entry.start,
|
|
347
|
-
timing:
|
|
348
|
-
path:
|
|
349
|
-
rotation:
|
|
350
|
-
scale:
|
|
351
|
-
})),
|
|
347
|
+
timing: n.animation.entry.timing ? { ...y.animation.entry.timing, ...n.animation.entry.timing } : y.animation.entry.timing,
|
|
348
|
+
path: n.animation.entry.path ? { ...pt, ...n.animation.entry.path } : y.animation.entry.path,
|
|
349
|
+
rotation: n.animation.entry.rotation ? { ...bt, ...n.animation.entry.rotation } : y.animation.entry.rotation,
|
|
350
|
+
scale: n.animation.entry.scale ? { ...yt, ...n.animation.entry.scale } : y.animation.entry.scale
|
|
351
|
+
})), n.interaction && (a.interaction = {
|
|
352
352
|
...y.interaction,
|
|
353
|
-
...
|
|
354
|
-
},
|
|
353
|
+
...n.interaction
|
|
354
|
+
}, n.interaction.focus && (a.interaction.focus = {
|
|
355
355
|
...y.interaction.focus,
|
|
356
|
-
...
|
|
357
|
-
}),
|
|
356
|
+
...n.interaction.focus
|
|
357
|
+
}), n.interaction.navigation && (a.interaction.navigation = {
|
|
358
358
|
...y.interaction.navigation,
|
|
359
|
-
...
|
|
360
|
-
}),
|
|
359
|
+
...n.interaction.navigation
|
|
360
|
+
}), n.interaction.gestures && (a.interaction.gestures = {
|
|
361
361
|
...y.interaction.gestures,
|
|
362
|
-
...
|
|
363
|
-
})),
|
|
362
|
+
...n.interaction.gestures
|
|
363
|
+
})), n.rendering && (a.rendering = {
|
|
364
364
|
...y.rendering,
|
|
365
|
-
...
|
|
366
|
-
},
|
|
365
|
+
...n.rendering
|
|
366
|
+
}, n.rendering.responsive && (a.rendering.responsive = {
|
|
367
367
|
...y.rendering.responsive,
|
|
368
|
-
...
|
|
369
|
-
breakpoints:
|
|
370
|
-
mobileDetection:
|
|
371
|
-
}),
|
|
368
|
+
...n.rendering.responsive,
|
|
369
|
+
breakpoints: n.rendering.responsive.breakpoints ? { ...y.rendering.responsive.breakpoints, ...n.rendering.responsive.breakpoints } : y.rendering.responsive.breakpoints,
|
|
370
|
+
mobileDetection: n.rendering.responsive.mobileDetection ? n.rendering.responsive.mobileDetection : y.rendering.responsive.mobileDetection
|
|
371
|
+
}), n.rendering.ui && (a.rendering.ui = {
|
|
372
372
|
...y.rendering.ui,
|
|
373
|
-
...
|
|
374
|
-
}),
|
|
373
|
+
...n.rendering.ui
|
|
374
|
+
}), n.rendering.performance && (a.rendering.performance = {
|
|
375
375
|
...y.rendering.performance,
|
|
376
|
-
...
|
|
376
|
+
...n.rendering.performance
|
|
377
377
|
})), a.config.debug = {
|
|
378
|
-
...
|
|
379
|
-
...
|
|
378
|
+
...Rt,
|
|
379
|
+
...n.config?.debug ?? {}
|
|
380
380
|
}, a;
|
|
381
381
|
}
|
|
382
|
-
function
|
|
383
|
-
return { ...
|
|
382
|
+
function kt(n, t) {
|
|
383
|
+
return { ...n ? wt[n] : wt.playful, ...t };
|
|
384
384
|
}
|
|
385
|
-
function
|
|
386
|
-
return { ...
|
|
385
|
+
function Wt(n, t) {
|
|
386
|
+
return { ...n ? xt[n] : xt.gentle, ...t };
|
|
387
387
|
}
|
|
388
|
-
function
|
|
389
|
-
return { ...
|
|
388
|
+
function Gt(n, t) {
|
|
389
|
+
return { ...n ? St[n] : St.gentle, ...t };
|
|
390
390
|
}
|
|
391
|
-
class
|
|
391
|
+
class qt {
|
|
392
392
|
constructor(t) {
|
|
393
393
|
this.activeAnimations = /* @__PURE__ */ new Map(), this.animationIdCounter = 0, this.config = t;
|
|
394
394
|
}
|
|
@@ -399,8 +399,8 @@ class Xt {
|
|
|
399
399
|
buildTransformString(t) {
|
|
400
400
|
const e = ["translate(-50%, -50%)"];
|
|
401
401
|
if (t.x !== void 0 || t.y !== void 0) {
|
|
402
|
-
const i = t.x ?? 0,
|
|
403
|
-
e.push(`translate(${i}px, ${
|
|
402
|
+
const i = t.x ?? 0, o = t.y ?? 0;
|
|
403
|
+
e.push(`translate(${i}px, ${o}px)`);
|
|
404
404
|
}
|
|
405
405
|
return t.rotation !== void 0 && e.push(`rotate(${t.rotation}deg)`), t.scale !== void 0 && e.push(`scale(${t.scale})`), e.join(" ");
|
|
406
406
|
}
|
|
@@ -413,9 +413,9 @@ class Xt {
|
|
|
413
413
|
* @param easing - CSS easing function (optional)
|
|
414
414
|
* @returns AnimationHandle that can be used to cancel or query the animation
|
|
415
415
|
*/
|
|
416
|
-
animateTransformCancellable(t, e, i,
|
|
416
|
+
animateTransformCancellable(t, e, i, o = null, s = null) {
|
|
417
417
|
this.cancelAllAnimations(t);
|
|
418
|
-
const r =
|
|
418
|
+
const r = o ?? this.config.duration, a = s ?? this.config.easing.default, h = this.buildTransformString(e), c = this.buildTransformString(i);
|
|
419
419
|
t.style.transition = "none";
|
|
420
420
|
const u = t.animate(
|
|
421
421
|
[
|
|
@@ -452,13 +452,13 @@ class Xt {
|
|
|
452
452
|
cancelAnimation(t, e = !0) {
|
|
453
453
|
const i = this.getCurrentTransform(t.element);
|
|
454
454
|
if (t.animation.cancel(), e) {
|
|
455
|
-
const
|
|
455
|
+
const o = this.buildTransformString({
|
|
456
456
|
x: i.x,
|
|
457
457
|
y: i.y,
|
|
458
458
|
rotation: i.rotation,
|
|
459
459
|
scale: i.scale
|
|
460
460
|
});
|
|
461
|
-
t.element.style.transform =
|
|
461
|
+
t.element.style.transform = o;
|
|
462
462
|
}
|
|
463
463
|
return this.activeAnimations.delete(t.element), i;
|
|
464
464
|
}
|
|
@@ -471,8 +471,8 @@ class Xt {
|
|
|
471
471
|
const e = this.activeAnimations.get(t);
|
|
472
472
|
e && this.cancelAnimation(e, !1);
|
|
473
473
|
const i = t.getAnimations();
|
|
474
|
-
for (const
|
|
475
|
-
|
|
474
|
+
for (const o of i)
|
|
475
|
+
o.cancel();
|
|
476
476
|
}
|
|
477
477
|
/**
|
|
478
478
|
* Get current transform state of an element (works mid-animation)
|
|
@@ -484,7 +484,7 @@ class Xt {
|
|
|
484
484
|
const i = getComputedStyle(t).transform;
|
|
485
485
|
if (i === "none" || !i)
|
|
486
486
|
return { x: 0, y: 0, rotation: 0, scale: 1 };
|
|
487
|
-
const
|
|
487
|
+
const o = new DOMMatrix(i), s = Math.sqrt(o.a * o.a + o.b * o.b), r = Math.atan2(o.b, o.a) * (180 / Math.PI), a = o.e, h = o.f;
|
|
488
488
|
return { x: a, y: h, rotation: r, scale: s };
|
|
489
489
|
}
|
|
490
490
|
/**
|
|
@@ -511,9 +511,9 @@ class Xt {
|
|
|
511
511
|
* @param easing - CSS easing function (optional)
|
|
512
512
|
* @returns Promise that resolves when animation completes
|
|
513
513
|
*/
|
|
514
|
-
animateTransform(t, e, i = null,
|
|
514
|
+
animateTransform(t, e, i = null, o = null) {
|
|
515
515
|
return new Promise((s) => {
|
|
516
|
-
const r = i ?? this.config.duration, a =
|
|
516
|
+
const r = i ?? this.config.duration, a = o ?? this.config.easing.default;
|
|
517
517
|
t.style.transition = `transform ${r}ms ${a}, box-shadow ${r}ms ${a}`, t.style.transform = this.buildTransformString(e), setTimeout(() => {
|
|
518
518
|
s();
|
|
519
519
|
}, r);
|
|
@@ -544,99 +544,99 @@ class Xt {
|
|
|
544
544
|
return new Promise((e) => setTimeout(e, t));
|
|
545
545
|
}
|
|
546
546
|
}
|
|
547
|
-
function V(
|
|
548
|
-
return
|
|
547
|
+
function V(n, t, e) {
|
|
548
|
+
return n + (t - n) * e;
|
|
549
549
|
}
|
|
550
|
-
function
|
|
551
|
-
const { overshoot:
|
|
552
|
-
let u = 0, l = 0, d = 1, m =
|
|
550
|
+
function Yt(n, t, e, i) {
|
|
551
|
+
const { overshoot: o, bounces: s, decayRatio: r } = i, a = e.x - t.x, h = e.y - t.y, c = Xt(s, r);
|
|
552
|
+
let u = 0, l = 0, d = 1, m = o, b = !1;
|
|
553
553
|
for (let g = 0; g < c.length; g++)
|
|
554
|
-
if (
|
|
554
|
+
if (n <= c[g].time) {
|
|
555
555
|
l = g === 0 ? 0 : c[g - 1].time, d = c[g].time, m = c[g].overshoot, b = c[g].isOvershoot;
|
|
556
556
|
break;
|
|
557
557
|
}
|
|
558
|
-
const p = (
|
|
558
|
+
const p = (n - l) / (d - l);
|
|
559
559
|
if (b)
|
|
560
|
-
u = 1 + m *
|
|
560
|
+
u = 1 + m * ot(p);
|
|
561
561
|
else if (l === 0)
|
|
562
|
-
u =
|
|
562
|
+
u = ot(p);
|
|
563
563
|
else {
|
|
564
564
|
const f = 1 + (c.find(
|
|
565
565
|
(S, v) => S.time > l && v > 0 && c[v - 1].isOvershoot
|
|
566
566
|
)?.overshoot || m);
|
|
567
|
-
u = V(f, 1,
|
|
567
|
+
u = V(f, 1, ot(p));
|
|
568
568
|
}
|
|
569
569
|
return {
|
|
570
570
|
x: t.x + a * u,
|
|
571
571
|
y: t.y + h * u
|
|
572
572
|
};
|
|
573
573
|
}
|
|
574
|
-
function
|
|
574
|
+
function Xt(n, t) {
|
|
575
575
|
const e = [];
|
|
576
576
|
let i = 0.6;
|
|
577
577
|
e.push({ time: i, overshoot: 0, isOvershoot: !1 });
|
|
578
|
-
let
|
|
579
|
-
const r = 0.4 / (
|
|
580
|
-
for (let a = 0; a <
|
|
581
|
-
i += r, e.push({ time: i, overshoot:
|
|
578
|
+
let o = 0.15;
|
|
579
|
+
const r = 0.4 / (n * 2);
|
|
580
|
+
for (let a = 0; a < n; a++)
|
|
581
|
+
i += r, e.push({ time: i, overshoot: o, isOvershoot: !0 }), i += r, e.push({ time: i, overshoot: o * t, isOvershoot: !1 }), o *= t;
|
|
582
582
|
return e.push({ time: 1, overshoot: 0, isOvershoot: !1 }), e;
|
|
583
583
|
}
|
|
584
|
-
function
|
|
585
|
-
const { stiffness:
|
|
584
|
+
function Bt(n, t, e, i) {
|
|
585
|
+
const { stiffness: o, damping: s, mass: r, oscillations: a } = i, h = e.x - t.x, c = e.y - t.y, u = Math.sqrt(o / r), l = s / (2 * Math.sqrt(o * r));
|
|
586
586
|
let d;
|
|
587
587
|
if (l < 1) {
|
|
588
|
-
const m = u * Math.sqrt(1 - l * l), b = Math.exp(-l * u *
|
|
588
|
+
const m = u * Math.sqrt(1 - l * l), b = Math.exp(-l * u * n * 3), p = Math.cos(m * n * a * Math.PI);
|
|
589
589
|
d = 1 - b * p;
|
|
590
590
|
} else
|
|
591
|
-
d = 1 - Math.exp(-u *
|
|
591
|
+
d = 1 - Math.exp(-u * n * 3);
|
|
592
592
|
return d = Math.max(0, Math.min(d, 1.3)), {
|
|
593
593
|
x: t.x + h * d,
|
|
594
594
|
y: t.y + c * d
|
|
595
595
|
};
|
|
596
596
|
}
|
|
597
|
-
function
|
|
598
|
-
const { amplitude:
|
|
597
|
+
function Jt(n, t, e, i) {
|
|
598
|
+
const { amplitude: o, frequency: s, decay: r, decayRate: a, phase: h } = i, c = e.x - t.x, u = e.y - t.y, l = Math.sqrt(c * c + u * u), d = l > 0 ? -u / l : 0, m = l > 0 ? c / l : 1, b = s * Math.PI * 2 * n + h, p = r ? Math.pow(1 - n, a) : 1, g = o * Math.sin(b) * p, f = Vt(n);
|
|
599
599
|
return {
|
|
600
600
|
x: V(t.x, e.x, f) + g * d,
|
|
601
601
|
y: V(t.y, e.y, f) + g * m
|
|
602
602
|
};
|
|
603
603
|
}
|
|
604
|
-
function
|
|
605
|
-
return 1 - (1 -
|
|
604
|
+
function ot(n) {
|
|
605
|
+
return 1 - (1 - n) * (1 - n);
|
|
606
606
|
}
|
|
607
|
-
function
|
|
608
|
-
return 1 - Math.pow(1 -
|
|
607
|
+
function Vt(n) {
|
|
608
|
+
return 1 - Math.pow(1 - n, 3);
|
|
609
609
|
}
|
|
610
|
-
function
|
|
611
|
-
const { amplitude: i, frequency:
|
|
610
|
+
function Kt(n, t, e) {
|
|
611
|
+
const { amplitude: i, frequency: o, decay: s } = e, r = Math.sin(n * o * Math.PI * 2), a = s ? Math.pow(1 - n, 2) : 1, h = i * r * a;
|
|
612
612
|
return t + h;
|
|
613
613
|
}
|
|
614
|
-
function
|
|
615
|
-
const { overshoot: i, bounces:
|
|
614
|
+
function Zt(n, t, e) {
|
|
615
|
+
const { overshoot: i, bounces: o } = e, s = [];
|
|
616
616
|
s.push({ time: 0.5, scale: i });
|
|
617
617
|
let r = i;
|
|
618
|
-
const a = 0.5, c = 0.5 / (
|
|
618
|
+
const a = 0.5, c = 0.5 / (o * 2);
|
|
619
619
|
let u = 0.5;
|
|
620
|
-
for (let d = 0; d <
|
|
620
|
+
for (let d = 0; d < o; d++) {
|
|
621
621
|
const m = 1 - (r - 1) * a;
|
|
622
|
-
u += c, s.push({ time: u, scale: m }), r = 1 + (r - 1) * a * a, u += c, d <
|
|
622
|
+
u += c, s.push({ time: u, scale: m }), r = 1 + (r - 1) * a * a, u += c, d < o - 1 && s.push({ time: u, scale: r });
|
|
623
623
|
}
|
|
624
624
|
s.push({ time: 1, scale: 1 });
|
|
625
625
|
let l = 1;
|
|
626
626
|
for (let d = 0; d < s.length; d++)
|
|
627
|
-
if (
|
|
628
|
-
const m = d === 0 ? 0 : s[d - 1].time, b = d === 0 ? 1 : s[d - 1].scale, p = (
|
|
627
|
+
if (n <= s[d].time) {
|
|
628
|
+
const m = d === 0 ? 0 : s[d - 1].time, b = d === 0 ? 1 : s[d - 1].scale, p = (n - m) / (s[d].time - m), g = ot(p);
|
|
629
629
|
l = b + (s[d].scale - b) * g;
|
|
630
630
|
break;
|
|
631
631
|
}
|
|
632
632
|
return l * t;
|
|
633
633
|
}
|
|
634
|
-
function
|
|
634
|
+
function Qt(n) {
|
|
635
635
|
const {
|
|
636
636
|
element: t,
|
|
637
637
|
startPosition: e,
|
|
638
638
|
endPosition: i,
|
|
639
|
-
pathConfig:
|
|
639
|
+
pathConfig: o,
|
|
640
640
|
duration: s,
|
|
641
641
|
imageWidth: r,
|
|
642
642
|
imageHeight: a,
|
|
@@ -647,38 +647,38 @@ function ee(o) {
|
|
|
647
647
|
startRotation: d,
|
|
648
648
|
scaleConfig: m,
|
|
649
649
|
startScale: b
|
|
650
|
-
} =
|
|
650
|
+
} = n, p = o.type, g = d !== void 0 && d !== h, f = l?.mode === "wobble", S = l?.wobble || { amplitude: 15, frequency: 3, decay: !0 }, v = g || f, w = b !== void 0 && b !== c, E = m?.mode === "pop", x = m?.pop || { overshoot: 1.2, bounces: 1 };
|
|
651
651
|
if ((p === "linear" || p === "arc") && !v && !(w || E)) {
|
|
652
652
|
u && u();
|
|
653
653
|
return;
|
|
654
654
|
}
|
|
655
|
-
const
|
|
655
|
+
const L = performance.now(), z = -r / 2, P = -a / 2;
|
|
656
656
|
function _(Y) {
|
|
657
|
-
const N = Y -
|
|
657
|
+
const N = Y - L, T = Math.min(N / s, 1);
|
|
658
658
|
let D;
|
|
659
659
|
switch (p) {
|
|
660
660
|
case "bounce": {
|
|
661
|
-
const O =
|
|
662
|
-
|
|
663
|
-
|
|
661
|
+
const O = kt(
|
|
662
|
+
o.bouncePreset,
|
|
663
|
+
o.bounce
|
|
664
664
|
);
|
|
665
|
-
D =
|
|
665
|
+
D = Yt(T, e, i, O);
|
|
666
666
|
break;
|
|
667
667
|
}
|
|
668
668
|
case "elastic": {
|
|
669
|
-
const O =
|
|
670
|
-
|
|
671
|
-
|
|
669
|
+
const O = Wt(
|
|
670
|
+
o.elasticPreset,
|
|
671
|
+
o.elastic
|
|
672
672
|
);
|
|
673
|
-
D =
|
|
673
|
+
D = Bt(T, e, i, O);
|
|
674
674
|
break;
|
|
675
675
|
}
|
|
676
676
|
case "wave": {
|
|
677
|
-
const O =
|
|
678
|
-
|
|
679
|
-
|
|
677
|
+
const O = Gt(
|
|
678
|
+
o.wavePreset,
|
|
679
|
+
o.wave
|
|
680
680
|
);
|
|
681
|
-
D =
|
|
681
|
+
D = Jt(T, e, i, O);
|
|
682
682
|
break;
|
|
683
683
|
}
|
|
684
684
|
default:
|
|
@@ -689,16 +689,16 @@ function ee(o) {
|
|
|
689
689
|
}
|
|
690
690
|
const k = D.x - i.x, H = D.y - i.y;
|
|
691
691
|
let R;
|
|
692
|
-
f ? R =
|
|
692
|
+
f ? R = Kt(T, h, S) : g ? R = V(d, h, T) : R = h;
|
|
693
693
|
let C;
|
|
694
|
-
E ? C =
|
|
694
|
+
E ? C = Zt(T, c, x) : w ? C = V(b, c, T) : C = c, t.style.transform = `translate(${z}px, ${P}px) translate(${k}px, ${H}px) rotate(${R}deg) scale(${C})`, T < 1 ? requestAnimationFrame(_) : (t.style.transform = `translate(${z}px, ${P}px) rotate(${h}deg) scale(${c})`, u && u());
|
|
695
695
|
}
|
|
696
696
|
requestAnimationFrame(_);
|
|
697
697
|
}
|
|
698
|
-
function
|
|
699
|
-
return
|
|
698
|
+
function te(n) {
|
|
699
|
+
return n === "bounce" || n === "elastic" || n === "wave";
|
|
700
700
|
}
|
|
701
|
-
const
|
|
701
|
+
const ee = {
|
|
702
702
|
radial: "center",
|
|
703
703
|
spiral: "center",
|
|
704
704
|
grid: "top",
|
|
@@ -706,20 +706,20 @@ const ne = {
|
|
|
706
706
|
random: "nearest-edge",
|
|
707
707
|
wave: "left"
|
|
708
708
|
};
|
|
709
|
-
class
|
|
709
|
+
class ie {
|
|
710
710
|
constructor(t, e) {
|
|
711
|
-
this.config = t, this.layoutAlgorithm = e, this.resolvedStartPosition = this.resolveStartPosition(), this.pathConfig = t.path ||
|
|
711
|
+
this.config = t, this.layoutAlgorithm = e, this.resolvedStartPosition = this.resolveStartPosition(), this.pathConfig = t.path || pt, this.rotationConfig = t.rotation || bt, this.scaleConfig = t.scale || yt;
|
|
712
712
|
}
|
|
713
713
|
/**
|
|
714
714
|
* Get the effective start position, considering layout-aware defaults
|
|
715
715
|
*/
|
|
716
716
|
resolveStartPosition() {
|
|
717
|
-
return this.config.start.position ? this.config.start.position :
|
|
717
|
+
return this.config.start.position ? this.config.start.position : ee[this.layoutAlgorithm] || "nearest-edge";
|
|
718
718
|
}
|
|
719
719
|
/**
|
|
720
720
|
* Calculate the starting position for an image's entry animation
|
|
721
721
|
*/
|
|
722
|
-
calculateStartPosition(t, e, i,
|
|
722
|
+
calculateStartPosition(t, e, i, o, s) {
|
|
723
723
|
const r = this.resolvedStartPosition, a = this.config.start.offset ?? 100;
|
|
724
724
|
switch (r) {
|
|
725
725
|
case "nearest-edge":
|
|
@@ -741,7 +741,7 @@ class oe {
|
|
|
741
741
|
t,
|
|
742
742
|
e,
|
|
743
743
|
i,
|
|
744
|
-
|
|
744
|
+
o,
|
|
745
745
|
s
|
|
746
746
|
);
|
|
747
747
|
default:
|
|
@@ -751,28 +751,28 @@ class oe {
|
|
|
751
751
|
/**
|
|
752
752
|
* Calculate start position from the nearest edge (current default behavior)
|
|
753
753
|
*/
|
|
754
|
-
calculateNearestEdge(t, e, i,
|
|
754
|
+
calculateNearestEdge(t, e, i, o) {
|
|
755
755
|
const s = t.x, r = t.y, a = s, h = i.width - s, c = r, u = i.height - r, l = Math.min(a, h, c, u);
|
|
756
756
|
let d = t.x, m = t.y;
|
|
757
|
-
return l === a ? d = -(e.width +
|
|
757
|
+
return l === a ? d = -(e.width + o) : l === h ? d = i.width + o : l === c ? m = -(e.height + o) : m = i.height + o, { x: d, y: m };
|
|
758
758
|
}
|
|
759
759
|
/**
|
|
760
760
|
* Calculate start position from a specific edge
|
|
761
761
|
*/
|
|
762
|
-
calculateEdgePosition(t, e, i,
|
|
762
|
+
calculateEdgePosition(t, e, i, o, s) {
|
|
763
763
|
let r = e.x, a = e.y;
|
|
764
764
|
switch (t) {
|
|
765
765
|
case "top":
|
|
766
766
|
a = -(i.height + s);
|
|
767
767
|
break;
|
|
768
768
|
case "bottom":
|
|
769
|
-
a =
|
|
769
|
+
a = o.height + s;
|
|
770
770
|
break;
|
|
771
771
|
case "left":
|
|
772
772
|
r = -(i.width + s);
|
|
773
773
|
break;
|
|
774
774
|
case "right":
|
|
775
|
-
r =
|
|
775
|
+
r = o.width + s;
|
|
776
776
|
break;
|
|
777
777
|
}
|
|
778
778
|
return { x: r, y: a };
|
|
@@ -781,9 +781,9 @@ class oe {
|
|
|
781
781
|
* Calculate start position from center with scale animation
|
|
782
782
|
*/
|
|
783
783
|
calculateCenterPosition(t, e, i) {
|
|
784
|
-
const
|
|
784
|
+
const o = t.width / 2, s = t.height / 2;
|
|
785
785
|
return {
|
|
786
|
-
x:
|
|
786
|
+
x: o,
|
|
787
787
|
y: s,
|
|
788
788
|
useScale: !0
|
|
789
789
|
// Signal to use scale animation from 0
|
|
@@ -792,14 +792,14 @@ class oe {
|
|
|
792
792
|
/**
|
|
793
793
|
* Calculate start position from a random edge
|
|
794
794
|
*/
|
|
795
|
-
calculateRandomEdge(t, e, i,
|
|
795
|
+
calculateRandomEdge(t, e, i, o) {
|
|
796
796
|
const s = ["top", "bottom", "left", "right"], r = s[Math.floor(Math.random() * s.length)];
|
|
797
|
-
return this.calculateEdgePosition(r, t, e, i,
|
|
797
|
+
return this.calculateEdgePosition(r, t, e, i, o);
|
|
798
798
|
}
|
|
799
799
|
/**
|
|
800
800
|
* Calculate start position on a circle around the container
|
|
801
801
|
*/
|
|
802
|
-
calculateCircularPosition(t, e, i,
|
|
802
|
+
calculateCircularPosition(t, e, i, o, s) {
|
|
803
803
|
const r = this.config.start.circular || {}, a = r.distribution || "even";
|
|
804
804
|
let h;
|
|
805
805
|
const c = r.radius || "120%";
|
|
@@ -811,7 +811,7 @@ class oe {
|
|
|
811
811
|
} else
|
|
812
812
|
h = typeof c == "number" ? c : 500;
|
|
813
813
|
let u;
|
|
814
|
-
a === "even" ? u =
|
|
814
|
+
a === "even" ? u = o / s * 2 * Math.PI : u = Math.random() * 2 * Math.PI;
|
|
815
815
|
const l = i.width / 2, d = i.height / 2, m = l + Math.cos(u) * h, b = d + Math.sin(u) * h;
|
|
816
816
|
return { x: m, y: b };
|
|
817
817
|
}
|
|
@@ -832,17 +832,17 @@ class oe {
|
|
|
832
832
|
* Build a CSS transform string for the start position
|
|
833
833
|
* Uses pixel-based centering offset for reliable cross-browser behavior
|
|
834
834
|
*/
|
|
835
|
-
buildStartTransform(t, e, i,
|
|
836
|
-
const c = t.x - e.x, u = t.y - e.y, l = a !== void 0 ? a : i, d = h !== void 0 ? h :
|
|
835
|
+
buildStartTransform(t, e, i, o, s, r, a, h) {
|
|
836
|
+
const c = t.x - e.x, u = t.y - e.y, l = a !== void 0 ? a : i, d = h !== void 0 ? h : o, m = s !== void 0 ? -s / 2 : 0, b = r !== void 0 ? -r / 2 : 0, p = s !== void 0 ? `translate(${m}px, ${b}px)` : "translate(-50%, -50%)";
|
|
837
837
|
return t.useScale ? `${p} translate(${c}px, ${u}px) rotate(${l}deg) scale(0)` : `${p} translate(${c}px, ${u}px) rotate(${l}deg) scale(${d})`;
|
|
838
838
|
}
|
|
839
839
|
/**
|
|
840
840
|
* Build the final CSS transform string
|
|
841
841
|
* Uses pixel-based centering offset for reliable cross-browser behavior
|
|
842
842
|
*/
|
|
843
|
-
buildFinalTransform(t, e, i,
|
|
844
|
-
if (i !== void 0 &&
|
|
845
|
-
const s = -i / 2, r = -
|
|
843
|
+
buildFinalTransform(t, e, i, o) {
|
|
844
|
+
if (i !== void 0 && o !== void 0) {
|
|
845
|
+
const s = -i / 2, r = -o / 2;
|
|
846
846
|
return `translate(${s}px, ${r}px) rotate(${t}deg) scale(${e})`;
|
|
847
847
|
}
|
|
848
848
|
return `translate(-50%, -50%) rotate(${t}deg) scale(${e})`;
|
|
@@ -859,7 +859,7 @@ class oe {
|
|
|
859
859
|
* Check if the current path type requires JavaScript animation
|
|
860
860
|
*/
|
|
861
861
|
requiresJSAnimation() {
|
|
862
|
-
return
|
|
862
|
+
return te(this.pathConfig.type);
|
|
863
863
|
}
|
|
864
864
|
/**
|
|
865
865
|
* Get the path configuration
|
|
@@ -908,12 +908,12 @@ class oe {
|
|
|
908
908
|
return t + (Math.random() - 0.5) * 60;
|
|
909
909
|
if (typeof i == "number")
|
|
910
910
|
return i;
|
|
911
|
-
const
|
|
912
|
-
return i.min + Math.random() *
|
|
911
|
+
const o = i.max - i.min;
|
|
912
|
+
return i.min + Math.random() * o;
|
|
913
913
|
}
|
|
914
914
|
case "spin": {
|
|
915
|
-
const i = this.rotationConfig.spinCount ?? 1,
|
|
916
|
-
return t + i * 360 *
|
|
915
|
+
const i = this.rotationConfig.spinCount ?? 1, o = this.resolveSpinDirection(t);
|
|
916
|
+
return t + i * 360 * o;
|
|
917
917
|
}
|
|
918
918
|
case "random":
|
|
919
919
|
return t + (Math.random() - 0.5) * 60;
|
|
@@ -961,7 +961,7 @@ class oe {
|
|
|
961
961
|
amplitude: 15,
|
|
962
962
|
frequency: 3,
|
|
963
963
|
decay: !0
|
|
964
|
-
}, { amplitude:
|
|
964
|
+
}, { amplitude: o, frequency: s, decay: r } = i, a = Math.sin(t * s * Math.PI * 2), h = r ? Math.pow(1 - t, 2) : 1, c = o * a * h;
|
|
965
965
|
return e + c;
|
|
966
966
|
}
|
|
967
967
|
/**
|
|
@@ -1018,7 +1018,7 @@ class oe {
|
|
|
1018
1018
|
const i = this.scaleConfig.pop || {
|
|
1019
1019
|
overshoot: 1.2,
|
|
1020
1020
|
bounces: 1
|
|
1021
|
-
}, { overshoot:
|
|
1021
|
+
}, { overshoot: o, bounces: s } = i, r = this.generateScaleBounceKeyframes(s, o);
|
|
1022
1022
|
let a = e;
|
|
1023
1023
|
for (let h = 0; h < r.length; h++)
|
|
1024
1024
|
if (t <= r[h].time) {
|
|
@@ -1034,12 +1034,12 @@ class oe {
|
|
|
1034
1034
|
generateScaleBounceKeyframes(t, e) {
|
|
1035
1035
|
const i = [];
|
|
1036
1036
|
i.push({ time: 0.5, scale: e });
|
|
1037
|
-
let
|
|
1037
|
+
let o = e;
|
|
1038
1038
|
const s = 0.5, a = 0.5 / (t * 2);
|
|
1039
1039
|
let h = 0.5;
|
|
1040
1040
|
for (let c = 0; c < t; c++) {
|
|
1041
|
-
const u = 1 - (
|
|
1042
|
-
h += a, i.push({ time: h, scale: u }),
|
|
1041
|
+
const u = 1 - (o - 1) * s;
|
|
1042
|
+
h += a, i.push({ time: h, scale: u }), o = 1 + (o - 1) * s * s, h += a, c < t - 1 && i.push({ time: h, scale: o });
|
|
1043
1043
|
}
|
|
1044
1044
|
return i.push({ time: 1, scale: 1 }), i;
|
|
1045
1045
|
}
|
|
@@ -1050,7 +1050,7 @@ class oe {
|
|
|
1050
1050
|
return 1 - (1 - t) * (1 - t);
|
|
1051
1051
|
}
|
|
1052
1052
|
}
|
|
1053
|
-
class
|
|
1053
|
+
class ne {
|
|
1054
1054
|
constructor(t, e = {}) {
|
|
1055
1055
|
this.config = t, this.imageConfig = e;
|
|
1056
1056
|
}
|
|
@@ -1062,19 +1062,19 @@ class se {
|
|
|
1062
1062
|
* @returns Array of layout objects with position, rotation, scale
|
|
1063
1063
|
*/
|
|
1064
1064
|
generate(t, e, i = {}) {
|
|
1065
|
-
const
|
|
1065
|
+
const o = [], { width: s, height: r } = e, a = this.config.spacing.padding, h = i.fixedHeight ?? 200, c = this.imageConfig.rotation?.mode ?? "none", u = this.imageConfig.rotation?.range?.min ?? -15, l = this.imageConfig.rotation?.range?.max ?? 15, d = this.imageConfig.sizing?.variance?.min ?? 1, m = this.imageConfig.sizing?.variance?.max ?? 1, b = d !== 1 || m !== 1, g = h * 1.5 / 2, f = h / 2, S = s - a - g, v = r - a - f, w = a + g, E = a + f;
|
|
1066
1066
|
for (let x = 0; x < t; x++) {
|
|
1067
|
-
const A = this.random(w, S),
|
|
1067
|
+
const A = this.random(w, S), L = this.random(E, v), z = c === "random" ? this.random(u, l) : 0, P = b ? this.random(d, m) : 1, _ = h * P, Y = {
|
|
1068
1068
|
id: x,
|
|
1069
1069
|
x: A,
|
|
1070
|
-
y:
|
|
1070
|
+
y: L,
|
|
1071
1071
|
rotation: z,
|
|
1072
1072
|
scale: P,
|
|
1073
1073
|
baseSize: _
|
|
1074
1074
|
};
|
|
1075
|
-
|
|
1075
|
+
o.push(Y);
|
|
1076
1076
|
}
|
|
1077
|
-
return
|
|
1077
|
+
return o;
|
|
1078
1078
|
}
|
|
1079
1079
|
/**
|
|
1080
1080
|
* Utility: Generate random number between min and max
|
|
@@ -1086,7 +1086,7 @@ class se {
|
|
|
1086
1086
|
return Math.random() * (e - t) + t;
|
|
1087
1087
|
}
|
|
1088
1088
|
}
|
|
1089
|
-
class
|
|
1089
|
+
class oe {
|
|
1090
1090
|
constructor(t, e = {}) {
|
|
1091
1091
|
this.config = t, this.imageConfig = e;
|
|
1092
1092
|
}
|
|
@@ -1098,10 +1098,10 @@ class ae {
|
|
|
1098
1098
|
* @returns Array of layout objects with position, rotation, scale
|
|
1099
1099
|
*/
|
|
1100
1100
|
generate(t, e, i = {}) {
|
|
1101
|
-
const
|
|
1101
|
+
const o = [], { width: s, height: r } = e, a = i.fixedHeight ?? 200, h = this.imageConfig.rotation?.mode ?? "none", c = this.imageConfig.rotation?.range?.min ?? -15, u = this.imageConfig.rotation?.range?.max ?? 15, l = this.imageConfig.sizing?.variance?.min ?? 1, d = this.imageConfig.sizing?.variance?.max ?? 1, m = l !== 1 || d !== 1, b = this.config.scaleDecay ?? 0, p = i.fixedHeight ?? a, g = s / 2, f = r / 2, S = Math.ceil(Math.sqrt(t));
|
|
1102
1102
|
if (t > 0) {
|
|
1103
1103
|
const E = m ? this.random(l, d) : 1, x = p * E;
|
|
1104
|
-
|
|
1104
|
+
o.push({
|
|
1105
1105
|
id: 0,
|
|
1106
1106
|
x: g,
|
|
1107
1107
|
y: f,
|
|
@@ -1115,7 +1115,7 @@ class ae {
|
|
|
1115
1115
|
}
|
|
1116
1116
|
let v = 1, w = 1;
|
|
1117
1117
|
for (; v < t; ) {
|
|
1118
|
-
const E = w / S, x = b > 0 ? 1 - E * b * 0.5 : 1, A = w * (p * 0.8),
|
|
1118
|
+
const E = w / S, x = b > 0 ? 1 - E * b * 0.5 : 1, A = w * (p * 0.8), L = A * 1.5, z = Math.PI * (3 * (L + A) - Math.sqrt((3 * L + A) * (L + 3 * A))), P = this.estimateWidth(p), _ = Math.floor(z / (P * 0.7));
|
|
1119
1119
|
if (_ === 0) {
|
|
1120
1120
|
w++;
|
|
1121
1121
|
continue;
|
|
@@ -1123,15 +1123,15 @@ class ae {
|
|
|
1123
1123
|
const Y = 2 * Math.PI / _, N = w * (20 * Math.PI / 180);
|
|
1124
1124
|
for (let T = 0; T < _ && v < t; T++) {
|
|
1125
1125
|
const D = T * Y + N, k = m ? this.random(l, d) : 1, H = x * k, R = p * H;
|
|
1126
|
-
let C = g + Math.cos(D) *
|
|
1127
|
-
const $ = this.config.spacing.padding ?? 50, U = R * 1.5 / 2,
|
|
1128
|
-
C - U < $ ? C = $ + U : C + U > s - $ && (C = s - $ - U), O -
|
|
1129
|
-
const
|
|
1130
|
-
|
|
1126
|
+
let C = g + Math.cos(D) * L, O = f + Math.sin(D) * A;
|
|
1127
|
+
const $ = this.config.spacing.padding ?? 50, U = R * 1.5 / 2, M = R / 2;
|
|
1128
|
+
C - U < $ ? C = $ + U : C + U > s - $ && (C = s - $ - U), O - M < $ ? O = $ + M : O + M > r - $ && (O = r - $ - M);
|
|
1129
|
+
const W = h === "random" ? this.random(c, u) : 0;
|
|
1130
|
+
o.push({
|
|
1131
1131
|
id: v,
|
|
1132
1132
|
x: C,
|
|
1133
1133
|
y: O,
|
|
1134
|
-
rotation:
|
|
1134
|
+
rotation: W,
|
|
1135
1135
|
scale: H,
|
|
1136
1136
|
baseSize: R,
|
|
1137
1137
|
zIndex: Math.max(1, 100 - w)
|
|
@@ -1140,7 +1140,7 @@ class ae {
|
|
|
1140
1140
|
}
|
|
1141
1141
|
w++;
|
|
1142
1142
|
}
|
|
1143
|
-
return
|
|
1143
|
+
return o;
|
|
1144
1144
|
}
|
|
1145
1145
|
/**
|
|
1146
1146
|
* Estimate image width based on height
|
|
@@ -1161,7 +1161,7 @@ class ae {
|
|
|
1161
1161
|
return Math.random() * (e - t) + t;
|
|
1162
1162
|
}
|
|
1163
1163
|
}
|
|
1164
|
-
const
|
|
1164
|
+
const se = {
|
|
1165
1165
|
columns: "auto",
|
|
1166
1166
|
rows: "auto",
|
|
1167
1167
|
stagger: "none",
|
|
@@ -1171,7 +1171,7 @@ const re = {
|
|
|
1171
1171
|
alignment: "center",
|
|
1172
1172
|
gap: 10,
|
|
1173
1173
|
overflowOffset: 0.25
|
|
1174
|
-
},
|
|
1174
|
+
}, Et = [
|
|
1175
1175
|
{ x: 1, y: 1 },
|
|
1176
1176
|
// bottom-right
|
|
1177
1177
|
{ x: -1, y: -1 },
|
|
@@ -1189,7 +1189,7 @@ const re = {
|
|
|
1189
1189
|
{ x: 0, y: 1 }
|
|
1190
1190
|
// down
|
|
1191
1191
|
];
|
|
1192
|
-
class
|
|
1192
|
+
class ae {
|
|
1193
1193
|
constructor(t, e = {}) {
|
|
1194
1194
|
this.config = t, this.imageConfig = e;
|
|
1195
1195
|
}
|
|
@@ -1201,13 +1201,13 @@ class ce {
|
|
|
1201
1201
|
* @returns Array of layout objects with position, rotation, scale
|
|
1202
1202
|
*/
|
|
1203
1203
|
generate(t, e, i = {}) {
|
|
1204
|
-
const
|
|
1204
|
+
const o = [], { width: s, height: r } = e, a = { ...se, ...this.config.grid }, h = this.config.spacing.padding, c = i.fixedHeight ?? 200, u = this.imageConfig.rotation?.mode ?? "none", l = this.imageConfig.sizing?.variance?.min ?? 1, d = this.imageConfig.sizing?.variance?.max ?? 1, m = l !== 1 || d !== 1, b = s - 2 * h, p = r - 2 * h, { columns: g, rows: f } = this.calculateGridDimensions(
|
|
1205
1205
|
t,
|
|
1206
1206
|
b,
|
|
1207
1207
|
p,
|
|
1208
1208
|
c,
|
|
1209
1209
|
a
|
|
1210
|
-
), S = a.stagger === "row", v = a.stagger === "column", w = S ? g + 0.5 : g, E = v ? f + 0.5 : f, x = (b - a.gap * (g - 1)) / w, A = (p - a.gap * (f - 1)) / E,
|
|
1210
|
+
), S = a.stagger === "row", v = a.stagger === "column", w = S ? g + 0.5 : g, E = v ? f + 0.5 : f, x = (b - a.gap * (g - 1)) / w, A = (p - a.gap * (f - 1)) / E, L = S ? x / 2 : 0, z = v ? A / 2 : 0, P = 1 + a.overlap, _ = Math.min(x, A) * P, Y = i.fixedHeight ? Math.min(i.fixedHeight, _) : _, N = g * x + (g - 1) * a.gap + L, T = f * A + (f - 1) * a.gap + z, D = h + (b - N) / 2, k = h + (p - T) / 2, H = g * f, R = a.columns !== "auto" && a.rows !== "auto", C = R && t > H;
|
|
1211
1211
|
typeof window < "u" && (window.__gridOverflowDebug = {
|
|
1212
1212
|
gridConfigColumns: a.columns,
|
|
1213
1213
|
gridConfigRows: a.rows,
|
|
@@ -1220,54 +1220,54 @@ class ce {
|
|
|
1220
1220
|
});
|
|
1221
1221
|
const O = C ? new Array(H).fill(0) : [], $ = Math.min(x, A) * a.overflowOffset;
|
|
1222
1222
|
for (let F = 0; F < t; F++) {
|
|
1223
|
-
let U,
|
|
1223
|
+
let U, M, W = 0;
|
|
1224
1224
|
if (C && F >= H) {
|
|
1225
1225
|
const q = F - H, j = q % H;
|
|
1226
|
-
|
|
1226
|
+
W = Math.floor(q / H) + 1, O[j]++, a.fillDirection === "row" ? (U = j % g, M = Math.floor(j / g)) : (M = j % f, U = Math.floor(j / f));
|
|
1227
1227
|
} else
|
|
1228
|
-
a.fillDirection === "row" ? (U = F % g,
|
|
1229
|
-
let
|
|
1230
|
-
if (a.stagger === "row" &&
|
|
1231
|
-
const q = (
|
|
1232
|
-
|
|
1228
|
+
a.fillDirection === "row" ? (U = F % g, M = Math.floor(F / g)) : (M = F % f, U = Math.floor(F / f));
|
|
1229
|
+
let G = D + U * (x + a.gap) + x / 2, X = k + M * (A + a.gap) + A / 2;
|
|
1230
|
+
if (a.stagger === "row" && M % 2 === 1 ? G += x / 2 : a.stagger === "column" && U % 2 === 1 && (X += A / 2), W > 0) {
|
|
1231
|
+
const q = (W - 1) % Et.length, j = Et[q];
|
|
1232
|
+
G += j.x * $, X += j.y * $;
|
|
1233
1233
|
}
|
|
1234
1234
|
if (a.jitter > 0) {
|
|
1235
1235
|
const q = x / 2 * a.jitter, j = A / 2 * a.jitter;
|
|
1236
|
-
|
|
1236
|
+
G += this.random(-q, q), X += this.random(-j, j);
|
|
1237
1237
|
}
|
|
1238
|
-
let B =
|
|
1238
|
+
let B = G, J = X;
|
|
1239
1239
|
if (!C && a.fillDirection === "row") {
|
|
1240
1240
|
const q = t % g || g;
|
|
1241
|
-
if (
|
|
1242
|
-
const
|
|
1243
|
-
let
|
|
1244
|
-
a.alignment === "center" ?
|
|
1241
|
+
if (M === Math.floor((t - 1) / g) && q < g) {
|
|
1242
|
+
const vt = q * x + (q - 1) * a.gap;
|
|
1243
|
+
let gt = 0;
|
|
1244
|
+
a.alignment === "center" ? gt = (N - vt) / 2 : a.alignment === "end" && (gt = N - vt), B += gt;
|
|
1245
1245
|
}
|
|
1246
1246
|
}
|
|
1247
|
-
const
|
|
1248
|
-
B = Math.max(
|
|
1249
|
-
let
|
|
1247
|
+
const rt = m ? this.random(l, d) : 1, K = Y * rt, it = K * 1.5 / 2, nt = K / 2, lt = h + it, ht = s - h - it, zt = h + nt, Ft = r - h - nt;
|
|
1248
|
+
B = Math.max(lt, Math.min(B, ht)), J = Math.max(zt, Math.min(J, Ft));
|
|
1249
|
+
let dt = 0;
|
|
1250
1250
|
if (u === "random") {
|
|
1251
1251
|
const q = this.imageConfig.rotation?.range?.min ?? -15, j = this.imageConfig.rotation?.range?.max ?? 15;
|
|
1252
|
-
a.jitter > 0 ?
|
|
1252
|
+
a.jitter > 0 ? dt = this.random(q * a.jitter, j * a.jitter) : dt = this.random(q, j);
|
|
1253
1253
|
}
|
|
1254
|
-
let
|
|
1255
|
-
C &&
|
|
1254
|
+
let ut;
|
|
1255
|
+
C && W > 0 ? ut = 50 - W : ut = C ? 100 + F : F + 1, o.push({
|
|
1256
1256
|
id: F,
|
|
1257
1257
|
x: B,
|
|
1258
1258
|
y: J,
|
|
1259
|
-
rotation:
|
|
1260
|
-
scale:
|
|
1259
|
+
rotation: dt,
|
|
1260
|
+
scale: rt,
|
|
1261
1261
|
baseSize: K,
|
|
1262
|
-
zIndex:
|
|
1262
|
+
zIndex: ut
|
|
1263
1263
|
});
|
|
1264
1264
|
}
|
|
1265
|
-
return
|
|
1265
|
+
return o;
|
|
1266
1266
|
}
|
|
1267
1267
|
/**
|
|
1268
1268
|
* Calculate optimal grid dimensions based on image count and container
|
|
1269
1269
|
*/
|
|
1270
|
-
calculateGridDimensions(t, e, i,
|
|
1270
|
+
calculateGridDimensions(t, e, i, o, s) {
|
|
1271
1271
|
let r, a;
|
|
1272
1272
|
if (s.columns !== "auto" && s.rows !== "auto")
|
|
1273
1273
|
r = s.columns, a = s.rows;
|
|
@@ -1289,14 +1289,14 @@ class ce {
|
|
|
1289
1289
|
return Math.random() * (e - t) + t;
|
|
1290
1290
|
}
|
|
1291
1291
|
}
|
|
1292
|
-
const
|
|
1292
|
+
const re = Math.PI * (3 - Math.sqrt(5)), ce = {
|
|
1293
1293
|
spiralType: "golden",
|
|
1294
1294
|
direction: "counterclockwise",
|
|
1295
1295
|
tightness: 1,
|
|
1296
1296
|
scaleDecay: 0,
|
|
1297
1297
|
startAngle: 0
|
|
1298
1298
|
};
|
|
1299
|
-
class
|
|
1299
|
+
class le {
|
|
1300
1300
|
constructor(t, e = {}) {
|
|
1301
1301
|
this.config = t, this.imageConfig = e;
|
|
1302
1302
|
}
|
|
@@ -1308,79 +1308,79 @@ class de {
|
|
|
1308
1308
|
* @returns Array of layout objects with position, rotation, scale
|
|
1309
1309
|
*/
|
|
1310
1310
|
generate(t, e, i = {}) {
|
|
1311
|
-
const
|
|
1311
|
+
const o = [], { width: s, height: r } = e, a = { ...ce, ...this.config.spiral }, h = this.config.spacing.padding, c = i.fixedHeight ?? 200, u = this.imageConfig.rotation?.mode ?? "none", l = this.imageConfig.rotation?.range?.min ?? -15, d = this.imageConfig.rotation?.range?.max ?? 15, m = this.imageConfig.sizing?.variance?.min ?? 1, b = this.imageConfig.sizing?.variance?.max ?? 1, p = m !== 1 || b !== 1, g = this.config.scaleDecay ?? a.scaleDecay, f = s / 2, S = r / 2, v = Math.min(
|
|
1312
1312
|
f - h - c / 2,
|
|
1313
1313
|
S - h - c / 2
|
|
1314
1314
|
), w = a.direction === "clockwise" ? -1 : 1;
|
|
1315
1315
|
for (let E = 0; E < t; E++) {
|
|
1316
1316
|
let x, A;
|
|
1317
1317
|
if (a.spiralType === "golden")
|
|
1318
|
-
x = E *
|
|
1318
|
+
x = E * re * w + a.startAngle, A = this.calculateGoldenRadius(E, t, v, a.tightness);
|
|
1319
1319
|
else if (a.spiralType === "archimedean") {
|
|
1320
|
-
const
|
|
1321
|
-
x =
|
|
1320
|
+
const G = E * 0.5 * a.tightness;
|
|
1321
|
+
x = G * w + a.startAngle, A = this.calculateArchimedeanRadius(G, t, v, a.tightness);
|
|
1322
1322
|
} else {
|
|
1323
|
-
const
|
|
1324
|
-
x =
|
|
1323
|
+
const G = E * 0.3 * a.tightness;
|
|
1324
|
+
x = G * w + a.startAngle, A = this.calculateLogarithmicRadius(G, t, v, a.tightness);
|
|
1325
1325
|
}
|
|
1326
|
-
const
|
|
1327
|
-
let
|
|
1326
|
+
const L = f + Math.cos(x) * A, z = S + Math.sin(x) * A, P = A / v, _ = g > 0 ? 1 - P * g * 0.5 : 1, Y = p ? this.random(m, b) : 1, N = _ * Y, T = c * N, k = T * 1.5 / 2, H = T / 2, R = h + k, C = s - h - k, O = h + H, $ = r - h - H, F = Math.max(R, Math.min(L, C)), U = Math.max(O, Math.min(z, $));
|
|
1327
|
+
let M = 0;
|
|
1328
1328
|
if (u === "random") {
|
|
1329
|
-
const
|
|
1330
|
-
|
|
1331
|
-
} else u === "tangent" && (
|
|
1332
|
-
const
|
|
1333
|
-
|
|
1329
|
+
const G = x * 180 / Math.PI % 360, X = this.random(l, d);
|
|
1330
|
+
M = a.spiralType === "golden" ? X : G * 0.1 + X * 0.9;
|
|
1331
|
+
} else u === "tangent" && (M = this.calculateSpiralTangent(x, A, a));
|
|
1332
|
+
const W = t - E;
|
|
1333
|
+
o.push({
|
|
1334
1334
|
id: E,
|
|
1335
1335
|
x: F,
|
|
1336
1336
|
y: U,
|
|
1337
|
-
rotation:
|
|
1337
|
+
rotation: M,
|
|
1338
1338
|
scale: N,
|
|
1339
1339
|
baseSize: T,
|
|
1340
|
-
zIndex:
|
|
1340
|
+
zIndex: W
|
|
1341
1341
|
});
|
|
1342
1342
|
}
|
|
1343
|
-
return
|
|
1343
|
+
return o;
|
|
1344
1344
|
}
|
|
1345
1345
|
/**
|
|
1346
1346
|
* Calculate tangent angle for spiral curve at given position
|
|
1347
1347
|
* This aligns the image along the spiral's direction of travel
|
|
1348
1348
|
*/
|
|
1349
1349
|
calculateSpiralTangent(t, e, i) {
|
|
1350
|
-
let
|
|
1350
|
+
let o;
|
|
1351
1351
|
if (i.spiralType === "golden")
|
|
1352
|
-
|
|
1352
|
+
o = t + Math.PI / 2;
|
|
1353
1353
|
else if (i.spiralType === "archimedean") {
|
|
1354
1354
|
const r = 1 / i.tightness, a = Math.atan(e / r);
|
|
1355
|
-
|
|
1355
|
+
o = t + a;
|
|
1356
1356
|
} else {
|
|
1357
1357
|
const r = 0.15 / i.tightness, a = Math.atan(1 / r);
|
|
1358
|
-
|
|
1358
|
+
o = t + a;
|
|
1359
1359
|
}
|
|
1360
|
-
return
|
|
1360
|
+
return o * 180 / Math.PI % 360 - 90;
|
|
1361
1361
|
}
|
|
1362
1362
|
/**
|
|
1363
1363
|
* Calculate radius for golden spiral (Vogel's model)
|
|
1364
1364
|
* Creates even distribution like sunflower seeds
|
|
1365
1365
|
*/
|
|
1366
|
-
calculateGoldenRadius(t, e, i,
|
|
1367
|
-
const r = i / Math.sqrt(e) * Math.sqrt(t) /
|
|
1366
|
+
calculateGoldenRadius(t, e, i, o) {
|
|
1367
|
+
const r = i / Math.sqrt(e) * Math.sqrt(t) / o;
|
|
1368
1368
|
return Math.min(r, i);
|
|
1369
1369
|
}
|
|
1370
1370
|
/**
|
|
1371
1371
|
* Calculate radius for Archimedean spiral
|
|
1372
1372
|
* r = a + b*θ (constant spacing between arms)
|
|
1373
1373
|
*/
|
|
1374
|
-
calculateArchimedeanRadius(t, e, i,
|
|
1375
|
-
const s = e * 0.5 *
|
|
1374
|
+
calculateArchimedeanRadius(t, e, i, o) {
|
|
1375
|
+
const s = e * 0.5 * o;
|
|
1376
1376
|
return t / s * i;
|
|
1377
1377
|
}
|
|
1378
1378
|
/**
|
|
1379
1379
|
* Calculate radius for logarithmic (equiangular) spiral
|
|
1380
1380
|
* r = a * e^(b*θ)
|
|
1381
1381
|
*/
|
|
1382
|
-
calculateLogarithmicRadius(t, e, i,
|
|
1383
|
-
const s = i * 0.05, r = 0.15 /
|
|
1382
|
+
calculateLogarithmicRadius(t, e, i, o) {
|
|
1383
|
+
const s = i * 0.05, r = 0.15 / o, a = s * Math.exp(r * t), h = e * 0.3 * o, c = s * Math.exp(r * h);
|
|
1384
1384
|
return a / c * i;
|
|
1385
1385
|
}
|
|
1386
1386
|
/**
|
|
@@ -1390,7 +1390,7 @@ class de {
|
|
|
1390
1390
|
return Math.random() * (e - t) + t;
|
|
1391
1391
|
}
|
|
1392
1392
|
}
|
|
1393
|
-
const
|
|
1393
|
+
const he = {
|
|
1394
1394
|
clusterCount: "auto",
|
|
1395
1395
|
clusterSpread: 150,
|
|
1396
1396
|
clusterSpacing: 200,
|
|
@@ -1398,7 +1398,7 @@ const ue = {
|
|
|
1398
1398
|
overlap: 0.3,
|
|
1399
1399
|
distribution: "gaussian"
|
|
1400
1400
|
};
|
|
1401
|
-
class
|
|
1401
|
+
class de {
|
|
1402
1402
|
constructor(t, e = {}) {
|
|
1403
1403
|
this.config = t, this.imageConfig = e;
|
|
1404
1404
|
}
|
|
@@ -1410,7 +1410,7 @@ class ge {
|
|
|
1410
1410
|
* @returns Array of layout objects with position, rotation, scale
|
|
1411
1411
|
*/
|
|
1412
1412
|
generate(t, e, i = {}) {
|
|
1413
|
-
const
|
|
1413
|
+
const o = [], { width: s, height: r } = e, a = { ...he, ...this.config.cluster }, h = this.config.spacing.padding, c = i.fixedHeight ?? 200, u = this.imageConfig.rotation?.mode ?? "none", l = this.imageConfig.rotation?.range?.min ?? -15, d = this.imageConfig.rotation?.range?.max ?? 15, m = this.imageConfig.sizing?.variance?.min ?? 1, b = this.imageConfig.sizing?.variance?.max ?? 1, p = m !== 1 || b !== 1, g = this.calculateClusterCount(
|
|
1414
1414
|
t,
|
|
1415
1415
|
a.clusterCount,
|
|
1416
1416
|
s,
|
|
@@ -1429,21 +1429,21 @@ class ge {
|
|
|
1429
1429
|
for (let w = 0; w < g; w++) {
|
|
1430
1430
|
const E = f[w], x = S[w];
|
|
1431
1431
|
for (let A = 0; A < x; A++) {
|
|
1432
|
-
let
|
|
1432
|
+
let L, z;
|
|
1433
1433
|
if (a.distribution === "gaussian")
|
|
1434
|
-
|
|
1434
|
+
L = this.gaussianRandom() * E.spread, z = this.gaussianRandom() * E.spread;
|
|
1435
1435
|
else {
|
|
1436
|
-
const
|
|
1437
|
-
|
|
1436
|
+
const M = this.random(0, Math.PI * 2), W = this.random(0, E.spread);
|
|
1437
|
+
L = Math.cos(M) * W, z = Math.sin(M) * W;
|
|
1438
1438
|
}
|
|
1439
1439
|
const P = 1 + a.overlap * 0.5, _ = 1 + a.overlap * 0.3;
|
|
1440
|
-
|
|
1440
|
+
L /= P, z /= P;
|
|
1441
1441
|
const Y = p ? this.random(m, b) : 1, N = _ * Y, T = c * N;
|
|
1442
|
-
let D = E.x +
|
|
1442
|
+
let D = E.x + L, k = E.y + z;
|
|
1443
1443
|
const R = T * 1.5 / 2, C = T / 2;
|
|
1444
1444
|
D = Math.max(h + R, Math.min(D, s - h - R)), k = Math.max(h + C, Math.min(k, r - h - C));
|
|
1445
|
-
const O = u === "random" ? this.random(l, d) : 0, F = Math.sqrt(
|
|
1446
|
-
|
|
1445
|
+
const O = u === "random" ? this.random(l, d) : 0, F = Math.sqrt(L * L + z * z) / E.spread, U = Math.round((1 - F) * 50) + 1;
|
|
1446
|
+
o.push({
|
|
1447
1447
|
id: v,
|
|
1448
1448
|
x: D,
|
|
1449
1449
|
y: k,
|
|
@@ -1454,24 +1454,24 @@ class ge {
|
|
|
1454
1454
|
}), v++;
|
|
1455
1455
|
}
|
|
1456
1456
|
}
|
|
1457
|
-
return
|
|
1457
|
+
return o;
|
|
1458
1458
|
}
|
|
1459
1459
|
/**
|
|
1460
1460
|
* Calculate optimal number of clusters based on image count and container
|
|
1461
1461
|
*/
|
|
1462
|
-
calculateClusterCount(t, e, i,
|
|
1462
|
+
calculateClusterCount(t, e, i, o, s) {
|
|
1463
1463
|
if (e !== "auto")
|
|
1464
1464
|
return Math.max(1, Math.min(e, t));
|
|
1465
1465
|
const a = Math.max(1, Math.ceil(t / 8)), h = Math.floor(
|
|
1466
|
-
i / s * (
|
|
1466
|
+
i / s * (o / s) * 0.6
|
|
1467
1467
|
);
|
|
1468
1468
|
return Math.max(1, Math.min(a, h, 10));
|
|
1469
1469
|
}
|
|
1470
1470
|
/**
|
|
1471
1471
|
* Generate cluster center positions with spacing constraints
|
|
1472
1472
|
*/
|
|
1473
|
-
generateClusterCenters(t, e, i,
|
|
1474
|
-
const r = [], h =
|
|
1473
|
+
generateClusterCenters(t, e, i, o, s) {
|
|
1474
|
+
const r = [], h = o + s.clusterSpread, c = e - o - s.clusterSpread, u = o + s.clusterSpread, l = i - o - s.clusterSpread;
|
|
1475
1475
|
for (let d = 0; d < t; d++) {
|
|
1476
1476
|
let m = null, b = -1;
|
|
1477
1477
|
for (let p = 0; p < 100; p++) {
|
|
@@ -1516,7 +1516,7 @@ class ge {
|
|
|
1516
1516
|
return Math.random() * (e - t) + t;
|
|
1517
1517
|
}
|
|
1518
1518
|
}
|
|
1519
|
-
class
|
|
1519
|
+
class ue {
|
|
1520
1520
|
constructor(t, e = {}) {
|
|
1521
1521
|
this.config = t, this.imageConfig = e;
|
|
1522
1522
|
}
|
|
@@ -1528,8 +1528,8 @@ class me {
|
|
|
1528
1528
|
* @returns Array of layout objects with position, rotation, scale
|
|
1529
1529
|
*/
|
|
1530
1530
|
generate(t, e, i = {}) {
|
|
1531
|
-
const
|
|
1532
|
-
|
|
1531
|
+
const o = [], { width: s, height: r } = e, a = i.fixedHeight ?? 200, h = this.config.spacing.padding ?? 50, c = this.imageConfig.rotation?.mode ?? "none", u = this.imageConfig.rotation?.range?.min ?? -15, l = this.imageConfig.rotation?.range?.max ?? 15, d = this.imageConfig.sizing?.variance?.min ?? 1, m = this.imageConfig.sizing?.variance?.max ?? 1, b = d !== 1 || m !== 1, p = i.fixedHeight ?? a, g = {
|
|
1532
|
+
...Dt,
|
|
1533
1533
|
...this.config.wave
|
|
1534
1534
|
}, { rows: f, amplitude: S, frequency: v, phaseShift: w, synchronization: E } = g, x = Math.ceil(t / f), z = p * 1.5 / 2, P = h + z, _ = s - h - z, Y = _ - P, N = x > 1 ? Y / (x - 1) : 0, T = h + S + p / 2, D = r - h - S - p / 2, k = D - T, H = f > 1 ? k / (f - 1) : 0;
|
|
1535
1535
|
let R = 0;
|
|
@@ -1538,14 +1538,14 @@ class me {
|
|
|
1538
1538
|
let $ = 0;
|
|
1539
1539
|
E === "offset" ? $ = C * w : E === "alternating" && ($ = C * Math.PI);
|
|
1540
1540
|
for (let F = 0; F < x && R < t; F++) {
|
|
1541
|
-
const U = x === 1 ? (P + _) / 2 : P + F * N,
|
|
1541
|
+
const U = x === 1 ? (P + _) / 2 : P + F * N, M = this.calculateWaveY(U, s, S, v, $), W = U, G = O + M, X = b ? this.random(d, m) : 1, B = p * X;
|
|
1542
1542
|
let J = 0;
|
|
1543
1543
|
c === "tangent" ? J = this.calculateRotation(U, s, S, v, $) : c === "random" && (J = this.random(u, l));
|
|
1544
|
-
const K = B * 1.5 / 2,
|
|
1545
|
-
|
|
1544
|
+
const K = B * 1.5 / 2, ct = B / 2, it = h + K, nt = s - h - K, lt = h + ct, ht = r - h - ct;
|
|
1545
|
+
o.push({
|
|
1546
1546
|
id: R,
|
|
1547
|
-
x: Math.max(
|
|
1548
|
-
y: Math.max(
|
|
1547
|
+
x: Math.max(it, Math.min(W, nt)),
|
|
1548
|
+
y: Math.max(lt, Math.min(G, ht)),
|
|
1549
1549
|
rotation: J,
|
|
1550
1550
|
scale: X,
|
|
1551
1551
|
baseSize: B,
|
|
@@ -1553,7 +1553,7 @@ class me {
|
|
|
1553
1553
|
}), R++;
|
|
1554
1554
|
}
|
|
1555
1555
|
}
|
|
1556
|
-
return
|
|
1556
|
+
return o;
|
|
1557
1557
|
}
|
|
1558
1558
|
/**
|
|
1559
1559
|
* Calculate Y position displacement on wave curve
|
|
@@ -1564,9 +1564,9 @@ class me {
|
|
|
1564
1564
|
* @param phase - Phase offset
|
|
1565
1565
|
* @returns Y displacement from baseline
|
|
1566
1566
|
*/
|
|
1567
|
-
calculateWaveY(t, e, i,
|
|
1567
|
+
calculateWaveY(t, e, i, o, s) {
|
|
1568
1568
|
const r = t / e;
|
|
1569
|
-
return i * Math.sin(
|
|
1569
|
+
return i * Math.sin(o * r * 2 * Math.PI + s);
|
|
1570
1570
|
}
|
|
1571
1571
|
/**
|
|
1572
1572
|
* Calculate rotation based on wave tangent
|
|
@@ -1577,8 +1577,8 @@ class me {
|
|
|
1577
1577
|
* @param phase - Phase offset
|
|
1578
1578
|
* @returns Rotation angle in degrees
|
|
1579
1579
|
*/
|
|
1580
|
-
calculateRotation(t, e, i,
|
|
1581
|
-
const r = t / e, a = i *
|
|
1580
|
+
calculateRotation(t, e, i, o, s) {
|
|
1581
|
+
const r = t / e, a = i * o * 2 * Math.PI * Math.cos(o * r * 2 * Math.PI + s) / e;
|
|
1582
1582
|
return Math.atan(a) * (180 / Math.PI);
|
|
1583
1583
|
}
|
|
1584
1584
|
/**
|
|
@@ -1593,7 +1593,7 @@ class me {
|
|
|
1593
1593
|
return Math.random() * (e - t) + t;
|
|
1594
1594
|
}
|
|
1595
1595
|
}
|
|
1596
|
-
class
|
|
1596
|
+
class ge {
|
|
1597
1597
|
constructor(t) {
|
|
1598
1598
|
this.config = t.layout, this.imageConfig = t.image, this.layouts = /* @__PURE__ */ new Map(), this.placementLayout = this.initLayout();
|
|
1599
1599
|
}
|
|
@@ -1604,17 +1604,17 @@ class fe {
|
|
|
1604
1604
|
initLayout() {
|
|
1605
1605
|
switch (this.config.algorithm) {
|
|
1606
1606
|
case "radial":
|
|
1607
|
-
return new
|
|
1607
|
+
return new oe(this.config, this.imageConfig);
|
|
1608
1608
|
case "grid":
|
|
1609
|
-
return new
|
|
1609
|
+
return new ae(this.config, this.imageConfig);
|
|
1610
1610
|
case "spiral":
|
|
1611
|
-
return new
|
|
1611
|
+
return new le(this.config, this.imageConfig);
|
|
1612
1612
|
case "cluster":
|
|
1613
|
-
return new
|
|
1613
|
+
return new de(this.config, this.imageConfig);
|
|
1614
1614
|
case "wave":
|
|
1615
|
-
return new
|
|
1615
|
+
return new ue(this.config, this.imageConfig);
|
|
1616
1616
|
default:
|
|
1617
|
-
return new
|
|
1617
|
+
return new ne(this.config, this.imageConfig);
|
|
1618
1618
|
}
|
|
1619
1619
|
}
|
|
1620
1620
|
/**
|
|
@@ -1625,10 +1625,10 @@ class fe {
|
|
|
1625
1625
|
* @returns Array of layout objects with position, rotation, scale
|
|
1626
1626
|
*/
|
|
1627
1627
|
generateLayout(t, e, i = {}) {
|
|
1628
|
-
const
|
|
1629
|
-
return
|
|
1628
|
+
const o = this.placementLayout.generate(t, e, i);
|
|
1629
|
+
return o.forEach((s) => {
|
|
1630
1630
|
this.layouts.set(s.id, s);
|
|
1631
|
-
}),
|
|
1631
|
+
}), o;
|
|
1632
1632
|
}
|
|
1633
1633
|
/**
|
|
1634
1634
|
* Get the original layout state for an image
|
|
@@ -1681,8 +1681,8 @@ class fe {
|
|
|
1681
1681
|
return;
|
|
1682
1682
|
if (typeof i == "number")
|
|
1683
1683
|
return i;
|
|
1684
|
-
const
|
|
1685
|
-
return s === "mobile" ?
|
|
1684
|
+
const o = i, s = this.resolveBreakpoint(t);
|
|
1685
|
+
return s === "mobile" ? o.mobile ?? o.tablet ?? o.screen : s === "tablet" ? o.tablet ?? o.screen ?? o.mobile : o.screen ?? o.tablet ?? o.mobile;
|
|
1686
1686
|
}
|
|
1687
1687
|
/**
|
|
1688
1688
|
* Calculate adaptive image size based on container dimensions and image count
|
|
@@ -1692,8 +1692,8 @@ class fe {
|
|
|
1692
1692
|
* @param viewportWidth - Current viewport width for baseHeight resolution
|
|
1693
1693
|
* @returns Calculated sizing result with height
|
|
1694
1694
|
*/
|
|
1695
|
-
calculateAdaptiveSize(t, e, i,
|
|
1696
|
-
const s = this.imageConfig.sizing, r = this.resolveBaseHeight(
|
|
1695
|
+
calculateAdaptiveSize(t, e, i, o) {
|
|
1696
|
+
const s = this.imageConfig.sizing, r = this.resolveBaseHeight(o);
|
|
1697
1697
|
if (r !== void 0)
|
|
1698
1698
|
return { height: r };
|
|
1699
1699
|
const a = s?.minSize ?? 50, h = s?.maxSize ?? 400, c = this.config.targetCoverage ?? 0.6, u = this.config.densityFactor ?? 1, { width: l, height: d } = t, p = l * d * c / e;
|
|
@@ -1713,109 +1713,75 @@ class fe {
|
|
|
1713
1713
|
return Math.max(e, Math.min(i, t));
|
|
1714
1714
|
}
|
|
1715
1715
|
}
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
* @param name - Loader identifier (e.g., 'static', 'google-drive', 'composite')
|
|
1720
|
-
* @param Loader - Loader class constructor to register
|
|
1721
|
-
*/
|
|
1722
|
-
static registerLoader(t, e) {
|
|
1723
|
-
Z.registry.set(t, e);
|
|
1724
|
-
}
|
|
1725
|
-
/**
|
|
1726
|
-
* Get a registered loader implementation
|
|
1727
|
-
* @param name - Loader identifier
|
|
1728
|
-
* @returns Loader class constructor
|
|
1729
|
-
* @throws Error if loader is not registered
|
|
1730
|
-
*/
|
|
1731
|
-
static getLoader(t) {
|
|
1732
|
-
const e = Z.registry.get(t);
|
|
1733
|
-
if (!e)
|
|
1734
|
-
throw new Error(
|
|
1735
|
-
`Loader "${t}" is not registered. Import "@frybynite/image-cloud/loaders/${t}" or "@frybynite/image-cloud/loaders/all".`
|
|
1736
|
-
);
|
|
1737
|
-
return e;
|
|
1738
|
-
}
|
|
1739
|
-
/**
|
|
1740
|
-
* Check if a loader is registered
|
|
1741
|
-
* @param name - Loader identifier
|
|
1742
|
-
* @returns True if the loader is registered, false otherwise
|
|
1743
|
-
*/
|
|
1744
|
-
static isRegistered(t) {
|
|
1745
|
-
return Z.registry.has(t);
|
|
1746
|
-
}
|
|
1747
|
-
};
|
|
1748
|
-
Z.registry = /* @__PURE__ */ new Map();
|
|
1749
|
-
let et = Z;
|
|
1750
|
-
var I = /* @__PURE__ */ ((o) => (o.IDLE = "idle", o.FOCUSING = "focusing", o.FOCUSED = "focused", o.UNFOCUSING = "unfocusing", o.CROSS_ANIMATING = "cross_animating", o))(I || {});
|
|
1751
|
-
function pe(o) {
|
|
1752
|
-
return o in pt;
|
|
1716
|
+
var I = /* @__PURE__ */ ((n) => (n.IDLE = "idle", n.FOCUSING = "focusing", n.FOCUSED = "focused", n.UNFOCUSING = "unfocusing", n.CROSS_ANIMATING = "cross_animating", n))(I || {});
|
|
1717
|
+
function me(n) {
|
|
1718
|
+
return n in mt;
|
|
1753
1719
|
}
|
|
1754
|
-
function
|
|
1755
|
-
return
|
|
1720
|
+
function fe(n) {
|
|
1721
|
+
return n ? me(n) ? mt[n] : n : mt.md;
|
|
1756
1722
|
}
|
|
1757
|
-
function
|
|
1758
|
-
if (!
|
|
1723
|
+
function pe(n) {
|
|
1724
|
+
if (!n) return "";
|
|
1759
1725
|
const t = [];
|
|
1760
|
-
if (
|
|
1761
|
-
if (typeof
|
|
1762
|
-
t.push(`drop-shadow(${
|
|
1726
|
+
if (n.grayscale !== void 0 && t.push(`grayscale(${n.grayscale})`), n.blur !== void 0 && t.push(`blur(${n.blur}px)`), n.brightness !== void 0 && t.push(`brightness(${n.brightness})`), n.contrast !== void 0 && t.push(`contrast(${n.contrast})`), n.saturate !== void 0 && t.push(`saturate(${n.saturate})`), n.opacity !== void 0 && t.push(`opacity(${n.opacity})`), n.sepia !== void 0 && t.push(`sepia(${n.sepia})`), n.hueRotate !== void 0 && t.push(`hue-rotate(${n.hueRotate}deg)`), n.invert !== void 0 && t.push(`invert(${n.invert})`), n.dropShadow !== void 0)
|
|
1727
|
+
if (typeof n.dropShadow == "string")
|
|
1728
|
+
t.push(`drop-shadow(${n.dropShadow})`);
|
|
1763
1729
|
else {
|
|
1764
|
-
const e =
|
|
1730
|
+
const e = n.dropShadow;
|
|
1765
1731
|
t.push(`drop-shadow(${e.x}px ${e.y}px ${e.blur}px ${e.color})`);
|
|
1766
1732
|
}
|
|
1767
1733
|
return t.join(" ");
|
|
1768
1734
|
}
|
|
1769
|
-
function
|
|
1770
|
-
if (!
|
|
1735
|
+
function Q(n) {
|
|
1736
|
+
if (!n || n.style === "none" || n.width === 0)
|
|
1771
1737
|
return "none";
|
|
1772
|
-
const t =
|
|
1738
|
+
const t = n.width ?? 0, e = n.style ?? "solid", i = n.color ?? "#000000";
|
|
1773
1739
|
return `${t}px ${e} ${i}`;
|
|
1774
1740
|
}
|
|
1775
|
-
function
|
|
1776
|
-
if (!
|
|
1741
|
+
function st(n) {
|
|
1742
|
+
if (!n) return {};
|
|
1777
1743
|
const t = {};
|
|
1778
|
-
if (
|
|
1779
|
-
const s =
|
|
1780
|
-
|
|
1781
|
-
} else
|
|
1782
|
-
if (
|
|
1783
|
-
const s =
|
|
1784
|
-
t.borderTop =
|
|
1785
|
-
} else
|
|
1786
|
-
|
|
1787
|
-
const
|
|
1788
|
-
if (t.filter =
|
|
1789
|
-
const s =
|
|
1790
|
-
t.outline = `${s}px ${r} ${a}`,
|
|
1791
|
-
}
|
|
1792
|
-
return
|
|
1744
|
+
if (n.borderRadiusTopLeft !== void 0 || n.borderRadiusTopRight !== void 0 || n.borderRadiusBottomRight !== void 0 || n.borderRadiusBottomLeft !== void 0) {
|
|
1745
|
+
const s = n.border?.radius ?? 0;
|
|
1746
|
+
n.borderRadiusTopLeft !== void 0 ? t.borderTopLeftRadius = `${n.borderRadiusTopLeft}px` : s && (t.borderTopLeftRadius = `${s}px`), n.borderRadiusTopRight !== void 0 ? t.borderTopRightRadius = `${n.borderRadiusTopRight}px` : s && (t.borderTopRightRadius = `${s}px`), n.borderRadiusBottomRight !== void 0 ? t.borderBottomRightRadius = `${n.borderRadiusBottomRight}px` : s && (t.borderBottomRightRadius = `${s}px`), n.borderRadiusBottomLeft !== void 0 ? t.borderBottomLeftRadius = `${n.borderRadiusBottomLeft}px` : s && (t.borderBottomLeftRadius = `${s}px`);
|
|
1747
|
+
} else n.border?.radius !== void 0 && (t.borderRadius = `${n.border.radius}px`);
|
|
1748
|
+
if (n.borderTop || n.borderRight || n.borderBottom || n.borderLeft) {
|
|
1749
|
+
const s = n.border || {}, r = { ...s, ...n.borderTop }, a = { ...s, ...n.borderRight }, h = { ...s, ...n.borderBottom }, c = { ...s, ...n.borderLeft };
|
|
1750
|
+
t.borderTop = Q(r), t.borderRight = Q(a), t.borderBottom = Q(h), t.borderLeft = Q(c);
|
|
1751
|
+
} else n.border && (t.border = Q(n.border));
|
|
1752
|
+
n.shadow !== void 0 && (t.boxShadow = fe(n.shadow));
|
|
1753
|
+
const o = pe(n.filter);
|
|
1754
|
+
if (t.filter = o || "none", n.opacity !== void 0 && (t.opacity = String(n.opacity)), n.cursor !== void 0 && (t.cursor = n.cursor), n.outline && n.outline.style !== "none" && (n.outline.width ?? 0) > 0) {
|
|
1755
|
+
const s = n.outline.width ?? 0, r = n.outline.style ?? "solid", a = n.outline.color ?? "#000000";
|
|
1756
|
+
t.outline = `${s}px ${r} ${a}`, n.outline.offset !== void 0 && (t.outlineOffset = `${n.outline.offset}px`);
|
|
1757
|
+
}
|
|
1758
|
+
return n.objectFit !== void 0 && (t.objectFit = n.objectFit), n.aspectRatio !== void 0 && (t.aspectRatio = n.aspectRatio), t;
|
|
1793
1759
|
}
|
|
1794
|
-
function
|
|
1795
|
-
t.borderRadius !== void 0 && (
|
|
1760
|
+
function tt(n, t) {
|
|
1761
|
+
t.borderRadius !== void 0 && (n.style.borderRadius = t.borderRadius), t.borderTopLeftRadius !== void 0 && (n.style.borderTopLeftRadius = t.borderTopLeftRadius), t.borderTopRightRadius !== void 0 && (n.style.borderTopRightRadius = t.borderTopRightRadius), t.borderBottomRightRadius !== void 0 && (n.style.borderBottomRightRadius = t.borderBottomRightRadius), t.borderBottomLeftRadius !== void 0 && (n.style.borderBottomLeftRadius = t.borderBottomLeftRadius), t.border !== void 0 && (n.style.border = t.border), t.borderTop !== void 0 && (n.style.borderTop = t.borderTop), t.borderRight !== void 0 && (n.style.borderRight = t.borderRight), t.borderBottom !== void 0 && (n.style.borderBottom = t.borderBottom), t.borderLeft !== void 0 && (n.style.borderLeft = t.borderLeft), t.boxShadow !== void 0 && (n.style.boxShadow = t.boxShadow), t.filter !== void 0 && (n.style.filter = t.filter), t.opacity !== void 0 && (n.style.opacity = t.opacity), t.cursor !== void 0 && (n.style.cursor = t.cursor), t.outline !== void 0 && (n.style.outline = t.outline), t.outlineOffset !== void 0 && (n.style.outlineOffset = t.outlineOffset), t.objectFit !== void 0 && (n.style.objectFit = t.objectFit), t.aspectRatio !== void 0 && (n.style.aspectRatio = t.aspectRatio);
|
|
1796
1762
|
}
|
|
1797
|
-
function
|
|
1798
|
-
return
|
|
1763
|
+
function Mt(n) {
|
|
1764
|
+
return n ? Array.isArray(n) ? n.join(" ") : n : "";
|
|
1799
1765
|
}
|
|
1800
|
-
function
|
|
1801
|
-
const e =
|
|
1766
|
+
function et(n, t) {
|
|
1767
|
+
const e = Mt(t);
|
|
1802
1768
|
e && e.split(" ").forEach((i) => {
|
|
1803
|
-
i.trim() &&
|
|
1769
|
+
i.trim() && n.classList.add(i.trim());
|
|
1804
1770
|
});
|
|
1805
1771
|
}
|
|
1806
|
-
function
|
|
1807
|
-
const e =
|
|
1772
|
+
function Lt(n, t) {
|
|
1773
|
+
const e = Mt(t);
|
|
1808
1774
|
e && e.split(" ").forEach((i) => {
|
|
1809
|
-
i.trim() &&
|
|
1775
|
+
i.trim() && n.classList.remove(i.trim());
|
|
1810
1776
|
});
|
|
1811
1777
|
}
|
|
1812
|
-
const
|
|
1778
|
+
const It = {
|
|
1813
1779
|
UNFOCUSING: 999,
|
|
1814
1780
|
FOCUSING: 1e3
|
|
1815
1781
|
};
|
|
1816
|
-
class
|
|
1782
|
+
class be {
|
|
1817
1783
|
constructor(t, e, i) {
|
|
1818
|
-
this.state = I.IDLE, this.currentFocus = null, this.focusData = null, this.outgoing = null, this.incoming = null, this.focusGeneration = 0, this.config = t, this.animationEngine = e, this.defaultStyles =
|
|
1784
|
+
this.state = I.IDLE, this.currentFocus = null, this.focusData = null, this.outgoing = null, this.incoming = null, this.focusGeneration = 0, this.config = t, this.animationEngine = e, this.defaultStyles = st(i?.default), this.focusedStyles = st(i?.focused), this.defaultClassName = i?.default?.className, this.focusedClassName = i?.focused?.className;
|
|
1819
1785
|
}
|
|
1820
1786
|
/**
|
|
1821
1787
|
* Get current state machine state
|
|
@@ -1840,9 +1806,9 @@ class ve {
|
|
|
1840
1806
|
* Returns actual pixel dimensions instead of scale factor for sharper rendering
|
|
1841
1807
|
*/
|
|
1842
1808
|
calculateFocusDimensions(t, e, i) {
|
|
1843
|
-
const
|
|
1809
|
+
const o = this.normalizeScalePercent(this.config.scalePercent), s = i.height * o, r = t / e;
|
|
1844
1810
|
let a = s, h = a * r;
|
|
1845
|
-
const c = i.width *
|
|
1811
|
+
const c = i.width * o;
|
|
1846
1812
|
return h > c && (h = c, a = h / r), { width: h, height: a };
|
|
1847
1813
|
}
|
|
1848
1814
|
/**
|
|
@@ -1850,7 +1816,7 @@ class ve {
|
|
|
1850
1816
|
* Scale is handled by animating actual dimensions for sharper rendering
|
|
1851
1817
|
*/
|
|
1852
1818
|
calculateFocusTransform(t, e) {
|
|
1853
|
-
const i = t.width / 2,
|
|
1819
|
+
const i = t.width / 2, o = t.height / 2, s = i - e.x, r = o - e.y;
|
|
1854
1820
|
return {
|
|
1855
1821
|
x: s,
|
|
1856
1822
|
y: r,
|
|
@@ -1865,8 +1831,8 @@ class ve {
|
|
|
1865
1831
|
buildDimensionZoomTransform(t) {
|
|
1866
1832
|
const e = ["translate(-50%, -50%)"];
|
|
1867
1833
|
if (t.x !== void 0 || t.y !== void 0) {
|
|
1868
|
-
const i = t.x ?? 0,
|
|
1869
|
-
e.push(`translate(${i}px, ${
|
|
1834
|
+
const i = t.x ?? 0, o = t.y ?? 0;
|
|
1835
|
+
e.push(`translate(${i}px, ${o}px)`);
|
|
1870
1836
|
}
|
|
1871
1837
|
return t.rotation !== void 0 && e.push(`rotate(${t.rotation}deg)`), e.join(" ");
|
|
1872
1838
|
}
|
|
@@ -1874,13 +1840,13 @@ class ve {
|
|
|
1874
1840
|
* Create a Web Animation that animates both transform (position) and dimensions
|
|
1875
1841
|
* This provides sharper zoom by re-rendering at target size instead of scaling pixels
|
|
1876
1842
|
*/
|
|
1877
|
-
animateWithDimensions(t, e, i,
|
|
1843
|
+
animateWithDimensions(t, e, i, o, s, r, a, h) {
|
|
1878
1844
|
const c = this.buildDimensionZoomTransform(e), u = this.buildDimensionZoomTransform(i);
|
|
1879
1845
|
return t.style.transition = "none", t.animate(
|
|
1880
1846
|
[
|
|
1881
1847
|
{
|
|
1882
1848
|
transform: c,
|
|
1883
|
-
width: `${
|
|
1849
|
+
width: `${o}px`,
|
|
1884
1850
|
height: `${s}px`
|
|
1885
1851
|
},
|
|
1886
1852
|
{
|
|
@@ -1900,13 +1866,13 @@ class ve {
|
|
|
1900
1866
|
* Apply focused styling to an element
|
|
1901
1867
|
*/
|
|
1902
1868
|
applyFocusedStyling(t, e) {
|
|
1903
|
-
t.style.zIndex = String(e), t.classList.add("fbn-ic-focused"),
|
|
1869
|
+
t.style.zIndex = String(e), t.classList.add("fbn-ic-focused"), tt(t, this.focusedStyles), et(t, this.focusedClassName);
|
|
1904
1870
|
}
|
|
1905
1871
|
/**
|
|
1906
1872
|
* Remove focused styling from an element
|
|
1907
1873
|
*/
|
|
1908
1874
|
removeFocusedStyling(t, e) {
|
|
1909
|
-
t.style.zIndex = e, t.classList.remove("fbn-ic-focused"),
|
|
1875
|
+
t.style.zIndex = e, t.classList.remove("fbn-ic-focused"), Lt(t, this.focusedClassName), tt(t, this.defaultStyles), et(t, this.defaultClassName);
|
|
1910
1876
|
}
|
|
1911
1877
|
/**
|
|
1912
1878
|
* Start focus animation for an image using dimension-based zoom
|
|
@@ -1914,10 +1880,10 @@ class ve {
|
|
|
1914
1880
|
* @param fromTransform - Optional starting transform (for mid-animation reversals)
|
|
1915
1881
|
* @param fromDimensions - Optional starting dimensions (for mid-animation reversals)
|
|
1916
1882
|
*/
|
|
1917
|
-
startFocusAnimation(t, e, i,
|
|
1883
|
+
startFocusAnimation(t, e, i, o, s) {
|
|
1918
1884
|
const r = t.style.zIndex || "", a = t.offsetWidth, h = t.offsetHeight, c = this.calculateFocusDimensions(a, h, e), u = this.calculateFocusTransform(e, i);
|
|
1919
|
-
this.applyFocusedStyling(t,
|
|
1920
|
-
const l =
|
|
1885
|
+
this.applyFocusedStyling(t, It.FOCUSING), this.animationEngine.cancelAllAnimations(t);
|
|
1886
|
+
const l = o ?? {
|
|
1921
1887
|
x: 0,
|
|
1922
1888
|
y: 0,
|
|
1923
1889
|
rotation: i.rotation,
|
|
@@ -1964,9 +1930,9 @@ class ve {
|
|
|
1964
1930
|
* Animates back to original dimensions for consistent behavior
|
|
1965
1931
|
* @param fromDimensions - Optional starting dimensions (for mid-animation reversals)
|
|
1966
1932
|
*/
|
|
1967
|
-
startUnfocusAnimation(t, e, i,
|
|
1968
|
-
t.style.zIndex = String(
|
|
1969
|
-
const s = i ?? this.focusData?.focusTransform ?? { x: 0, y: 0, rotation: 0, scale: 1 }, r =
|
|
1933
|
+
startUnfocusAnimation(t, e, i, o) {
|
|
1934
|
+
t.style.zIndex = String(It.UNFOCUSING), this.animationEngine.cancelAllAnimations(t);
|
|
1935
|
+
const s = i ?? this.focusData?.focusTransform ?? { x: 0, y: 0, rotation: 0, scale: 1 }, r = o?.width ?? this.focusData?.focusWidth ?? t.offsetWidth, a = o?.height ?? this.focusData?.focusHeight ?? t.offsetHeight, h = {
|
|
1970
1936
|
x: 0,
|
|
1971
1937
|
y: 0,
|
|
1972
1938
|
rotation: e.rotation,
|
|
@@ -2014,10 +1980,10 @@ class ve {
|
|
|
2014
1980
|
* Caller is responsible for calling animationEngine.cancelAllAnimations() afterwards.
|
|
2015
1981
|
*/
|
|
2016
1982
|
captureMidAnimationState(t) {
|
|
2017
|
-
const e = getComputedStyle(t), i = new DOMMatrix(e.transform),
|
|
2018
|
-
return t.style.width = `${
|
|
1983
|
+
const e = getComputedStyle(t), i = new DOMMatrix(e.transform), o = t.offsetWidth, s = t.offsetHeight, r = i.e + o * 0.5, a = i.f + s * 0.5, h = Math.atan2(i.b, i.a) * (180 / Math.PI);
|
|
1984
|
+
return t.style.width = `${o}px`, t.style.height = `${s}px`, t.style.transform = `translate(-50%, -50%) translate(${r}px, ${a}px) rotate(${h}deg)`, t.style.transition = "none", {
|
|
2019
1985
|
transform: { x: r, y: a, rotation: h, scale: 1 },
|
|
2020
|
-
dimensions: { width:
|
|
1986
|
+
dimensions: { width: o, height: s }
|
|
2021
1987
|
};
|
|
2022
1988
|
}
|
|
2023
1989
|
/**
|
|
@@ -2032,10 +1998,10 @@ class ve {
|
|
|
2032
1998
|
/**
|
|
2033
1999
|
* Reset an element instantly to its original position and dimensions (no animation)
|
|
2034
2000
|
*/
|
|
2035
|
-
resetElementInstantly(t, e, i,
|
|
2001
|
+
resetElementInstantly(t, e, i, o, s) {
|
|
2036
2002
|
this.animationEngine.cancelAllAnimations(t);
|
|
2037
2003
|
const r = ["translate(-50%, -50%)"];
|
|
2038
|
-
r.push("translate(0px, 0px)"), r.push(`rotate(${e.rotation}deg)`), t.style.transition = "none", t.style.transform = r.join(" "),
|
|
2004
|
+
r.push("translate(0px, 0px)"), r.push(`rotate(${e.rotation}deg)`), t.style.transition = "none", t.style.transform = r.join(" "), o !== void 0 && s !== void 0 && (t.style.width = `${o}px`, t.style.height = `${s}px`), this.removeFocusedStyling(t, i);
|
|
2039
2005
|
}
|
|
2040
2006
|
/**
|
|
2041
2007
|
* Focus (zoom) an image to center of container
|
|
@@ -2054,10 +2020,10 @@ class ve {
|
|
|
2054
2020
|
), this.incoming = null, this.state = I.UNFOCUSING, await this.waitForAnimation(this.outgoing.animationHandle), this.removeFocusedStyling(this.outgoing.element, this.focusData?.originalZIndex || ""), this.outgoing = null, this.currentFocus = null, this.focusData = null, this.state = I.IDLE;
|
|
2055
2021
|
return;
|
|
2056
2022
|
}
|
|
2057
|
-
const
|
|
2023
|
+
const o = ++this.focusGeneration;
|
|
2058
2024
|
switch (this.state) {
|
|
2059
2025
|
case I.IDLE:
|
|
2060
|
-
if (this.state = I.FOCUSING, this.incoming = this.startFocusAnimation(t, e, i), await this.waitForAnimation(this.incoming.animationHandle), this.focusGeneration !==
|
|
2026
|
+
if (this.state = I.FOCUSING, this.incoming = this.startFocusAnimation(t, e, i), await this.waitForAnimation(this.incoming.animationHandle), this.focusGeneration !== o) return;
|
|
2061
2027
|
this.currentFocus = t, this.incoming = null, this.state = I.FOCUSED;
|
|
2062
2028
|
break;
|
|
2063
2029
|
case I.FOCUSED:
|
|
@@ -2067,7 +2033,7 @@ class ve {
|
|
|
2067
2033
|
)), this.incoming = this.startFocusAnimation(t, e, i), await Promise.all([
|
|
2068
2034
|
this.outgoing ? this.waitForAnimation(this.outgoing.animationHandle) : Promise.resolve(),
|
|
2069
2035
|
this.waitForAnimation(this.incoming.animationHandle)
|
|
2070
|
-
]), this.focusGeneration !==
|
|
2036
|
+
]), this.focusGeneration !== o)
|
|
2071
2037
|
return;
|
|
2072
2038
|
this.outgoing && (this.removeFocusedStyling(this.outgoing.element, this.outgoing.originalState.zIndex?.toString() || ""), this.outgoing = null), this.currentFocus = t, this.incoming = null, this.state = I.FOCUSED;
|
|
2073
2039
|
break;
|
|
@@ -2078,14 +2044,14 @@ class ve {
|
|
|
2078
2044
|
this.focusData?.originalZIndex || "",
|
|
2079
2045
|
this.focusData?.originalWidth,
|
|
2080
2046
|
this.focusData?.originalHeight
|
|
2081
|
-
), this.incoming = null), this.incoming = this.startFocusAnimation(t, e, i), await this.waitForAnimation(this.incoming.animationHandle), this.focusGeneration !==
|
|
2047
|
+
), this.incoming = null), this.incoming = this.startFocusAnimation(t, e, i), await this.waitForAnimation(this.incoming.animationHandle), this.focusGeneration !== o) return;
|
|
2082
2048
|
this.currentFocus = t, this.incoming = null, this.state = I.FOCUSED;
|
|
2083
2049
|
break;
|
|
2084
2050
|
case I.UNFOCUSING:
|
|
2085
2051
|
if (this.state = I.CROSS_ANIMATING, this.incoming = this.startFocusAnimation(t, e, i), await Promise.all([
|
|
2086
2052
|
this.outgoing ? this.waitForAnimation(this.outgoing.animationHandle) : Promise.resolve(),
|
|
2087
2053
|
this.waitForAnimation(this.incoming.animationHandle)
|
|
2088
|
-
]), this.focusGeneration !==
|
|
2054
|
+
]), this.focusGeneration !== o) return;
|
|
2089
2055
|
this.outgoing && (this.removeFocusedStyling(this.outgoing.element, this.outgoing.originalState.zIndex?.toString() || ""), this.outgoing = null), this.currentFocus = t, this.incoming = null, this.state = I.FOCUSED;
|
|
2090
2056
|
break;
|
|
2091
2057
|
case I.CROSS_ANIMATING:
|
|
@@ -2106,7 +2072,7 @@ class ve {
|
|
|
2106
2072
|
if (this.incoming = this.startFocusAnimation(t, e, i, s, r), await Promise.all([
|
|
2107
2073
|
this.outgoing ? this.waitForAnimation(this.outgoing.animationHandle) : Promise.resolve(),
|
|
2108
2074
|
this.waitForAnimation(this.incoming.animationHandle)
|
|
2109
|
-
]), this.focusGeneration !==
|
|
2075
|
+
]), this.focusGeneration !== o) return;
|
|
2110
2076
|
this.outgoing && (this.removeFocusedStyling(this.outgoing.element, this.outgoing.originalState.zIndex?.toString() || ""), this.outgoing = null), this.currentFocus = t, this.incoming = null, this.state = I.FOCUSED;
|
|
2111
2077
|
return;
|
|
2112
2078
|
}
|
|
@@ -2128,7 +2094,7 @@ class ve {
|
|
|
2128
2094
|
if (this.incoming = this.startFocusAnimation(t, e, i), await Promise.all([
|
|
2129
2095
|
this.outgoing ? this.waitForAnimation(this.outgoing.animationHandle) : Promise.resolve(),
|
|
2130
2096
|
this.waitForAnimation(this.incoming.animationHandle)
|
|
2131
|
-
]), this.focusGeneration !==
|
|
2097
|
+
]), this.focusGeneration !== o) return;
|
|
2132
2098
|
this.outgoing && (this.removeFocusedStyling(this.outgoing.element, this.outgoing.originalState.zIndex?.toString() || ""), this.outgoing = null), this.currentFocus = t, this.incoming = null, this.state = I.FOCUSED;
|
|
2133
2099
|
break;
|
|
2134
2100
|
}
|
|
@@ -2170,8 +2136,8 @@ class ve {
|
|
|
2170
2136
|
return;
|
|
2171
2137
|
}
|
|
2172
2138
|
this.state = I.UNFOCUSING;
|
|
2173
|
-
const e = this.currentFocus, i = this.focusData.originalState,
|
|
2174
|
-
this.outgoing = this.startUnfocusAnimation(e, i), await this.waitForAnimation(this.outgoing.animationHandle), this.focusGeneration === t && (this.removeFocusedStyling(e,
|
|
2139
|
+
const e = this.currentFocus, i = this.focusData.originalState, o = this.focusData.originalZIndex;
|
|
2140
|
+
this.outgoing = this.startUnfocusAnimation(e, i), await this.waitForAnimation(this.outgoing.animationHandle), this.focusGeneration === t && (this.removeFocusedStyling(e, o), this.outgoing = null, this.currentFocus = null, this.focusData = null, this.state = I.IDLE);
|
|
2175
2141
|
}
|
|
2176
2142
|
/**
|
|
2177
2143
|
* Swap focus from current image to a new one (alias for focusImage with cross-animation)
|
|
@@ -2211,8 +2177,8 @@ class ve {
|
|
|
2211
2177
|
*/
|
|
2212
2178
|
setDragOffset(t) {
|
|
2213
2179
|
if (!this.currentFocus || !this.focusData || this.state !== I.FOCUSED) return;
|
|
2214
|
-
const e = this.currentFocus, i = this.focusData.focusTransform,
|
|
2215
|
-
|
|
2180
|
+
const e = this.currentFocus, i = this.focusData.focusTransform, o = ["translate(-50%, -50%)"], s = (i.x ?? 0) + t, r = i.y ?? 0;
|
|
2181
|
+
o.push(`translate(${s}px, ${r}px)`), i.rotation !== void 0 && o.push(`rotate(${i.rotation}deg)`), e.style.transition = "none", e.style.transform = o.join(" ");
|
|
2216
2182
|
}
|
|
2217
2183
|
/**
|
|
2218
2184
|
* Clear the drag offset, optionally animating back to center
|
|
@@ -2221,8 +2187,8 @@ class ve {
|
|
|
2221
2187
|
*/
|
|
2222
2188
|
clearDragOffset(t, e = 150) {
|
|
2223
2189
|
if (!this.currentFocus || !this.focusData || this.state !== I.FOCUSED) return;
|
|
2224
|
-
const i = this.currentFocus,
|
|
2225
|
-
s.push(`translate(${r}px, ${a}px)`),
|
|
2190
|
+
const i = this.currentFocus, o = this.focusData.focusTransform, s = ["translate(-50%, -50%)"], r = o.x ?? 0, a = o.y ?? 0;
|
|
2191
|
+
s.push(`translate(${r}px, ${a}px)`), o.rotation !== void 0 && s.push(`rotate(${o.rotation}deg)`);
|
|
2226
2192
|
const h = s.join(" ");
|
|
2227
2193
|
t ? (i.style.transition = `transform ${e}ms ease-out`, i.style.transform = h, setTimeout(() => {
|
|
2228
2194
|
this.currentFocus === i && (i.style.transition = "none");
|
|
@@ -2253,7 +2219,7 @@ class ve {
|
|
|
2253
2219
|
), this.state = I.IDLE, this.currentFocus = null, this.focusData = null, this.outgoing = null, this.incoming = null;
|
|
2254
2220
|
}
|
|
2255
2221
|
}
|
|
2256
|
-
const
|
|
2222
|
+
const ye = 50, ve = 0.5, we = 20, xe = 0.3, Se = 150, Ee = 30, at = class at {
|
|
2257
2223
|
constructor(t, e) {
|
|
2258
2224
|
this.enabled = !1, this.touchState = null, this.recentTouchTimestamp = 0, this.container = t, this.callbacks = e, this.boundTouchStart = this.handleTouchStart.bind(this), this.boundTouchMove = this.handleTouchMove.bind(this), this.boundTouchEnd = this.handleTouchEnd.bind(this), this.boundTouchCancel = this.handleTouchCancel.bind(this);
|
|
2259
2225
|
}
|
|
@@ -2280,7 +2246,7 @@ const we = 50, xe = 0.5, Se = 20, Ee = 0.3, Ie = 150, Ae = 30, ct = class ct {
|
|
|
2280
2246
|
* Used to prevent click-outside from unfocusing immediately after touch
|
|
2281
2247
|
*/
|
|
2282
2248
|
hadRecentTouch() {
|
|
2283
|
-
return Date.now() - this.recentTouchTimestamp <
|
|
2249
|
+
return Date.now() - this.recentTouchTimestamp < at.TOUCH_CLICK_DELAY;
|
|
2284
2250
|
}
|
|
2285
2251
|
handleTouchStart(t) {
|
|
2286
2252
|
if (t.touches.length !== 1) return;
|
|
@@ -2297,586 +2263,123 @@ const we = 50, xe = 0.5, Se = 20, Ee = 0.3, Ie = 150, Ae = 30, ct = class ct {
|
|
|
2297
2263
|
}
|
|
2298
2264
|
handleTouchMove(t) {
|
|
2299
2265
|
if (!this.touchState || t.touches.length !== 1) return;
|
|
2300
|
-
const e = t.touches[0], i = e.clientX - this.touchState.startX,
|
|
2301
|
-
if (this.touchState.isHorizontalSwipe === null && Math.sqrt(i * i +
|
|
2302
|
-
const a = Math.atan2(Math.abs(
|
|
2303
|
-
this.touchState.isHorizontalSwipe = a <=
|
|
2266
|
+
const e = t.touches[0], i = e.clientX - this.touchState.startX, o = e.clientY - this.touchState.startY;
|
|
2267
|
+
if (this.touchState.isHorizontalSwipe === null && Math.sqrt(i * i + o * o) > 10) {
|
|
2268
|
+
const a = Math.atan2(Math.abs(o), Math.abs(i)) * (180 / Math.PI);
|
|
2269
|
+
this.touchState.isHorizontalSwipe = a <= Ee;
|
|
2304
2270
|
}
|
|
2305
2271
|
if (this.touchState.isHorizontalSwipe !== !1 && this.touchState.isHorizontalSwipe === !0) {
|
|
2306
2272
|
t.preventDefault(), this.touchState.isDragging = !0, this.touchState.currentX = e.clientX;
|
|
2307
|
-
const s = i *
|
|
2273
|
+
const s = i * xe;
|
|
2308
2274
|
this.callbacks.onDragOffset(s);
|
|
2309
2275
|
}
|
|
2310
2276
|
}
|
|
2311
2277
|
handleTouchEnd(t) {
|
|
2312
2278
|
if (!this.touchState) return;
|
|
2313
2279
|
this.recentTouchTimestamp = Date.now();
|
|
2314
|
-
const e = this.touchState.currentX - this.touchState.startX, i = performance.now() - this.touchState.startTime,
|
|
2280
|
+
const e = this.touchState.currentX - this.touchState.startX, i = performance.now() - this.touchState.startTime, o = Math.abs(e) / i, s = Math.abs(e);
|
|
2315
2281
|
let r = !1;
|
|
2316
|
-
this.touchState.isHorizontalSwipe === !0 && this.touchState.isDragging && (s >=
|
|
2282
|
+
this.touchState.isHorizontalSwipe === !0 && this.touchState.isDragging && (s >= ye || o >= ve && s >= we) && (r = !0, e < 0 ? this.callbacks.onNext() : this.callbacks.onPrev()), this.touchState.isDragging && this.callbacks.onDragEnd(r), this.touchState = null;
|
|
2317
2283
|
}
|
|
2318
2284
|
handleTouchCancel(t) {
|
|
2319
2285
|
this.touchState?.isDragging && this.callbacks.onDragEnd(!1), this.touchState = null;
|
|
2320
2286
|
}
|
|
2321
2287
|
};
|
|
2322
|
-
|
|
2323
|
-
let
|
|
2324
|
-
class
|
|
2325
|
-
/**
|
|
2326
|
-
* Create a new ImageFilter
|
|
2327
|
-
* @param extensions - Array of allowed file extensions (without dots)
|
|
2328
|
-
* Defaults to common image formats if not provided
|
|
2329
|
-
*/
|
|
2288
|
+
at.TOUCH_CLICK_DELAY = 300;
|
|
2289
|
+
let ft = at;
|
|
2290
|
+
class Ie {
|
|
2330
2291
|
constructor(t) {
|
|
2331
|
-
this.
|
|
2332
|
-
"
|
|
2333
|
-
"jpeg",
|
|
2334
|
-
"png",
|
|
2335
|
-
"gif",
|
|
2336
|
-
"webp",
|
|
2337
|
-
"bmp"
|
|
2338
|
-
];
|
|
2292
|
+
if (this._prepared = !1, this._discoveredUrls = [], this.apiKey = t.apiKey ?? "", this.apiEndpoint = t.apiEndpoint ?? "https://www.googleapis.com/drive/v3/files", this.debugLogging = t.debugLogging ?? !1, this.sources = t.sources ?? [], !this.sources || this.sources.length === 0)
|
|
2293
|
+
throw new Error("GoogleDriveLoader requires at least one source to be configured");
|
|
2339
2294
|
}
|
|
2340
2295
|
/**
|
|
2341
|
-
*
|
|
2342
|
-
* @param
|
|
2343
|
-
* @returns True if the file extension is allowed
|
|
2296
|
+
* Prepare the loader by discovering all images from configured sources
|
|
2297
|
+
* @param filter - Filter to apply to discovered images
|
|
2344
2298
|
*/
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2299
|
+
async prepare(t) {
|
|
2300
|
+
this._discoveredUrls = [];
|
|
2301
|
+
for (const e of this.sources)
|
|
2302
|
+
if ("folders" in e)
|
|
2303
|
+
for (const i of e.folders) {
|
|
2304
|
+
const o = e.recursive !== void 0 ? e.recursive : !0, s = await this.loadFromFolder(i, t, o);
|
|
2305
|
+
this._discoveredUrls.push(...s);
|
|
2306
|
+
}
|
|
2307
|
+
else if ("files" in e) {
|
|
2308
|
+
const i = await this.loadFiles(e.files, t);
|
|
2309
|
+
this._discoveredUrls.push(...i);
|
|
2310
|
+
}
|
|
2311
|
+
this._prepared = !0;
|
|
2348
2312
|
}
|
|
2349
2313
|
/**
|
|
2350
|
-
* Get the
|
|
2351
|
-
* @
|
|
2314
|
+
* Get the number of discovered images
|
|
2315
|
+
* @throws Error if called before prepare()
|
|
2352
2316
|
*/
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
// isAllowedSize(sizeBytes: number): boolean
|
|
2358
|
-
// isAllowedDate(date: Date): boolean
|
|
2359
|
-
// isAllowedDimensions(width: number, height: number): boolean
|
|
2360
|
-
}
|
|
2361
|
-
const Ce = `
|
|
2362
|
-
.fbn-ic-gallery {
|
|
2363
|
-
position: relative;
|
|
2364
|
-
width: 100%;
|
|
2365
|
-
height: 100%;
|
|
2366
|
-
overflow: hidden;
|
|
2367
|
-
perspective: 1000px;
|
|
2368
|
-
}
|
|
2369
|
-
|
|
2370
|
-
.fbn-ic-image {
|
|
2371
|
-
position: absolute;
|
|
2372
|
-
cursor: pointer;
|
|
2373
|
-
transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2374
|
-
box-shadow 0.6s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2375
|
-
filter 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2376
|
-
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2377
|
-
border 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2378
|
-
outline 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2379
|
-
z-index 0s 0.6s;
|
|
2380
|
-
will-change: transform;
|
|
2381
|
-
user-select: none;
|
|
2382
|
-
backface-visibility: hidden;
|
|
2383
|
-
-webkit-backface-visibility: hidden;
|
|
2384
|
-
}
|
|
2385
|
-
|
|
2386
|
-
.fbn-ic-image.fbn-ic-focused {
|
|
2387
|
-
z-index: 1000;
|
|
2388
|
-
transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2389
|
-
box-shadow 0.6s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2390
|
-
filter 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2391
|
-
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2392
|
-
border 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2393
|
-
outline 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2394
|
-
z-index 0s 0s;
|
|
2395
|
-
will-change: auto;
|
|
2396
|
-
}
|
|
2397
|
-
|
|
2398
|
-
.fbn-ic-counter {
|
|
2399
|
-
position: fixed;
|
|
2400
|
-
bottom: 24px;
|
|
2401
|
-
left: 50%;
|
|
2402
|
-
transform: translateX(-50%);
|
|
2403
|
-
z-index: 10001;
|
|
2404
|
-
pointer-events: none;
|
|
2405
|
-
}
|
|
2406
|
-
|
|
2407
|
-
.fbn-ic-hidden {
|
|
2408
|
-
display: none !important;
|
|
2409
|
-
}
|
|
2410
|
-
`;
|
|
2411
|
-
function Re() {
|
|
2412
|
-
if (typeof document > "u") return;
|
|
2413
|
-
const o = "fbn-ic-functional-styles";
|
|
2414
|
-
if (document.getElementById(o)) return;
|
|
2415
|
-
const t = document.createElement("style");
|
|
2416
|
-
t.id = o, t.textContent = Ce, document.head.appendChild(t);
|
|
2417
|
-
}
|
|
2418
|
-
class Le {
|
|
2419
|
-
constructor(t = {}) {
|
|
2420
|
-
this.fullConfig = Gt(t), t.container instanceof HTMLElement ? (this.containerRef = t.container, this.containerId = null) : (this.containerRef = null, this.containerId = t.container || "imageCloud"), this.imagesLoaded = !1, this.imageElements = [], this.imageLayouts = [], this.currentImageHeight = 225, this.currentFocusIndex = null, this.hoveredImage = null, this.resizeTimeout = null, this.displayQueue = [], this.queueInterval = null, this.loadGeneration = 0, this.loadingElAutoCreated = !1, this.errorElAutoCreated = !1, this.counterEl = null, this.counterElAutoCreated = !1, this.animationEngine = new Xt(this.fullConfig.animation), this.layoutEngine = new fe({
|
|
2421
|
-
layout: this.fullConfig.layout,
|
|
2422
|
-
image: this.fullConfig.image
|
|
2423
|
-
}), this.zoomEngine = new ve(this.fullConfig.interaction.focus, this.animationEngine, this.fullConfig.styling), this.defaultStyles = rt(this.fullConfig.styling?.default), this.hoverStyles = rt(this.fullConfig.styling?.hover), this.defaultClassName = this.fullConfig.styling?.default?.className, this.hoverClassName = this.fullConfig.styling?.hover?.className;
|
|
2424
|
-
const e = this.fullConfig.animation.entry || y.animation.entry;
|
|
2425
|
-
this.entryAnimationEngine = new oe(
|
|
2426
|
-
e,
|
|
2427
|
-
this.fullConfig.layout.algorithm
|
|
2428
|
-
), this.swipeEngine = null, this.imageFilter = this.createImageFilter(), this.containerEl = null, this.loadingEl = null, this.errorEl = null;
|
|
2317
|
+
imagesLength() {
|
|
2318
|
+
if (!this._prepared)
|
|
2319
|
+
throw new Error("GoogleDriveLoader.imagesLength() called before prepare()");
|
|
2320
|
+
return this._discoveredUrls.length;
|
|
2429
2321
|
}
|
|
2430
2322
|
/**
|
|
2431
|
-
*
|
|
2323
|
+
* Get the ordered list of image URLs
|
|
2324
|
+
* @throws Error if called before prepare()
|
|
2432
2325
|
*/
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2326
|
+
imageURLs() {
|
|
2327
|
+
if (!this._prepared)
|
|
2328
|
+
throw new Error("GoogleDriveLoader.imageURLs() called before prepare()");
|
|
2329
|
+
return [...this._discoveredUrls];
|
|
2436
2330
|
}
|
|
2437
2331
|
/**
|
|
2438
|
-
*
|
|
2439
|
-
* Processes loaders array, merges shared config, wraps in CompositeLoader if needed
|
|
2440
|
-
* Uses dynamic imports to trigger loader registration and enable tree-shaking
|
|
2332
|
+
* Check if the loader has been prepared
|
|
2441
2333
|
*/
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
if (!t || t.length === 0)
|
|
2445
|
-
throw new Error("No loaders configured. Provide `images`, `loaders`, or both.");
|
|
2446
|
-
const i = await Promise.all(
|
|
2447
|
-
t.map((s) => this.createLoaderFromEntry(s, e))
|
|
2448
|
-
);
|
|
2449
|
-
if (i.length === 1)
|
|
2450
|
-
return i[0];
|
|
2451
|
-
await import("@frybynite/image-cloud/loaders/composite");
|
|
2452
|
-
const n = et.getLoader("composite");
|
|
2453
|
-
return new n({
|
|
2454
|
-
loaders: i,
|
|
2455
|
-
debugLogging: this.fullConfig.config.debug?.loaders
|
|
2456
|
-
});
|
|
2334
|
+
isPrepared() {
|
|
2335
|
+
return this._prepared;
|
|
2457
2336
|
}
|
|
2458
2337
|
/**
|
|
2459
|
-
*
|
|
2460
|
-
*
|
|
2338
|
+
* Extract folder ID from various Google Drive URL formats
|
|
2339
|
+
* @param folderUrl - Google Drive folder URL
|
|
2340
|
+
* @returns Folder ID or null if invalid
|
|
2461
2341
|
*/
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
await import("@frybynite/image-cloud/loaders/google-drive");
|
|
2476
|
-
const i = et.getLoader("google-drive"), n = t.googleDrive, s = {
|
|
2477
|
-
...n,
|
|
2478
|
-
allowedExtensions: n.allowedExtensions ?? e.allowedExtensions,
|
|
2479
|
-
debugLogging: n.debugLogging ?? this.fullConfig.config.debug?.loaders
|
|
2480
|
-
};
|
|
2481
|
-
return new i(s);
|
|
2482
|
-
} else
|
|
2483
|
-
throw new Error(`Unknown loader entry: ${JSON.stringify(t)}`);
|
|
2342
|
+
extractFolderId(t) {
|
|
2343
|
+
const e = [
|
|
2344
|
+
/\/folders\/([a-zA-Z0-9_-]+)/,
|
|
2345
|
+
// Standard format
|
|
2346
|
+
/id=([a-zA-Z0-9_-]+)/
|
|
2347
|
+
// Alternative format
|
|
2348
|
+
];
|
|
2349
|
+
for (const i of e) {
|
|
2350
|
+
const o = t.match(i);
|
|
2351
|
+
if (o && o[1])
|
|
2352
|
+
return o[1];
|
|
2353
|
+
}
|
|
2354
|
+
return null;
|
|
2484
2355
|
}
|
|
2485
2356
|
/**
|
|
2486
|
-
*
|
|
2357
|
+
* Load images from a Google Drive folder
|
|
2358
|
+
* @param folderUrl - Google Drive folder URL
|
|
2359
|
+
* @param filter - Filter to apply to discovered images
|
|
2360
|
+
* @param recursive - Whether to include images from subfolders
|
|
2361
|
+
* @returns Promise resolving to array of image URLs
|
|
2487
2362
|
*/
|
|
2488
|
-
async
|
|
2363
|
+
async loadFromFolder(t, e, i = !0) {
|
|
2364
|
+
const o = this.extractFolderId(t);
|
|
2365
|
+
if (!o)
|
|
2366
|
+
throw new Error("Invalid Google Drive folder URL. Please check the URL format.");
|
|
2367
|
+
if (!this.apiKey || this.apiKey === "YOUR_API_KEY_HERE")
|
|
2368
|
+
return this.loadImagesDirectly(o, e);
|
|
2489
2369
|
try {
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
throw new Error(`Container #${this.containerId} not found`);
|
|
2494
|
-
this.containerEl.classList.add("fbn-ic-gallery"), this.swipeEngine = new bt(this.containerEl, {
|
|
2495
|
-
onNext: () => this.navigateToNextImage(),
|
|
2496
|
-
onPrev: () => this.navigateToPreviousImage(),
|
|
2497
|
-
onDragOffset: (t) => this.zoomEngine.setDragOffset(t),
|
|
2498
|
-
onDragEnd: (t) => {
|
|
2499
|
-
t ? this.zoomEngine.clearDragOffset(!1) : this.zoomEngine.clearDragOffset(!0, Ie);
|
|
2500
|
-
}
|
|
2501
|
-
}), this.setupUI(), this.setupEventListeners(), this.imageLoader = await this.createLoader(), this.logDebug("ImageCloud initialized"), await this.loadImages();
|
|
2502
|
-
} catch (t) {
|
|
2503
|
-
console.error("Gallery initialization failed:", t), this.errorEl && t instanceof Error && this.showError("Gallery failed to initialize: " + t.message);
|
|
2370
|
+
return i ? await this.loadImagesRecursively(o, e) : await this.loadImagesFromSingleFolder(o, e);
|
|
2371
|
+
} catch (s) {
|
|
2372
|
+
return console.error("Error loading from Google Drive API:", s), this.loadImagesDirectly(o, e);
|
|
2504
2373
|
}
|
|
2505
2374
|
}
|
|
2506
|
-
setupUI() {
|
|
2507
|
-
const t = this.fullConfig.rendering.ui;
|
|
2508
|
-
t.showLoadingSpinner && (t.loadingElement ? (this.loadingEl = this.resolveElement(t.loadingElement), this.loadingElAutoCreated = !1) : (this.loadingEl = this.createDefaultLoadingElement(), this.loadingElAutoCreated = !0)), t.errorElement ? (this.errorEl = this.resolveElement(t.errorElement), this.errorElAutoCreated = !1) : (this.errorEl = this.createDefaultErrorElement(), this.errorElAutoCreated = !0), t.showImageCounter && (t.counterElement ? (this.counterEl = this.resolveElement(t.counterElement), this.counterElAutoCreated = !1) : (this.counterEl = this.createDefaultCounterElement(), this.counterElAutoCreated = !0));
|
|
2509
|
-
}
|
|
2510
|
-
resolveElement(t) {
|
|
2511
|
-
return t instanceof HTMLElement ? t : document.getElementById(t);
|
|
2512
|
-
}
|
|
2513
|
-
createDefaultLoadingElement() {
|
|
2514
|
-
const t = document.createElement("div");
|
|
2515
|
-
t.className = "fbn-ic-loading fbn-ic-hidden";
|
|
2516
|
-
const e = document.createElement("div");
|
|
2517
|
-
e.className = "fbn-ic-spinner", t.appendChild(e);
|
|
2518
|
-
const i = document.createElement("p");
|
|
2519
|
-
return i.textContent = "Loading images...", t.appendChild(i), this.containerEl.appendChild(t), t;
|
|
2520
|
-
}
|
|
2521
|
-
createDefaultErrorElement() {
|
|
2522
|
-
const t = document.createElement("div");
|
|
2523
|
-
return t.className = "fbn-ic-error fbn-ic-hidden", this.containerEl.appendChild(t), t;
|
|
2524
|
-
}
|
|
2525
|
-
createDefaultCounterElement() {
|
|
2526
|
-
const t = document.createElement("div");
|
|
2527
|
-
return t.className = "fbn-ic-counter fbn-ic-hidden", this.containerEl.appendChild(t), t;
|
|
2528
|
-
}
|
|
2529
|
-
setupEventListeners() {
|
|
2530
|
-
document.addEventListener("keydown", (t) => {
|
|
2531
|
-
t.key === "Escape" ? (this.zoomEngine.unfocusImage(), this.currentFocusIndex = null, this.swipeEngine?.disable(), this.hideCounter()) : t.key === "ArrowRight" ? this.navigateToNextImage() : t.key === "ArrowLeft" ? this.navigateToPreviousImage() : (t.key === "Enter" || t.key === " ") && this.hoveredImage && (this.handleImageClick(this.hoveredImage.element, this.hoveredImage.layout), t.preventDefault());
|
|
2532
|
-
}), document.addEventListener("click", (t) => {
|
|
2533
|
-
this.swipeEngine?.hadRecentTouch() || t.target.closest(".fbn-ic-image") || (this.zoomEngine.unfocusImage(), this.currentFocusIndex = null, this.swipeEngine?.disable(), this.hideCounter());
|
|
2534
|
-
}), window.addEventListener("resize", () => this.handleResize());
|
|
2535
|
-
}
|
|
2536
2375
|
/**
|
|
2537
|
-
*
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
const t = (this.currentFocusIndex + 1) % this.imageLayouts.length, e = this.imageElements.find(
|
|
2542
|
-
(n) => n.dataset.imageId === String(t)
|
|
2543
|
-
);
|
|
2544
|
-
if (!e) return;
|
|
2545
|
-
const i = this.imageLayouts[t];
|
|
2546
|
-
i && (this.currentFocusIndex = t, this.handleImageClick(e, i), this.updateCounter(t));
|
|
2547
|
-
}
|
|
2548
|
-
/**
|
|
2549
|
-
* Navigate to the previous image (Left arrow)
|
|
2550
|
-
*/
|
|
2551
|
-
navigateToPreviousImage() {
|
|
2552
|
-
if (this.currentFocusIndex === null || this.imageElements.length === 0) return;
|
|
2553
|
-
const t = (this.currentFocusIndex - 1 + this.imageLayouts.length) % this.imageLayouts.length, e = this.imageElements.find(
|
|
2554
|
-
(n) => n.dataset.imageId === String(t)
|
|
2555
|
-
);
|
|
2556
|
-
if (!e) return;
|
|
2557
|
-
const i = this.imageLayouts[t];
|
|
2558
|
-
i && (this.currentFocusIndex = t, this.handleImageClick(e, i), this.updateCounter(t));
|
|
2559
|
-
}
|
|
2560
|
-
/**
|
|
2561
|
-
* Navigate to a specific image by index
|
|
2562
|
-
*/
|
|
2563
|
-
handleResize() {
|
|
2564
|
-
this.imagesLoaded && (this.resizeTimeout !== null && clearTimeout(this.resizeTimeout), this.resizeTimeout = window.setTimeout(() => {
|
|
2565
|
-
const t = this.getImageHeight();
|
|
2566
|
-
t !== this.currentImageHeight ? (this.logDebug(`Window resized to new breakpoint (height: ${t}px). Reloading images...`), this.loadImages()) : this.logDebug("Window resized (no breakpoint change)");
|
|
2567
|
-
}, 500));
|
|
2568
|
-
}
|
|
2569
|
-
getImageHeight() {
|
|
2570
|
-
const t = window.innerWidth, e = this.fullConfig.layout.responsive, n = this.fullConfig.image.sizing?.maxSize ?? 400;
|
|
2571
|
-
return e ? t <= e.mobile.maxWidth ? Math.min(100, n) : t <= e.tablet.maxWidth ? Math.min(180, n) : Math.min(225, n) : t <= 767 ? Math.min(100, n) : t <= 1199 ? Math.min(180, n) : Math.min(225, n);
|
|
2572
|
-
}
|
|
2573
|
-
/**
|
|
2574
|
-
* Get container bounds for layout calculations
|
|
2575
|
-
*/
|
|
2576
|
-
getContainerBounds() {
|
|
2577
|
-
return this.containerEl ? {
|
|
2578
|
-
width: this.containerEl.offsetWidth,
|
|
2579
|
-
height: this.containerEl.offsetHeight || window.innerHeight * 0.7
|
|
2580
|
-
} : { width: window.innerWidth, height: window.innerHeight * 0.7 };
|
|
2581
|
-
}
|
|
2582
|
-
/**
|
|
2583
|
-
* Load images using the unified loader interface
|
|
2584
|
-
*/
|
|
2585
|
-
async loadImages() {
|
|
2586
|
-
try {
|
|
2587
|
-
this.showLoading(!0), this.hideError(), this.clearImageCloud(), await this.imageLoader.prepare(this.imageFilter);
|
|
2588
|
-
const t = this.imageLoader.imagesLength();
|
|
2589
|
-
let e = this.imageLoader.imageURLs();
|
|
2590
|
-
if (t === 0) {
|
|
2591
|
-
this.showError("No images found."), this.showLoading(!1);
|
|
2592
|
-
return;
|
|
2593
|
-
}
|
|
2594
|
-
const i = this.getContainerBounds(), n = this.getImageHeight(), s = window.innerWidth;
|
|
2595
|
-
this.logDebug(`Adaptive sizing input: container=${i.width}x${i.height}px, images=${t}, responsiveMax=${n}px`);
|
|
2596
|
-
const r = this.layoutEngine.calculateAdaptiveSize(
|
|
2597
|
-
i,
|
|
2598
|
-
t,
|
|
2599
|
-
n,
|
|
2600
|
-
s
|
|
2601
|
-
);
|
|
2602
|
-
this.logDebug(`Adaptive sizing result: height=${r.height}px`), await this.createImageCloud(e, r.height), this.showLoading(!1), this.imagesLoaded = !0;
|
|
2603
|
-
} catch (t) {
|
|
2604
|
-
console.error("Error loading images:", t), t instanceof Error && this.showError(t.message || "Failed to load images."), this.showLoading(!1);
|
|
2605
|
-
}
|
|
2606
|
-
}
|
|
2607
|
-
/**
|
|
2608
|
-
* Helper for debug logging
|
|
2609
|
-
*/
|
|
2610
|
-
logDebug(...t) {
|
|
2611
|
-
this.fullConfig.config.debug?.enabled && typeof console < "u" && console.log(...t);
|
|
2612
|
-
}
|
|
2613
|
-
async createImageCloud(t, e) {
|
|
2614
|
-
if (!this.containerEl) return;
|
|
2615
|
-
const i = this.getContainerBounds();
|
|
2616
|
-
this.currentImageHeight = e;
|
|
2617
|
-
const n = this.loadGeneration, s = this.layoutEngine.generateLayout(t.length, i, { fixedHeight: e });
|
|
2618
|
-
this.imageLayouts = s, this.displayQueue = [];
|
|
2619
|
-
let r = 0;
|
|
2620
|
-
const a = (c) => {
|
|
2621
|
-
this.containerEl && (this.containerEl.appendChild(c), this.imageElements.push(c), requestAnimationFrame(() => {
|
|
2622
|
-
if (c.offsetWidth, c.style.opacity = this.defaultStyles.opacity ?? "1", c.dataset.startX && (this.entryAnimationEngine.requiresJSAnimation() || this.entryAnimationEngine.requiresJSRotation() || this.entryAnimationEngine.requiresJSScale() || c.dataset.startRotation !== c.dataset.rotation || c.dataset.startScale !== c.dataset.scale)) {
|
|
2623
|
-
const d = {
|
|
2624
|
-
x: parseFloat(c.dataset.startX),
|
|
2625
|
-
y: parseFloat(c.dataset.startY)
|
|
2626
|
-
}, m = {
|
|
2627
|
-
x: parseFloat(c.dataset.endX),
|
|
2628
|
-
y: parseFloat(c.dataset.endY)
|
|
2629
|
-
}, b = parseFloat(c.dataset.imageWidth), p = parseFloat(c.dataset.imageHeight), g = parseFloat(c.dataset.rotation), f = parseFloat(c.dataset.scale), S = c.dataset.startRotation ? parseFloat(c.dataset.startRotation) : g, v = c.dataset.startScale ? parseFloat(c.dataset.startScale) : f, w = this.entryAnimationEngine.getTiming();
|
|
2630
|
-
ee({
|
|
2631
|
-
element: c,
|
|
2632
|
-
startPosition: d,
|
|
2633
|
-
endPosition: m,
|
|
2634
|
-
pathConfig: this.entryAnimationEngine.getPathConfig(),
|
|
2635
|
-
duration: w.duration,
|
|
2636
|
-
imageWidth: b,
|
|
2637
|
-
imageHeight: p,
|
|
2638
|
-
rotation: g,
|
|
2639
|
-
scale: f,
|
|
2640
|
-
rotationConfig: this.entryAnimationEngine.getRotationConfig(),
|
|
2641
|
-
startRotation: S,
|
|
2642
|
-
scaleConfig: this.entryAnimationEngine.getScaleConfig(),
|
|
2643
|
-
startScale: v
|
|
2644
|
-
});
|
|
2645
|
-
} else {
|
|
2646
|
-
const d = c.dataset.finalTransform || "";
|
|
2647
|
-
c.style.transform = d;
|
|
2648
|
-
}
|
|
2649
|
-
const l = parseInt(c.dataset.imageId || "0");
|
|
2650
|
-
if (this.fullConfig.config.debug?.enabled && l < 3) {
|
|
2651
|
-
const d = c.dataset.finalTransform || "";
|
|
2652
|
-
console.log(`Image ${l} final state:`, {
|
|
2653
|
-
left: c.style.left,
|
|
2654
|
-
top: c.style.top,
|
|
2655
|
-
width: c.style.width,
|
|
2656
|
-
height: c.style.height,
|
|
2657
|
-
computedWidth: c.offsetWidth,
|
|
2658
|
-
computedHeight: c.offsetHeight,
|
|
2659
|
-
transform: d,
|
|
2660
|
-
pathType: this.entryAnimationEngine.getPathType()
|
|
2661
|
-
});
|
|
2662
|
-
}
|
|
2663
|
-
}), r++);
|
|
2664
|
-
}, h = () => {
|
|
2665
|
-
if (this.logDebug("Starting queue processing, enabled:", this.fullConfig.animation.queue.enabled), !this.fullConfig.animation.queue.enabled) {
|
|
2666
|
-
for (; this.displayQueue.length > 0; ) {
|
|
2667
|
-
const c = this.displayQueue.shift();
|
|
2668
|
-
c && a(c);
|
|
2669
|
-
}
|
|
2670
|
-
return;
|
|
2671
|
-
}
|
|
2672
|
-
this.queueInterval !== null && clearInterval(this.queueInterval), this.queueInterval = window.setInterval(() => {
|
|
2673
|
-
if (n !== this.loadGeneration) {
|
|
2674
|
-
this.queueInterval !== null && (clearInterval(this.queueInterval), this.queueInterval = null);
|
|
2675
|
-
return;
|
|
2676
|
-
}
|
|
2677
|
-
if (this.displayQueue.length > 0) {
|
|
2678
|
-
const c = this.displayQueue.shift();
|
|
2679
|
-
c && a(c);
|
|
2680
|
-
}
|
|
2681
|
-
r >= t.length && this.displayQueue.length === 0 && this.queueInterval !== null && (clearInterval(this.queueInterval), this.queueInterval = null);
|
|
2682
|
-
}, this.fullConfig.animation.queue.interval);
|
|
2683
|
-
};
|
|
2684
|
-
if ("IntersectionObserver" in window && this.containerEl) {
|
|
2685
|
-
const c = new IntersectionObserver((u) => {
|
|
2686
|
-
u.forEach((l) => {
|
|
2687
|
-
l.isIntersecting && (h(), c.disconnect());
|
|
2688
|
-
});
|
|
2689
|
-
}, { threshold: 0.1, rootMargin: "50px" });
|
|
2690
|
-
c.observe(this.containerEl);
|
|
2691
|
-
} else
|
|
2692
|
-
h();
|
|
2693
|
-
this.fullConfig.config.debug?.centers && this.containerEl && (this.containerEl.querySelectorAll(".fbn-ic-debug-center").forEach((c) => c.remove()), s.forEach((c, u) => {
|
|
2694
|
-
const l = document.createElement("div");
|
|
2695
|
-
l.className = "fbn-ic-debug-center", l.style.position = "absolute", l.style.width = "12px", l.style.height = "12px", l.style.borderRadius = "50%", l.style.backgroundColor = "red", l.style.border = "2px solid yellow", l.style.zIndex = "9999", l.style.pointerEvents = "none";
|
|
2696
|
-
const d = c.x, m = c.y;
|
|
2697
|
-
l.style.left = `${d - 6}px`, l.style.top = `${m - 6}px`, l.title = `Image ${u}: center (${Math.round(d)}, ${Math.round(m)})`, this.containerEl.appendChild(l);
|
|
2698
|
-
})), t.forEach((c, u) => {
|
|
2699
|
-
const l = document.createElement("img");
|
|
2700
|
-
l.referrerPolicy = "no-referrer", l.classList.add("fbn-ic-image"), l.dataset.imageId = String(u);
|
|
2701
|
-
const d = s[u];
|
|
2702
|
-
l.style.position = "absolute", l.style.width = "auto", l.style.height = `${e}px`, l.style.left = `${d.x}px`, l.style.top = `${d.y}px`, d.zIndex && (l.style.zIndex = String(d.zIndex)), it(l, this.defaultStyles), nt(l, this.defaultClassName), l.addEventListener("mouseenter", () => {
|
|
2703
|
-
this.hoveredImage = { element: l, layout: d }, this.zoomEngine.isInvolved(l) || (it(l, this.hoverStyles), nt(l, this.hoverClassName));
|
|
2704
|
-
}), l.addEventListener("mouseleave", () => {
|
|
2705
|
-
this.hoveredImage = null, this.zoomEngine.isInvolved(l) || (it(l, this.defaultStyles), Ft(l, this.hoverClassName), nt(l, this.defaultClassName));
|
|
2706
|
-
}), l.addEventListener("click", (m) => {
|
|
2707
|
-
m.stopPropagation(), this.handleImageClick(l, d);
|
|
2708
|
-
}), l.style.opacity = "0", l.style.transition = this.entryAnimationEngine.getTransitionCSS(), l.onload = () => {
|
|
2709
|
-
if (n !== this.loadGeneration)
|
|
2710
|
-
return;
|
|
2711
|
-
const m = l.naturalWidth / l.naturalHeight, b = e * m;
|
|
2712
|
-
l.style.width = `${b}px`;
|
|
2713
|
-
const p = { x: d.x, y: d.y }, g = { width: b, height: e }, f = this.entryAnimationEngine.calculateStartPosition(
|
|
2714
|
-
p,
|
|
2715
|
-
g,
|
|
2716
|
-
i,
|
|
2717
|
-
u,
|
|
2718
|
-
t.length
|
|
2719
|
-
), S = this.entryAnimationEngine.calculateStartRotation(d.rotation), v = this.entryAnimationEngine.calculateStartScale(d.scale), w = this.entryAnimationEngine.buildFinalTransform(
|
|
2720
|
-
d.rotation,
|
|
2721
|
-
d.scale,
|
|
2722
|
-
b,
|
|
2723
|
-
e
|
|
2724
|
-
), E = this.entryAnimationEngine.buildStartTransform(
|
|
2725
|
-
f,
|
|
2726
|
-
p,
|
|
2727
|
-
d.rotation,
|
|
2728
|
-
d.scale,
|
|
2729
|
-
b,
|
|
2730
|
-
e,
|
|
2731
|
-
S,
|
|
2732
|
-
v
|
|
2733
|
-
);
|
|
2734
|
-
this.fullConfig.config.debug?.enabled && u < 3 && console.log(`Image ${u}:`, {
|
|
2735
|
-
finalPosition: p,
|
|
2736
|
-
imageSize: g,
|
|
2737
|
-
left: d.x,
|
|
2738
|
-
top: d.y,
|
|
2739
|
-
finalTransform: w,
|
|
2740
|
-
renderedWidth: b,
|
|
2741
|
-
renderedHeight: e
|
|
2742
|
-
}), l.style.transform = E, l.dataset.finalTransform = w, (this.entryAnimationEngine.requiresJSAnimation() || this.entryAnimationEngine.requiresJSRotation() || this.entryAnimationEngine.requiresJSScale() || S !== d.rotation || v !== d.scale) && (l.dataset.startX = String(f.x), l.dataset.startY = String(f.y), l.dataset.endX = String(p.x), l.dataset.endY = String(p.y), l.dataset.imageWidth = String(b), l.dataset.imageHeight = String(e), l.dataset.rotation = String(d.rotation), l.dataset.scale = String(d.scale), l.dataset.startRotation = String(S), l.dataset.startScale = String(v)), this.displayQueue.push(l);
|
|
2743
|
-
}, l.onerror = () => r++, l.src = c;
|
|
2744
|
-
});
|
|
2745
|
-
}
|
|
2746
|
-
async handleImageClick(t, e) {
|
|
2747
|
-
if (!this.containerEl) return;
|
|
2748
|
-
const i = this.zoomEngine.isFocused(t), n = {
|
|
2749
|
-
width: this.containerEl.offsetWidth,
|
|
2750
|
-
height: this.containerEl.offsetHeight
|
|
2751
|
-
};
|
|
2752
|
-
if (i)
|
|
2753
|
-
await this.zoomEngine.unfocusImage(), this.currentFocusIndex = null, this.swipeEngine?.disable(), this.hideCounter();
|
|
2754
|
-
else {
|
|
2755
|
-
const s = t.dataset.imageId;
|
|
2756
|
-
this.currentFocusIndex = s !== void 0 ? parseInt(s, 10) : null, this.swipeEngine?.enable(), await this.zoomEngine.focusImage(t, n, e), this.currentFocusIndex !== null && this.updateCounter(this.currentFocusIndex);
|
|
2757
|
-
}
|
|
2758
|
-
}
|
|
2759
|
-
/**
|
|
2760
|
-
* Clear the image cloud and reset state
|
|
2761
|
-
*/
|
|
2762
|
-
clearImageCloud() {
|
|
2763
|
-
this.queueInterval !== null && (clearInterval(this.queueInterval), this.queueInterval = null), this.loadGeneration++, this.displayQueue = [], this.containerEl && this.containerEl.querySelectorAll(".fbn-ic-image, .fbn-ic-debug-center").forEach((t) => t.remove()), this.imageElements = [], this.imageLayouts = [], this.currentFocusIndex = null, this.hoveredImage = null, this.layoutEngine.reset(), this.zoomEngine.reset(), this.imagesLoaded = !1;
|
|
2764
|
-
}
|
|
2765
|
-
showLoading(t) {
|
|
2766
|
-
!this.fullConfig.rendering.ui.showLoadingSpinner || !this.loadingEl || (t ? this.loadingEl.classList.remove("fbn-ic-hidden") : this.loadingEl.classList.add("fbn-ic-hidden"));
|
|
2767
|
-
}
|
|
2768
|
-
showError(t) {
|
|
2769
|
-
this.errorEl && (this.errorEl.textContent = t, this.errorEl.classList.remove("fbn-ic-hidden"));
|
|
2770
|
-
}
|
|
2771
|
-
hideError() {
|
|
2772
|
-
this.errorEl && this.errorEl.classList.add("fbn-ic-hidden");
|
|
2773
|
-
}
|
|
2774
|
-
updateCounter(t) {
|
|
2775
|
-
!this.fullConfig.rendering.ui.showImageCounter || !this.counterEl || (this.counterEl.textContent = `${t + 1} of ${this.imageElements.length}`, this.counterEl.classList.remove("fbn-ic-hidden"));
|
|
2776
|
-
}
|
|
2777
|
-
hideCounter() {
|
|
2778
|
-
this.counterEl && this.counterEl.classList.add("fbn-ic-hidden");
|
|
2779
|
-
}
|
|
2780
|
-
/**
|
|
2781
|
-
* Destroy the gallery and clean up resources
|
|
2782
|
-
*/
|
|
2783
|
-
destroy() {
|
|
2784
|
-
this.clearImageCloud(), this.loadingElAutoCreated && this.loadingEl && (this.loadingEl.remove(), this.loadingEl = null), this.errorElAutoCreated && this.errorEl && (this.errorEl.remove(), this.errorEl = null), this.counterElAutoCreated && this.counterEl && (this.counterEl.remove(), this.counterEl = null), this.resizeTimeout !== null && clearTimeout(this.resizeTimeout), this.swipeEngine?.destroy();
|
|
2785
|
-
}
|
|
2786
|
-
}
|
|
2787
|
-
class Me {
|
|
2788
|
-
constructor(t) {
|
|
2789
|
-
if (this._prepared = !1, this._discoveredUrls = [], this.apiKey = t.apiKey ?? "", this.apiEndpoint = t.apiEndpoint ?? "https://www.googleapis.com/drive/v3/files", this.debugLogging = t.debugLogging ?? !1, this.sources = t.sources ?? [], !this.sources || this.sources.length === 0)
|
|
2790
|
-
throw new Error("GoogleDriveLoader requires at least one source to be configured");
|
|
2791
|
-
}
|
|
2792
|
-
/**
|
|
2793
|
-
* Prepare the loader by discovering all images from configured sources
|
|
2794
|
-
* @param filter - Filter to apply to discovered images
|
|
2795
|
-
*/
|
|
2796
|
-
async prepare(t) {
|
|
2797
|
-
this._discoveredUrls = [];
|
|
2798
|
-
for (const e of this.sources)
|
|
2799
|
-
if ("folders" in e)
|
|
2800
|
-
for (const i of e.folders) {
|
|
2801
|
-
const n = e.recursive !== void 0 ? e.recursive : !0, s = await this.loadFromFolder(i, t, n);
|
|
2802
|
-
this._discoveredUrls.push(...s);
|
|
2803
|
-
}
|
|
2804
|
-
else if ("files" in e) {
|
|
2805
|
-
const i = await this.loadFiles(e.files, t);
|
|
2806
|
-
this._discoveredUrls.push(...i);
|
|
2807
|
-
}
|
|
2808
|
-
this._prepared = !0;
|
|
2809
|
-
}
|
|
2810
|
-
/**
|
|
2811
|
-
* Get the number of discovered images
|
|
2812
|
-
* @throws Error if called before prepare()
|
|
2813
|
-
*/
|
|
2814
|
-
imagesLength() {
|
|
2815
|
-
if (!this._prepared)
|
|
2816
|
-
throw new Error("GoogleDriveLoader.imagesLength() called before prepare()");
|
|
2817
|
-
return this._discoveredUrls.length;
|
|
2818
|
-
}
|
|
2819
|
-
/**
|
|
2820
|
-
* Get the ordered list of image URLs
|
|
2821
|
-
* @throws Error if called before prepare()
|
|
2822
|
-
*/
|
|
2823
|
-
imageURLs() {
|
|
2824
|
-
if (!this._prepared)
|
|
2825
|
-
throw new Error("GoogleDriveLoader.imageURLs() called before prepare()");
|
|
2826
|
-
return [...this._discoveredUrls];
|
|
2827
|
-
}
|
|
2828
|
-
/**
|
|
2829
|
-
* Check if the loader has been prepared
|
|
2830
|
-
*/
|
|
2831
|
-
isPrepared() {
|
|
2832
|
-
return this._prepared;
|
|
2833
|
-
}
|
|
2834
|
-
/**
|
|
2835
|
-
* Extract folder ID from various Google Drive URL formats
|
|
2836
|
-
* @param folderUrl - Google Drive folder URL
|
|
2837
|
-
* @returns Folder ID or null if invalid
|
|
2838
|
-
*/
|
|
2839
|
-
extractFolderId(t) {
|
|
2840
|
-
const e = [
|
|
2841
|
-
/\/folders\/([a-zA-Z0-9_-]+)/,
|
|
2842
|
-
// Standard format
|
|
2843
|
-
/id=([a-zA-Z0-9_-]+)/
|
|
2844
|
-
// Alternative format
|
|
2845
|
-
];
|
|
2846
|
-
for (const i of e) {
|
|
2847
|
-
const n = t.match(i);
|
|
2848
|
-
if (n && n[1])
|
|
2849
|
-
return n[1];
|
|
2850
|
-
}
|
|
2851
|
-
return null;
|
|
2852
|
-
}
|
|
2853
|
-
/**
|
|
2854
|
-
* Load images from a Google Drive folder
|
|
2855
|
-
* @param folderUrl - Google Drive folder URL
|
|
2856
|
-
* @param filter - Filter to apply to discovered images
|
|
2857
|
-
* @param recursive - Whether to include images from subfolders
|
|
2858
|
-
* @returns Promise resolving to array of image URLs
|
|
2859
|
-
*/
|
|
2860
|
-
async loadFromFolder(t, e, i = !0) {
|
|
2861
|
-
const n = this.extractFolderId(t);
|
|
2862
|
-
if (!n)
|
|
2863
|
-
throw new Error("Invalid Google Drive folder URL. Please check the URL format.");
|
|
2864
|
-
if (!this.apiKey || this.apiKey === "YOUR_API_KEY_HERE")
|
|
2865
|
-
return this.loadImagesDirectly(n, e);
|
|
2866
|
-
try {
|
|
2867
|
-
return i ? await this.loadImagesRecursively(n, e) : await this.loadImagesFromSingleFolder(n, e);
|
|
2868
|
-
} catch (s) {
|
|
2869
|
-
return console.error("Error loading from Google Drive API:", s), this.loadImagesDirectly(n, e);
|
|
2870
|
-
}
|
|
2871
|
-
}
|
|
2872
|
-
/**
|
|
2873
|
-
* Load images from a single folder (non-recursive)
|
|
2874
|
-
* @param folderId - Google Drive folder ID
|
|
2875
|
-
* @param filter - Filter to apply to discovered images
|
|
2876
|
-
* @returns Promise resolving to array of image URLs
|
|
2376
|
+
* Load images from a single folder (non-recursive)
|
|
2377
|
+
* @param folderId - Google Drive folder ID
|
|
2378
|
+
* @param filter - Filter to apply to discovered images
|
|
2379
|
+
* @returns Promise resolving to array of image URLs
|
|
2877
2380
|
*/
|
|
2878
2381
|
async loadImagesFromSingleFolder(t, e) {
|
|
2879
|
-
const i = [],
|
|
2382
|
+
const i = [], o = `'${t}' in parents and trashed=false`, r = `${this.apiEndpoint}?q=${encodeURIComponent(o)}&fields=files(id,name,mimeType,thumbnailLink)&key=${this.apiKey}`, a = await fetch(r);
|
|
2880
2383
|
if (!a.ok)
|
|
2881
2384
|
throw new Error(`API request failed: ${a.status} ${a.statusText}`);
|
|
2882
2385
|
const c = (await a.json()).files.filter(
|
|
@@ -2894,10 +2397,10 @@ class Me {
|
|
|
2894
2397
|
*/
|
|
2895
2398
|
async loadFiles(t, e) {
|
|
2896
2399
|
const i = [];
|
|
2897
|
-
for (const
|
|
2898
|
-
const s = this.extractFileId(
|
|
2400
|
+
for (const o of t) {
|
|
2401
|
+
const s = this.extractFileId(o);
|
|
2899
2402
|
if (!s) {
|
|
2900
|
-
this.log(`Skipping invalid file URL: ${
|
|
2403
|
+
this.log(`Skipping invalid file URL: ${o}`);
|
|
2901
2404
|
continue;
|
|
2902
2405
|
}
|
|
2903
2406
|
if (this.apiKey && this.apiKey !== "YOUR_API_KEY_HERE")
|
|
@@ -2933,9 +2436,9 @@ class Me {
|
|
|
2933
2436
|
// Generic id parameter
|
|
2934
2437
|
];
|
|
2935
2438
|
for (const i of e) {
|
|
2936
|
-
const
|
|
2937
|
-
if (
|
|
2938
|
-
return
|
|
2439
|
+
const o = t.match(i);
|
|
2440
|
+
if (o && o[1])
|
|
2441
|
+
return o[1];
|
|
2939
2442
|
}
|
|
2940
2443
|
return null;
|
|
2941
2444
|
}
|
|
@@ -2946,7 +2449,7 @@ class Me {
|
|
|
2946
2449
|
* @returns Promise resolving to array of image URLs
|
|
2947
2450
|
*/
|
|
2948
2451
|
async loadImagesRecursively(t, e) {
|
|
2949
|
-
const i = [],
|
|
2452
|
+
const i = [], o = `'${t}' in parents and trashed=false`, r = `${this.apiEndpoint}?q=${encodeURIComponent(o)}&fields=files(id,name,mimeType,thumbnailLink)&key=${this.apiKey}`, a = await fetch(r);
|
|
2950
2453
|
if (!a.ok)
|
|
2951
2454
|
throw new Error(`API request failed: ${a.status} ${a.statusText}`);
|
|
2952
2455
|
const h = await a.json(), c = h.files.filter(
|
|
@@ -2973,10 +2476,10 @@ class Me {
|
|
|
2973
2476
|
*/
|
|
2974
2477
|
async loadImagesDirectly(t, e) {
|
|
2975
2478
|
try {
|
|
2976
|
-
const i = `https://drive.google.com/embeddedfolderview?id=${t}`,
|
|
2977
|
-
if (!
|
|
2479
|
+
const i = `https://drive.google.com/embeddedfolderview?id=${t}`, o = await fetch(i, { mode: "cors" });
|
|
2480
|
+
if (!o.ok)
|
|
2978
2481
|
throw new Error("Cannot access folder directly (CORS or permissions issue)");
|
|
2979
|
-
const s = await
|
|
2482
|
+
const s = await o.text(), r = /\/file\/d\/([a-zA-Z0-9_-]+)/g, a = [...s.matchAll(r)];
|
|
2980
2483
|
return [...new Set(a.map((u) => u[1]))].map(
|
|
2981
2484
|
(u) => `https://drive.google.com/uc?export=view&id=${u}`
|
|
2982
2485
|
);
|
|
@@ -3005,7 +2508,7 @@ class Me {
|
|
|
3005
2508
|
this.debugLogging && typeof console < "u" && console.log(...t);
|
|
3006
2509
|
}
|
|
3007
2510
|
}
|
|
3008
|
-
class
|
|
2511
|
+
class Ae {
|
|
3009
2512
|
constructor(t) {
|
|
3010
2513
|
if (this._prepared = !1, this._discoveredUrls = [], this.validateUrls = t.validateUrls !== !1, this.validationTimeout = t.validationTimeout ?? 5e3, this.validationMethod = t.validationMethod ?? "head", this.debugLogging = t.debugLogging ?? !1, this.sources = t.sources ?? [], !this.sources || this.sources.length === 0)
|
|
3011
2514
|
throw new Error("StaticImageLoader requires at least one source to be configured");
|
|
@@ -3069,13 +2572,13 @@ class ze {
|
|
|
3069
2572
|
if (!Array.isArray(t))
|
|
3070
2573
|
return console.warn("URLs must be an array:", t), [];
|
|
3071
2574
|
const i = [];
|
|
3072
|
-
for (const
|
|
3073
|
-
const s =
|
|
2575
|
+
for (const o of t) {
|
|
2576
|
+
const s = o.split("/").pop() || o;
|
|
3074
2577
|
if (!e.isAllowed(s)) {
|
|
3075
|
-
this.log(`Skipping filtered URL: ${
|
|
2578
|
+
this.log(`Skipping filtered URL: ${o}`);
|
|
3076
2579
|
continue;
|
|
3077
2580
|
}
|
|
3078
|
-
this.validateUrls ? await this.validateUrl(
|
|
2581
|
+
this.validateUrls ? await this.validateUrl(o) ? i.push(o) : console.warn(`Skipping invalid/missing URL: ${o}`) : i.push(o);
|
|
3079
2582
|
}
|
|
3080
2583
|
return i;
|
|
3081
2584
|
}
|
|
@@ -3089,16 +2592,16 @@ class ze {
|
|
|
3089
2592
|
async processPath(t, e, i) {
|
|
3090
2593
|
if (!Array.isArray(e))
|
|
3091
2594
|
return console.warn("files must be an array:", e), [];
|
|
3092
|
-
const
|
|
2595
|
+
const o = [];
|
|
3093
2596
|
for (const s of e) {
|
|
3094
2597
|
if (!i.isAllowed(s)) {
|
|
3095
2598
|
this.log(`Skipping filtered file: ${s}`);
|
|
3096
2599
|
continue;
|
|
3097
2600
|
}
|
|
3098
2601
|
const r = this.constructUrl(t, s);
|
|
3099
|
-
this.validateUrls ? await this.validateUrl(r) ?
|
|
2602
|
+
this.validateUrls ? await this.validateUrl(r) ? o.push(r) : console.warn(`Skipping invalid/missing file: ${r}`) : o.push(r);
|
|
3100
2603
|
}
|
|
3101
|
-
return
|
|
2604
|
+
return o;
|
|
3102
2605
|
}
|
|
3103
2606
|
/**
|
|
3104
2607
|
* Process a JSON endpoint source
|
|
@@ -3109,17 +2612,17 @@ class ze {
|
|
|
3109
2612
|
*/
|
|
3110
2613
|
async processJson(t, e) {
|
|
3111
2614
|
this.log(`Fetching JSON endpoint: ${t}`);
|
|
3112
|
-
const i = new AbortController(),
|
|
2615
|
+
const i = new AbortController(), o = setTimeout(() => i.abort(), 1e4);
|
|
3113
2616
|
try {
|
|
3114
2617
|
const s = await fetch(t, { signal: i.signal });
|
|
3115
|
-
if (clearTimeout(
|
|
2618
|
+
if (clearTimeout(o), !s.ok)
|
|
3116
2619
|
throw new Error(`HTTP ${s.status} fetching ${t}`);
|
|
3117
2620
|
const r = await s.json();
|
|
3118
2621
|
if (!r || !Array.isArray(r.images))
|
|
3119
2622
|
throw new Error('JSON source must return JSON with shape { "images": ["url1", "url2", ...] }');
|
|
3120
2623
|
return this.log(`JSON endpoint returned ${r.images.length} image(s)`), await this.processUrls(r.images, e);
|
|
3121
2624
|
} catch (s) {
|
|
3122
|
-
throw clearTimeout(
|
|
2625
|
+
throw clearTimeout(o), s instanceof Error && s.name === "AbortError" ? new Error(`Timeout fetching JSON endpoint: ${t}`) : s;
|
|
3123
2626
|
}
|
|
3124
2627
|
}
|
|
3125
2628
|
/**
|
|
@@ -3141,11 +2644,11 @@ class ze {
|
|
|
3141
2644
|
if (!(t.startsWith(window.location.origin) || t.startsWith("/")))
|
|
3142
2645
|
return this.log(`Skipping validation for cross-origin URL: ${t}`), !0;
|
|
3143
2646
|
try {
|
|
3144
|
-
const i = new AbortController(),
|
|
2647
|
+
const i = new AbortController(), o = setTimeout(() => i.abort(), this.validationTimeout), s = await fetch(t, {
|
|
3145
2648
|
method: "HEAD",
|
|
3146
2649
|
signal: i.signal
|
|
3147
2650
|
});
|
|
3148
|
-
return clearTimeout(
|
|
2651
|
+
return clearTimeout(o), s.ok ? !0 : (this.log(`Validation failed for ${t}: HTTP ${s.status}`), !1);
|
|
3149
2652
|
} catch (i) {
|
|
3150
2653
|
return i instanceof Error && (i.name === "AbortError" ? this.log(`Validation timeout for ${t}`) : this.log(`Validation failed for ${t}:`, i.message)), !1;
|
|
3151
2654
|
}
|
|
@@ -3162,112 +2665,564 @@ class ze {
|
|
|
3162
2665
|
return `${i}/${e}`;
|
|
3163
2666
|
if (typeof window > "u")
|
|
3164
2667
|
return `${i}/${e}`;
|
|
3165
|
-
const
|
|
3166
|
-
return `${
|
|
2668
|
+
const o = window.location.origin, r = (t.startsWith("/") ? t : "/" + t).replace(/\/$/, "");
|
|
2669
|
+
return `${o}${r}/${e}`;
|
|
2670
|
+
}
|
|
2671
|
+
/**
|
|
2672
|
+
* Check if URL is absolute (contains protocol)
|
|
2673
|
+
* @param url - URL to check
|
|
2674
|
+
* @returns True if absolute URL
|
|
2675
|
+
*/
|
|
2676
|
+
isAbsoluteUrl(t) {
|
|
2677
|
+
try {
|
|
2678
|
+
return new URL(t), !0;
|
|
2679
|
+
} catch {
|
|
2680
|
+
return !1;
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
/**
|
|
2684
|
+
* Debug logging helper
|
|
2685
|
+
* @param args - Arguments to log
|
|
2686
|
+
*/
|
|
2687
|
+
log(...t) {
|
|
2688
|
+
this.debugLogging && typeof console < "u" && console.log(...t);
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
class Te {
|
|
2692
|
+
constructor(t) {
|
|
2693
|
+
if (this._prepared = !1, this._discoveredUrls = [], this.loaders = t.loaders, this.debugLogging = t.debugLogging ?? !1, !this.loaders || this.loaders.length === 0)
|
|
2694
|
+
throw new Error("CompositeLoader requires at least one loader to be configured");
|
|
2695
|
+
this.log(`CompositeLoader initialized with ${this.loaders.length} loader(s)`);
|
|
2696
|
+
}
|
|
2697
|
+
/**
|
|
2698
|
+
* Prepare all loaders in parallel and combine their results
|
|
2699
|
+
* @param filter - Filter to apply to discovered images
|
|
2700
|
+
*/
|
|
2701
|
+
async prepare(t) {
|
|
2702
|
+
this._discoveredUrls = [], this.log(`Preparing ${this.loaders.length} loader(s) in parallel`);
|
|
2703
|
+
const e = this.loaders.map((i, o) => i.prepare(t).then(() => {
|
|
2704
|
+
this.log(`Loader ${o} prepared with ${i.imagesLength()} images`);
|
|
2705
|
+
}).catch((s) => {
|
|
2706
|
+
console.warn(`Loader ${o} failed to prepare:`, s);
|
|
2707
|
+
}));
|
|
2708
|
+
await Promise.all(e);
|
|
2709
|
+
for (const i of this.loaders)
|
|
2710
|
+
if (i.isPrepared()) {
|
|
2711
|
+
const o = i.imageURLs();
|
|
2712
|
+
this._discoveredUrls.push(...o);
|
|
2713
|
+
}
|
|
2714
|
+
this._prepared = !0, this.log(`CompositeLoader prepared with ${this._discoveredUrls.length} total images`);
|
|
2715
|
+
}
|
|
2716
|
+
/**
|
|
2717
|
+
* Get the combined number of discovered images
|
|
2718
|
+
* @throws Error if called before prepare()
|
|
2719
|
+
*/
|
|
2720
|
+
imagesLength() {
|
|
2721
|
+
if (!this._prepared)
|
|
2722
|
+
throw new Error("CompositeLoader.imagesLength() called before prepare()");
|
|
2723
|
+
return this._discoveredUrls.length;
|
|
2724
|
+
}
|
|
2725
|
+
/**
|
|
2726
|
+
* Get the combined ordered list of image URLs
|
|
2727
|
+
* @throws Error if called before prepare()
|
|
2728
|
+
*/
|
|
2729
|
+
imageURLs() {
|
|
2730
|
+
if (!this._prepared)
|
|
2731
|
+
throw new Error("CompositeLoader.imageURLs() called before prepare()");
|
|
2732
|
+
return [...this._discoveredUrls];
|
|
2733
|
+
}
|
|
2734
|
+
/**
|
|
2735
|
+
* Check if the loader has been prepared
|
|
2736
|
+
*/
|
|
2737
|
+
isPrepared() {
|
|
2738
|
+
return this._prepared;
|
|
2739
|
+
}
|
|
2740
|
+
/**
|
|
2741
|
+
* Debug logging helper
|
|
2742
|
+
* @param args - Arguments to log
|
|
2743
|
+
*/
|
|
2744
|
+
log(...t) {
|
|
2745
|
+
this.debugLogging && typeof console < "u" && console.log("[CompositeLoader]", ...t);
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
class Ce {
|
|
2749
|
+
/**
|
|
2750
|
+
* Create a new ImageFilter
|
|
2751
|
+
* @param extensions - Array of allowed file extensions (without dots)
|
|
2752
|
+
* Defaults to common image formats if not provided
|
|
2753
|
+
*/
|
|
2754
|
+
constructor(t) {
|
|
2755
|
+
this.allowedExtensions = t || [
|
|
2756
|
+
"jpg",
|
|
2757
|
+
"jpeg",
|
|
2758
|
+
"png",
|
|
2759
|
+
"gif",
|
|
2760
|
+
"webp",
|
|
2761
|
+
"bmp"
|
|
2762
|
+
];
|
|
2763
|
+
}
|
|
2764
|
+
/**
|
|
2765
|
+
* Check if a filename has an allowed extension
|
|
2766
|
+
* @param filename - The filename to check (can include path or query string)
|
|
2767
|
+
* @returns True if the file extension is allowed
|
|
2768
|
+
*/
|
|
2769
|
+
isAllowed(t) {
|
|
2770
|
+
const i = t.split("?")[0].split(".").pop()?.toLowerCase();
|
|
2771
|
+
return i ? this.allowedExtensions.includes(i) : !1;
|
|
2772
|
+
}
|
|
2773
|
+
/**
|
|
2774
|
+
* Get the list of allowed extensions
|
|
2775
|
+
* @returns Array of allowed extensions
|
|
2776
|
+
*/
|
|
2777
|
+
getAllowedExtensions() {
|
|
2778
|
+
return [...this.allowedExtensions];
|
|
2779
|
+
}
|
|
2780
|
+
// Future expansion methods:
|
|
2781
|
+
// isAllowedSize(sizeBytes: number): boolean
|
|
2782
|
+
// isAllowedDate(date: Date): boolean
|
|
2783
|
+
// isAllowedDimensions(width: number, height: number): boolean
|
|
2784
|
+
}
|
|
2785
|
+
const Re = `
|
|
2786
|
+
.fbn-ic-gallery {
|
|
2787
|
+
position: relative;
|
|
2788
|
+
width: 100%;
|
|
2789
|
+
height: 100%;
|
|
2790
|
+
overflow: hidden;
|
|
2791
|
+
perspective: 1000px;
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2794
|
+
.fbn-ic-image {
|
|
2795
|
+
position: absolute;
|
|
2796
|
+
cursor: pointer;
|
|
2797
|
+
transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2798
|
+
box-shadow 0.6s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2799
|
+
filter 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2800
|
+
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2801
|
+
border 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2802
|
+
outline 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2803
|
+
z-index 0s 0.6s;
|
|
2804
|
+
will-change: transform;
|
|
2805
|
+
user-select: none;
|
|
2806
|
+
backface-visibility: hidden;
|
|
2807
|
+
-webkit-backface-visibility: hidden;
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2810
|
+
.fbn-ic-image.fbn-ic-focused {
|
|
2811
|
+
z-index: 1000;
|
|
2812
|
+
transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2813
|
+
box-shadow 0.6s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2814
|
+
filter 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2815
|
+
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2816
|
+
border 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2817
|
+
outline 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
2818
|
+
z-index 0s 0s;
|
|
2819
|
+
will-change: auto;
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2822
|
+
.fbn-ic-counter {
|
|
2823
|
+
position: fixed;
|
|
2824
|
+
bottom: 24px;
|
|
2825
|
+
left: 50%;
|
|
2826
|
+
transform: translateX(-50%);
|
|
2827
|
+
z-index: 10001;
|
|
2828
|
+
pointer-events: none;
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2831
|
+
.fbn-ic-hidden {
|
|
2832
|
+
display: none !important;
|
|
2833
|
+
}
|
|
2834
|
+
`;
|
|
2835
|
+
function Me() {
|
|
2836
|
+
if (typeof document > "u") return;
|
|
2837
|
+
const n = "fbn-ic-functional-styles";
|
|
2838
|
+
if (document.getElementById(n)) return;
|
|
2839
|
+
const t = document.createElement("style");
|
|
2840
|
+
t.id = n, t.textContent = Re, document.head.appendChild(t);
|
|
2841
|
+
}
|
|
2842
|
+
class Le {
|
|
2843
|
+
constructor(t = {}) {
|
|
2844
|
+
this.fullConfig = jt(t), t.container instanceof HTMLElement ? (this.containerRef = t.container, this.containerId = null) : (this.containerRef = null, this.containerId = t.container || "imageCloud"), this.imagesLoaded = !1, this.imageElements = [], this.imageLayouts = [], this.currentImageHeight = 225, this.currentFocusIndex = null, this.hoveredImage = null, this.resizeTimeout = null, this.displayQueue = [], this.queueInterval = null, this.loadGeneration = 0, this.loadingElAutoCreated = !1, this.errorElAutoCreated = !1, this.counterEl = null, this.counterElAutoCreated = !1, this.animationEngine = new qt(this.fullConfig.animation), this.layoutEngine = new ge({
|
|
2845
|
+
layout: this.fullConfig.layout,
|
|
2846
|
+
image: this.fullConfig.image
|
|
2847
|
+
}), this.zoomEngine = new be(this.fullConfig.interaction.focus, this.animationEngine, this.fullConfig.styling), this.defaultStyles = st(this.fullConfig.styling?.default), this.hoverStyles = st(this.fullConfig.styling?.hover), this.defaultClassName = this.fullConfig.styling?.default?.className, this.hoverClassName = this.fullConfig.styling?.hover?.className;
|
|
2848
|
+
const e = this.fullConfig.animation.entry || y.animation.entry;
|
|
2849
|
+
this.entryAnimationEngine = new ie(
|
|
2850
|
+
e,
|
|
2851
|
+
this.fullConfig.layout.algorithm
|
|
2852
|
+
), this.swipeEngine = null, this.imageFilter = this.createImageFilter(), this.imageLoader = this.createLoader(), this.containerEl = null, this.loadingEl = null, this.errorEl = null;
|
|
2853
|
+
}
|
|
2854
|
+
/**
|
|
2855
|
+
* Create image filter based on shared loader config
|
|
2856
|
+
*/
|
|
2857
|
+
createImageFilter() {
|
|
2858
|
+
const t = this.fullConfig.config.loaders?.allowedExtensions;
|
|
2859
|
+
return new Ce(t);
|
|
2860
|
+
}
|
|
2861
|
+
/**
|
|
2862
|
+
* Create appropriate image loader based on config
|
|
2863
|
+
* Processes loaders array, merges shared config, wraps in CompositeLoader if needed
|
|
2864
|
+
*/
|
|
2865
|
+
createLoader() {
|
|
2866
|
+
const t = this.fullConfig.loaders, e = this.fullConfig.config.loaders ?? {};
|
|
2867
|
+
if (!t || t.length === 0)
|
|
2868
|
+
throw new Error("No loaders configured. Provide `images`, `loaders`, or both.");
|
|
2869
|
+
const i = t.map((o) => this.createLoaderFromEntry(o, e));
|
|
2870
|
+
return i.length === 1 ? i[0] : new Te({
|
|
2871
|
+
loaders: i,
|
|
2872
|
+
debugLogging: this.fullConfig.config.debug?.loaders
|
|
2873
|
+
});
|
|
2874
|
+
}
|
|
2875
|
+
/**
|
|
2876
|
+
* Create a single loader from a LoaderEntry, merging shared config
|
|
2877
|
+
*/
|
|
2878
|
+
createLoaderFromEntry(t, e) {
|
|
2879
|
+
if ("static" in t) {
|
|
2880
|
+
const i = t.static, o = {
|
|
2881
|
+
...i,
|
|
2882
|
+
validateUrls: i.validateUrls ?? e.validateUrls,
|
|
2883
|
+
validationTimeout: i.validationTimeout ?? e.validationTimeout,
|
|
2884
|
+
validationMethod: i.validationMethod ?? e.validationMethod,
|
|
2885
|
+
allowedExtensions: i.allowedExtensions ?? e.allowedExtensions,
|
|
2886
|
+
debugLogging: i.debugLogging ?? this.fullConfig.config.debug?.loaders
|
|
2887
|
+
};
|
|
2888
|
+
return new Ae(o);
|
|
2889
|
+
} else if ("googleDrive" in t) {
|
|
2890
|
+
const i = t.googleDrive, o = {
|
|
2891
|
+
...i,
|
|
2892
|
+
allowedExtensions: i.allowedExtensions ?? e.allowedExtensions,
|
|
2893
|
+
debugLogging: i.debugLogging ?? this.fullConfig.config.debug?.loaders
|
|
2894
|
+
};
|
|
2895
|
+
return new Ie(o);
|
|
2896
|
+
} else
|
|
2897
|
+
throw new Error(`Unknown loader entry: ${JSON.stringify(t)}`);
|
|
2898
|
+
}
|
|
2899
|
+
/**
|
|
2900
|
+
* Initialize the gallery
|
|
2901
|
+
*/
|
|
2902
|
+
async init() {
|
|
2903
|
+
try {
|
|
2904
|
+
if (Me(), this.containerRef)
|
|
2905
|
+
this.containerEl = this.containerRef;
|
|
2906
|
+
else if (this.containerEl = document.getElementById(this.containerId), !this.containerEl)
|
|
2907
|
+
throw new Error(`Container #${this.containerId} not found`);
|
|
2908
|
+
this.containerEl.classList.add("fbn-ic-gallery"), this.swipeEngine = new ft(this.containerEl, {
|
|
2909
|
+
onNext: () => this.navigateToNextImage(),
|
|
2910
|
+
onPrev: () => this.navigateToPreviousImage(),
|
|
2911
|
+
onDragOffset: (t) => this.zoomEngine.setDragOffset(t),
|
|
2912
|
+
onDragEnd: (t) => {
|
|
2913
|
+
t ? this.zoomEngine.clearDragOffset(!1) : this.zoomEngine.clearDragOffset(!0, Se);
|
|
2914
|
+
}
|
|
2915
|
+
}), this.setupUI(), this.setupEventListeners(), this.logDebug("ImageCloud initialized"), await this.loadImages();
|
|
2916
|
+
} catch (t) {
|
|
2917
|
+
console.error("Gallery initialization failed:", t), this.errorEl && t instanceof Error && this.showError("Gallery failed to initialize: " + t.message);
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
setupUI() {
|
|
2921
|
+
const t = this.fullConfig.rendering.ui;
|
|
2922
|
+
t.showLoadingSpinner && (t.loadingElement ? (this.loadingEl = this.resolveElement(t.loadingElement), this.loadingElAutoCreated = !1) : (this.loadingEl = this.createDefaultLoadingElement(), this.loadingElAutoCreated = !0)), t.errorElement ? (this.errorEl = this.resolveElement(t.errorElement), this.errorElAutoCreated = !1) : (this.errorEl = this.createDefaultErrorElement(), this.errorElAutoCreated = !0), t.showImageCounter && (t.counterElement ? (this.counterEl = this.resolveElement(t.counterElement), this.counterElAutoCreated = !1) : (this.counterEl = this.createDefaultCounterElement(), this.counterElAutoCreated = !0));
|
|
2923
|
+
}
|
|
2924
|
+
resolveElement(t) {
|
|
2925
|
+
return t instanceof HTMLElement ? t : document.getElementById(t);
|
|
2926
|
+
}
|
|
2927
|
+
createDefaultLoadingElement() {
|
|
2928
|
+
const t = document.createElement("div");
|
|
2929
|
+
t.className = "fbn-ic-loading fbn-ic-hidden";
|
|
2930
|
+
const e = document.createElement("div");
|
|
2931
|
+
e.className = "fbn-ic-spinner", t.appendChild(e);
|
|
2932
|
+
const i = document.createElement("p");
|
|
2933
|
+
return i.textContent = "Loading images...", t.appendChild(i), this.containerEl.appendChild(t), t;
|
|
2934
|
+
}
|
|
2935
|
+
createDefaultErrorElement() {
|
|
2936
|
+
const t = document.createElement("div");
|
|
2937
|
+
return t.className = "fbn-ic-error fbn-ic-hidden", this.containerEl.appendChild(t), t;
|
|
2938
|
+
}
|
|
2939
|
+
createDefaultCounterElement() {
|
|
2940
|
+
const t = document.createElement("div");
|
|
2941
|
+
return t.className = "fbn-ic-counter fbn-ic-hidden", this.containerEl.appendChild(t), t;
|
|
2942
|
+
}
|
|
2943
|
+
setupEventListeners() {
|
|
2944
|
+
document.addEventListener("keydown", (t) => {
|
|
2945
|
+
t.key === "Escape" ? (this.zoomEngine.unfocusImage(), this.currentFocusIndex = null, this.swipeEngine?.disable(), this.hideCounter()) : t.key === "ArrowRight" ? this.navigateToNextImage() : t.key === "ArrowLeft" ? this.navigateToPreviousImage() : (t.key === "Enter" || t.key === " ") && this.hoveredImage && (this.handleImageClick(this.hoveredImage.element, this.hoveredImage.layout), t.preventDefault());
|
|
2946
|
+
}), document.addEventListener("click", (t) => {
|
|
2947
|
+
this.swipeEngine?.hadRecentTouch() || t.target.closest(".fbn-ic-image") || (this.zoomEngine.unfocusImage(), this.currentFocusIndex = null, this.swipeEngine?.disable(), this.hideCounter());
|
|
2948
|
+
}), window.addEventListener("resize", () => this.handleResize());
|
|
2949
|
+
}
|
|
2950
|
+
/**
|
|
2951
|
+
* Navigate to the next image (Right arrow)
|
|
2952
|
+
*/
|
|
2953
|
+
navigateToNextImage() {
|
|
2954
|
+
if (this.currentFocusIndex === null || this.imageElements.length === 0) return;
|
|
2955
|
+
const t = (this.currentFocusIndex + 1) % this.imageLayouts.length, e = this.imageElements.find(
|
|
2956
|
+
(o) => o.dataset.imageId === String(t)
|
|
2957
|
+
);
|
|
2958
|
+
if (!e) return;
|
|
2959
|
+
const i = this.imageLayouts[t];
|
|
2960
|
+
i && (this.currentFocusIndex = t, this.handleImageClick(e, i), this.updateCounter(t));
|
|
3167
2961
|
}
|
|
3168
2962
|
/**
|
|
3169
|
-
*
|
|
3170
|
-
* @param url - URL to check
|
|
3171
|
-
* @returns True if absolute URL
|
|
2963
|
+
* Navigate to the previous image (Left arrow)
|
|
3172
2964
|
*/
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
2965
|
+
navigateToPreviousImage() {
|
|
2966
|
+
if (this.currentFocusIndex === null || this.imageElements.length === 0) return;
|
|
2967
|
+
const t = (this.currentFocusIndex - 1 + this.imageLayouts.length) % this.imageLayouts.length, e = this.imageElements.find(
|
|
2968
|
+
(o) => o.dataset.imageId === String(t)
|
|
2969
|
+
);
|
|
2970
|
+
if (!e) return;
|
|
2971
|
+
const i = this.imageLayouts[t];
|
|
2972
|
+
i && (this.currentFocusIndex = t, this.handleImageClick(e, i), this.updateCounter(t));
|
|
3179
2973
|
}
|
|
3180
2974
|
/**
|
|
3181
|
-
*
|
|
3182
|
-
* @param args - Arguments to log
|
|
2975
|
+
* Navigate to a specific image by index
|
|
3183
2976
|
*/
|
|
3184
|
-
|
|
3185
|
-
this.
|
|
2977
|
+
handleResize() {
|
|
2978
|
+
this.imagesLoaded && (this.resizeTimeout !== null && clearTimeout(this.resizeTimeout), this.resizeTimeout = window.setTimeout(() => {
|
|
2979
|
+
const t = this.getImageHeight();
|
|
2980
|
+
t !== this.currentImageHeight ? (this.logDebug(`Window resized to new breakpoint (height: ${t}px). Reloading images...`), this.loadImages()) : this.logDebug("Window resized (no breakpoint change)");
|
|
2981
|
+
}, 500));
|
|
3186
2982
|
}
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
if (this._prepared = !1, this._discoveredUrls = [], this.loaders = t.loaders, this.debugLogging = t.debugLogging ?? !1, !this.loaders || this.loaders.length === 0)
|
|
3191
|
-
throw new Error("CompositeLoader requires at least one loader to be configured");
|
|
3192
|
-
this.log(`CompositeLoader initialized with ${this.loaders.length} loader(s)`);
|
|
2983
|
+
getImageHeight() {
|
|
2984
|
+
const t = window.innerWidth, e = this.fullConfig.layout.responsive, o = this.fullConfig.image.sizing?.maxSize ?? 400;
|
|
2985
|
+
return e ? t <= e.mobile.maxWidth ? Math.min(100, o) : t <= e.tablet.maxWidth ? Math.min(180, o) : Math.min(225, o) : t <= 767 ? Math.min(100, o) : t <= 1199 ? Math.min(180, o) : Math.min(225, o);
|
|
3193
2986
|
}
|
|
3194
2987
|
/**
|
|
3195
|
-
*
|
|
3196
|
-
* @param filter - Filter to apply to discovered images
|
|
2988
|
+
* Get container bounds for layout calculations
|
|
3197
2989
|
*/
|
|
3198
|
-
|
|
3199
|
-
this.
|
|
3200
|
-
|
|
3201
|
-
this.
|
|
3202
|
-
}
|
|
3203
|
-
console.warn(`Loader ${n} failed to prepare:`, s);
|
|
3204
|
-
}));
|
|
3205
|
-
await Promise.all(e);
|
|
3206
|
-
for (const i of this.loaders)
|
|
3207
|
-
if (i.isPrepared()) {
|
|
3208
|
-
const n = i.imageURLs();
|
|
3209
|
-
this._discoveredUrls.push(...n);
|
|
3210
|
-
}
|
|
3211
|
-
this._prepared = !0, this.log(`CompositeLoader prepared with ${this._discoveredUrls.length} total images`);
|
|
2990
|
+
getContainerBounds() {
|
|
2991
|
+
return this.containerEl ? {
|
|
2992
|
+
width: this.containerEl.offsetWidth,
|
|
2993
|
+
height: this.containerEl.offsetHeight || window.innerHeight * 0.7
|
|
2994
|
+
} : { width: window.innerWidth, height: window.innerHeight * 0.7 };
|
|
3212
2995
|
}
|
|
3213
2996
|
/**
|
|
3214
|
-
*
|
|
3215
|
-
* @throws Error if called before prepare()
|
|
2997
|
+
* Load images using the unified loader interface
|
|
3216
2998
|
*/
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
2999
|
+
async loadImages() {
|
|
3000
|
+
try {
|
|
3001
|
+
this.showLoading(!0), this.hideError(), this.clearImageCloud(), await this.imageLoader.prepare(this.imageFilter);
|
|
3002
|
+
const t = this.imageLoader.imagesLength();
|
|
3003
|
+
let e = this.imageLoader.imageURLs();
|
|
3004
|
+
if (t === 0) {
|
|
3005
|
+
this.showError("No images found."), this.showLoading(!1);
|
|
3006
|
+
return;
|
|
3007
|
+
}
|
|
3008
|
+
const i = this.getContainerBounds(), o = this.getImageHeight(), s = window.innerWidth;
|
|
3009
|
+
this.logDebug(`Adaptive sizing input: container=${i.width}x${i.height}px, images=${t}, responsiveMax=${o}px`);
|
|
3010
|
+
const r = this.layoutEngine.calculateAdaptiveSize(
|
|
3011
|
+
i,
|
|
3012
|
+
t,
|
|
3013
|
+
o,
|
|
3014
|
+
s
|
|
3015
|
+
);
|
|
3016
|
+
this.logDebug(`Adaptive sizing result: height=${r.height}px`), await this.createImageCloud(e, r.height), this.showLoading(!1), this.imagesLoaded = !0;
|
|
3017
|
+
} catch (t) {
|
|
3018
|
+
console.error("Error loading images:", t), t instanceof Error && this.showError(t.message || "Failed to load images."), this.showLoading(!1);
|
|
3019
|
+
}
|
|
3221
3020
|
}
|
|
3222
3021
|
/**
|
|
3223
|
-
*
|
|
3224
|
-
* @throws Error if called before prepare()
|
|
3022
|
+
* Helper for debug logging
|
|
3225
3023
|
*/
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3024
|
+
logDebug(...t) {
|
|
3025
|
+
this.fullConfig.config.debug?.enabled && typeof console < "u" && console.log(...t);
|
|
3026
|
+
}
|
|
3027
|
+
async createImageCloud(t, e) {
|
|
3028
|
+
if (!this.containerEl) return;
|
|
3029
|
+
const i = this.getContainerBounds();
|
|
3030
|
+
this.currentImageHeight = e;
|
|
3031
|
+
const o = this.loadGeneration, s = this.layoutEngine.generateLayout(t.length, i, { fixedHeight: e });
|
|
3032
|
+
this.imageLayouts = s, this.displayQueue = [];
|
|
3033
|
+
let r = 0;
|
|
3034
|
+
const a = (c) => {
|
|
3035
|
+
this.containerEl && (this.containerEl.appendChild(c), this.imageElements.push(c), requestAnimationFrame(() => {
|
|
3036
|
+
if (c.offsetWidth, c.style.opacity = this.defaultStyles.opacity ?? "1", c.dataset.startX && (this.entryAnimationEngine.requiresJSAnimation() || this.entryAnimationEngine.requiresJSRotation() || this.entryAnimationEngine.requiresJSScale() || c.dataset.startRotation !== c.dataset.rotation || c.dataset.startScale !== c.dataset.scale)) {
|
|
3037
|
+
const d = {
|
|
3038
|
+
x: parseFloat(c.dataset.startX),
|
|
3039
|
+
y: parseFloat(c.dataset.startY)
|
|
3040
|
+
}, m = {
|
|
3041
|
+
x: parseFloat(c.dataset.endX),
|
|
3042
|
+
y: parseFloat(c.dataset.endY)
|
|
3043
|
+
}, b = parseFloat(c.dataset.imageWidth), p = parseFloat(c.dataset.imageHeight), g = parseFloat(c.dataset.rotation), f = parseFloat(c.dataset.scale), S = c.dataset.startRotation ? parseFloat(c.dataset.startRotation) : g, v = c.dataset.startScale ? parseFloat(c.dataset.startScale) : f, w = this.entryAnimationEngine.getTiming();
|
|
3044
|
+
Qt({
|
|
3045
|
+
element: c,
|
|
3046
|
+
startPosition: d,
|
|
3047
|
+
endPosition: m,
|
|
3048
|
+
pathConfig: this.entryAnimationEngine.getPathConfig(),
|
|
3049
|
+
duration: w.duration,
|
|
3050
|
+
imageWidth: b,
|
|
3051
|
+
imageHeight: p,
|
|
3052
|
+
rotation: g,
|
|
3053
|
+
scale: f,
|
|
3054
|
+
rotationConfig: this.entryAnimationEngine.getRotationConfig(),
|
|
3055
|
+
startRotation: S,
|
|
3056
|
+
scaleConfig: this.entryAnimationEngine.getScaleConfig(),
|
|
3057
|
+
startScale: v
|
|
3058
|
+
});
|
|
3059
|
+
} else {
|
|
3060
|
+
const d = c.dataset.finalTransform || "";
|
|
3061
|
+
c.style.transform = d;
|
|
3062
|
+
}
|
|
3063
|
+
const l = parseInt(c.dataset.imageId || "0");
|
|
3064
|
+
if (this.fullConfig.config.debug?.enabled && l < 3) {
|
|
3065
|
+
const d = c.dataset.finalTransform || "";
|
|
3066
|
+
console.log(`Image ${l} final state:`, {
|
|
3067
|
+
left: c.style.left,
|
|
3068
|
+
top: c.style.top,
|
|
3069
|
+
width: c.style.width,
|
|
3070
|
+
height: c.style.height,
|
|
3071
|
+
computedWidth: c.offsetWidth,
|
|
3072
|
+
computedHeight: c.offsetHeight,
|
|
3073
|
+
transform: d,
|
|
3074
|
+
pathType: this.entryAnimationEngine.getPathType()
|
|
3075
|
+
});
|
|
3076
|
+
}
|
|
3077
|
+
}), r++);
|
|
3078
|
+
}, h = () => {
|
|
3079
|
+
if (this.logDebug("Starting queue processing, enabled:", this.fullConfig.animation.queue.enabled), !this.fullConfig.animation.queue.enabled) {
|
|
3080
|
+
for (; this.displayQueue.length > 0; ) {
|
|
3081
|
+
const c = this.displayQueue.shift();
|
|
3082
|
+
c && a(c);
|
|
3083
|
+
}
|
|
3084
|
+
return;
|
|
3085
|
+
}
|
|
3086
|
+
this.queueInterval !== null && clearInterval(this.queueInterval), this.queueInterval = window.setInterval(() => {
|
|
3087
|
+
if (o !== this.loadGeneration) {
|
|
3088
|
+
this.queueInterval !== null && (clearInterval(this.queueInterval), this.queueInterval = null);
|
|
3089
|
+
return;
|
|
3090
|
+
}
|
|
3091
|
+
if (this.displayQueue.length > 0) {
|
|
3092
|
+
const c = this.displayQueue.shift();
|
|
3093
|
+
c && a(c);
|
|
3094
|
+
}
|
|
3095
|
+
r >= t.length && this.displayQueue.length === 0 && this.queueInterval !== null && (clearInterval(this.queueInterval), this.queueInterval = null);
|
|
3096
|
+
}, this.fullConfig.animation.queue.interval);
|
|
3097
|
+
};
|
|
3098
|
+
if ("IntersectionObserver" in window && this.containerEl) {
|
|
3099
|
+
const c = new IntersectionObserver((u) => {
|
|
3100
|
+
u.forEach((l) => {
|
|
3101
|
+
l.isIntersecting && (h(), c.disconnect());
|
|
3102
|
+
});
|
|
3103
|
+
}, { threshold: 0.1, rootMargin: "50px" });
|
|
3104
|
+
c.observe(this.containerEl);
|
|
3105
|
+
} else
|
|
3106
|
+
h();
|
|
3107
|
+
this.fullConfig.config.debug?.centers && this.containerEl && (this.containerEl.querySelectorAll(".fbn-ic-debug-center").forEach((c) => c.remove()), s.forEach((c, u) => {
|
|
3108
|
+
const l = document.createElement("div");
|
|
3109
|
+
l.className = "fbn-ic-debug-center", l.style.position = "absolute", l.style.width = "12px", l.style.height = "12px", l.style.borderRadius = "50%", l.style.backgroundColor = "red", l.style.border = "2px solid yellow", l.style.zIndex = "9999", l.style.pointerEvents = "none";
|
|
3110
|
+
const d = c.x, m = c.y;
|
|
3111
|
+
l.style.left = `${d - 6}px`, l.style.top = `${m - 6}px`, l.title = `Image ${u}: center (${Math.round(d)}, ${Math.round(m)})`, this.containerEl.appendChild(l);
|
|
3112
|
+
})), t.forEach((c, u) => {
|
|
3113
|
+
const l = document.createElement("img");
|
|
3114
|
+
l.referrerPolicy = "no-referrer", l.classList.add("fbn-ic-image"), l.dataset.imageId = String(u);
|
|
3115
|
+
const d = s[u];
|
|
3116
|
+
l.style.position = "absolute", l.style.width = "auto", l.style.height = `${e}px`, l.style.left = `${d.x}px`, l.style.top = `${d.y}px`, d.zIndex && (l.style.zIndex = String(d.zIndex)), tt(l, this.defaultStyles), et(l, this.defaultClassName), l.addEventListener("mouseenter", () => {
|
|
3117
|
+
this.hoveredImage = { element: l, layout: d }, this.zoomEngine.isInvolved(l) || (tt(l, this.hoverStyles), et(l, this.hoverClassName));
|
|
3118
|
+
}), l.addEventListener("mouseleave", () => {
|
|
3119
|
+
this.hoveredImage = null, this.zoomEngine.isInvolved(l) || (tt(l, this.defaultStyles), Lt(l, this.hoverClassName), et(l, this.defaultClassName));
|
|
3120
|
+
}), l.addEventListener("click", (m) => {
|
|
3121
|
+
m.stopPropagation(), this.handleImageClick(l, d);
|
|
3122
|
+
}), l.style.opacity = "0", l.style.transition = this.entryAnimationEngine.getTransitionCSS(), l.onload = () => {
|
|
3123
|
+
if (o !== this.loadGeneration)
|
|
3124
|
+
return;
|
|
3125
|
+
const m = l.naturalWidth / l.naturalHeight, b = e * m;
|
|
3126
|
+
l.style.width = `${b}px`;
|
|
3127
|
+
const p = { x: d.x, y: d.y }, g = { width: b, height: e }, f = this.entryAnimationEngine.calculateStartPosition(
|
|
3128
|
+
p,
|
|
3129
|
+
g,
|
|
3130
|
+
i,
|
|
3131
|
+
u,
|
|
3132
|
+
t.length
|
|
3133
|
+
), S = this.entryAnimationEngine.calculateStartRotation(d.rotation), v = this.entryAnimationEngine.calculateStartScale(d.scale), w = this.entryAnimationEngine.buildFinalTransform(
|
|
3134
|
+
d.rotation,
|
|
3135
|
+
d.scale,
|
|
3136
|
+
b,
|
|
3137
|
+
e
|
|
3138
|
+
), E = this.entryAnimationEngine.buildStartTransform(
|
|
3139
|
+
f,
|
|
3140
|
+
p,
|
|
3141
|
+
d.rotation,
|
|
3142
|
+
d.scale,
|
|
3143
|
+
b,
|
|
3144
|
+
e,
|
|
3145
|
+
S,
|
|
3146
|
+
v
|
|
3147
|
+
);
|
|
3148
|
+
this.fullConfig.config.debug?.enabled && u < 3 && console.log(`Image ${u}:`, {
|
|
3149
|
+
finalPosition: p,
|
|
3150
|
+
imageSize: g,
|
|
3151
|
+
left: d.x,
|
|
3152
|
+
top: d.y,
|
|
3153
|
+
finalTransform: w,
|
|
3154
|
+
renderedWidth: b,
|
|
3155
|
+
renderedHeight: e
|
|
3156
|
+
}), l.style.transform = E, l.dataset.finalTransform = w, (this.entryAnimationEngine.requiresJSAnimation() || this.entryAnimationEngine.requiresJSRotation() || this.entryAnimationEngine.requiresJSScale() || S !== d.rotation || v !== d.scale) && (l.dataset.startX = String(f.x), l.dataset.startY = String(f.y), l.dataset.endX = String(p.x), l.dataset.endY = String(p.y), l.dataset.imageWidth = String(b), l.dataset.imageHeight = String(e), l.dataset.rotation = String(d.rotation), l.dataset.scale = String(d.scale), l.dataset.startRotation = String(S), l.dataset.startScale = String(v)), this.displayQueue.push(l);
|
|
3157
|
+
}, l.onerror = () => r++, l.src = c;
|
|
3158
|
+
});
|
|
3159
|
+
}
|
|
3160
|
+
async handleImageClick(t, e) {
|
|
3161
|
+
if (!this.containerEl) return;
|
|
3162
|
+
const i = this.zoomEngine.isFocused(t), o = {
|
|
3163
|
+
width: this.containerEl.offsetWidth,
|
|
3164
|
+
height: this.containerEl.offsetHeight
|
|
3165
|
+
};
|
|
3166
|
+
if (i)
|
|
3167
|
+
await this.zoomEngine.unfocusImage(), this.currentFocusIndex = null, this.swipeEngine?.disable(), this.hideCounter();
|
|
3168
|
+
else {
|
|
3169
|
+
const s = t.dataset.imageId;
|
|
3170
|
+
this.currentFocusIndex = s !== void 0 ? parseInt(s, 10) : null, this.swipeEngine?.enable(), await this.zoomEngine.focusImage(t, o, e), this.currentFocusIndex !== null && this.updateCounter(this.currentFocusIndex);
|
|
3171
|
+
}
|
|
3230
3172
|
}
|
|
3231
3173
|
/**
|
|
3232
|
-
*
|
|
3174
|
+
* Clear the image cloud and reset state
|
|
3233
3175
|
*/
|
|
3234
|
-
|
|
3235
|
-
|
|
3176
|
+
clearImageCloud() {
|
|
3177
|
+
this.queueInterval !== null && (clearInterval(this.queueInterval), this.queueInterval = null), this.loadGeneration++, this.displayQueue = [], this.containerEl && this.containerEl.querySelectorAll(".fbn-ic-image, .fbn-ic-debug-center").forEach((t) => t.remove()), this.imageElements = [], this.imageLayouts = [], this.currentFocusIndex = null, this.hoveredImage = null, this.layoutEngine.reset(), this.zoomEngine.reset(), this.imagesLoaded = !1;
|
|
3178
|
+
}
|
|
3179
|
+
showLoading(t) {
|
|
3180
|
+
!this.fullConfig.rendering.ui.showLoadingSpinner || !this.loadingEl || (t ? this.loadingEl.classList.remove("fbn-ic-hidden") : this.loadingEl.classList.add("fbn-ic-hidden"));
|
|
3181
|
+
}
|
|
3182
|
+
showError(t) {
|
|
3183
|
+
this.errorEl && (this.errorEl.textContent = t, this.errorEl.classList.remove("fbn-ic-hidden"));
|
|
3184
|
+
}
|
|
3185
|
+
hideError() {
|
|
3186
|
+
this.errorEl && this.errorEl.classList.add("fbn-ic-hidden");
|
|
3187
|
+
}
|
|
3188
|
+
updateCounter(t) {
|
|
3189
|
+
!this.fullConfig.rendering.ui.showImageCounter || !this.counterEl || (this.counterEl.textContent = `${t + 1} of ${this.imageElements.length}`, this.counterEl.classList.remove("fbn-ic-hidden"));
|
|
3190
|
+
}
|
|
3191
|
+
hideCounter() {
|
|
3192
|
+
this.counterEl && this.counterEl.classList.add("fbn-ic-hidden");
|
|
3236
3193
|
}
|
|
3237
3194
|
/**
|
|
3238
|
-
*
|
|
3239
|
-
* @param args - Arguments to log
|
|
3195
|
+
* Destroy the gallery and clean up resources
|
|
3240
3196
|
*/
|
|
3241
|
-
|
|
3242
|
-
this.
|
|
3197
|
+
destroy() {
|
|
3198
|
+
this.clearImageCloud(), this.loadingElAutoCreated && this.loadingEl && (this.loadingEl.remove(), this.loadingEl = null), this.errorElAutoCreated && this.errorEl && (this.errorEl.remove(), this.errorEl = null), this.counterElAutoCreated && this.counterEl && (this.counterEl.remove(), this.counterEl = null), this.resizeTimeout !== null && clearTimeout(this.resizeTimeout), this.swipeEngine?.destroy();
|
|
3243
3199
|
}
|
|
3244
3200
|
}
|
|
3245
3201
|
export {
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3202
|
+
qt as AnimationEngine,
|
|
3203
|
+
wt as BOUNCE_PRESETS,
|
|
3204
|
+
de as ClusterPlacementLayout,
|
|
3205
|
+
Te as CompositeLoader,
|
|
3250
3206
|
y as DEFAULT_CONFIG,
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3207
|
+
Ct as DEFAULT_SHARED_LOADER_CONFIG,
|
|
3208
|
+
xt as ELASTIC_PRESETS,
|
|
3209
|
+
ie as EntryAnimationEngine,
|
|
3210
|
+
Re as FUNCTIONAL_CSS,
|
|
3211
|
+
Ie as GoogleDriveLoader,
|
|
3212
|
+
ae as GridPlacementLayout,
|
|
3257
3213
|
Le as ImageCloud,
|
|
3258
|
-
|
|
3214
|
+
Ce as ImageFilter,
|
|
3259
3215
|
Le as ImageGallery,
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
ie as requiresJSAnimation
|
|
3216
|
+
ge as LayoutEngine,
|
|
3217
|
+
oe as RadialPlacementLayout,
|
|
3218
|
+
ne as RandomPlacementLayout,
|
|
3219
|
+
le as SpiralPlacementLayout,
|
|
3220
|
+
Ae as StaticImageLoader,
|
|
3221
|
+
St as WAVE_PATH_PRESETS,
|
|
3222
|
+
ue as WavePlacementLayout,
|
|
3223
|
+
be as ZoomEngine,
|
|
3224
|
+
Qt as animatePath,
|
|
3225
|
+
Me as injectFunctionalStyles,
|
|
3226
|
+
te as requiresJSAnimation
|
|
3272
3227
|
};
|
|
3273
3228
|
//# sourceMappingURL=image-cloud.js.map
|