@rxdrag/website-lib-react 0.0.4 → 0.0.7

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.
Files changed (99) hide show
  1. package/dist/ReactModalTrigger-9207e763.js +26 -0
  2. package/dist/ReactModalTrigger-9207e763.js.map +1 -0
  3. package/dist/components/ContactForm/ContactForm.d.ts +2 -1
  4. package/dist/components/Icon/index.d.ts +2 -1
  5. package/dist/components/RichTextOutline/parseOutline.d.ts +5 -0
  6. package/dist/components/all.d.ts +0 -21
  7. package/dist/components/index.d.ts +0 -5
  8. package/dist/forms.d.ts +1 -0
  9. package/dist/forms.mjs +1649 -0
  10. package/dist/forms.mjs.map +1 -0
  11. package/dist/index.mjs +9 -3918
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/jsx-runtime-c02cc059.js +325 -0
  14. package/dist/jsx-runtime-c02cc059.js.map +1 -0
  15. package/dist/media.d.ts +1 -0
  16. package/dist/media.mjs +613 -0
  17. package/dist/media.mjs.map +1 -0
  18. package/dist/richtext.d.ts +1 -0
  19. package/dist/richtext.mjs +191 -0
  20. package/dist/richtext.mjs.map +1 -0
  21. package/dist/ui.d.ts +10 -0
  22. package/dist/ui.mjs +687 -0
  23. package/dist/ui.mjs.map +1 -0
  24. package/dist/video.d.ts +2 -0
  25. package/dist/video.mjs +426 -0
  26. package/dist/video.mjs.map +1 -0
  27. package/forms.ts +1 -0
  28. package/index.ts +1 -0
  29. package/media.ts +1 -0
  30. package/package.json +40 -5
  31. package/richtext.ts +1 -0
  32. package/src/components/Analytics/eventHandlers.ts +173 -0
  33. package/src/components/Analytics/index.tsx +21 -0
  34. package/src/components/Analytics/singleton.ts +214 -0
  35. package/src/components/Analytics/tracking.ts +221 -0
  36. package/src/components/Analytics/types.ts +60 -0
  37. package/src/components/Analytics/utils.ts +95 -0
  38. package/src/components/AttachmentIcon/index.tsx +53 -0
  39. package/src/components/BackgroundHlsVideoPlayer.tsx +97 -0
  40. package/src/components/BackgroundVideoPlayer.tsx +32 -0
  41. package/src/components/Bulletin.tsx +30 -0
  42. package/src/components/ContactForm/ContactForm.tsx +296 -0
  43. package/src/components/ContactForm/FileUpload2.tsx +423 -0
  44. package/src/components/ContactForm/Input.tsx +48 -0
  45. package/src/components/ContactForm/Input2.tsx +59 -0
  46. package/src/components/ContactForm/Submit.tsx +48 -0
  47. package/src/components/ContactForm/TelInput.tsx +215 -0
  48. package/src/components/ContactForm/TelInput2.tsx +213 -0
  49. package/src/components/ContactForm/Textarea.tsx +48 -0
  50. package/src/components/ContactForm/Textarea2.tsx +89 -0
  51. package/src/components/ContactForm/countryDialCodes.ts +243 -0
  52. package/src/components/ContactForm/factory.tsx +60 -0
  53. package/src/components/ContactForm/funcs.ts +64 -0
  54. package/src/components/ContactForm/hooks/useInlineLabelPadding.ts +43 -0
  55. package/src/components/ContactForm/hooks/useTelControl.ts +81 -0
  56. package/src/components/ContactForm/index.ts +7 -0
  57. package/src/components/ContactForm/types.ts +68 -0
  58. package/src/components/Icon/index.tsx +20 -0
  59. package/src/components/Medias/MainMedia.tsx +257 -0
  60. package/src/components/Medias/Thumbnail.tsx +62 -0
  61. package/src/components/Medias/VideoPlayer.tsx +114 -0
  62. package/src/components/Medias/index.tsx +271 -0
  63. package/src/components/ProductCard/ProductCard.tsx +24 -0
  64. package/src/components/ProductCard/ProductCta/index.tsx +28 -0
  65. package/src/components/ProductCard/ProductCta/style.css +4 -0
  66. package/src/components/ProductCard/ProductDescription/index.tsx +13 -0
  67. package/src/components/ProductCard/ProductDescription/style.css +6 -0
  68. package/src/components/ProductCard/ProductMedia/index.tsx +35 -0
  69. package/src/components/ProductCard/ProductMedia/style.css +6 -0
  70. package/src/components/ProductCard/ProductTitle/index.tsx +7 -0
  71. package/src/components/ProductCard/ProductTitle/style.css +4 -0
  72. package/src/components/ProductCard/ProductView.tsx +36 -0
  73. package/src/components/ProductCard/index.ts +5 -0
  74. package/src/components/ProductCard/useQueryProduct.ts +32 -0
  75. package/src/components/ReactModalTrigger.tsx +28 -0
  76. package/src/components/ReactVideoPlayer.tsx +332 -0
  77. package/src/components/RichTextOutline/index.tsx +74 -0
  78. package/src/components/RichTextOutline/parseOutline.ts +63 -0
  79. package/src/components/RichTextOutline/useAcitviedHeading.ts +142 -0
  80. package/src/components/RichTextOutline/useAnchorScroll.ts +24 -0
  81. package/src/components/Scroller.tsx +39 -0
  82. package/src/components/SearchInput.tsx +21 -0
  83. package/src/components/Share/index.tsx +86 -0
  84. package/src/components/Share/socials.tsx +80 -0
  85. package/src/components/Share//350/265/204/346/226/231.md +7 -0
  86. package/src/components/ToTop.tsx +72 -0
  87. package/src/components/VideoPlayIcon.tsx +43 -0
  88. package/src/components/all.ts +25 -0
  89. package/src/components/index.ts +12 -0
  90. package/src/forms.ts +1 -0
  91. package/src/index.ts +1 -0
  92. package/src/media.ts +1 -0
  93. package/src/richtext.ts +1 -0
  94. package/src/types/view-model.ts +37 -0
  95. package/src/ui.ts +10 -0
  96. package/src/video.ts +2 -0
  97. package/ui.ts +1 -0
  98. package/video.ts +1 -0
  99. package/dist/style.css +0 -17
