@linktr.ee/messaging-react 1.32.1 → 1.33.0-rc-1777272812

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,292 +0,0 @@
1
- import { jsxs as T, jsx as n } from "react/jsx-runtime";
2
- import { FileIcon as _, ImageIcon as G, SpeakerHighIcon as Y, VideoCameraIcon as Z, FileMdIcon as J, FileTextIcon as Q, FileZipIcon as ee, FilePptIcon as te, FileCsvIcon as ne, FileXlsIcon as ae, FileDocIcon as ie, FilePdfIcon as re, CircleNotchIcon as oe, PlayIcon as H, PauseIcon as se } from "@phosphor-icons/react";
3
- import le, { useRef as P, useState as s, useCallback as F, useEffect as E } from "react";
4
- const ce = [
5
- [/pdf/, "pdf"],
6
- [/wordprocessingml|msword|\.doc/, "doc"],
7
- [/spreadsheetml|ms-excel|\.xls/, "xls"],
8
- [/csv/, "csv"],
9
- [/presentationml|ms-powerpoint|\.ppt/, "ppt"],
10
- [/zip|x-rar|x-7z|x-tar|x-gzip/, "zip"],
11
- [/plain|rtf/, "text"],
12
- [/markdown/, "markdown"]
13
- ];
14
- function $(a) {
15
- return a.startsWith("video/") ? "video" : a.startsWith("audio/") ? "audio" : a.startsWith("image/") ? "image" : "document";
16
- }
17
- function ue(a) {
18
- const i = ce.find(
19
- ([r]) => r.test(a)
20
- );
21
- return i ? i[1] : "generic";
22
- }
23
- const de = {
24
- video: Z,
25
- audio: Y,
26
- image: G,
27
- document: _
28
- }, fe = {
29
- pdf: re,
30
- doc: ie,
31
- xls: ae,
32
- csv: ne,
33
- ppt: te,
34
- zip: ee,
35
- text: Q,
36
- markdown: J,
37
- generic: _
38
- };
39
- function me(a) {
40
- const i = $(a);
41
- return i !== "document" ? de[i] : fe[ue(a)];
42
- }
43
- function he(a, i) {
44
- return le.createElement(me(a), i);
45
- }
46
- const pe = (a) => {
47
- var i, r;
48
- return "touches" in a ? ((i = a.touches[0]) == null ? void 0 : i.clientX) ?? ((r = a.changedTouches[0]) == null ? void 0 : r.clientX) ?? 0 : a.clientX;
49
- }, be = ({
50
- source: a,
51
- mimeType: i,
52
- poster: r,
53
- autoPlay: X = !1,
54
- playing: u,
55
- loop: y = !1,
56
- controls: v = !0,
57
- showProgress: q = !1,
58
- muted: z = !1
59
- }) => {
60
- const M = $(i), d = P(null), C = P(null), l = P(null), D = P(u), [f, o] = s(X), [w, g] = s(0), [m, R] = s(!1), [A, S] = s(!1), [x, k] = s(!1), [K, h] = s(!1), [j, O] = s(!0), [L, U] = s(null), W = F(() => {
61
- k(!1), o(!0);
62
- }, []), N = F((e) => {
63
- const t = C.current;
64
- if (!t) return 0;
65
- const p = t.getBoundingClientRect();
66
- return Math.max(
67
- 0,
68
- Math.min(1, (pe(e) - p.left) / p.width)
69
- );
70
- }, []), c = F((e) => {
71
- const t = d.current;
72
- t && t.duration && (t.currentTime = e * t.duration);
73
- }, []), I = (e) => {
74
- e.stopPropagation(), R(!0);
75
- const t = N(e);
76
- g(t), c(t);
77
- };
78
- E(() => {
79
- u !== void 0 && u !== D.current && (D.current = u, o(u));
80
- }, [u]), E(() => {
81
- if (!f) {
82
- l.current !== null && (cancelAnimationFrame(l.current), l.current = null);
83
- return;
84
- }
85
- const e = () => {
86
- const t = d.current;
87
- t && t.duration && !m && g(t.currentTime / t.duration), l.current = requestAnimationFrame(e);
88
- };
89
- return l.current = requestAnimationFrame(e), () => {
90
- l.current !== null && cancelAnimationFrame(l.current);
91
- };
92
- }, [f, m]), E(() => {
93
- const e = d.current;
94
- e && (f ? e.play().catch((t) => {
95
- o(!1), k(!0);
96
- }) : e.pause());
97
- }, [f]), E(() => {
98
- if (!m) return;
99
- const e = (p) => g(N(p)), t = (p) => {
100
- R(!1), c(N(p));
101
- };
102
- return window.addEventListener("mousemove", e), window.addEventListener("mouseup", t), window.addEventListener("touchmove", e, { passive: !0 }), window.addEventListener("touchend", t), () => {
103
- window.removeEventListener("mousemove", e), window.removeEventListener("mouseup", t), window.removeEventListener("touchmove", e), window.removeEventListener("touchend", t);
104
- };
105
- }, [m, N, c]);
106
- const V = L ? { aspectRatio: String(L) } : void 0, B = L ? "" : " aspect-video", b = Math.round(w * 100);
107
- return /* @__PURE__ */ T(
108
- "div",
109
- {
110
- role: "button",
111
- tabIndex: 0,
112
- className: `relative cursor-pointer overflow-hidden bg-black ${B}`,
113
- style: V,
114
- onClick: () => {
115
- x || v && o((e) => !e);
116
- },
117
- onKeyDown: (e) => {
118
- e.key !== "Enter" && e.key !== " " || (e.preventDefault(), !x && v && o((t) => !t));
119
- },
120
- children: [
121
- r && (M === "audio" || j) && /* @__PURE__ */ n(
122
- "img",
123
- {
124
- src: r,
125
- alt: "",
126
- className: "absolute inset-0 h-full w-full object-cover"
127
- }
128
- ),
129
- !r && (M === "audio" || j) && /* @__PURE__ */ n("div", { className: "absolute inset-0 flex items-center justify-center", children: he(i, {
130
- className: "size-12 text-black/20",
131
- weight: "regular"
132
- }) }),
133
- /* @__PURE__ */ n("div", { className: "absolute inset-0", children: M === "audio" ? /* @__PURE__ */ n(
134
- "audio",
135
- {
136
- ref: d,
137
- src: a,
138
- loop: y,
139
- muted: z,
140
- style: { width: "100%", height: "100%" },
141
- onLoadStart: () => h(!0),
142
- onCanPlay: () => {
143
- h(!1), O(!1);
144
- },
145
- onWaiting: () => h(!0),
146
- onPlay: () => k(!1),
147
- onEnded: () => {
148
- y || (o(!1), g(0));
149
- },
150
- children: /* @__PURE__ */ n("track", { kind: "captions" })
151
- }
152
- ) : /* @__PURE__ */ n(
153
- "video",
154
- {
155
- ref: d,
156
- src: a,
157
- loop: y,
158
- muted: z,
159
- playsInline: !0,
160
- style: { width: "100%", height: "100%" },
161
- onLoadStart: () => h(!0),
162
- onCanPlay: () => {
163
- h(!1), O(!1);
164
- },
165
- onWaiting: () => h(!0),
166
- onPlay: () => k(!1),
167
- onLoadedMetadata: () => {
168
- const e = d.current;
169
- e instanceof HTMLVideoElement && e.videoWidth && e.videoHeight && U(e.videoWidth / e.videoHeight);
170
- },
171
- onEnded: () => {
172
- y || (o(!1), g(0));
173
- },
174
- children: /* @__PURE__ */ n("track", { kind: "captions" })
175
- }
176
- ) }),
177
- K && !x && /* @__PURE__ */ n("div", { className: "absolute inset-0 z-10 flex items-center justify-center", children: /* @__PURE__ */ n(
178
- oe,
179
- {
180
- className: "size-8 animate-spin text-white/80",
181
- weight: "bold"
182
- }
183
- ) }),
184
- x && !v && /* @__PURE__ */ n(
185
- "div",
186
- {
187
- className: "absolute inset-0 z-30 flex cursor-pointer items-center justify-center bg-black/35",
188
- role: "button",
189
- tabIndex: 0,
190
- "aria-label": "Play preview",
191
- onClick: (e) => {
192
- e.stopPropagation(), W();
193
- },
194
- onKeyDown: (e) => {
195
- e.key !== "Enter" && e.key !== " " || (e.preventDefault(), e.stopPropagation(), W());
196
- },
197
- children: /* @__PURE__ */ n("span", { className: "flex size-16 items-center justify-center rounded-full bg-white/20 text-white backdrop-blur-sm", children: /* @__PURE__ */ n(H, { className: "size-9 translate-x-0.5", weight: "fill" }) })
198
- }
199
- ),
200
- q && !v && /* @__PURE__ */ n("div", { className: "absolute inset-x-0 bottom-0 px-3 pb-2.5 pt-6 bg-gradient-to-t from-black/40 to-transparent", children: /* @__PURE__ */ n(
201
- "div",
202
- {
203
- role: "slider",
204
- "aria-label": "Playback position",
205
- "aria-valuenow": b,
206
- "aria-valuemin": 0,
207
- "aria-valuemax": 100,
208
- tabIndex: 0,
209
- ref: C,
210
- className: "relative flex h-4 w-full cursor-pointer items-center",
211
- onMouseDown: I,
212
- onTouchStart: I,
213
- onClick: (e) => e.stopPropagation(),
214
- onKeyDown: (e) => {
215
- e.key === "ArrowRight" && c(Math.min(1, w + 0.05)), e.key === "ArrowLeft" && c(Math.max(0, w - 0.05));
216
- },
217
- children: /* @__PURE__ */ n("div", { className: "w-full overflow-hidden rounded-full bg-white/30 h-1", children: /* @__PURE__ */ n(
218
- "div",
219
- {
220
- className: "h-full rounded-full bg-white",
221
- style: { width: `${b}%` }
222
- }
223
- ) })
224
- }
225
- ) }),
226
- v && /* @__PURE__ */ T("div", { className: "absolute inset-x-0 bottom-0 flex items-center gap-2 bg-gradient-to-t from-black/60 to-transparent px-3 pb-2.5 pt-6 transition-all duration-200", children: [
227
- /* @__PURE__ */ n(
228
- "button",
229
- {
230
- type: "button",
231
- onClick: (e) => {
232
- e.stopPropagation(), o((t) => !t);
233
- },
234
- className: "shrink-0 text-white",
235
- "aria-label": f ? "Pause" : "Play",
236
- children: f ? /* @__PURE__ */ n(se, { className: "size-5", weight: "fill" }) : /* @__PURE__ */ n(H, { className: "size-5 translate-x-px", weight: "fill" })
237
- }
238
- ),
239
- /* @__PURE__ */ T(
240
- "div",
241
- {
242
- role: "slider",
243
- "aria-label": "Playback position",
244
- "aria-valuenow": b,
245
- "aria-valuemin": 0,
246
- "aria-valuemax": 100,
247
- tabIndex: 0,
248
- ref: C,
249
- className: "relative flex h-4 w-full cursor-pointer items-center",
250
- onMouseDown: I,
251
- onTouchStart: I,
252
- onClick: (e) => e.stopPropagation(),
253
- onMouseEnter: () => S(!0),
254
- onMouseLeave: () => S(!1),
255
- onKeyDown: (e) => {
256
- e.key === "ArrowRight" && c(Math.min(1, w + 0.05)), e.key === "ArrowLeft" && c(Math.max(0, w - 0.05));
257
- },
258
- children: [
259
- /* @__PURE__ */ n(
260
- "div",
261
- {
262
- className: `w-full overflow-hidden rounded-full bg-white/30 transition-all duration-200 ${A || m ? "h-1.5" : "h-1"}`,
263
- children: /* @__PURE__ */ n(
264
- "div",
265
- {
266
- className: "h-full rounded-full bg-white",
267
- style: { width: `${b}%` }
268
- }
269
- )
270
- }
271
- ),
272
- /* @__PURE__ */ n(
273
- "div",
274
- {
275
- className: `absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${A || m ? "scale-100 opacity-100" : "scale-0 opacity-0"}`,
276
- style: { left: `${b}%` }
277
- }
278
- )
279
- ]
280
- }
281
- )
282
- ] })
283
- ]
284
- }
285
- );
286
- };
287
- export {
288
- be as M,
289
- $ as g,
290
- he as r
291
- };
292
- //# sourceMappingURL=MediaPlayer-B9Ws2NeE.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MediaPlayer-B9Ws2NeE.js","sources":["../src/components/LockedAttachment/utils/mimeType.ts","../src/components/LockedAttachment/utils/icons.ts","../src/components/LockedAttachment/components/MediaPlayer.tsx"],"sourcesContent":["export type AttachmentSourceType = 'image' | 'audio' | 'video' | 'document'\n\nexport type DocumentIconType =\n | 'pdf'\n | 'doc'\n | 'xls'\n | 'csv'\n | 'ppt'\n | 'zip'\n | 'text'\n | 'markdown'\n | 'generic'\n\nconst DOCUMENT_ICON_PATTERNS: Array<[RegExp, DocumentIconType]> = [\n [/pdf/, 'pdf'],\n [/wordprocessingml|msword|\\.doc/, 'doc'],\n [/spreadsheetml|ms-excel|\\.xls/, 'xls'],\n [/csv/, 'csv'],\n [/presentationml|ms-powerpoint|\\.ppt/, 'ppt'],\n [/zip|x-rar|x-7z|x-tar|x-gzip/, 'zip'],\n [/plain|rtf/, 'text'],\n [/markdown/, 'markdown'],\n]\n\nexport function getSourceType(mimeType: string): AttachmentSourceType {\n if (mimeType.startsWith('video/')) return 'video'\n if (mimeType.startsWith('audio/')) return 'audio'\n if (mimeType.startsWith('image/')) return 'image'\n return 'document'\n}\n\nexport function getDocumentIconType(mimeType: string): DocumentIconType {\n const match = DOCUMENT_ICON_PATTERNS.find(([pattern]) =>\n pattern.test(mimeType)\n )\n return match ? match[1] : 'generic'\n}\n","import {\n FileIcon,\n FileCsvIcon,\n FileDocIcon,\n FileMdIcon,\n FilePdfIcon,\n FilePptIcon,\n FileTextIcon,\n FileXlsIcon,\n FileZipIcon,\n ImageIcon,\n SpeakerHighIcon,\n VideoCameraIcon,\n IconProps,\n} from '@phosphor-icons/react'\nimport React from 'react'\n\nimport { getDocumentIconType, getSourceType } from './mimeType'\nimport type { AttachmentSourceType } from './mimeType'\n\nexport const MEDIA_TYPE_ICON: Record<AttachmentSourceType, React.ElementType> =\n {\n video: VideoCameraIcon,\n audio: SpeakerHighIcon,\n image: ImageIcon,\n document: FileIcon,\n }\n\nconst DOCUMENT_ICON_COMPONENT = {\n pdf: FilePdfIcon,\n doc: FileDocIcon,\n xls: FileXlsIcon,\n csv: FileCsvIcon,\n ppt: FilePptIcon,\n zip: FileZipIcon,\n text: FileTextIcon,\n markdown: FileMdIcon,\n generic: FileIcon,\n} as const\n\nexport function getTypeIcon(mimeType: string): React.ElementType {\n const sourceType = getSourceType(mimeType)\n if (sourceType !== 'document') return MEDIA_TYPE_ICON[sourceType]\n return DOCUMENT_ICON_COMPONENT[getDocumentIconType(mimeType)]\n}\n\n/** Use instead of `<TypeIcon />` where TypeIcon = getTypeIcon(mime) to satisfy react-hooks/static-components. */\nexport function renderTypeIcon(\n mimeType: string,\n props: IconProps\n): React.ReactElement {\n return React.createElement(getTypeIcon(mimeType), props)\n}\n","import { CircleNotchIcon, PauseIcon, PlayIcon } from '@phosphor-icons/react'\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { isDevBuild } from '../../../utils/isDevBuild'\nimport { renderTypeIcon } from '../utils/icons'\nimport { getSourceType } from '../utils/mimeType'\n\ntype TouchEventUnion =\n | MouseEvent\n | TouchEvent\n | React.MouseEvent\n | React.TouchEvent\n\n\nconst getClientXFromEvent = (e: TouchEventUnion): number => {\n if ('touches' in e) {\n return e.touches[0]?.clientX ?? e.changedTouches[0]?.clientX ?? 0\n }\n return e.clientX\n}\n\nexport interface MediaPlayerProps {\n source: string\n mimeType: string\n poster?: string\n autoPlay?: boolean\n /** Controlled playing state. When provided, syncs to internal play/pause. */\n playing?: boolean\n loop?: boolean\n controls?: boolean\n showProgress?: boolean\n /** When true, requests muted playback (helps autoplay policies on video). */\n muted?: boolean\n}\n\nconst MediaPlayer: React.FC<MediaPlayerProps> = ({\n source,\n mimeType,\n poster,\n autoPlay = false,\n playing: playingProp,\n loop = false,\n controls = true,\n showProgress = false,\n muted = false,\n}) => {\n // --- Derived ---\n const sourceType = getSourceType(mimeType)\n\n // --- Refs ---\n const playerRef = useRef<HTMLMediaElement>(null)\n const trackRef = useRef<HTMLDivElement>(null)\n const rafRef = useRef<number | null>(null)\n const prevPlayingPropRef = useRef(playingProp)\n\n // --- State: playback ---\n const [playing, setPlaying] = useState(autoPlay)\n const [played, setPlayed] = useState(0)\n const [seeking, setSeeking] = useState(false)\n\n // --- State: UI ---\n const [scrubberHovered, setScrubberHovered] = useState(false)\n /** Set when autoplay/play() was rejected so user can start via gesture (no controls UI). */\n const [manualPlayRequired, setManualPlayRequired] = useState(false)\n\n // --- State: loading ---\n const [buffering, setBuffering] = useState(false)\n /** True until the first canPlay fires for the current source — hides controls/spinner behind poster. */\n const [initialLoad, setInitialLoad] = useState(true)\n const [videoAspect, setVideoAspect] = useState<number | null>(null)\n\n // --- Callbacks ---\n const startPlaybackFromGesture = useCallback(() => {\n setManualPlayRequired(false)\n setPlaying(true)\n }, [])\n\n const getFraction = useCallback((e: TouchEventUnion) => {\n const track = trackRef.current\n if (!track) return 0\n const rect = track.getBoundingClientRect()\n return Math.max(\n 0,\n Math.min(1, (getClientXFromEvent(e) - rect.left) / rect.width)\n )\n }, [])\n\n const seekTo = useCallback((fraction: number) => {\n const el = playerRef.current\n if (el && el.duration) el.currentTime = fraction * el.duration\n }, [])\n\n const handleTrackPointerDown = (\n e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>\n ) => {\n e.stopPropagation()\n setSeeking(true)\n const fraction = getFraction(e)\n setPlayed(fraction)\n seekTo(fraction)\n }\n\n // --- Effects ---\n\n // Sync controlled playing prop to internal state\n useEffect(() => {\n if (\n playingProp !== undefined &&\n playingProp !== prevPlayingPropRef.current\n ) {\n prevPlayingPropRef.current = playingProp\n setPlaying(playingProp)\n }\n }, [playingProp])\n\n // RAF-driven progress updates\n useEffect(() => {\n if (!playing) {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n return\n }\n const tick = () => {\n const el = playerRef.current\n if (el && el.duration && !seeking) setPlayed(el.currentTime / el.duration)\n rafRef.current = requestAnimationFrame(tick)\n }\n rafRef.current = requestAnimationFrame(tick)\n return () => {\n if (rafRef.current !== null) cancelAnimationFrame(rafRef.current)\n }\n }, [playing, seeking])\n\n // ReactPlayer v3 uses native HTML media elements and does not support a\n // declarative `playing` prop — playback must be driven imperatively.\n useEffect(() => {\n const el = playerRef.current\n if (!el) return\n if (playing) {\n void el.play().catch((err) => {\n setPlaying(false)\n setManualPlayRequired(true)\n if (isDevBuild()) {\n console.debug('[MediaPlayer] play() failed', err)\n }\n })\n } else {\n el.pause()\n }\n }, [playing])\n\n // Global seeking listeners\n useEffect(() => {\n if (!seeking) return\n const onMove = (e: MouseEvent | TouchEvent) => setPlayed(getFraction(e))\n const onUp = (e: MouseEvent | TouchEvent) => {\n setSeeking(false)\n seekTo(getFraction(e))\n }\n window.addEventListener('mousemove', onMove)\n window.addEventListener('mouseup', onUp)\n window.addEventListener('touchmove', onMove, { passive: true })\n window.addEventListener('touchend', onUp)\n return () => {\n window.removeEventListener('mousemove', onMove)\n window.removeEventListener('mouseup', onUp)\n window.removeEventListener('touchmove', onMove)\n window.removeEventListener('touchend', onUp)\n }\n }, [seeking, getFraction, seekTo])\n\n // --- Derived render values ---\n // Use natural aspect ratio once metadata loads, fall back to 16:9 before then.\n const aspectStyle = videoAspect\n ? { aspectRatio: String(videoAspect) }\n : undefined\n const aspectClass = !videoAspect ? ' aspect-video' : ''\n const scrubberPercent = Math.round(played * 100)\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n className={`relative cursor-pointer overflow-hidden bg-black ${aspectClass}`}\n style={aspectStyle}\n onClick={() => {\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n >\n {/* For audio, poster persists as a visual background. For video, hide once loaded. */}\n {poster && (sourceType === 'audio' || initialLoad) && (\n <img\n src={poster}\n alt=\"\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n )}\n {!poster && (sourceType === 'audio' || initialLoad) && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <div className=\"absolute inset-0\">\n {sourceType === 'audio' ? (\n <audio\n ref={playerRef as React.RefObject<HTMLAudioElement>}\n src={source}\n loop={loop}\n muted={muted}\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </audio>\n ) : (\n <video\n ref={playerRef as React.RefObject<HTMLVideoElement>}\n src={source}\n loop={loop}\n muted={muted}\n playsInline\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onLoadedMetadata={() => {\n const el = playerRef.current\n if (\n el instanceof HTMLVideoElement &&\n el.videoWidth &&\n el.videoHeight\n ) {\n setVideoAspect(el.videoWidth / el.videoHeight)\n }\n }}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </video>\n )}\n </div>\n\n {buffering && !manualPlayRequired && (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center\">\n <CircleNotchIcon\n className=\"size-8 animate-spin text-white/80\"\n weight=\"bold\"\n />\n </div>\n )}\n\n {manualPlayRequired && !controls && (\n <div\n className=\"absolute inset-0 z-30 flex cursor-pointer items-center justify-center bg-black/35\"\n role=\"button\"\n tabIndex={0}\n aria-label=\"Play preview\"\n onClick={(e) => {\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n >\n <span className=\"flex size-16 items-center justify-center rounded-full bg-white/20 text-white backdrop-blur-sm\">\n <PlayIcon className=\"size-9 translate-x-0.5\" weight=\"fill\" />\n </span>\n </div>\n )}\n\n {showProgress && !controls && (\n <div className=\"absolute inset-x-0 bottom-0 px-3 pb-2.5 pt-6 bg-gradient-to-t from-black/40 to-transparent\">\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => {\n if (e.key === 'ArrowRight') seekTo(Math.min(1, played + 0.05))\n if (e.key === 'ArrowLeft') seekTo(Math.max(0, played - 0.05))\n }}\n >\n <div className=\"w-full overflow-hidden rounded-full bg-white/30 h-1\">\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n </div>\n )}\n\n {controls && (\n <div className=\"absolute inset-x-0 bottom-0 flex items-center gap-2 bg-gradient-to-t from-black/60 to-transparent px-3 pb-2.5 pt-6 transition-all duration-200\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n setPlaying((p) => !p)\n }}\n className=\"shrink-0 text-white\"\n aria-label={playing ? 'Pause' : 'Play'}\n >\n {playing ? (\n <PauseIcon className=\"size-5\" weight=\"fill\" />\n ) : (\n <PlayIcon className=\"size-5 translate-x-px\" weight=\"fill\" />\n )}\n </button>\n\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onMouseEnter={() => setScrubberHovered(true)}\n onMouseLeave={() => setScrubberHovered(false)}\n onKeyDown={(e) => {\n if (e.key === 'ArrowRight') seekTo(Math.min(1, played + 0.05))\n if (e.key === 'ArrowLeft') seekTo(Math.max(0, played - 0.05))\n }}\n >\n <div\n className={`w-full overflow-hidden rounded-full bg-white/30 transition-all duration-200 ${scrubberHovered || seeking ? 'h-1.5' : 'h-1'}`}\n >\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n <div\n className={`absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${scrubberHovered || seeking ? 'scale-100 opacity-100' : 'scale-0 opacity-0'}`}\n style={{ left: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default MediaPlayer\n"],"names":["DOCUMENT_ICON_PATTERNS","getSourceType","mimeType","getDocumentIconType","match","pattern","MEDIA_TYPE_ICON","VideoCameraIcon","SpeakerHighIcon","ImageIcon","FileIcon","DOCUMENT_ICON_COMPONENT","FilePdfIcon","FileDocIcon","FileXlsIcon","FileCsvIcon","FilePptIcon","FileZipIcon","FileTextIcon","FileMdIcon","getTypeIcon","sourceType","renderTypeIcon","props","React","getClientXFromEvent","e","_a","_b","MediaPlayer","source","poster","autoPlay","playingProp","loop","controls","showProgress","muted","playerRef","useRef","trackRef","rafRef","prevPlayingPropRef","playing","setPlaying","useState","played","setPlayed","seeking","setSeeking","scrubberHovered","setScrubberHovered","manualPlayRequired","setManualPlayRequired","buffering","setBuffering","initialLoad","setInitialLoad","videoAspect","setVideoAspect","startPlaybackFromGesture","useCallback","getFraction","track","rect","seekTo","fraction","el","handleTrackPointerDown","useEffect","tick","err","onMove","onUp","aspectStyle","aspectClass","scrubberPercent","jsxs","p","jsx","CircleNotchIcon","PlayIcon","PauseIcon"],"mappings":"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"}