@acoustte-digital-services/digitalstore-controls-dev 0.8.1-dev.20260523055026 → 0.8.1-dev.20260525045412

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-BYK57CMC.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,11 +172,19 @@ var HlsPlayer = React.memo(
140
172
  }
141
173
  }, [JSON.stringify(resolvedSources)]);
142
174
  useEffect(() => {
175
+ if (!isInView) return;
143
176
  if (isPlayOnHover) return;
144
- initHls(
145
- /* autoPlayAfterLoad */
146
- playOptions === "autoplay"
147
- );
177
+ if (playOptions === "autoplay") {
178
+ initHls(
179
+ /* autoPlayAfterLoad */
180
+ true
181
+ );
182
+ } else {
183
+ initHls(
184
+ /* autoPlayAfterLoad */
185
+ false
186
+ );
187
+ }
148
188
  return () => {
149
189
  if (hlsRef.current) {
150
190
  hlsRef.current.destroy();
@@ -152,10 +192,17 @@ var HlsPlayer = React.memo(
152
192
  }
153
193
  hlsInitializedRef.current = false;
154
194
  };
155
- }, [JSON.stringify(resolvedSources), isPlayOnHover]);
195
+ }, [JSON.stringify(resolvedSources), isPlayOnHover, isInView]);
156
196
  const handlePlayPause = useCallback(() => {
157
197
  const v = videoRef.current;
158
198
  if (!v) return;
199
+ if (!hlsInitializedRef.current) {
200
+ initHls(
201
+ /* autoPlayAfterLoad */
202
+ true
203
+ );
204
+ return;
205
+ }
159
206
  if (v.paused) {
160
207
  wasManuallyPausedRef.current = false;
161
208
  v.play().then(() => setIsPlaying(true));
@@ -164,7 +211,7 @@ var HlsPlayer = React.memo(
164
211
  v.pause();
165
212
  setIsPlaying(false);
166
213
  }
167
- }, []);
214
+ }, [initHls]);
168
215
  const handleMuteToggle = useCallback(() => {
169
216
  const v = videoRef.current;
170
217
  if (!v) return;
@@ -217,6 +264,11 @@ var HlsPlayer = React.memo(
217
264
  videoRef.current.pause();
218
265
  videoRef.current.currentTime = 0;
219
266
  setIsPlaying(false);
267
+ if (hlsRef.current) {
268
+ hlsRef.current.destroy();
269
+ hlsRef.current = null;
270
+ hlsInitializedRef.current = false;
271
+ }
220
272
  }
221
273
  }, [isPlayOnHover, isMobile, isPlaying]);
222
274
  const handleMouseMove = useCallback(() => {
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,11 +336,19 @@ 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;
308
- initHls(
309
- /* autoPlayAfterLoad */
310
- playOptions === "autoplay"
311
- );
341
+ if (playOptions === "autoplay") {
342
+ initHls(
343
+ /* autoPlayAfterLoad */
344
+ true
345
+ );
346
+ } else {
347
+ initHls(
348
+ /* autoPlayAfterLoad */
349
+ false
350
+ );
351
+ }
312
352
  return () => {
313
353
  if (hlsRef.current) {
314
354
  hlsRef.current.destroy();
@@ -316,10 +356,17 @@ var init_HlsPlayer = __esm({
316
356
  }
317
357
  hlsInitializedRef.current = false;
318
358
  };
319
- }, [JSON.stringify(resolvedSources), isPlayOnHover]);
359
+ }, [JSON.stringify(resolvedSources), isPlayOnHover, isInView]);
320
360
  const handlePlayPause = (0, import_react4.useCallback)(() => {
321
361
  const v = videoRef.current;
322
362
  if (!v) return;
363
+ if (!hlsInitializedRef.current) {
364
+ initHls(
365
+ /* autoPlayAfterLoad */
366
+ true
367
+ );
368
+ return;
369
+ }
323
370
  if (v.paused) {
324
371
  wasManuallyPausedRef.current = false;
325
372
  v.play().then(() => setIsPlaying(true));
@@ -328,7 +375,7 @@ var init_HlsPlayer = __esm({
328
375
  v.pause();
329
376
  setIsPlaying(false);
330
377
  }
331
- }, []);
378
+ }, [initHls]);
332
379
  const handleMuteToggle = (0, import_react4.useCallback)(() => {
333
380
  const v = videoRef.current;
334
381
  if (!v) return;
@@ -381,6 +428,11 @@ var init_HlsPlayer = __esm({
381
428
  videoRef.current.pause();
382
429
  videoRef.current.currentTime = 0;
383
430
  setIsPlaying(false);
431
+ if (hlsRef.current) {
432
+ hlsRef.current.destroy();
433
+ hlsRef.current = null;
434
+ hlsInitializedRef.current = false;
435
+ }
384
436
  }
385
437
  }, [isPlayOnHover, isMobile, isPlaying]);
386
438
  const handleMouseMove = (0, import_react4.useCallback)(() => {
@@ -1655,20 +1707,17 @@ var DeviceAssetSelector = ({
1655
1707
  apiBaseUrl: assetBaseUrl,
1656
1708
  session
1657
1709
  }
1658
- ) : (
1659
- // eslint-disable-next-line @next/next/no-img-element
1660
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1661
- "img",
1662
- {
1663
- style: styles,
1664
- loading: "lazy",
1665
- className: "object-cover w-full",
1666
- src: resolvedAssetUrl,
1667
- width: selectedAsset.intrinsicWidth,
1668
- height: selectedAsset.intrinsicHeight,
1669
- alt: title || "Asset image"
1670
- }
1671
- )
1710
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1711
+ "img",
1712
+ {
1713
+ style: styles,
1714
+ loading: "lazy",
1715
+ className: "object-cover w-full",
1716
+ src: resolvedAssetUrl,
1717
+ width: selectedAsset.intrinsicWidth,
1718
+ height: selectedAsset.intrinsicHeight,
1719
+ alt: title || "Asset image"
1720
+ }
1672
1721
  );
1673
1722
  if (width) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { width }, children: renderMedia() });
