@acoustte-digital-services/digitalstore-controls-dev 0.8.1-dev.20260422065945 → 0.8.1-dev.20260422073350

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-VVEZGWP4.mjs";
4
+ } from "./chunk-ELASRK22.mjs";
5
5
  export {
6
6
  HlsPlayer_default as default
7
7
  };
@@ -2,13 +2,6 @@
2
2
  import React, { useRef, useEffect, useState, useCallback } from "react";
3
3
  import Hls from "hls.js";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
- var resolveActiveSource = (sources) => {
6
- for (const { src, media } of sources) {
7
- if (media && window.matchMedia(media).matches) return src;
8
- }
9
- const fallback = sources.find((s) => !s.media);
10
- return fallback?.src ?? sources[0]?.src ?? "";
11
- };
12
5
  var HlsPlayer = React.memo(
13
6
  ({
14
7
  sources,
@@ -27,7 +20,7 @@ var HlsPlayer = React.memo(
27
20
  const [isHovered, setIsHovered] = useState(false);
28
21
  const [isMobile, setIsMobile] = useState(false);
29
22
  const wasManuallyPausedRef = useRef(false);
30
- const resolvedSources = sources && sources.length > 0 ? sources : assetUrl ? [{ src: assetUrl }] : [];
23
+ const resolvedSources = sources && sources.length > 0 ? sources : assetUrl ? [{ src: assetUrl, posterUrl }] : [];
31
24
  useEffect(() => {
32
25
  const checkMobile = () => {
33
26
  const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
@@ -41,41 +34,38 @@ var HlsPlayer = React.memo(
41
34
  window.addEventListener("resize", checkMobile);
42
35
  return () => window.removeEventListener("resize", checkMobile);
43
36
  }, []);
44
- const [activeSrc, setActiveSrc] = useState("");
45
- useEffect(() => {
46
- if (resolvedSources.length === 0) return;
47
- const update = () => setActiveSrc(resolveActiveSource(resolvedSources));
48
- update();
49
- const mqls = resolvedSources.filter((s) => s.media).map((s) => window.matchMedia(s.media));
50
- mqls.forEach((mql) => mql.addEventListener("change", update));
51
- return () => mqls.forEach((mql) => mql.removeEventListener("change", update));
52
- }, [JSON.stringify(resolvedSources)]);
53
37
  useEffect(() => {
54
38
  const v = videoRef.current;
55
- if (!v || !activeSrc) return;
39
+ if (!v || resolvedSources.length === 0) return;
56
40
  if (hlsRef.current) {
57
41
  hlsRef.current.destroy();
58
42
  hlsRef.current = null;
59
43
  }
60
44
  if (Hls.isSupported()) {
61
45
  const hls = new Hls();
62
- hls.loadSource(activeSrc);
63
- hls.attachMedia(v);
64
- hls.on(Hls.Events.MANIFEST_PARSED, () => {
65
- if (isPlaying && !wasManuallyPausedRef.current) {
66
- v.play().catch(console.error);
67
- }
68
- });
46
+ const onLoadStart = () => {
47
+ const chosenSrc = v.currentSrc;
48
+ if (!chosenSrc) return;
49
+ hls.loadSource(chosenSrc);
50
+ hls.attachMedia(v);
51
+ hls.on(Hls.Events.MANIFEST_PARSED, () => {
52
+ if (isPlaying && !wasManuallyPausedRef.current) {
53
+ v.play().catch(console.error);
54
+ }
55
+ });
56
+ };
57
+ v.addEventListener("loadstart", onLoadStart, { once: true });
58
+ v.load();
69
59
  hlsRef.current = hls;
70
60
  return () => {
61
+ v.removeEventListener("loadstart", onLoadStart);
71
62
  hls.destroy();
72
63
  hlsRef.current = null;
73
64
  };
74
65
  } else if (v.canPlayType("application/vnd.apple.mpegurl")) {
75
- v.src = activeSrc;
76
66
  v.load();
77
67
  }
78
- }, [activeSrc]);
68
+ }, [JSON.stringify(resolvedSources)]);
79
69
  const handlePlayPause = useCallback(() => {
80
70
  const v = videoRef.current;
81
71
  if (!v) return;
@@ -104,6 +94,8 @@ var HlsPlayer = React.memo(
104
94
  setIsPlaying(false);
105
95
  }
106
96
  }, [playOptions, isMobile]);
97
+ const posterSources = resolvedSources.filter((s) => s.media && s.posterUrl);
98
+ const fallbackPoster = posterUrl ?? resolvedSources.find((s) => !s.media)?.posterUrl ?? resolvedSources[0]?.posterUrl;
107
99
  if (resolvedSources.length === 0) return null;
108
100
  return /* @__PURE__ */ jsxs(
109
101
  "div",
@@ -117,23 +109,40 @@ var HlsPlayer = React.memo(
117
109
  {
118
110
  ref: videoRef,
119
111
  className: "w-full h-full object-contain",
120
- poster: posterUrl,
121
112
  controls: showControls && (isMobile || isPlaying),
122
113
  muted: playOptions === "autoplay" || playOptions === "playOnHover",
123
114
  autoPlay: playOptions === "autoplay",
124
115
  loop,
125
116
  playsInline: true,
126
- onClick: !isMobile && !isPlaying ? handlePlayPause : void 0
117
+ onClick: !isMobile && !isPlaying ? handlePlayPause : void 0,
118
+ children: resolvedSources.map(({ src, media }, i) => /* @__PURE__ */ jsx(
119
+ "source",
120
+ {
121
+ src,
122
+ type: "application/x-mpegURL",
123
+ ...media ? { media } : {}
124
+ },
125
+ i
126
+ ))
127
127
  }
128
128
  ),
129
- !isMobile && playOptions === "playOnHover" && posterUrl && /* @__PURE__ */ jsx(
130
- "img",
129
+ fallbackPoster && !isPlaying && /* @__PURE__ */ jsxs(
130
+ "picture",
131
131
  {
132
- src: posterUrl,
133
- width: intrinsicWidth,
134
- height: intrinsicHeight,
135
- alt: "poster",
136
- className: `absolute inset-0 object-cover transition-opacity ${isHovered ? "opacity-0" : "opacity-100"}`
132
+ className: `absolute inset-0 transition-opacity ${!isMobile && playOptions === "playOnHover" && isHovered ? "opacity-0" : "opacity-100"}`,
133
+ children: [
134
+ posterSources.map(({ media, posterUrl: src }, i) => /* @__PURE__ */ jsx("source", { media, srcSet: src }, i)),
135
+ /* @__PURE__ */ jsx(
136
+ "img",
137
+ {
138
+ src: fallbackPoster,
139
+ width: intrinsicWidth,
140
+ height: intrinsicHeight,
141
+ alt: "poster",
142
+ className: "w-full h-full object-cover"
143
+ }
144
+ )
145
+ ]
137
146
  }
138
147
  ),
139
148
  !isMobile && !isPlaying && /* @__PURE__ */ jsx(
package/dist/index.js CHANGED
@@ -271,7 +271,7 @@ var HlsPlayer_exports = {};
271
271
  __export(HlsPlayer_exports, {
272
272
  default: () => HlsPlayer_default
273
273
  });
274
- var import_react33, import_hls, import_jsx_runtime42, resolveActiveSource, HlsPlayer, HlsPlayer_default;
274
+ var import_react33, import_hls, import_jsx_runtime42, HlsPlayer, HlsPlayer_default;
275
275
  var init_HlsPlayer = __esm({
276
276
  "src/components/HlsPlayer.tsx"() {
277
277
  "use strict";
@@ -279,13 +279,6 @@ var init_HlsPlayer = __esm({
279
279
  import_react33 = __toESM(require("react"));
280
280
  import_hls = __toESM(require("hls.js"));
281
281
  import_jsx_runtime42 = require("react/jsx-runtime");
282
- resolveActiveSource = (sources) => {
283
- for (const { src, media } of sources) {
284
- if (media && window.matchMedia(media).matches) return src;
285
- }
286
- const fallback = sources.find((s) => !s.media);
287
- return fallback?.src ?? sources[0]?.src ?? "";
288
- };
289
282
  HlsPlayer = import_react33.default.memo(
290
283
  ({
291
284
  sources,
@@ -304,7 +297,7 @@ var init_HlsPlayer = __esm({
304
297
  const [isHovered, setIsHovered] = (0, import_react33.useState)(false);
305
298
  const [isMobile, setIsMobile] = (0, import_react33.useState)(false);
306
299
  const wasManuallyPausedRef = (0, import_react33.useRef)(false);
307
- const resolvedSources = sources && sources.length > 0 ? sources : assetUrl ? [{ src: assetUrl }] : [];
300
+ const resolvedSources = sources && sources.length > 0 ? sources : assetUrl ? [{ src: assetUrl, posterUrl }] : [];
308
301
  (0, import_react33.useEffect)(() => {
309
302
  const checkMobile = () => {
310
303
  const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
@@ -318,41 +311,38 @@ var init_HlsPlayer = __esm({
318
311
  window.addEventListener("resize", checkMobile);
319
312
  return () => window.removeEventListener("resize", checkMobile);
320
313
  }, []);
321
- const [activeSrc, setActiveSrc] = (0, import_react33.useState)("");
322
- (0, import_react33.useEffect)(() => {
323
- if (resolvedSources.length === 0) return;
324
- const update = () => setActiveSrc(resolveActiveSource(resolvedSources));
325
- update();
326
- const mqls = resolvedSources.filter((s) => s.media).map((s) => window.matchMedia(s.media));
327
- mqls.forEach((mql) => mql.addEventListener("change", update));
328
- return () => mqls.forEach((mql) => mql.removeEventListener("change", update));
329
- }, [JSON.stringify(resolvedSources)]);
330
314
  (0, import_react33.useEffect)(() => {
331
315
  const v = videoRef.current;
332
- if (!v || !activeSrc) return;
316
+ if (!v || resolvedSources.length === 0) return;
333
317
  if (hlsRef.current) {
334
318
  hlsRef.current.destroy();
335
319
  hlsRef.current = null;
336
320
  }
337
321
  if (import_hls.default.isSupported()) {
338
322
  const hls = new import_hls.default();
339
- hls.loadSource(activeSrc);
340
- hls.attachMedia(v);
341
- hls.on(import_hls.default.Events.MANIFEST_PARSED, () => {
342
- if (isPlaying && !wasManuallyPausedRef.current) {
343
- v.play().catch(console.error);
344
- }
345
- });
323
+ const onLoadStart = () => {
324
+ const chosenSrc = v.currentSrc;
325
+ if (!chosenSrc) return;
326
+ hls.loadSource(chosenSrc);
327
+ hls.attachMedia(v);
328
+ hls.on(import_hls.default.Events.MANIFEST_PARSED, () => {
329
+ if (isPlaying && !wasManuallyPausedRef.current) {
330
+ v.play().catch(console.error);
331
+ }
332
+ });
333
+ };
334
+ v.addEventListener("loadstart", onLoadStart, { once: true });
335
+ v.load();
346
336
  hlsRef.current = hls;
347
337
  return () => {
338
+ v.removeEventListener("loadstart", onLoadStart);
348
339
  hls.destroy();
349
340
  hlsRef.current = null;
350
341
  };
351
342
  } else if (v.canPlayType("application/vnd.apple.mpegurl")) {
352
- v.src = activeSrc;
353
343
  v.load();
354
344
  }
355
- }, [activeSrc]);
345
+ }, [JSON.stringify(resolvedSources)]);
356
346
  const handlePlayPause = (0, import_react33.useCallback)(() => {
357
347
  const v = videoRef.current;
358
348
  if (!v) return;
@@ -381,6 +371,8 @@ var init_HlsPlayer = __esm({
381
371
  setIsPlaying(false);
382
372
  }
383
373
  }, [playOptions, isMobile]);
374
+ const posterSources = resolvedSources.filter((s) => s.media && s.posterUrl);
375
+ const fallbackPoster = posterUrl ?? resolvedSources.find((s) => !s.media)?.posterUrl ?? resolvedSources[0]?.posterUrl;
384
376
  if (resolvedSources.length === 0) return null;
385
377
  return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
386
378
  "div",
@@ -394,23 +386,40 @@ var init_HlsPlayer = __esm({
394
386
  {
395
387
  ref: videoRef,
396
388
  className: "w-full h-full object-contain",
397
- poster: posterUrl,
398
389
  controls: showControls && (isMobile || isPlaying),
399
390
  muted: playOptions === "autoplay" || playOptions === "playOnHover",
400
391
  autoPlay: playOptions === "autoplay",
401
392
  loop,
402
393
  playsInline: true,
403
- onClick: !isMobile && !isPlaying ? handlePlayPause : void 0
394
+ onClick: !isMobile && !isPlaying ? handlePlayPause : void 0,
395
+ children: resolvedSources.map(({ src, media }, i) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
396
+ "source",
397
+ {
398
+ src,
399
+ type: "application/x-mpegURL",
400
+ ...media ? { media } : {}
401
+ },
402
+ i
403
+ ))
404
404
  }
405
405
  ),
406
- !isMobile && playOptions === "playOnHover" && posterUrl && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
407
- "img",
406
+ fallbackPoster && !isPlaying && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
407
+ "picture",
408
408
  {
409
- src: posterUrl,
410
- width: intrinsicWidth,
411
- height: intrinsicHeight,
412
- alt: "poster",
413
- className: `absolute inset-0 object-cover transition-opacity ${isHovered ? "opacity-0" : "opacity-100"}`
409
+ className: `absolute inset-0 transition-opacity ${!isMobile && playOptions === "playOnHover" && isHovered ? "opacity-0" : "opacity-100"}`,
410
+ children: [
411
+ posterSources.map(({ media, posterUrl: src }, i) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("source", { media, srcSet: src }, i)),
412
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
413
+ "img",
414
+ {
415
+ src: fallbackPoster,
416
+ width: intrinsicWidth,
417
+ height: intrinsicHeight,
418
+ alt: "poster",
419
+ className: "w-full h-full object-cover"
420
+ }
421
+ )
422
+ ]
414
423
  }
415
424
  ),
416
425
  !isMobile && !isPlaying && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
@@ -5174,13 +5183,17 @@ var ImageGalleryNode = (props) => {
5174
5183
  const src = resolveImageUrl(img.imageUrl);
5175
5184
  if (!src) return [];
5176
5185
  const media = deviceToMediaQuery(img.device);
5177
- return [{ src, ...media ? { media } : {} }];
5186
+ const posterUrl = resolvePosterUrl(img.posterUrl);
5187
+ return [{ src, ...media ? { media } : {}, ...posterUrl ? { posterUrl } : {} }];
5178
5188
  }),
5179
5189
  // Unconstrained fallback(s) — no media attr, always matches.
5180
- ...hlsImages.filter((img) => !img.device).map((img) => ({ src: resolveImageUrl(img.imageUrl) })).filter((s) => !!s.src)
5190
+ ...hlsImages.filter((img) => !img.device).map((img) => {
5191
+ const src = resolveImageUrl(img.imageUrl);
5192
+ const posterUrl = resolvePosterUrl(img.posterUrl);
5193
+ return { src, ...posterUrl ? { posterUrl } : {} };
5194
+ }).filter((s) => !!s.src)
5181
5195
  ];
5182
5196
  const primaryHls = hlsImages.find((img) => !img.device) ?? hlsImages[0];
5183
- const hlsPosterUrl = primaryHls ? resolvePosterUrl(primaryHls.posterUrl) : void 0;
5184
5197
  const hlsIntrinsicWidth = primaryHls ? parseMaybeNumber(primaryHls.intrinsicWidth)?.toString() : void 0;
5185
5198
  const hlsIntrinsicHeight = primaryHls ? parseMaybeNumber(primaryHls.intrinsicHeight)?.toString() : void 0;
5186
5199
  const staticSources = staticImages.filter((img) => !!img.device);
@@ -5196,7 +5209,6 @@ var ImageGalleryNode = (props) => {
5196
5209
  HlsPlayer3,
5197
5210
  {
5198
5211
  sources: hlsSources,
5199
- posterUrl: hlsPosterUrl,
5200
5212
  intrinsicWidth: hlsIntrinsicWidth,
5201
5213
  intrinsicHeight: hlsIntrinsicHeight,
5202
5214
  showControls: primaryHls?.showControls ?? false,
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HlsPlayer_default
3
- } from "./chunk-VVEZGWP4.mjs";
3
+ } from "./chunk-ELASRK22.mjs";
4
4
  import {
5
5
  Button_default,
6
6
  ServiceClient_default,
@@ -2638,7 +2638,7 @@ var DeviceAssetSelector_default = DeviceAssetSelector;
2638
2638
 
2639
2639
  // src/components/pageRenderingEngine/nodes/ImageNode.tsx
2640
2640
  import { Fragment as Fragment3, jsx as jsx39 } from "react/jsx-runtime";
2641
- var HlsPlayer = dynamic(() => import("./HlsPlayer-O6BEBDTQ.mjs"), {
2641
+ var HlsPlayer = dynamic(() => import("./HlsPlayer-IKEZJ5A5.mjs"), {
2642
2642
  ssr: false
2643
2643
  });
2644
2644
  var getNestedValue = (obj, path) => {
@@ -4107,7 +4107,7 @@ var Pagination_default = Pagination;
4107
4107
  // src/components/pageRenderingEngine/nodes/ImageGalleryNode.tsx
4108
4108
  import dynamic5 from "next/dynamic";
4109
4109
  import { Fragment as Fragment9, jsx as jsx58, jsxs as jsxs33 } from "react/jsx-runtime";
4110
- var HlsPlayer2 = dynamic5(() => import("./HlsPlayer-O6BEBDTQ.mjs"), { ssr: false });
4110
+ var HlsPlayer2 = dynamic5(() => import("./HlsPlayer-IKEZJ5A5.mjs"), { ssr: false });
4111
4111
  var deviceToMediaQuery = (device) => {
4112
4112
  switch (device) {
4113
4113
  case "sm":
@@ -4156,13 +4156,17 @@ var ImageGalleryNode = (props) => {
4156
4156
  const src = resolveImageUrl(img.imageUrl);
4157
4157
  if (!src) return [];
4158
4158
  const media = deviceToMediaQuery(img.device);
4159
- return [{ src, ...media ? { media } : {} }];
4159
+ const posterUrl = resolvePosterUrl(img.posterUrl);
4160
+ return [{ src, ...media ? { media } : {}, ...posterUrl ? { posterUrl } : {} }];
4160
4161
  }),
4161
4162
  // Unconstrained fallback(s) — no media attr, always matches.
4162
- ...hlsImages.filter((img) => !img.device).map((img) => ({ src: resolveImageUrl(img.imageUrl) })).filter((s) => !!s.src)
4163
+ ...hlsImages.filter((img) => !img.device).map((img) => {
4164
+ const src = resolveImageUrl(img.imageUrl);
4165
+ const posterUrl = resolvePosterUrl(img.posterUrl);
4166
+ return { src, ...posterUrl ? { posterUrl } : {} };
4167
+ }).filter((s) => !!s.src)
4163
4168
  ];
4164
4169
  const primaryHls = hlsImages.find((img) => !img.device) ?? hlsImages[0];
4165
- const hlsPosterUrl = primaryHls ? resolvePosterUrl(primaryHls.posterUrl) : void 0;
4166
4170
  const hlsIntrinsicWidth = primaryHls ? parseMaybeNumber(primaryHls.intrinsicWidth)?.toString() : void 0;
4167
4171
  const hlsIntrinsicHeight = primaryHls ? parseMaybeNumber(primaryHls.intrinsicHeight)?.toString() : void 0;
4168
4172
  const staticSources = staticImages.filter((img) => !!img.device);
@@ -4178,7 +4182,6 @@ var ImageGalleryNode = (props) => {
4178
4182
  HlsPlayer2,
4179
4183
  {
4180
4184
  sources: hlsSources,
4181
- posterUrl: hlsPosterUrl,
4182
4185
  intrinsicWidth: hlsIntrinsicWidth,
4183
4186
  intrinsicHeight: hlsIntrinsicHeight,
4184
4187
  showControls: primaryHls?.showControls ?? false,
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.20260422065945",
3
+ "version": "0.8.1-dev.20260422073350",
4
4
  "description": "Reusable React components",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",