package/dist/media.mjs ADDED
@@ -0,0 +1,613 @@
1
+ import { j as jsxRuntimeExports } from "./jsx-runtime-c02cc059.js";
2
+ import clsx from "clsx";
3
+ import require$$0, { useRef, useState, useEffect, useCallback, forwardRef } from "react";
4
+ import { MediaType } from "@rxdrag/rxcms-models";
5
+ import Hls from "hls.js";
6
+ function VideoPlayer(props) {
7
+ var _a, _b;
8
+ const { media, size = "normal", playButtonClass } = props;
9
+ const videoRef = useRef(null);
10
+ const hlsRef = useRef(null);
11
+ const [isPlaying, setIsPlaying] = useState(false);
12
+ const handlePlayClick = require$$0.useCallback(
13
+ (e) => {
14
+ e.stopPropagation();
15
+ if (videoRef.current) {
16
+ if (isPlaying) {
17
+ videoRef.current.pause();
18
+ } else {
19
+ videoRef.current.play();
20
+ }
21
+ }
22
+ },
23
+ [isPlaying]
24
+ );
25
+ useEffect(() => {
26
+ var _a2;
27
+ if (!videoRef.current || !((_a2 = media.file) == null ? void 0 : _a2.original))
28
+ return;
29
+ const video = videoRef.current;
30
+ const videoUrl = media.file.original;
31
+ const handlePlay = () => {
32
+ setIsPlaying(true);
33
+ };
34
+ const handlePause = () => {
35
+ setIsPlaying(false);
36
+ };
37
+ video.addEventListener("play", handlePlay);
38
+ video.addEventListener("pause", handlePause);
39
+ if (media.storageType === "cloudflare_stream") {
40
+ if (!Hls.isSupported()) {
41
+ if (video.canPlayType("application/vnd.apple.mpegurl")) {
42
+ video.src = videoUrl;
43
+ }
44
+ } else {
45
+ const hls = new Hls({
46
+ enableWorker: true
47
+ });
48
+ hls.loadSource(videoUrl);
49
+ hls.attachMedia(video);
50
+ hlsRef.current = hls;
51
+ }
52
+ } else {
53
+ video.src = videoUrl;
54
+ }
55
+ return () => {
56
+ video.removeEventListener("play", handlePlay);
57
+ video.removeEventListener("pause", handlePause);
58
+ if (hlsRef.current) {
59
+ hlsRef.current.destroy();
60
+ hlsRef.current = null;
61
+ }
62
+ };
63
+ }, [(_a = media.file) == null ? void 0 : _a.original, media.storageType]);
64
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative w-full h-full group cursor-pointer", onClick: handlePlayClick, children: [
65
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
66
+ "video",
67
+ {
68
+ ref: videoRef,
69
+ preload: "metadata",
70
+ poster: (_b = media.file) == null ? void 0 : _b.thumbnail,
71
+ className: "absolute inset-0 w-full h-full object-cover",
72
+ controls: false,
73
+ playsInline: true
74
+ }
75
+ ),
76
+ !isPlaying && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 flex items-center justify-center z-10 bg-black/10 group-hover:bg-black/20 transition-colors", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
77
+ "div",
78
+ {
79
+ className: clsx(
80
+ "rounded-full bg-white/90 hover:bg-white flex items-center justify-center shadow-lg transition-all hover:scale-110 backdrop-blur-sm",
81
+ size === "small" ? "w-8 h-8" : "w-14 h-14",
82
+ playButtonClass
83
+ ),
84
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
85
+ "svg",
86
+ {
87
+ xmlns: "http://www.w3.org/2000/svg",
88
+ viewBox: "0 0 24 24",
89
+ fill: "currentColor",
90
+ className: clsx(
91
+ "text-gray-900 ml-1",
92
+ size === "small" ? "w-4 h-4" : "w-8 h-8"
93
+ ),
94
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
95
+ "path",
96
+ {
97
+ fillRule: "evenodd",
98
+ d: "M4.5 5.653c0-1.426 1.529-2.33 2.779-1.643l11.54 6.348c1.295.712 1.295 2.573 0 3.248L7.28 19.987C6.03 20.673 4.5 19.77 4.5 18.562V5.653z",
99
+ clipRule: "evenodd"
100
+ }
101
+ )
102
+ }
103
+ )
104
+ }
105
+ ) })
106
+ ] });
107
+ }
108
+ const MainMedia = ({
109
+ value,
110
+ selectedId,
111
+ aspect,
112
+ enableZoom,
113
+ className,
114
+ arrowButtonClass,
115
+ arrowIconClass,
116
+ playButtonClass,
117
+ onPrevious,
118
+ onNext,
119
+ canPrevious,
120
+ canNext
121
+ }) => {
122
+ const mainAreaRef = useRef(null);
123
+ const [isZoomed, setIsZoomed] = useState(false);
124
+ const [position, setPosition] = useState({ x: 0, y: 0 });
125
+ const hoverTimerRef = useRef(null);
126
+ const lastMousePosRef = useRef({ x: 0, y: 0 });
127
+ const selectedMedia = value == null ? void 0 : value.find((media) => media.id === selectedId);
128
+ const isVideo = (selectedMedia == null ? void 0 : selectedMedia.mediaType) === MediaType.video;
129
+ useEffect(() => {
130
+ setIsZoomed(false);
131
+ setPosition({ x: 0, y: 0 });
132
+ if (hoverTimerRef.current) {
133
+ clearTimeout(hoverTimerRef.current);
134
+ }
135
+ }, [selectedId]);
136
+ useEffect(() => {
137
+ return () => {
138
+ if (hoverTimerRef.current) {
139
+ clearTimeout(hoverTimerRef.current);
140
+ }
141
+ };
142
+ }, []);
143
+ const updateZoomPosition = useCallback((clientX, clientY) => {
144
+ if (mainAreaRef.current) {
145
+ const { left, top, width, height } = mainAreaRef.current.getBoundingClientRect();
146
+ const x = clientX - left;
147
+ const y = clientY - top;
148
+ const ratioX = Math.max(0, Math.min(1, x / width));
149
+ const ratioY = Math.max(0, Math.min(1, y / height));
150
+ const newX = width * (0.5 - ratioX);
151
+ const newY = height * (0.5 - ratioY);
152
+ setPosition({ x: newX, y: newY });
153
+ }
154
+ }, []);
155
+ const handleMouseEnter = useCallback(
156
+ (e) => {
157
+ if (!enableZoom || isVideo)
158
+ return;
159
+ lastMousePosRef.current = { x: e.clientX, y: e.clientY };
160
+ hoverTimerRef.current = setTimeout(() => {
161
+ setIsZoomed(true);
162
+ updateZoomPosition(
163
+ lastMousePosRef.current.x,
164
+ lastMousePosRef.current.y
165
+ );
166
+ }, 1e3);
167
+ },
168
+ [enableZoom, isVideo, updateZoomPosition]
169
+ );
170
+ const handleMouseMove = useCallback(
171
+ (e) => {
172
+ if (!enableZoom || isVideo)
173
+ return;
174
+ lastMousePosRef.current = { x: e.clientX, y: e.clientY };
175
+ if (isZoomed) {
176
+ updateZoomPosition(e.clientX, e.clientY);
177
+ }
178
+ },
179
+ [enableZoom, isVideo, isZoomed, updateZoomPosition]
180
+ );
181
+ const handleMouseLeave = useCallback(() => {
182
+ if (hoverTimerRef.current) {
183
+ clearTimeout(hoverTimerRef.current);
184
+ }
185
+ setIsZoomed(false);
186
+ setPosition({ x: 0, y: 0 });
187
+ }, []);
188
+ const handleClick = useCallback(
189
+ (e) => {
190
+ if (!enableZoom || isVideo)
191
+ return;
192
+ if (hoverTimerRef.current) {
193
+ clearTimeout(hoverTimerRef.current);
194
+ }
195
+ if (isZoomed) {
196
+ setIsZoomed(false);
197
+ setPosition({ x: 0, y: 0 });
198
+ } else {
199
+ setIsZoomed(true);
200
+ updateZoomPosition(e.clientX, e.clientY);
201
+ }
202
+ },
203
+ [enableZoom, isVideo, isZoomed, updateZoomPosition]
204
+ );
205
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
206
+ "div",
207
+ {
208
+ ref: mainAreaRef,
209
+ className: clsx(
210
+ "relative group overflow-hidden rounded-xl bg-gray-100 dark:bg-gray-800 z-0",
211
+ aspect,
212
+ className,
213
+ enableZoom && !isVideo && "cursor-crosshair"
214
+ ),
215
+ onMouseEnter: handleMouseEnter,
216
+ onMouseMove: handleMouseMove,
217
+ onMouseLeave: handleMouseLeave,
218
+ onClick: handleClick,
219
+ children: [
220
+ !isZoomed && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute inset-0 flex items-center justify-between p-4 pointer-events-none z-20", children: [
221
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
222
+ "button",
223
+ {
224
+ onClick: (e) => {
225
+ e.stopPropagation();
226
+ onPrevious();
227
+ },
228
+ disabled: !canPrevious,
229
+ className: clsx(
230
+ "pointer-events-auto transition-all duration-200 rounded-full p-2",
231
+ "bg-white/80 dark:bg-black/50 backdrop-blur-sm shadow-sm",
232
+ "hover:bg-white dark:hover:bg-black/70 hover:scale-105 active:scale-95",
233
+ "text-gray-800 dark:text-white",
234
+ !canPrevious ? "opacity-0 translate-x-[-10px]" : "opacity-0 group-hover:opacity-100 translate-x-0",
235
+ arrowButtonClass
236
+ ),
237
+ "aria-label": "Previous slide",
238
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
239
+ "svg",
240
+ {
241
+ xmlns: "http://www.w3.org/2000/svg",
242
+ className: clsx("h-5 w-5", arrowIconClass),
243
+ fill: "none",
244
+ viewBox: "0 0 24 24",
245
+ stroke: "currentColor",
246
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
247
+ "path",
248
+ {
249
+ strokeLinecap: "round",
250
+ strokeLinejoin: "round",
251
+ strokeWidth: 2,
252
+ d: "M15 19l-7-7 7-7"
253
+ }
254
+ )
255
+ }
256
+ )
257
+ }
258
+ ),
259
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
260
+ "button",
261
+ {
262
+ onClick: (e) => {
263
+ e.stopPropagation();
264
+ onNext();
265
+ },
266
+ disabled: !canNext,
267
+ className: clsx(
268
+ "pointer-events-auto transition-all duration-200 rounded-full p-2",
269
+ "bg-white/80 dark:bg-black/50 backdrop-blur-sm shadow-sm",
270
+ "hover:bg-white dark:hover:bg-black/70 hover:scale-105 active:scale-95",
271
+ "text-gray-800 dark:text-white",
272
+ !canNext ? "opacity-0 translate-x-[10px]" : "opacity-0 group-hover:opacity-100 translate-x-0",
273
+ arrowButtonClass
274
+ ),
275
+ "aria-label": "Next slide",
276
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
277
+ "svg",
278
+ {
279
+ xmlns: "http://www.w3.org/2000/svg",
280
+ className: clsx("h-5 w-5", arrowIconClass),
281
+ fill: "none",
282
+ viewBox: "0 0 24 24",
283
+ stroke: "currentColor",
284
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
285
+ "path",
286
+ {
287
+ strokeLinecap: "round",
288
+ strokeLinejoin: "round",
289
+ strokeWidth: 2,
290
+ d: "M9 5l7 7-7 7"
291
+ }
292
+ )
293
+ }
294
+ )
295
+ }
296
+ )
297
+ ] }),
298
+ value == null ? void 0 : value.map((media) => {
299
+ var _a, _b;
300
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
301
+ "div",
302
+ {
303
+ className: clsx(
304
+ "absolute inset-0 transition-opacity duration-500 ease-in-out",
305
+ media.id === selectedId ? "opacity-100 z-10" : "opacity-0 z-0 pointer-events-none"
306
+ ),
307
+ children: media.mediaType === MediaType.video ? /* @__PURE__ */ jsxRuntimeExports.jsx(VideoPlayer, { media, playButtonClass }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
308
+ "img",
309
+ {
310
+ src: ((_a = media == null ? void 0 : media.file) == null ? void 0 : _a.resize) || ((_b = media == null ? void 0 : media.file) == null ? void 0 : _b.url),
311
+ alt: media == null ? void 0 : media.alt,
312
+ className: "w-full h-full object-cover object-center origin-center",
313
+ style: {
314
+ transform: media.id === selectedId ? `translate(${position.x}px, ${position.y}px) scale(${isZoomed ? 2 : 1})` : void 0,
315
+ transition: isZoomed ? "none" : "transform 0.3s ease-out"
316
+ }
317
+ }
318
+ )
319
+ },
320
+ media.id
321
+ );
322
+ })
323
+ ]
324
+ }
325
+ );
326
+ };
327
+ const Thumbnail = ({
328
+ media,
329
+ isSelected,
330
+ onClick,
331
+ aspect,
332
+ className,
333
+ imageClass,
334
+ playButtonClass
335
+ }) => {
336
+ var _a, _b, _c;
337
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
338
+ "div",
339
+ {
340
+ className: clsx(
341
+ "relative cursor-pointer overflow-hidden rounded-lg transition-all duration-200",
342
+ aspect,
343
+ isSelected ? "ring-2 ring-primary ring-offset-2 ring-offset-white dark:ring-offset-gray-950" : "opacity-70 hover:opacity-100 hover:ring-2 hover:ring-gray-200 dark:hover:ring-gray-700",
344
+ className
345
+ ),
346
+ onClick,
347
+ children: media.mediaType === MediaType.video ? /* @__PURE__ */ jsxRuntimeExports.jsx(
348
+ "div",
349
+ {
350
+ className: clsx(
351
+ "w-full h-full relative pointer-events-none [&>div]:!aspect-auto [&>div]:!w-full [&>div]:!h-full transition-transform duration-500",
352
+ isSelected ? "scale-110" : "scale-100",
353
+ imageClass
354
+ ),
355
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(VideoPlayer, { media, size: "small", playButtonClass })
356
+ }
357
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
358
+ "img",
359
+ {
360
+ src: ((_a = media == null ? void 0 : media.file) == null ? void 0 : _a.thumbnail) || ((_b = media == null ? void 0 : media.file) == null ? void 0 : _b.resize) || ((_c = media == null ? void 0 : media.file) == null ? void 0 : _c.url),
361
+ alt: media == null ? void 0 : media.alt,
362
+ className: clsx(
363
+ "w-full h-full object-cover transition-transform duration-500",
364
+ isSelected ? "scale-110" : "scale-100",
365
+ imageClass
366
+ )
367
+ }
368
+ )
369
+ }
370
+ );
371
+ };
372
+ const Medias = forwardRef((props, ref) => {
373
+ var _a;
374
+ const {
375
+ value,
376
+ className,
377
+ children,
378
+ aspect = "aspect-[1/1]",
379
+ thumbnailAspect = "aspect-[1/1]",
380
+ enableZoom = true,
381
+ thumbnailPosition = "bottom",
382
+ visibleCount = 6,
383
+ classNames,
384
+ ...rest
385
+ } = props;
386
+ const {
387
+ mainArea,
388
+ navigation,
389
+ thumbnail,
390
+ thumbnailImage,
391
+ arrowButton,
392
+ arrowIcon,
393
+ playButton,
394
+ navigationInner
395
+ } = classNames || {};
396
+ const [selectedId, setSelectedId] = useState(
397
+ ((_a = value == null ? void 0 : value[0]) == null ? void 0 : _a.id) || ""
398
+ );
399
+ useEffect(() => {
400
+ var _a2;
401
+ setSelectedId(((_a2 = value == null ? void 0 : value[0]) == null ? void 0 : _a2.id) || "");
402
+ }, [value]);
403
+ const selectedIndex = (value == null ? void 0 : value.findIndex((media) => media.id === selectedId)) || 0;
404
+ const totalItems = (value == null ? void 0 : value.length) || 0;
405
+ const handlePrevious = useCallback(() => {
406
+ var _a2;
407
+ if (selectedIndex > 0) {
408
+ const prevIndex = selectedIndex - 1;
409
+ setSelectedId(((_a2 = value == null ? void 0 : value[prevIndex]) == null ? void 0 : _a2.id) || "");
410
+ }
411
+ }, [selectedIndex, value]);
412
+ const handleNext = useCallback(() => {
413
+ var _a2;
414
+ if (selectedIndex < totalItems - 1) {
415
+ const currentMediaIndex = (value == null ? void 0 : value.findIndex((media) => media.id === selectedId)) || 0;
416
+ const nextIndex = currentMediaIndex + 1;
417
+ setSelectedId(((_a2 = value == null ? void 0 : value[nextIndex]) == null ? void 0 : _a2.id) || "");
418
+ }
419
+ }, [selectedIndex, totalItems, value, selectedId]);
420
+ const handleKeyDown = useCallback(
421
+ (e) => {
422
+ if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
423
+ handlePrevious();
424
+ } else if (e.key === "ArrowRight" || e.key === "ArrowDown") {
425
+ handleNext();
426
+ }
427
+ },
428
+ [handleNext, handlePrevious]
429
+ );
430
+ useEffect(() => {
431
+ window.addEventListener("keydown", handleKeyDown);
432
+ return () => window.removeEventListener("keydown", handleKeyDown);
433
+ }, [handleKeyDown]);
434
+ const canPrevious = selectedIndex > 0;
435
+ const canNext = selectedIndex < totalItems - 1;
436
+ const isVerticalThumbs = thumbnailPosition === "left";
437
+ const actualVisibleCount = visibleCount;
438
+ const halfVisible = Math.floor(actualVisibleCount / 2);
439
+ const startIndex = Math.max(
440
+ 0,
441
+ Math.min(selectedIndex - halfVisible, totalItems - actualVisibleCount)
442
+ );
443
+ const endIndex = Math.min(startIndex + actualVisibleCount, totalItems);
444
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
445
+ "div",
446
+ {
447
+ ref,
448
+ className: clsx(
449
+ "flex gap-4",
450
+ isVerticalThumbs ? "flex-col md:flex-row-reverse" : "flex-col",
451
+ className
452
+ ),
453
+ ...rest,
454
+ children: [
455
+ children,
456
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
457
+ MainMedia,
458
+ {
459
+ value,
460
+ selectedId,
461
+ aspect,
462
+ enableZoom,
463
+ className: clsx(
464
+ isVerticalThumbs ? "w-full md:flex-1" : "w-full",
465
+ mainArea
466
+ ),
467
+ arrowButtonClass: arrowButton,
468
+ arrowIconClass: arrowIcon,
469
+ playButtonClass: playButton,
470
+ onPrevious: handlePrevious,
471
+ onNext: handleNext,
472
+ canPrevious,
473
+ canNext
474
+ }
475
+ ),
476
+ totalItems > 1 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
477
+ "div",
478
+ {
479
+ className: clsx(
480
+ "relative group/thumbs",
481
+ isVerticalThumbs ? "w-full mt-4 md:w-24 md:h-full md:px-1" : "w-full mt-4",
482
+ navigation
483
+ ),
484
+ children: [
485
+ totalItems > actualVisibleCount && /* @__PURE__ */ jsxRuntimeExports.jsx(
486
+ "button",
487
+ {
488
+ onClick: handlePrevious,
489
+ disabled: !canPrevious,
490
+ className: clsx(
491
+ "absolute z-10 w-8 h-8 flex items-center justify-center rounded-full",
492
+ "bg-white/60 dark:bg-black/50 shadow-sm backdrop-blur-sm",
493
+ "text-gray-700 dark:text-gray-200 transition-all duration-200",
494
+ isVerticalThumbs ? "left-2 top-1/2 -translate-y-1/2 md:top-2 md:left-1/2 md:-translate-x-1/2" : "left-2 top-1/2 -translate-y-1/2",
495
+ !canPrevious ? "opacity-0 pointer-events-none" : "opacity-0 group-hover/thumbs:opacity-100 hover:bg-white/90 dark:hover:bg-black/80",
496
+ arrowButton
497
+ ),
498
+ "aria-label": "Previous",
499
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
500
+ "svg",
501
+ {
502
+ xmlns: "http://www.w3.org/2000/svg",
503
+ className: clsx(
504
+ "h-4 w-4",
505
+ isVerticalThumbs && "md:rotate-90",
506
+ arrowIcon
507
+ ),
508
+ fill: "none",
509
+ viewBox: "0 0 24 24",
510
+ stroke: "currentColor",
511
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
512
+ "path",
513
+ {
514
+ strokeLinecap: "round",
515
+ strokeLinejoin: "round",
516
+ strokeWidth: 2,
517
+ d: "M15 19l-7-7 7-7"
518
+ }
519
+ )
520
+ }
521
+ )
522
+ }
523
+ ),
524
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
525
+ "div",
526
+ {
527
+ className: clsx(
528
+ "flex-1",
529
+ isVerticalThumbs ? "w-full px-0.5 md:h-full md:py-0.5" : "w-full px-0.5"
530
+ ),
531
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
532
+ "div",
533
+ {
534
+ className: clsx(
535
+ "gap-2 md:gap-3",
536
+ navigationInner,
537
+ isVerticalThumbs ? "grid md:flex md:flex-col" : "grid"
538
+ ),
539
+ style: {
540
+ gridTemplateColumns: `repeat(${actualVisibleCount}, minmax(0, 1fr))`
541
+ },
542
+ children: value == null ? void 0 : value.map((media, index) => {
543
+ if (index < startIndex || index >= endIndex)
544
+ return null;
545
+ const isSelected = selectedId === media.id;
546
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
547
+ Thumbnail,
548
+ {
549
+ media,
550
+ isSelected,
551
+ onClick: () => setSelectedId(media.id),
552
+ aspect: thumbnailAspect,
553
+ className: thumbnail,
554
+ imageClass: thumbnailImage,
555
+ playButtonClass: playButton
556
+ },
557
+ media.id
558
+ );
559
+ })
560
+ }
561
+ )
562
+ }
563
+ ),
564
+ totalItems > actualVisibleCount && /* @__PURE__ */ jsxRuntimeExports.jsx(
565
+ "button",
566
+ {
567
+ onClick: handleNext,
568
+ disabled: !canNext,
569
+ className: clsx(
570
+ "absolute z-10 w-8 h-8 flex items-center justify-center rounded-full",
571
+ "bg-white/60 dark:bg-black/50 shadow-sm backdrop-blur-sm",
572
+ "text-gray-700 dark:text-gray-200 transition-all duration-200",
573
+ isVerticalThumbs ? "right-2 top-1/2 -translate-y-1/2 md:bottom-2 md:left-1/2 md:-translate-x-1/2" : "right-2 top-1/2 -translate-y-1/2",
574
+ !canNext ? "opacity-0 pointer-events-none" : "opacity-0 group-hover/thumbs:opacity-100 hover:bg-white/90 dark:hover:bg-black/80",
575
+ arrowButton
576
+ ),
577
+ "aria-label": "Next",
578
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
579
+ "svg",
580
+ {
581
+ xmlns: "http://www.w3.org/2000/svg",
582
+ className: clsx(
583
+ "h-4 w-4",
584
+ isVerticalThumbs && "md:rotate-90",
585
+ arrowIcon
586
+ ),
587
+ fill: "none",
588
+ viewBox: "0 0 24 24",
589
+ stroke: "currentColor",
590
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
591
+ "path",
592
+ {
593
+ strokeLinecap: "round",
594
+ strokeLinejoin: "round",
595
+ strokeWidth: 2,
596
+ d: "M9 5l7 7-7 7"
597
+ }
598
+ )
599
+ }
600
+ )
601
+ }
602
+ )
603
+ ]
604
+ }
605
+ )
606
+ ]
607
+ }
608
+ );
609
+ });
610
+ export {
611
+ Medias
612
+ };
613
+ //# sourceMappingURL=media.mjs.map