1674
1723
  if (nodeProps?.format) {
@@ -3482,15 +3531,12 @@ var ImageNode = (props) => {
3482
3531
  posterUrl = AssetUtility_default.resolveUrl(props.assetBaseUrl, props.node.posterUrl);
3483
3532
  } else if (props.dataitem && props.node.datafield) {
3484
3533
  const image = getNestedValue(props.dataitem, props.node.datafield);
3485
- try {
3486
- if (typeof image === "string") {
3487
- assets = JSON.parse(image);
3488
- } else if (Array.isArray(image)) {
3489
- assets = image;
3490
- } else if (image && typeof image === "object") {
3491
- assets = [image];
3492
- }
3493
- } catch {
3534
+ if (typeof image === "string") {
3535
+ assets = JSON.parse(image);
3536
+ } else if (Array.isArray(image)) {
3537
+ assets = image;
3538
+ } else if (image && typeof image === "object") {
3539
+ assets = [image];
3494
3540
  }
3495
3541
  if (assets && assets.length > 0) {
3496
3542
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HlsPlayer_default
3
- } from "./chunk-72PHGKW4.mjs";
3
+ } from "./chunk-BYK57CMC.mjs";
4
4
  import {
5
5
  Button_default,
6
6
  ClientButton_default,
@@ -168,20 +168,17 @@ var DeviceAssetSelector = ({
168
168
  apiBaseUrl: assetBaseUrl,
169
169
  session
170
170
  }
171
- ) : (
172
- // eslint-disable-next-line @next/next/no-img-element
173
- /* @__PURE__ */ jsx3(
174
- "img",
175
- {
176
- style: styles,
177
- loading: "lazy",
178
- className: "object-cover w-full",
179
- src: resolvedAssetUrl,
180
- width: selectedAsset.intrinsicWidth,
181
- height: selectedAsset.intrinsicHeight,
182
- alt: title || "Asset image"
183
- }
184
- )
171
+ ) : /* @__PURE__ */ jsx3(
172
+ "img",
173
+ {
174
+ style: styles,
175
+ loading: "lazy",
176
+ className: "object-cover w-full",
177
+ src: resolvedAssetUrl,
178
+ width: selectedAsset.intrinsicWidth,
179
+ height: selectedAsset.intrinsicHeight,
180
+ alt: title || "Asset image"
181
+ }
185
182
  );
186
183
  if (width) return /* @__PURE__ */ jsx3("div", { style: { width }, children: renderMedia() });
187
184
  if (nodeProps?.format) {
@@ -1978,7 +1975,7 @@ import React28 from "react";
1978
1975
  // src/components/pageRenderingEngine/nodes/ImageNode.tsx
1979
1976
  import dynamic3 from "next/dynamic";
1980
1977
  import { jsx as jsx38 } from "react/jsx-runtime";
1981
- var HlsPlayer = dynamic3(() => import("./HlsPlayer-GZR4QXJY.mjs"), { ssr: false });
1978
+ var HlsPlayer = dynamic3(() => import("./HlsPlayer-OPTPF5PZ.mjs"), { ssr: false });
1982
1979
  var getNestedValue = (obj, path) => {
1983
1980
  if (!obj || !path) return void 0;
1984
1981
  return path.split(".").reduce((current, key) => {
@@ -1999,15 +1996,12 @@ var ImageNode = (props) => {
1999
1996
  posterUrl = AssetUtility_default.resolveUrl(props.assetBaseUrl, props.node.posterUrl);
2000
1997
  } else if (props.dataitem && props.node.datafield) {
2001
1998
  const image = getNestedValue(props.dataitem, props.node.datafield);
2002
- try {
2003
- if (typeof image === "string") {
2004
- assets = JSON.parse(image);
2005
- } else if (Array.isArray(image)) {
2006
- assets = image;
2007
- } else if (image && typeof image === "object") {
2008
- assets = [image];
2009
- }
2010
- } catch {
1999
+ if (typeof image === "string") {
2000
+ assets = JSON.parse(image);
2001
+ } else if (Array.isArray(image)) {
2002
+ assets = image;
2003
+ } else if (image && typeof image === "object") {
2004
+ assets = [image];
2011
2005
  }
2012
2006
  if (assets && assets.length > 0) {
2013
2007
  return /* @__PURE__ */ jsx38(
@@ -3638,7 +3632,7 @@ var Pagination_default = Pagination;
3638
3632
  // src/components/pageRenderingEngine/nodes/ImageGalleryNode.tsx
3639
3633
  import dynamic7 from "next/dynamic";
3640
3634
  import { Fragment as Fragment7, jsx as jsx57, jsxs as jsxs31 } from "react/jsx-runtime";
3641
- var HlsPlayer2 = dynamic7(() => import("./HlsPlayer-GZR4QXJY.mjs"), { ssr: false });
3635
+ var HlsPlayer2 = dynamic7(() => import("./HlsPlayer-OPTPF5PZ.mjs"), { ssr: false });
3642
3636
  var deviceToMediaQuery = (device) => {
3643
3637
  switch (device) {
3644
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.20260523055026",
3
+ "version": "0.8.1-dev.20260525045412",
4
4
  "description": "Reusable React components",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",