@thewhateverapp/tile-sdk 0.13.14 → 0.13.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/TileProvider.d.ts +3 -1
- package/dist/react/TileProvider.d.ts.map +1 -1
- package/dist/react/TileProvider.js +4 -4
- package/dist/react/overlay/Slideshow.d.ts.map +1 -1
- package/dist/react/overlay/Slideshow.js +81 -7
- package/dist/react/overlay/VideoPlayer.d.ts +11 -1
- package/dist/react/overlay/VideoPlayer.d.ts.map +1 -1
- package/dist/react/overlay/VideoPlayer.js +14 -11
- package/dist/templates/slideshow/PersistentSlideshow.tsx.template.d.ts +1 -1
- package/dist/templates/slideshow/PersistentSlideshow.tsx.template.d.ts.map +1 -1
- package/dist/templates/slideshow/PersistentSlideshow.tsx.template.js +44 -1
- package/package.json +1 -1
|
@@ -38,7 +38,9 @@ export declare const TileContext: React.Context<TileContextValue | null>;
|
|
|
38
38
|
interface TileProviderProps {
|
|
39
39
|
children: React.ReactNode;
|
|
40
40
|
router?: any;
|
|
41
|
+
/** Override tileId (for runtime injection, e.g., base workers) */
|
|
42
|
+
tileId?: string;
|
|
41
43
|
}
|
|
42
|
-
export declare function TileProvider({ children, router }: TileProviderProps): React.JSX.Element;
|
|
44
|
+
export declare function TileProvider({ children, router, tileId: propTileId }: TileProviderProps): React.JSX.Element;
|
|
43
45
|
export {};
|
|
44
46
|
//# sourceMappingURL=TileProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TileProvider.d.ts","sourceRoot":"","sources":["../../src/react/TileProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0D,MAAM,OAAO,CAAC;AAC/E,OAAO,EAAiB,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EACV,SAAS,EACT,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,KAAK,IAAI,CAAC;IAC5D,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IACpD,qBAAqB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,QAAQ,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE;QACP,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACjD,CAAC;IACF,SAAS,EAAE;QACT,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACxC,CAAC;IACF,IAAI,EAAE;QACJ,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5E,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QACtD,cAAc,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;KACpC,CAAC;IACF,KAAK,EAAE;QACL,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;QACpE,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE,iBAAiB,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;QAChE,WAAW,EAAE,CAAC,OAAO,CAAC,EAAE,iBAAiB,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;KACpE,CAAC;CACH;AAED,eAAO,MAAM,WAAW,wCAA+C,CAAC;AAExE,UAAU,iBAAiB;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"TileProvider.d.ts","sourceRoot":"","sources":["../../src/react/TileProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0D,MAAM,OAAO,CAAC;AAC/E,OAAO,EAAiB,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EACV,SAAS,EACT,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,KAAK,IAAI,CAAC;IAC5D,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IACpD,qBAAqB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,QAAQ,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE;QACP,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACjD,CAAC;IACF,SAAS,EAAE;QACT,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACxC,CAAC;IACF,IAAI,EAAE;QACJ,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5E,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QACtD,cAAc,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;KACpC,CAAC;IACF,KAAK,EAAE;QACL,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;QACpE,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE,iBAAiB,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;QAChE,WAAW,EAAE,CAAC,OAAO,CAAC,EAAE,iBAAiB,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;KACpE,CAAC;CACH;AAED,eAAO,MAAM,WAAW,wCAA+C,CAAC;AAExE,UAAU,iBAAiB;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,iBAAiB,qBAkEvF"}
|
|
@@ -2,14 +2,14 @@ import React, { createContext, useEffect, useState } from 'react';
|
|
|
2
2
|
import { getTileBridge } from '../bridge/TileBridge';
|
|
3
3
|
import { StateClient } from '../state/StateClient';
|
|
4
4
|
export const TileContext = createContext(null);
|
|
5
|
-
export function TileProvider({ children, router }) {
|
|
5
|
+
export function TileProvider({ children, router, tileId: propTileId }) {
|
|
6
6
|
const [isReady, setIsReady] = useState(false);
|
|
7
7
|
const [stateClient, setStateClient] = useState(null);
|
|
8
8
|
const bridge = getTileBridge(router);
|
|
9
|
-
// Get tileId from environment variable
|
|
10
|
-
const tileId = typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_TILE_ID
|
|
9
|
+
// Get tileId from prop (runtime injection) or environment variable (build-time)
|
|
10
|
+
const tileId = propTileId || (typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_TILE_ID
|
|
11
11
|
? process.env.NEXT_PUBLIC_TILE_ID
|
|
12
|
-
: null;
|
|
12
|
+
: null);
|
|
13
13
|
useEffect(() => {
|
|
14
14
|
// Create state client if tileId exists
|
|
15
15
|
if (tileId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Slideshow.d.ts","sourceRoot":"","sources":["../../../src/react/overlay/Slideshow.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAOZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAMf,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,oBAAoB,CAAC,EAAE,uBAAuB,CAAC;KAChD;CACF;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,EAAE,iBAAiB,CAAC;CAC7B;AAED,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;AAErD;;;;;GAKG;AACH,cAAM,uBAAuB;IAC3B,OAAO,CAAC,cAAc,CAAiC;IACvD,OAAO,CAAC,YAAY,CAMlB;IACF,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,kBAAkB,CAAe;IAEzC;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,OAAO,CAAC,EAAE;QACzC,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B,GAAG,IAAI;IAgCR;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;OAEG;IACH,OAAO,CAAC,eAAe;IAQvB,IAAI,IAAI,IAAI;
|
|
1
|
+
{"version":3,"file":"Slideshow.d.ts","sourceRoot":"","sources":["../../../src/react/overlay/Slideshow.tsx"],"names":[],"mappings":"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"}
|
|
@@ -75,12 +75,21 @@ class SlideshowSingletonClass {
|
|
|
75
75
|
}
|
|
76
76
|
// Navigation controls
|
|
77
77
|
next() {
|
|
78
|
-
|
|
78
|
+
console.log('[SlideshowSingleton] next() called:', {
|
|
79
|
+
isTransitioning: this.currentState.isTransitioning,
|
|
80
|
+
totalSlides: this.currentState.totalSlides,
|
|
81
|
+
currentIndex: this.currentState.currentIndex,
|
|
82
|
+
});
|
|
83
|
+
if (this.currentState.isTransitioning || this.currentState.totalSlides <= 1) {
|
|
84
|
+
console.log('[SlideshowSingleton] next() blocked:', this.currentState.isTransitioning ? 'transitioning' : 'single slide');
|
|
79
85
|
return;
|
|
86
|
+
}
|
|
87
|
+
const newIndex = (this.currentState.currentIndex + 1) % this.currentState.totalSlides;
|
|
88
|
+
console.log('[SlideshowSingleton] next() advancing to index:', newIndex);
|
|
80
89
|
this.currentState = {
|
|
81
90
|
...this.currentState,
|
|
82
91
|
isTransitioning: true,
|
|
83
|
-
currentIndex:
|
|
92
|
+
currentIndex: newIndex,
|
|
84
93
|
};
|
|
85
94
|
this.notifyListeners();
|
|
86
95
|
setTimeout(() => {
|
|
@@ -89,12 +98,21 @@ class SlideshowSingletonClass {
|
|
|
89
98
|
}, this.transitionDuration);
|
|
90
99
|
}
|
|
91
100
|
prev() {
|
|
92
|
-
|
|
101
|
+
console.log('[SlideshowSingleton] prev() called:', {
|
|
102
|
+
isTransitioning: this.currentState.isTransitioning,
|
|
103
|
+
totalSlides: this.currentState.totalSlides,
|
|
104
|
+
currentIndex: this.currentState.currentIndex,
|
|
105
|
+
});
|
|
106
|
+
if (this.currentState.isTransitioning || this.currentState.totalSlides <= 1) {
|
|
107
|
+
console.log('[SlideshowSingleton] prev() blocked:', this.currentState.isTransitioning ? 'transitioning' : 'single slide');
|
|
93
108
|
return;
|
|
109
|
+
}
|
|
110
|
+
const newIndex = (this.currentState.currentIndex - 1 + this.currentState.totalSlides) % this.currentState.totalSlides;
|
|
111
|
+
console.log('[SlideshowSingleton] prev() going back to index:', newIndex);
|
|
94
112
|
this.currentState = {
|
|
95
113
|
...this.currentState,
|
|
96
114
|
isTransitioning: true,
|
|
97
|
-
currentIndex:
|
|
115
|
+
currentIndex: newIndex,
|
|
98
116
|
};
|
|
99
117
|
this.notifyListeners();
|
|
100
118
|
setTimeout(() => {
|
|
@@ -217,10 +235,34 @@ export function Slideshow({ images, intervalMs = 5000, autoAdvance = true, trans
|
|
|
217
235
|
const touchCurrentRef = useRef(null);
|
|
218
236
|
useEffect(() => {
|
|
219
237
|
const container = containerRef.current;
|
|
220
|
-
|
|
238
|
+
console.log('[Slideshow Swipe] Effect running:', {
|
|
239
|
+
hasContainer: !!container,
|
|
240
|
+
swipeable,
|
|
241
|
+
totalSlides: state.totalSlides,
|
|
242
|
+
isTransitioning: state.isTransitioning,
|
|
243
|
+
});
|
|
244
|
+
if (!container) {
|
|
245
|
+
console.log('[Slideshow Swipe] ❌ No container ref');
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (!swipeable) {
|
|
249
|
+
console.log('[Slideshow Swipe] ❌ Swipeable is false');
|
|
221
250
|
return;
|
|
251
|
+
}
|
|
252
|
+
if (state.totalSlides <= 1) {
|
|
253
|
+
console.log('[Slideshow Swipe] ❌ Only', state.totalSlides, 'slide(s)');
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
console.log('[Slideshow Swipe] ✅ Attaching touch listeners to container');
|
|
222
257
|
const handleTouchStart = (e) => {
|
|
223
258
|
const touch = e.touches[0];
|
|
259
|
+
console.log('[Slideshow Swipe] touchstart:', {
|
|
260
|
+
hasTouch: !!touch,
|
|
261
|
+
clientX: touch?.clientX,
|
|
262
|
+
clientY: touch?.clientY,
|
|
263
|
+
target: e.target?.tagName,
|
|
264
|
+
currentTarget: e.currentTarget?.tagName,
|
|
265
|
+
});
|
|
224
266
|
if (!touch)
|
|
225
267
|
return;
|
|
226
268
|
touchStartRef.current = {
|
|
@@ -231,28 +273,40 @@ export function Slideshow({ images, intervalMs = 5000, autoAdvance = true, trans
|
|
|
231
273
|
touchCurrentRef.current = { x: touch.clientX, y: touch.clientY };
|
|
232
274
|
};
|
|
233
275
|
const handleTouchMove = (e) => {
|
|
234
|
-
if (!touchStartRef.current)
|
|
276
|
+
if (!touchStartRef.current) {
|
|
277
|
+
console.log('[Slideshow Swipe] touchmove: no touchStart ref');
|
|
235
278
|
return;
|
|
279
|
+
}
|
|
236
280
|
const touch = e.touches[0];
|
|
237
|
-
if (!touch)
|
|
281
|
+
if (!touch) {
|
|
282
|
+
console.log('[Slideshow Swipe] touchmove: no touch');
|
|
238
283
|
return;
|
|
284
|
+
}
|
|
239
285
|
touchCurrentRef.current = { x: touch.clientX, y: touch.clientY };
|
|
240
286
|
// Prevent default and stop propagation for horizontal swipes
|
|
241
287
|
const deltaX = touch.clientX - touchStartRef.current.x;
|
|
242
288
|
const deltaY = touch.clientY - touchStartRef.current.y;
|
|
243
289
|
if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 10) {
|
|
290
|
+
console.log('[Slideshow Swipe] touchmove: horizontal swipe detected, preventing default', { deltaX, deltaY });
|
|
244
291
|
e.preventDefault();
|
|
245
292
|
e.stopPropagation();
|
|
246
293
|
}
|
|
247
294
|
};
|
|
248
295
|
const handleTouchEnd = (e) => {
|
|
296
|
+
console.log('[Slideshow Swipe] touchend:', {
|
|
297
|
+
hasTouchStart: !!touchStartRef.current,
|
|
298
|
+
hasTouchCurrent: !!touchCurrentRef.current,
|
|
299
|
+
isTransitioning: state.isTransitioning,
|
|
300
|
+
});
|
|
249
301
|
if (!touchStartRef.current || !touchCurrentRef.current) {
|
|
302
|
+
console.log('[Slideshow Swipe] touchend: missing refs, aborting');
|
|
250
303
|
touchStartRef.current = null;
|
|
251
304
|
touchCurrentRef.current = null;
|
|
252
305
|
return;
|
|
253
306
|
}
|
|
254
307
|
// Don't process if transitioning
|
|
255
308
|
if (state.isTransitioning) {
|
|
309
|
+
console.log('[Slideshow Swipe] touchend: transitioning, aborting');
|
|
256
310
|
touchStartRef.current = null;
|
|
257
311
|
touchCurrentRef.current = null;
|
|
258
312
|
return;
|
|
@@ -265,16 +319,34 @@ export function Slideshow({ images, intervalMs = 5000, autoAdvance = true, trans
|
|
|
265
319
|
const isHorizontalSwipe = Math.abs(deltaX) > Math.abs(deltaY);
|
|
266
320
|
const isValidSwipe = Math.abs(deltaX) > minSwipeDistance && isHorizontalSwipe;
|
|
267
321
|
const isQuickSwipe = deltaTime < 500 || Math.abs(deltaX) > 60;
|
|
322
|
+
console.log('[Slideshow Swipe] touchend analysis:', {
|
|
323
|
+
deltaX,
|
|
324
|
+
deltaY,
|
|
325
|
+
deltaTime,
|
|
326
|
+
minSwipeDistance,
|
|
327
|
+
isHorizontalSwipe,
|
|
328
|
+
isValidSwipe,
|
|
329
|
+
isQuickSwipe,
|
|
330
|
+
willTrigger: isValidSwipe && isQuickSwipe,
|
|
331
|
+
direction: deltaX > 0 ? 'prev' : 'next',
|
|
332
|
+
});
|
|
268
333
|
if (isValidSwipe && isQuickSwipe) {
|
|
269
334
|
e.preventDefault();
|
|
270
335
|
e.stopPropagation();
|
|
271
336
|
if (deltaX > 0) {
|
|
337
|
+
console.log('[Slideshow Swipe] 🎯 Triggering PREV');
|
|
272
338
|
singleton.prev();
|
|
273
339
|
}
|
|
274
340
|
else {
|
|
341
|
+
console.log('[Slideshow Swipe] 🎯 Triggering NEXT');
|
|
275
342
|
singleton.next();
|
|
276
343
|
}
|
|
277
344
|
}
|
|
345
|
+
else {
|
|
346
|
+
console.log('[Slideshow Swipe] ❌ Swipe not valid:', {
|
|
347
|
+
reason: !isHorizontalSwipe ? 'not horizontal' : !isValidSwipe ? 'too short' : 'too slow',
|
|
348
|
+
});
|
|
349
|
+
}
|
|
278
350
|
touchStartRef.current = null;
|
|
279
351
|
touchCurrentRef.current = null;
|
|
280
352
|
};
|
|
@@ -282,7 +354,9 @@ export function Slideshow({ images, intervalMs = 5000, autoAdvance = true, trans
|
|
|
282
354
|
container.addEventListener('touchstart', handleTouchStart, { passive: false });
|
|
283
355
|
container.addEventListener('touchmove', handleTouchMove, { passive: false });
|
|
284
356
|
container.addEventListener('touchend', handleTouchEnd, { passive: false });
|
|
357
|
+
console.log('[Slideshow Swipe] ✅ Listeners attached successfully');
|
|
285
358
|
return () => {
|
|
359
|
+
console.log('[Slideshow Swipe] Cleaning up listeners');
|
|
286
360
|
container.removeEventListener('touchstart', handleTouchStart);
|
|
287
361
|
container.removeEventListener('touchmove', handleTouchMove);
|
|
288
362
|
container.removeEventListener('touchend', handleTouchEnd);
|
|
@@ -112,6 +112,16 @@ export interface CuePoint {
|
|
|
112
112
|
data?: unknown;
|
|
113
113
|
}
|
|
114
114
|
export interface VideoPlayerProps {
|
|
115
|
+
/** Video source URL (overrides env var NEXT_PUBLIC_VIDEO_*) */
|
|
116
|
+
src?: string;
|
|
117
|
+
/** Poster/thumbnail URL (overrides env var) */
|
|
118
|
+
poster?: string;
|
|
119
|
+
/** Loop video (overrides env var, default: true) */
|
|
120
|
+
loop?: boolean;
|
|
121
|
+
/** Muted (overrides env var, default: true) */
|
|
122
|
+
muted?: boolean;
|
|
123
|
+
/** Autoplay (overrides env var, default: false) */
|
|
124
|
+
autoplay?: boolean;
|
|
115
125
|
children?: ReactNode;
|
|
116
126
|
className?: string;
|
|
117
127
|
videoClassName?: string;
|
|
@@ -133,7 +143,7 @@ export interface VideoPlayerProps {
|
|
|
133
143
|
* </VideoPlayer>
|
|
134
144
|
* ```
|
|
135
145
|
*/
|
|
136
|
-
export declare function VideoPlayer({ controls, children, className, videoClassName, cuePoints, onCuePoint, onTimeUpdate, }: VideoPlayerProps): React.JSX.Element;
|
|
146
|
+
export declare function VideoPlayer({ src: propSrc, poster: propPoster, loop: propLoop, muted: propMuted, autoplay: propAutoplay, controls, children, className, videoClassName, cuePoints, onCuePoint, onTimeUpdate, }: VideoPlayerProps): React.JSX.Element;
|
|
137
147
|
/**
|
|
138
148
|
* Hook to access video state and controls from within VideoPlayer children.
|
|
139
149
|
* Also aliased as useVideo for compatibility.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../../../src/react/overlay/VideoPlayer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAOZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAOf,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,cAAc,CAAC,EAAE,gBAAgB,CAAC;QAClC,UAAU,CAAC,EAAE,WAAW,CAAC;QACzB,gBAAgB,CAAC,EAAE,mBAAmB,CAAC;KACxC;CACF;AASD,UAAU,WAAW;IACnB,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC/C,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC;IACpE,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,UAAU,SAAS;IACjB,WAAW,EAAE,MAAM,OAAO,CAAC;IAC3B,MAAM,EAAE;QACN,eAAe,EAAE,MAAM,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,UAAU,EAAE;QACV,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,KAAK,MAAM,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,WAAW,CAAC;CAClF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,GAAG,EAAE,SAAS,CAAC;KAChB;CACF;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;AAEjD;;;;;;GAMG;AACH,cAAM,mBAAmB;IACvB,OAAO,CAAC,cAAc,CAAiC;IACvD,OAAO,CAAC,YAAY,CASlB;IACF,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,eAAe,CAAS;IAEhC;;OAEG;IACH,QAAQ,IAAI,gBAAgB;IAwD5B;;OAEG;IACG,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B7D;;OAEG;YACW,OAAO;IA2DrB;;OAEG;IACH,uBAAuB,IAAI,IAAI;IA0C/B;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI;IAOtC;;OAEG;IACH,WAAW,IAAI,gBAAgB;IAK/B,IAAI,IAAI,IAAI;IAIZ,KAAK,IAAI,IAAI;IAIb,MAAM,IAAI,IAAI;IASd,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIxB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAI9B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAK5B,QAAQ,IAAI,UAAU;IAItB,aAAa,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,IAAI;IAOlD,OAAO,CAAC,WAAW;CAIpB;AA8HD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;CAC7C;AAID,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC1C,YAAY,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CAChE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,EAC1B,QAAgB,EAChB,QAAQ,EACR,SAAc,EACd,cAAmB,EACnB,SAAc,EACd,UAAU,EACV,YAAY,GACb,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../../../src/react/overlay/VideoPlayer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -370,17 +370,20 @@ const VideoContext = createContext(null);
|
|
|
370
370
|
* </VideoPlayer>
|
|
371
371
|
* ```
|
|
372
372
|
*/
|
|
373
|
-
export function VideoPlayer({ controls = false, children, className = '', videoClassName = '', cuePoints = [], onCuePoint, onTimeUpdate, }) {
|
|
373
|
+
export function VideoPlayer({ src: propSrc, poster: propPoster, loop: propLoop, muted: propMuted, autoplay: propAutoplay, controls = false, children, className = '', videoClassName = '', cuePoints = [], onCuePoint, onTimeUpdate, }) {
|
|
374
374
|
const containerRef = useRef(null);
|
|
375
375
|
const videoRefProxy = useRef(null);
|
|
376
376
|
const triggeredCuePointsRef = useRef(new Set());
|
|
377
377
|
const lastTimeRef = useRef(0);
|
|
378
378
|
const [state, setState] = useState(() => getVideoSingleton().getState());
|
|
379
379
|
const [metadataError, setMetadataError] = useState(null);
|
|
380
|
-
// Get video metadata from env vars
|
|
380
|
+
// Get video metadata from env vars (as fallback)
|
|
381
381
|
const metadata = getVideoMetadataFromEnv();
|
|
382
|
-
|
|
383
|
-
const
|
|
382
|
+
// Props override env vars
|
|
383
|
+
const src = propSrc || metadata?.videoUrl || null;
|
|
384
|
+
const poster = propPoster || metadata?.thumbnail || undefined;
|
|
385
|
+
const loop = propLoop ?? metadata?.loop ?? true;
|
|
386
|
+
const muted = propMuted ?? metadata?.muted ?? true;
|
|
384
387
|
// Subscribe to singleton state changes
|
|
385
388
|
useEffect(() => {
|
|
386
389
|
const singleton = getVideoSingleton();
|
|
@@ -410,21 +413,21 @@ export function VideoPlayer({ controls = false, children, className = '', videoC
|
|
|
410
413
|
singleton.attachTo(containerRef.current);
|
|
411
414
|
// Update video ref proxy
|
|
412
415
|
videoRefProxy.current = singleton.getVideoRef();
|
|
413
|
-
// Set loop preference
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
416
|
+
// Set loop preference (use resolved loop value)
|
|
417
|
+
singleton.setLoop(loop);
|
|
418
|
+
// Set muted preference
|
|
419
|
+
singleton.setMuted(muted);
|
|
417
420
|
// Load source if available
|
|
418
421
|
if (src) {
|
|
419
422
|
singleton.loadSource(src, poster);
|
|
420
423
|
}
|
|
421
|
-
else if (!metadata) {
|
|
422
|
-
setMetadataError('No video
|
|
424
|
+
else if (!metadata && !propSrc) {
|
|
425
|
+
setMetadataError('No video source provided');
|
|
423
426
|
}
|
|
424
427
|
// Set up visibility handling
|
|
425
428
|
singleton.setupVisibilityHandling();
|
|
426
429
|
// Note: We don't detach on unmount - that's the whole point of persistence!
|
|
427
|
-
}, [src, poster, metadata]);
|
|
430
|
+
}, [src, poster, loop, muted, metadata, propSrc]);
|
|
428
431
|
// Handle cue points and time updates
|
|
429
432
|
useEffect(() => {
|
|
430
433
|
const { currentTime, duration } = state;
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* React component that attaches to the SlideshowManager singleton.
|
|
5
5
|
* The slideshow state persists across route changes.
|
|
6
6
|
*/
|
|
7
|
-
export declare const persistentSlideshowTemplate = "'use client';\n\nimport { useEffect, useState, useRef, useCallback, createContext, useContext, ReactNode } from 'react';\nimport { SlideshowManager, SlideshowState, SlideImage } from '../lib/SlideshowManager';\n\n// Context to share slideshow state with overlays\ninterface SlideshowContextValue {\n state: SlideshowState;\n controls: {\n next: () => void;\n prev: () => void;\n goTo: (index: number) => void;\n pause: () => void;\n resume: () => void;\n toggle: () => void;\n };\n}\n\nconst SlideshowContext = createContext<SlideshowContextValue | null>(null);\n\nexport function useSlideshow(): SlideshowContextValue {\n const context = useContext(SlideshowContext);\n if (!context) {\n throw new Error('useSlideshow must be used within PersistentSlideshow');\n }\n return context;\n}\n\ninterface PersistentSlideshowProps {\n images: SlideImage[];\n /** Auto-advance interval in milliseconds (default: 5000) */\n intervalMs?: number;\n /** Auto-advance slides (default: true) */\n autoAdvance?: boolean;\n /** Transition type (default: 'fade') */\n transition?: 'fade' | 'slide' | 'none';\n /** Transition duration in ms (default: 500) */\n transitionDuration?: number;\n /** Show navigation dots (default: true) */\n showDots?: boolean;\n /** Show navigation arrows (default: true) */\n showArrows?: boolean;\n /** Enable swipe gestures on touch devices (default: true) */\n swipeable?: boolean;\n /** Additional class names */\n className?: string;\n /** Image container class names */\n imageClassName?: string;\n /** Children rendered as overlay */\n children?: ReactNode;\n}\n\nexport function PersistentSlideshow({\n images,\n intervalMs = 5000,\n autoAdvance = true,\n transition = 'fade',\n transitionDuration = 500,\n showDots = true,\n showArrows = true,\n swipeable = true,\n className = '',\n imageClassName = '',\n children\n}: PersistentSlideshowProps) {\n const [state, setState] = useState<SlideshowState>(SlideshowManager.getState());\n const containerRef = useRef<HTMLDivElement>(null);\n const touchStartRef = useRef<{ x: number; y: number; time: number } | null>(null);\n const touchCurrentRef = useRef<{ x: number; y: number } | null>(null);\n\n // Touch/swipe handlers using native events (React touch events are passive)\n useEffect(() => {\n const container = containerRef.current;\n if (!container || !swipeable || state.totalSlides <= 1) return;\n\n const handleTouchStart = (e: TouchEvent) => {\n const touch = e.touches[0];\n if (!touch) return;\n\n touchStartRef.current = {\n x: touch.clientX,\n y: touch.clientY,\n time: Date.now(),\n };\n touchCurrentRef.current = { x: touch.clientX, y: touch.clientY };\n };\n\n const handleTouchMove = (e: TouchEvent) => {\n if (!touchStartRef.current) return;\n const touch = e.touches[0];\n if (!touch) return;\n\n touchCurrentRef.current = { x: touch.clientX, y: touch.clientY };\n\n // Prevent default and stop propagation for horizontal swipes\n const deltaX = touch.clientX - touchStartRef.current.x;\n const deltaY = touch.clientY - touchStartRef.current.y;\n if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 10) {\n e.preventDefault();\n e.stopPropagation();\n }\n };\n\n const handleTouchEnd = (e: TouchEvent) => {\n if (!touchStartRef.current || !touchCurrentRef.current) {\n touchStartRef.current = null;\n touchCurrentRef.current = null;\n return;\n }\n\n // Don't process if transitioning\n if (state.isTransitioning) {\n touchStartRef.current = null;\n touchCurrentRef.current = null;\n return;\n }\n\n const deltaX = touchCurrentRef.current.x - touchStartRef.current.x;\n const deltaY = touchCurrentRef.current.y - touchStartRef.current.y;\n const deltaTime = Date.now() - touchStartRef.current.time;\n\n // Lower threshold for smaller tiles - 30px minimum swipe distance\n const minSwipeDistance = 30;\n const isHorizontalSwipe = Math.abs(deltaX) > Math.abs(deltaY);\n const isValidSwipe = Math.abs(deltaX) > minSwipeDistance && isHorizontalSwipe;\n const isQuickSwipe = deltaTime < 500 || Math.abs(deltaX) > 60;\n\n if (isValidSwipe && isQuickSwipe) {\n e.preventDefault();\n e.stopPropagation();\n\n if (deltaX > 0) {\n SlideshowManager.prev();\n } else {\n SlideshowManager.next();\n }\n }\n\n touchStartRef.current = null;\n touchCurrentRef.current = null;\n };\n\n // Use passive: false on all to allow preventDefault()\n container.addEventListener('touchstart', handleTouchStart, { passive: false });\n container.addEventListener('touchmove', handleTouchMove, { passive: false });\n container.addEventListener('touchend', handleTouchEnd, { passive: false });\n\n return () => {\n container.removeEventListener('touchstart', handleTouchStart);\n container.removeEventListener('touchmove', handleTouchMove);\n container.removeEventListener('touchend', handleTouchEnd);\n };\n }, [swipeable, state.totalSlides, state.isTransitioning]);\n\n useEffect(() => {\n // Initialize slideshow with images\n SlideshowManager.initialize(images, {\n intervalMs,\n transitionDuration,\n autoAdvance,\n });\n\n // Subscribe to state changes\n const unsubscribe = SlideshowManager.onStateChange(setState);\n\n return () => {\n unsubscribe();\n // Don't destroy - let slideshow persist for route changes\n };\n }, [images, intervalMs, transitionDuration, autoAdvance]);\n\n const contextValue: SlideshowContextValue = {\n state,\n controls: {\n next: () => SlideshowManager.next(),\n prev: () => SlideshowManager.prev(),\n goTo: (index) => SlideshowManager.goTo(index),\n pause: () => SlideshowManager.pause(),\n resume: () => SlideshowManager.resume(),\n toggle: () => SlideshowManager.toggle(),\n },\n };\n\n // Get transition styles\n const getTransitionStyles = (index: number): React.CSSProperties => {\n const isActive = index === state.currentIndex;\n\n switch (transition) {\n case 'fade':\n return {\n opacity: isActive ? 1 : 0,\n transition: `opacity ${transitionDuration}ms ease-in-out`,\n position: 'absolute',\n inset: 0,\n };\n case 'slide':\n const offset = (index - state.currentIndex) * 100;\n return {\n transform: `translateX(${offset}%)`,\n transition: `transform ${transitionDuration}ms ease-in-out`,\n position: 'absolute',\n inset: 0,\n };\n case 'none':\n default:\n return {\n opacity: isActive ? 1 : 0,\n position: 'absolute',\n inset: 0,\n };\n }\n };\n\n if (images.length === 0) {\n return (\n <div className={`relative w-full h-full bg-black flex items-center justify-center ${className}`}>\n <p className=\"text-white/60\">No images</p>\n </div>\n );\n }\n\n return (\n <SlideshowContext.Provider value={contextValue}>\n <div\n ref={containerRef}\n className={`relative w-full h-full bg-black overflow-hidden ${className}`}\n style={{ touchAction: swipeable && state.totalSlides > 1 ? 'none' : 'auto' }}\n >\n {/* Image container */}\n <div className=\"relative w-full h-full\">\n {state.images.map((image, index) => (\n <div\n key={`${image.url}-${index}`}\n style={getTransitionStyles(index)}\n className={imageClassName}\n >\n <img\n src={image.url}\n alt={image.alt || `Slide ${index + 1}`}\n className=\"w-full h-full object-contain\"\n loading={index === 0 ? 'eager' : 'lazy'}\n />\n </div>\n ))}\n </div>\n\n {/* Navigation arrows */}\n {showArrows && state.totalSlides > 1 && (\n <>\n <button\n onClick={() => SlideshowManager.prev()}\n disabled={state.isTransitioning}\n className=\"absolute left-2 top-1/2 -translate-y-1/2 p-2 bg-black/40 hover:bg-black/60 rounded-full text-white transition-colors disabled:opacity-50\"\n aria-label=\"Previous slide\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n <button\n onClick={() => SlideshowManager.next()}\n disabled={state.isTransitioning}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 p-2 bg-black/40 hover:bg-black/60 rounded-full text-white transition-colors disabled:opacity-50\"\n aria-label=\"Next slide\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n </>\n )}\n\n {/* Navigation dots */}\n {showDots && state.totalSlides > 1 && (\n <div className=\"absolute bottom-3 left-1/2 -translate-x-1/2 flex gap-1.5\">\n {state.images.map((_, index) => (\n <button\n key={index}\n onClick={() => SlideshowManager.goTo(index)}\n disabled={state.isTransitioning}\n className={`w-2 h-2 rounded-full transition-colors ${\n index === state.currentIndex\n ? 'bg-white'\n : 'bg-white/40 hover:bg-white/60'\n }`}\n aria-label={`Go to slide ${index + 1}`}\n />\n ))}\n </div>\n )}\n\n {/* Overlay children - pointer-events managed by individual OverlaySlot components */}\n <div className=\"absolute inset-0 z-10 pointer-events-none\">\n {children}\n </div>\n </div>\n </SlideshowContext.Provider>\n );\n}\n";
|
|
7
|
+
export declare const persistentSlideshowTemplate = "'use client';\n\nimport { useEffect, useState, useRef, useCallback, createContext, useContext, ReactNode } from 'react';\nimport { SlideshowManager, SlideshowState, SlideImage } from '../lib/SlideshowManager';\n\n// Context to share slideshow state with overlays\ninterface SlideshowContextValue {\n state: SlideshowState;\n controls: {\n next: () => void;\n prev: () => void;\n goTo: (index: number) => void;\n pause: () => void;\n resume: () => void;\n toggle: () => void;\n };\n}\n\nconst SlideshowContext = createContext<SlideshowContextValue | null>(null);\n\nexport function useSlideshow(): SlideshowContextValue {\n const context = useContext(SlideshowContext);\n if (!context) {\n throw new Error('useSlideshow must be used within PersistentSlideshow');\n }\n return context;\n}\n\ninterface PersistentSlideshowProps {\n images: SlideImage[];\n /** Auto-advance interval in milliseconds (default: 5000) */\n intervalMs?: number;\n /** Auto-advance slides (default: true) */\n autoAdvance?: boolean;\n /** Transition type (default: 'fade') */\n transition?: 'fade' | 'slide' | 'none';\n /** Transition duration in ms (default: 500) */\n transitionDuration?: number;\n /** Show navigation dots (default: true) */\n showDots?: boolean;\n /** Show navigation arrows (default: true) */\n showArrows?: boolean;\n /** Enable swipe gestures on touch devices (default: true) */\n swipeable?: boolean;\n /** Additional class names */\n className?: string;\n /** Image container class names */\n imageClassName?: string;\n /** Children rendered as overlay */\n children?: ReactNode;\n}\n\nexport function PersistentSlideshow({\n images,\n intervalMs = 5000,\n autoAdvance = true,\n transition = 'fade',\n transitionDuration = 500,\n showDots = true,\n showArrows = true,\n swipeable = true,\n className = '',\n imageClassName = '',\n children\n}: PersistentSlideshowProps) {\n const [state, setState] = useState<SlideshowState>(SlideshowManager.getState());\n const containerRef = useRef<HTMLDivElement>(null);\n const touchStartRef = useRef<{ x: number; y: number; time: number } | null>(null);\n const touchCurrentRef = useRef<{ x: number; y: number } | null>(null);\n\n // Touch/swipe handlers using native events (React touch events are passive)\n useEffect(() => {\n const container = containerRef.current;\n\n console.log('[PersistentSlideshow] Touch effect running:', {\n hasContainer: !!container,\n swipeable,\n totalSlides: state.totalSlides,\n });\n\n if (!container) {\n console.log('[PersistentSlideshow] No container ref');\n return;\n }\n if (!swipeable) {\n console.log('[PersistentSlideshow] Swipeable disabled');\n return;\n }\n if (state.totalSlides <= 1) {\n console.log('[PersistentSlideshow] Only', state.totalSlides, 'slide(s)');\n return;\n }\n\n console.log('[PersistentSlideshow] Attaching touch listeners');\n\n const handleTouchStart = (e: TouchEvent) => {\n const touch = e.touches[0];\n console.log('[PersistentSlideshow] touchstart', { hasTouch: !!touch, x: touch?.clientX, y: touch?.clientY });\n if (!touch) return;\n\n touchStartRef.current = {\n x: touch.clientX,\n y: touch.clientY,\n time: Date.now(),\n };\n touchCurrentRef.current = { x: touch.clientX, y: touch.clientY };\n };\n\n const handleTouchMove = (e: TouchEvent) => {\n if (!touchStartRef.current) return;\n const touch = e.touches[0];\n if (!touch) return;\n\n touchCurrentRef.current = { x: touch.clientX, y: touch.clientY };\n\n // Prevent default and stop propagation for horizontal swipes\n const deltaX = touch.clientX - touchStartRef.current.x;\n const deltaY = touch.clientY - touchStartRef.current.y;\n if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 10) {\n console.log('[PersistentSlideshow] touchmove horizontal', { deltaX, deltaY });\n e.preventDefault();\n e.stopPropagation();\n }\n };\n\n const handleTouchEnd = (e: TouchEvent) => {\n console.log('[PersistentSlideshow] touchend', {\n hasStart: !!touchStartRef.current,\n hasCurrent: !!touchCurrentRef.current,\n isTransitioning: state.isTransitioning,\n });\n\n if (!touchStartRef.current || !touchCurrentRef.current) {\n touchStartRef.current = null;\n touchCurrentRef.current = null;\n return;\n }\n\n // Don't process if transitioning\n if (state.isTransitioning) {\n touchStartRef.current = null;\n touchCurrentRef.current = null;\n return;\n }\n\n const deltaX = touchCurrentRef.current.x - touchStartRef.current.x;\n const deltaY = touchCurrentRef.current.y - touchStartRef.current.y;\n const deltaTime = Date.now() - touchStartRef.current.time;\n\n // Lower threshold for smaller tiles - 30px minimum swipe distance\n const minSwipeDistance = 30;\n const isHorizontalSwipe = Math.abs(deltaX) > Math.abs(deltaY);\n const isValidSwipe = Math.abs(deltaX) > minSwipeDistance && isHorizontalSwipe;\n const isQuickSwipe = deltaTime < 500 || Math.abs(deltaX) > 60;\n\n console.log('[PersistentSlideshow] touchend analysis', {\n deltaX,\n deltaY,\n deltaTime,\n isHorizontalSwipe,\n isValidSwipe,\n isQuickSwipe,\n willTrigger: isValidSwipe && isQuickSwipe,\n });\n\n if (isValidSwipe && isQuickSwipe) {\n e.preventDefault();\n e.stopPropagation();\n\n if (deltaX > 0) {\n console.log('[PersistentSlideshow] PREV');\n SlideshowManager.prev();\n } else {\n console.log('[PersistentSlideshow] NEXT');\n SlideshowManager.next();\n }\n }\n\n touchStartRef.current = null;\n touchCurrentRef.current = null;\n };\n\n // Use passive: false on all to allow preventDefault()\n container.addEventListener('touchstart', handleTouchStart, { passive: false });\n container.addEventListener('touchmove', handleTouchMove, { passive: false });\n container.addEventListener('touchend', handleTouchEnd, { passive: false });\n\n console.log('[PersistentSlideshow] Listeners attached');\n\n return () => {\n console.log('[PersistentSlideshow] Removing listeners');\n container.removeEventListener('touchstart', handleTouchStart);\n container.removeEventListener('touchmove', handleTouchMove);\n container.removeEventListener('touchend', handleTouchEnd);\n };\n }, [swipeable, state.totalSlides, state.isTransitioning]);\n\n useEffect(() => {\n // Initialize slideshow with images\n SlideshowManager.initialize(images, {\n intervalMs,\n transitionDuration,\n autoAdvance,\n });\n\n // Subscribe to state changes\n const unsubscribe = SlideshowManager.onStateChange(setState);\n\n return () => {\n unsubscribe();\n // Don't destroy - let slideshow persist for route changes\n };\n }, [images, intervalMs, transitionDuration, autoAdvance]);\n\n const contextValue: SlideshowContextValue = {\n state,\n controls: {\n next: () => SlideshowManager.next(),\n prev: () => SlideshowManager.prev(),\n goTo: (index) => SlideshowManager.goTo(index),\n pause: () => SlideshowManager.pause(),\n resume: () => SlideshowManager.resume(),\n toggle: () => SlideshowManager.toggle(),\n },\n };\n\n // Get transition styles\n const getTransitionStyles = (index: number): React.CSSProperties => {\n const isActive = index === state.currentIndex;\n\n switch (transition) {\n case 'fade':\n return {\n opacity: isActive ? 1 : 0,\n transition: `opacity ${transitionDuration}ms ease-in-out`,\n position: 'absolute',\n inset: 0,\n };\n case 'slide':\n const offset = (index - state.currentIndex) * 100;\n return {\n transform: `translateX(${offset}%)`,\n transition: `transform ${transitionDuration}ms ease-in-out`,\n position: 'absolute',\n inset: 0,\n };\n case 'none':\n default:\n return {\n opacity: isActive ? 1 : 0,\n position: 'absolute',\n inset: 0,\n };\n }\n };\n\n if (images.length === 0) {\n return (\n <div className={`relative w-full h-full bg-black flex items-center justify-center ${className}`}>\n <p className=\"text-white/60\">No images</p>\n </div>\n );\n }\n\n return (\n <SlideshowContext.Provider value={contextValue}>\n <div\n ref={containerRef}\n className={`relative w-full h-full bg-black overflow-hidden ${className}`}\n style={{ touchAction: swipeable && state.totalSlides > 1 ? 'none' : 'auto' }}\n >\n {/* Image container */}\n <div className=\"relative w-full h-full\">\n {state.images.map((image, index) => (\n <div\n key={`${image.url}-${index}`}\n style={getTransitionStyles(index)}\n className={imageClassName}\n >\n <img\n src={image.url}\n alt={image.alt || `Slide ${index + 1}`}\n className=\"w-full h-full object-contain\"\n loading={index === 0 ? 'eager' : 'lazy'}\n />\n </div>\n ))}\n </div>\n\n {/* Navigation arrows */}\n {showArrows && state.totalSlides > 1 && (\n <>\n <button\n onClick={() => SlideshowManager.prev()}\n disabled={state.isTransitioning}\n className=\"absolute left-2 top-1/2 -translate-y-1/2 p-2 bg-black/40 hover:bg-black/60 rounded-full text-white transition-colors disabled:opacity-50\"\n aria-label=\"Previous slide\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n <button\n onClick={() => SlideshowManager.next()}\n disabled={state.isTransitioning}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 p-2 bg-black/40 hover:bg-black/60 rounded-full text-white transition-colors disabled:opacity-50\"\n aria-label=\"Next slide\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n </>\n )}\n\n {/* Navigation dots */}\n {showDots && state.totalSlides > 1 && (\n <div className=\"absolute bottom-3 left-1/2 -translate-x-1/2 flex gap-1.5\">\n {state.images.map((_, index) => (\n <button\n key={index}\n onClick={() => SlideshowManager.goTo(index)}\n disabled={state.isTransitioning}\n className={`w-2 h-2 rounded-full transition-colors ${\n index === state.currentIndex\n ? 'bg-white'\n : 'bg-white/40 hover:bg-white/60'\n }`}\n aria-label={`Go to slide ${index + 1}`}\n />\n ))}\n </div>\n )}\n\n {/* Overlay children - pointer-events managed by individual OverlaySlot components */}\n <div className=\"absolute inset-0 z-10 pointer-events-none\">\n {children}\n </div>\n </div>\n </SlideshowContext.Provider>\n );\n}\n";
|
|
8
8
|
//# sourceMappingURL=PersistentSlideshow.tsx.template.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PersistentSlideshow.tsx.template.d.ts","sourceRoot":"","sources":["../../../src/templates/slideshow/PersistentSlideshow.tsx.template.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,
|
|
1
|
+
{"version":3,"file":"PersistentSlideshow.tsx.template.d.ts","sourceRoot":"","sources":["../../../src/templates/slideshow/PersistentSlideshow.tsx.template.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,ukXAsVvC,CAAC"}
|
|
@@ -77,10 +77,31 @@ export function PersistentSlideshow({
|
|
|
77
77
|
// Touch/swipe handlers using native events (React touch events are passive)
|
|
78
78
|
useEffect(() => {
|
|
79
79
|
const container = containerRef.current;
|
|
80
|
-
|
|
80
|
+
|
|
81
|
+
console.log('[PersistentSlideshow] Touch effect running:', {
|
|
82
|
+
hasContainer: !!container,
|
|
83
|
+
swipeable,
|
|
84
|
+
totalSlides: state.totalSlides,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (!container) {
|
|
88
|
+
console.log('[PersistentSlideshow] No container ref');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (!swipeable) {
|
|
92
|
+
console.log('[PersistentSlideshow] Swipeable disabled');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (state.totalSlides <= 1) {
|
|
96
|
+
console.log('[PersistentSlideshow] Only', state.totalSlides, 'slide(s)');
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
console.log('[PersistentSlideshow] Attaching touch listeners');
|
|
81
101
|
|
|
82
102
|
const handleTouchStart = (e: TouchEvent) => {
|
|
83
103
|
const touch = e.touches[0];
|
|
104
|
+
console.log('[PersistentSlideshow] touchstart', { hasTouch: !!touch, x: touch?.clientX, y: touch?.clientY });
|
|
84
105
|
if (!touch) return;
|
|
85
106
|
|
|
86
107
|
touchStartRef.current = {
|
|
@@ -102,12 +123,19 @@ export function PersistentSlideshow({
|
|
|
102
123
|
const deltaX = touch.clientX - touchStartRef.current.x;
|
|
103
124
|
const deltaY = touch.clientY - touchStartRef.current.y;
|
|
104
125
|
if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 10) {
|
|
126
|
+
console.log('[PersistentSlideshow] touchmove horizontal', { deltaX, deltaY });
|
|
105
127
|
e.preventDefault();
|
|
106
128
|
e.stopPropagation();
|
|
107
129
|
}
|
|
108
130
|
};
|
|
109
131
|
|
|
110
132
|
const handleTouchEnd = (e: TouchEvent) => {
|
|
133
|
+
console.log('[PersistentSlideshow] touchend', {
|
|
134
|
+
hasStart: !!touchStartRef.current,
|
|
135
|
+
hasCurrent: !!touchCurrentRef.current,
|
|
136
|
+
isTransitioning: state.isTransitioning,
|
|
137
|
+
});
|
|
138
|
+
|
|
111
139
|
if (!touchStartRef.current || !touchCurrentRef.current) {
|
|
112
140
|
touchStartRef.current = null;
|
|
113
141
|
touchCurrentRef.current = null;
|
|
@@ -131,13 +159,25 @@ export function PersistentSlideshow({
|
|
|
131
159
|
const isValidSwipe = Math.abs(deltaX) > minSwipeDistance && isHorizontalSwipe;
|
|
132
160
|
const isQuickSwipe = deltaTime < 500 || Math.abs(deltaX) > 60;
|
|
133
161
|
|
|
162
|
+
console.log('[PersistentSlideshow] touchend analysis', {
|
|
163
|
+
deltaX,
|
|
164
|
+
deltaY,
|
|
165
|
+
deltaTime,
|
|
166
|
+
isHorizontalSwipe,
|
|
167
|
+
isValidSwipe,
|
|
168
|
+
isQuickSwipe,
|
|
169
|
+
willTrigger: isValidSwipe && isQuickSwipe,
|
|
170
|
+
});
|
|
171
|
+
|
|
134
172
|
if (isValidSwipe && isQuickSwipe) {
|
|
135
173
|
e.preventDefault();
|
|
136
174
|
e.stopPropagation();
|
|
137
175
|
|
|
138
176
|
if (deltaX > 0) {
|
|
177
|
+
console.log('[PersistentSlideshow] PREV');
|
|
139
178
|
SlideshowManager.prev();
|
|
140
179
|
} else {
|
|
180
|
+
console.log('[PersistentSlideshow] NEXT');
|
|
141
181
|
SlideshowManager.next();
|
|
142
182
|
}
|
|
143
183
|
}
|
|
@@ -151,7 +191,10 @@ export function PersistentSlideshow({
|
|
|
151
191
|
container.addEventListener('touchmove', handleTouchMove, { passive: false });
|
|
152
192
|
container.addEventListener('touchend', handleTouchEnd, { passive: false });
|
|
153
193
|
|
|
194
|
+
console.log('[PersistentSlideshow] Listeners attached');
|
|
195
|
+
|
|
154
196
|
return () => {
|
|
197
|
+
console.log('[PersistentSlideshow] Removing listeners');
|
|
155
198
|
container.removeEventListener('touchstart', handleTouchStart);
|
|
156
199
|
container.removeEventListener('touchmove', handleTouchMove);
|
|
157
200
|
container.removeEventListener('touchend', handleTouchEnd);
|