@acoustte-digital-services/digitalstore-controls-dev 0.8.1-dev.20260523060518 → 0.8.1-dev.20260525053215

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.
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  HlsPlayer_default
4
- } from "./chunk-72PHGKW4.mjs";
4
+ } from "./chunk-F6CXFHUE.mjs";
5
5
  export {
6
6
  HlsPlayer_default as default
7
7
  };
@@ -54,6 +54,7 @@ var HlsPlayer = React.memo(
54
54
  const inactivityTimerRef = useRef(null);
55
55
  const clickTimerRef = useRef(null);
56
56
  const hlsInitializedRef = useRef(false);
57
+ const [isInView, setIsInView] = useState(false);
57
58
  const INACTIVITY_DELAY = 2500;
58
59
  const CLICK_DEBOUNCE = 220;
59
60
  const resolvedSources = sources && sources.length > 0 ? sources : assetUrl ? [{ src: assetUrl, posterUrl }] : [];
@@ -70,6 +71,25 @@ var HlsPlayer = React.memo(
70
71
  window.addEventListener("resize", checkMobile);
71
72
  return () => window.removeEventListener("resize", checkMobile);
72
73
  }, []);
74
+ useEffect(() => {
75
+ const container = containerRef.current;
76
+ if (!container || typeof IntersectionObserver === "undefined") {
77
+ setIsInView(true);
78
+ return;
79
+ }
80
+ const observer = new IntersectionObserver(
81
+ ([entry]) => {
82
+ if (entry.isIntersecting) {
83
+ setIsInView(true);
84
+ observer.disconnect();
85
+ }
86
+ },
87
+ { threshold: 0.25 }
88
+ // 25% of the player must be visible to trigger
89
+ );
90
+ observer.observe(container);
91
+ return () => observer.disconnect();
92
+ }, []);
73
93
  useEffect(() => {
74
94
  const onFullscreenChange = () => {
75
95
  setIsFullscreen(getFullscreenElement() === containerRef.current);
@@ -122,7 +142,19 @@ var HlsPlayer = React.memo(
122
142
  if (!chosenSrc) return;
123
143
  hlsInitializedRef.current = true;
124
144
  if (Hls.isSupported()) {
125
- const hls = new Hls();
145
+ const hlsConfig = isPlayOnHover ? {
146
+ // For hover-play: only buffer enough to start playing smoothly.
147
+ // maxBufferLength – target seconds of forward buffer (default 30s → 10s)
148
+ // maxMaxBufferLength – hard ceiling hls.js won't exceed (default 600s → 15s)
149
+ // maxBufferSize – byte ceiling before hls.js pauses loading (default 60MB → 10MB)
150
+ // lowLatencyMode – off; we don't need ultra-low latency for on-demand hover clips
151
+ maxBufferLength: 10,
152
+ maxMaxBufferLength: 15,
153
+ maxBufferSize: 10 * 1e3 * 1e3,
154
+ // 10 MB
155
+ lowLatencyMode: false
156
+ } : {};
157
+ const hls = new Hls(hlsConfig);
126
158
  hls.loadSource(chosenSrc);
127
159
  hls.attachMedia(v);
128
160
  hls.on(Hls.Events.MANIFEST_PARSED, () => {
@@ -140,10 +172,12 @@ var HlsPlayer = React.memo(
140
172
  }
141
173
  }, [JSON.stringify(resolvedSources)]);
142
174
  useEffect(() => {
175
+ if (!isInView) return;
143
176
  if (isPlayOnHover) return;
177
+ if (playOptions !== "autoplay") return;
144
178
  initHls(
145
179
  /* autoPlayAfterLoad */
146
- playOptions === "autoplay"
180
+ true
147
181
  );
148
182
  return () => {
149
183
  if (hlsRef.current) {
@@ -152,10 +186,17 @@ var HlsPlayer = React.memo(
152
186
  }
153
187
  hlsInitializedRef.current = false;
154
188
  };
155
- }, [JSON.stringify(resolvedSources), isPlayOnHover]);
189
+ }, [JSON.stringify(resolvedSources), isPlayOnHover, isInView, playOptions]);
156
190
  const handlePlayPause = useCallback(() => {
157
191
  const v = videoRef.current;
158
192
  if (!v) return;
193
+ if (!hlsInitializedRef.current) {
194
+ initHls(
195
+ /* autoPlayAfterLoad */
196
+ true
197
+ );
198
+ return;
199
+ }
159
200
  if (v.paused) {
160
201
  wasManuallyPausedRef.current = false;
161
202
  v.play().then(() => setIsPlaying(true));
@@ -164,7 +205,7 @@ var HlsPlayer = React.memo(
164
205
  v.pause();
165
206
  setIsPlaying(false);
166
207
  }
167
- }, []);
208
+ }, [initHls]);
168
209
  const handleMuteToggle = useCallback(() => {
169
210
  const v = videoRef.current;
170
211
  if (!v) return;
@@ -217,6 +258,11 @@ var HlsPlayer = React.memo(
217
258
  videoRef.current.pause();
218
259
  videoRef.current.currentTime = 0;
219
260
  setIsPlaying(false);
261
+ if (hlsRef.current) {
262
+ hlsRef.current.destroy();
263
+ hlsRef.current = null;
264
+ hlsInitializedRef.current = false;
265
+ }
220
266
  }
221
267
  }, [isPlayOnHover, isMobile, isPlaying]);
222
268
  const handleMouseMove = useCallback(() => {
@@ -269,10 +315,10 @@ var HlsPlayer = React.memo(
269
315
  autoPlay: playOptions === "autoplay",
270
316
  loop,
271
317
  playsInline: true,
272
- preload: isPlayOnHover ? "none" : "auto",
318
+ preload: playOptions === "autoplay" ? "auto" : "none",
273
319
  onClick: handleVideoClick,
274
320
  onDoubleClick: handleVideoDoubleClick,
275
- children: !isPlayOnHover && resolvedSources.map(({ src, media }, i) => /* @__PURE__ */ jsx(
321
+ children: playOptions === "autoplay" && resolvedSources.map(({ src, media }, i) => /* @__PURE__ */ jsx(
276
322
  "source",
277
323
  {
278
324
  src,
package/dist/index.js CHANGED
@@ -218,6 +218,7 @@ var init_HlsPlayer = __esm({
218
218
  const inactivityTimerRef = (0, import_react4.useRef)(null);
219
219
  const clickTimerRef = (0, import_react4.useRef)(null);
220
220
  const hlsInitializedRef = (0, import_react4.useRef)(false);
221
+ const [isInView, setIsInView] = (0, import_react4.useState)(false);
221
222
  const INACTIVITY_DELAY = 2500;
222
223
  const CLICK_DEBOUNCE = 220;
223
224
  const resolvedSources = sources && sources.length > 0 ? sources : assetUrl ? [{ src: assetUrl, posterUrl }] : [];
@@ -234,6 +235,25 @@ var init_HlsPlayer = __esm({
234
235
  window.addEventListener("resize", checkMobile);
235
236
  return () => window.removeEventListener("resize", checkMobile);
236
237
  }, []);
238
+ (0, import_react4.useEffect)(() => {
239
+ const container = containerRef.current;
240
+ if (!container || typeof IntersectionObserver === "undefined") {
241
+ setIsInView(true);
242
+ return;
243
+ }
244
+ const observer = new IntersectionObserver(
245
+ ([entry]) => {
246
+ if (entry.isIntersecting) {
247
+ setIsInView(true);
248
+ observer.disconnect();
249
+ }
250
+ },
251
+ { threshold: 0.25 }
252
+ // 25% of the player must be visible to trigger
253
+ );
254
+ observer.observe(container);
255
+ return () => observer.disconnect();
256
+ }, []);
237
257
  (0, import_react4.useEffect)(() => {
238
258
  const onFullscreenChange = () => {
239
259
  setIsFullscreen(getFullscreenElement() === containerRef.current);
@@ -286,7 +306,19 @@ var init_HlsPlayer = __esm({
286
306
  if (!chosenSrc) return;
287
307
  hlsInitializedRef.current = true;
288
308
  if (import_hls.default.isSupported()) {
289
- const hls = new import_hls.default();
309
+ const hlsConfig = isPlayOnHover ? {
310
+ // For hover-play: only buffer enough to start playing smoothly.
311
+ // maxBufferLength – target seconds of forward buffer (default 30s → 10s)
312
+ // maxMaxBufferLength – hard ceiling hls.js won't exceed (default 600s → 15s)
313
+ // maxBufferSize – byte ceiling before hls.js pauses loading (default 60MB → 10MB)
314
+ // lowLatencyMode – off; we don't need ultra-low latency for on-demand hover clips
315
+ maxBufferLength: 10,
316
+ maxMaxBufferLength: 15,
317
+ maxBufferSize: 10 * 1e3 * 1e3,
318
+ // 10 MB
319
+ lowLatencyMode: false
320
+ } : {};
321
+ const hls = new import_hls.default(hlsConfig);
290
322
  hls.loadSource(chosenSrc);
291
323
  hls.attachMedia(v);
292
324
  hls.on(import_hls.default.Events.MANIFEST_PARSED, () => {
@@ -304,10 +336,12 @@ var init_HlsPlayer = __esm({
304
336
  }
305
337
  }, [JSON.stringify(resolvedSources)]);
306
338
  (0, import_react4.useEffect)(() => {
339
+ if (!isInView) return;
307
340
  if (isPlayOnHover) return;
341
+ if (playOptions !== "autoplay") return;
308
342
  initHls(
309
343
  /* autoPlayAfterLoad */
310
- playOptions === "autoplay"
344
+ true
311
345
  );
312
346
  return () => {
313
347
  if (hlsRef.current) {
@@ -316,10 +350,17 @@ var init_HlsPlayer = __esm({
316
350
  }
317
351
  hlsInitializedRef.current = false;
318
352
  };
319
- }, [JSON.stringify(resolvedSources), isPlayOnHover]);
353
+ }, [JSON.stringify(resolvedSources), isPlayOnHover, isInView, playOptions]);
320
354
  const handlePlayPause = (0, import_react4.useCallback)(() => {
321
355
  const v = videoRef.current;
322
356
  if (!v) return;
357
+ if (!hlsInitializedRef.current) {
358
+ initHls(
359
+ /* autoPlayAfterLoad */
360
+ true
361
+ );
362
+ return;
363
+ }
323
364
  if (v.paused) {
324
365
  wasManuallyPausedRef.current = false;
325
366
  v.play().then(() => setIsPlaying(true));
@@ -328,7 +369,7 @@ var init_HlsPlayer = __esm({
328
369
  v.pause();
329
370
  setIsPlaying(false);
330
371
  }
331
- }, []);
372
+ }, [initHls]);
332
373
  const handleMuteToggle = (0, import_react4.useCallback)(() => {
333
374
  const v = videoRef.current;
334
375
  if (!v) return;
@@ -381,6 +422,11 @@ var init_HlsPlayer = __esm({
381
422
  videoRef.current.pause();
382
423
  videoRef.current.currentTime = 0;
383
424
  setIsPlaying(false);
425
+ if (hlsRef.current) {
426
+ hlsRef.current.destroy();
427
+ hlsRef.current = null;
428
+ hlsInitializedRef.current = false;
429
+ }
384
430
  }
385
431
  }, [isPlayOnHover, isMobile, isPlaying]);
386
432
  const handleMouseMove = (0, import_react4.useCallback)(() => {
@@ -433,10 +479,10 @@ var init_HlsPlayer = __esm({
433
479
  autoPlay: playOptions === "autoplay",
434
480
  loop,
435
481
  playsInline: true,
436
- preload: isPlayOnHover ? "none" : "auto",
482
+ preload: playOptions === "autoplay" ? "auto" : "none",
437
483
  onClick: handleVideoClick,
438
484
  onDoubleClick: handleVideoDoubleClick,
439
- children: !isPlayOnHover && resolvedSources.map(({ src, media }, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
485
+ children: playOptions === "autoplay" && resolvedSources.map(({ src, media }, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
440
486
  "source",
441
487
  {
442
488
  src,
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HlsPlayer_default
3
- } from "./chunk-72PHGKW4.mjs";
3
+ } from "./chunk-F6CXFHUE.mjs";
4
4
  import {
5
5
  Button_default,
6
6
  ClientButton_default,
@@ -1975,7 +1975,7 @@ import React28 from "react";
1975
1975
  // src/components/pageRenderingEngine/nodes/ImageNode.tsx
1976
1976
  import dynamic3 from "next/dynamic";
1977
1977
  import { jsx as jsx38 } from "react/jsx-runtime";
1978
- var HlsPlayer = dynamic3(() => import("./HlsPlayer-GZR4QXJY.mjs"), { ssr: false });
1978
+ var HlsPlayer = dynamic3(() => import("./HlsPlayer-G27NMG7A.mjs"), { ssr: false });
1979
1979
  var getNestedValue = (obj, path) => {
1980
1980
  if (!obj || !path) return void 0;
1981
1981
  return path.split(".").reduce((current, key) => {
@@ -3632,7 +3632,7 @@ var Pagination_default = Pagination;
3632
3632
  // src/components/pageRenderingEngine/nodes/ImageGalleryNode.tsx
3633
3633
  import dynamic7 from "next/dynamic";
3634
3634
  import { Fragment as Fragment7, jsx as jsx57, jsxs as jsxs31 } from "react/jsx-runtime";
3635
- var HlsPlayer2 = dynamic7(() => import("./HlsPlayer-GZR4QXJY.mjs"), { ssr: false });
3635
+ var HlsPlayer2 = dynamic7(() => import("./HlsPlayer-G27NMG7A.mjs"), { ssr: false });
3636
3636
  var deviceToMediaQuery = (device) => {
3637
3637
  switch (device) {
3638
3638
  case "sm":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acoustte-digital-services/digitalstore-controls-dev",
3
- "version": "0.8.1-dev.20260523060518",
3
+ "version": "0.8.1-dev.20260525053215",
4
4
  "description": "Reusable React components",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",