@hopeplayer/core 1.4.0 → 1.6.0
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.
- package/dist/HopePlayerElement.d.ts +42 -2
- package/dist/HopePlayerElement.d.ts.map +1 -1
- package/dist/chunks/NativeEme-CXosVcw8.js +80 -0
- package/dist/chunks/NativeEme-CXosVcw8.js.map +1 -0
- package/dist/chunks/{accessibility-DeUIoAda.js → accessibility-DFx4CE0H.js} +9 -8
- package/dist/chunks/{accessibility-DeUIoAda.js.map → accessibility-DFx4CE0H.js.map} +1 -1
- package/dist/chunks/adTriggers-BIAWe8o4.js +419 -0
- package/dist/chunks/adTriggers-BIAWe8o4.js.map +1 -0
- package/dist/chunks/{ads-CdWbE9aD.js → ads-DlpHPpR9.js} +3 -3
- package/dist/chunks/ads-DlpHPpR9.js.map +1 -0
- package/dist/chunks/analytics-DEjTAJO9.js +281 -0
- package/dist/chunks/analytics-DEjTAJO9.js.map +1 -0
- package/dist/chunks/{cast-BQ-suTcF.js → cast-vHyi7oV_.js} +2 -2
- package/dist/chunks/{cast-BQ-suTcF.js.map → cast-vHyi7oV_.js.map} +1 -1
- package/dist/chunks/dash-CWjy-y7B.js +22 -0
- package/dist/chunks/dash-CWjy-y7B.js.map +1 -0
- package/dist/chunks/docPip-wybMVP1H.js +82 -0
- package/dist/chunks/docPip-wybMVP1H.js.map +1 -0
- package/dist/chunks/heatmap-Bb7neaYU.js +92 -0
- package/dist/chunks/heatmap-Bb7neaYU.js.map +1 -0
- package/dist/chunks/{history-DAbqEhNB.js → history-CwqLXiZi.js} +2 -2
- package/dist/chunks/{history-DAbqEhNB.js.map → history-CwqLXiZi.js.map} +1 -1
- package/dist/chunks/interactive-CgltIneu.js +189 -0
- package/dist/chunks/interactive-CgltIneu.js.map +1 -0
- package/dist/chunks/keySystems-CNzjRq6e.js +70 -0
- package/dist/chunks/keySystems-CNzjRq6e.js.map +1 -0
- package/dist/chunks/{loopSection-CvF4l5uf.js → loopSection-Bwk4W8vz.js} +16 -16
- package/dist/chunks/loopSection-Bwk4W8vz.js.map +1 -0
- package/dist/chunks/{markers-B04NMI79.js → markers-L69W3kj6.js} +53 -51
- package/dist/chunks/markers-L69W3kj6.js.map +1 -0
- package/dist/chunks/player-D2_HRzot.js +4351 -0
- package/dist/chunks/player-D2_HRzot.js.map +1 -0
- package/dist/chunks/{playlist-C6Mh9BE8.js → playlist-CHfStNbQ.js} +29 -21
- package/dist/chunks/playlist-CHfStNbQ.js.map +1 -0
- package/dist/chunks/plugin-style-CPJELe-i.js +17 -0
- package/dist/chunks/plugin-style-CPJELe-i.js.map +1 -0
- package/dist/chunks/pluginHost-cN2uGFeG.js +566 -0
- package/dist/chunks/pluginHost-cN2uGFeG.js.map +1 -0
- package/dist/chunks/redirectScreen-TIqLdvBY.js +239 -0
- package/dist/chunks/redirectScreen-TIqLdvBY.js.map +1 -0
- package/dist/chunks/{rewardedUnlock-CGhQyWOk.js → rewardedUnlock-DUqYwXTr.js} +2 -2
- package/dist/chunks/{rewardedUnlock-CGhQyWOk.js.map → rewardedUnlock-DUqYwXTr.js.map} +1 -1
- package/dist/chunks/segments-Ds-c1b5e.js +66 -0
- package/dist/chunks/segments-Ds-c1b5e.js.map +1 -0
- package/dist/chunks/{skipSegments-BbWzPpXz.js → skipSegments-ByNoF1qZ.js} +2 -2
- package/dist/chunks/{skipSegments-BbWzPpXz.js.map → skipSegments-ByNoF1qZ.js.map} +1 -1
- package/dist/chunks/{spriteThumbnails-B7oDZFTo.js → spriteThumbnails-Cr9UmkM9.js} +74 -51
- package/dist/chunks/spriteThumbnails-Cr9UmkM9.js.map +1 -0
- package/dist/chunks/{statsPanel-DSClIwA3.js → statsPanel-D0DtoFgS.js} +2 -2
- package/dist/chunks/statsPanel-D0DtoFgS.js.map +1 -0
- package/dist/chunks/{sticky-D_eLCNFk.js → sticky-BDStzjBM.js} +27 -26
- package/dist/chunks/sticky-BDStzjBM.js.map +1 -0
- package/dist/chunks/{story-BLBij82f.js → story-CodA2dfn.js} +2 -2
- package/dist/chunks/{story-BLBij82f.js.map → story-CodA2dfn.js.map} +1 -1
- package/dist/chunks/transcript-LG7E9UYE.js +186 -0
- package/dist/chunks/transcript-LG7E9UYE.js.map +1 -0
- package/dist/controls/ContextMenu.d.ts +1 -0
- package/dist/controls/ContextMenu.d.ts.map +1 -1
- package/dist/controls/ControlBar.d.ts +6 -0
- package/dist/controls/ControlBar.d.ts.map +1 -1
- package/dist/controls/SeekBar.d.ts +5 -2
- package/dist/controls/SeekBar.d.ts.map +1 -1
- package/dist/controls/SettingsMenu.d.ts +2 -1
- package/dist/controls/SettingsMenu.d.ts.map +1 -1
- package/dist/drm/NativeEme.d.ts +23 -0
- package/dist/drm/NativeEme.d.ts.map +1 -0
- package/dist/drm/keySystems.d.ts +18 -0
- package/dist/drm/keySystems.d.ts.map +1 -0
- package/dist/hls/SourceManager.d.ts +31 -5
- package/dist/hls/SourceManager.d.ts.map +1 -1
- package/dist/hls/dashEngine.d.ts +85 -0
- package/dist/hls/dashEngine.d.ts.map +1 -0
- package/dist/hls/sourceGroups.d.ts.map +1 -1
- package/dist/hope-player.js +1 -1
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/types.d.ts +28 -0
- package/dist/i18n/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/keyboard/KeyboardController.d.ts +14 -0
- package/dist/keyboard/KeyboardController.d.ts.map +1 -1
- package/dist/plugin-api/PluginAds.d.ts +61 -0
- package/dist/plugin-api/PluginAds.d.ts.map +1 -0
- package/dist/plugin-api/PluginHost.d.ts +6 -0
- package/dist/plugin-api/PluginHost.d.ts.map +1 -1
- package/dist/plugin-api/types.d.ts +39 -0
- package/dist/plugin-api/types.d.ts.map +1 -1
- package/dist/plugins/accessibility/Accessibility.d.ts.map +1 -1
- package/dist/plugins/ad-triggers/AdTriggers.d.ts +5 -0
- package/dist/plugins/ad-triggers/AdTriggers.d.ts.map +1 -1
- package/dist/plugins/ads/AdsController.d.ts +2 -0
- package/dist/plugins/ads/AdsController.d.ts.map +1 -1
- package/dist/plugins/analytics/QoeTracker.d.ts +71 -0
- package/dist/plugins/analytics/QoeTracker.d.ts.map +1 -0
- package/dist/plugins/analytics/index.d.ts +6 -0
- package/dist/plugins/analytics/index.d.ts.map +1 -0
- package/dist/plugins/doc-pip/DocumentPip.d.ts +44 -0
- package/dist/plugins/doc-pip/DocumentPip.d.ts.map +1 -0
- package/dist/plugins/doc-pip/index.d.ts +5 -0
- package/dist/plugins/doc-pip/index.d.ts.map +1 -0
- package/dist/plugins/heatmap/Heatmap.d.ts +36 -0
- package/dist/plugins/heatmap/Heatmap.d.ts.map +1 -0
- package/dist/plugins/heatmap/index.d.ts +6 -0
- package/dist/plugins/heatmap/index.d.ts.map +1 -0
- package/dist/plugins/interactive/Interactive.d.ts +45 -0
- package/dist/plugins/interactive/Interactive.d.ts.map +1 -0
- package/dist/plugins/interactive/index.d.ts +6 -0
- package/dist/plugins/interactive/index.d.ts.map +1 -0
- package/dist/plugins/markers/MarkProgress.d.ts +3 -1
- package/dist/plugins/markers/MarkProgress.d.ts.map +1 -1
- package/dist/plugins/playlist/PlaylistRunner.d.ts +2 -0
- package/dist/plugins/playlist/PlaylistRunner.d.ts.map +1 -1
- package/dist/plugins/redirect-screen/RedirectScreen.d.ts +3 -1
- package/dist/plugins/redirect-screen/RedirectScreen.d.ts.map +1 -1
- package/dist/plugins/segments/Segments.d.ts +1 -0
- package/dist/plugins/segments/Segments.d.ts.map +1 -1
- package/dist/plugins/sprite-thumbnails/SpriteThumbnails.d.ts +9 -0
- package/dist/plugins/sprite-thumbnails/SpriteThumbnails.d.ts.map +1 -1
- package/dist/plugins/sticky/StickyManager.d.ts +2 -0
- package/dist/plugins/sticky/StickyManager.d.ts.map +1 -1
- package/dist/plugins/transcript/Transcript.d.ts +65 -0
- package/dist/plugins/transcript/Transcript.d.ts.map +1 -0
- package/dist/plugins/transcript/index.d.ts +6 -0
- package/dist/plugins/transcript/index.d.ts.map +1 -0
- package/dist/screens/ErrorScreen.d.ts +1 -1
- package/dist/screens/ErrorScreen.d.ts.map +1 -1
- package/dist/subtitles/attachTracks.d.ts +6 -0
- package/dist/subtitles/attachTracks.d.ts.map +1 -1
- package/dist/types/index.d.ts +320 -16
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/plugin-style.d.ts +5 -0
- package/dist/utils/plugin-style.d.ts.map +1 -0
- package/package.json +2 -1
- package/dist/chunks/adTriggers-DXmtF4t2.js +0 -410
- package/dist/chunks/adTriggers-DXmtF4t2.js.map +0 -1
- package/dist/chunks/ads-CdWbE9aD.js.map +0 -1
- package/dist/chunks/loopSection-CvF4l5uf.js.map +0 -1
- package/dist/chunks/markers-B04NMI79.js.map +0 -1
- package/dist/chunks/player-D7WQxMzr.js +0 -3894
- package/dist/chunks/player-D7WQxMzr.js.map +0 -1
- package/dist/chunks/playlist-C6Mh9BE8.js.map +0 -1
- package/dist/chunks/pluginHost-DjvLmMYZ.js +0 -376
- package/dist/chunks/pluginHost-DjvLmMYZ.js.map +0 -1
- package/dist/chunks/redirectScreen-5HAVRtxe.js +0 -208
- package/dist/chunks/redirectScreen-5HAVRtxe.js.map +0 -1
- package/dist/chunks/segments-gCPrWRig.js +0 -63
- package/dist/chunks/segments-gCPrWRig.js.map +0 -1
- package/dist/chunks/spriteThumbnails-B7oDZFTo.js.map +0 -1
- package/dist/chunks/statsPanel-DSClIwA3.js.map +0 -1
- package/dist/chunks/sticky-D_eLCNFk.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spriteThumbnails-Cr9UmkM9.js","sources":["../../src/plugins/sprite-thumbnails/SpriteThumbnails.ts","../../src/plugins/sprite-thumbnails/index.ts"],"sourcesContent":["import type { SpriteThumbnailsOptions } from '../../types';\nimport { formatTime } from '../../utils/format-time';\n\nexport interface SpriteThumbnailsPlayerContext {\n videoEl: HTMLVideoElement;\n /** Önizlemenin bağlandığı seek bar — zaman eşlemesi (chapter boşlukları dahil) onun `ratioAtClientX`'inden. */\n seekBar: {\n readonly el: HTMLElement;\n ratioAtClientX(clientX: number): number;\n suppressHoverTime(key: string, suppressed: boolean): void;\n markerLabelAt?(clientX: number): string | null;\n };\n /** Responsive ölçekleme için referans genişlik — genelde player/video alanının genişliği. */\n playerWidth(): number;\n}\n\n/** Bir önizleme karesi: hangi görselin hangi dikdörtgeni. */\ninterface Frame {\n url: string;\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\ninterface Sheet {\n img: HTMLImageElement;\n ready: boolean;\n failed: boolean;\n promise: Promise<void>;\n}\n\nexport interface VttCue {\n start: number;\n end: number;\n url: string;\n /** `#xywh` yoksa null → görselin tamamı. */\n rect: { x: number; y: number; w: number; h: number } | null;\n}\n\n/** Aynı anda bellekte (decode edilmiş) tutulan en fazla sheet — uzun videolarda bellek sınırsız büyümesin. */\nconst MAX_CACHED_SHEETS = 8;\n/** Sheet numarası şablonu: `%d` ya da sıfır dolgulu `%03d`. */\nconst SHEET_TEMPLATE = /%(0(\\d+))?d/;\n\n/**\n * Seek bar hover önizlemesi. Kaynak: tek görsel, çok parçalı (%d / %03d şablonu ya da sheets) veya WebVTT (#xywh).\n * sheetDuration verilmezse ilk sheet'in ızgarasından hesaplanır. Kurulumda hiçbir şey indirilmez; yalnızca imlecin\n * altındaki sheet + komşuları yüklenir, decode bitmeden gösterilmez, LRU cache.\n */\nexport class SpriteThumbnails {\n private readonly tooltip: HTMLElement;\n private readonly imageEl: HTMLElement;\n private readonly timeEl: HTMLElement;\n private readonly sheets = new Map<string, Sheet>();\n private vttCues: VttCue[] | null = null;\n private vttLoading: Promise<void> | null = null;\n /** Çok parçalı modda otomatik hesaplanan sheet süresi (ilk sheet yüklenince). */\n private derivedSheetDuration: number | null = null;\n /** `lowRes` sheet'i — LRU dışında, hep bellekte. */\n private lowSheet: Sheet | null = null;\n /** Son çizilen asıl karenin genişliği (VTT'de `width` yok). */\n private lastFrameWidth = 0;\n private warmed = false;\n private hovering = false;\n private lastClientX = 0;\n private rafId: number | null = null;\n private destroyed = false;\n\n constructor(\n private readonly ctx: SpriteThumbnailsPlayerContext,\n private readonly options: SpriteThumbnailsOptions\n ) {\n this.tooltip = document.createElement('div');\n this.tooltip.setAttribute('part', 'sprite-tooltip');\n this.tooltip.className = 'hp-sprite-tooltip';\n this.imageEl = document.createElement('div');\n this.imageEl.className = 'hp-sprite-image';\n this.timeEl = document.createElement('div');\n this.timeEl.className = 'hp-sprite-time';\n this.tooltip.append(this.imageEl, this.timeEl);\n ctx.seekBar.el.appendChild(this.tooltip);\n // Önizlemenin altında zaman zaten yazıyor — varsayılan hover zamanı ikinci kez göstermesin.\n ctx.seekBar.suppressHoverTime('sprite', true);\n\n ctx.seekBar.el.addEventListener('pointerenter', this.onPointerEnter);\n ctx.seekBar.el.addEventListener('pointermove', this.onPointerMove);\n ctx.seekBar.el.addEventListener('pointerleave', this.onPointerLeave);\n ctx.videoEl.addEventListener('play', this.warm);\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.ctx.seekBar.el.removeEventListener('pointerenter', this.onPointerEnter);\n this.ctx.seekBar.el.removeEventListener('pointermove', this.onPointerMove);\n this.ctx.seekBar.el.removeEventListener('pointerleave', this.onPointerLeave);\n this.ctx.videoEl.removeEventListener('play', this.warm);\n this.tooltip.remove();\n this.ctx.seekBar.suppressHoverTime('sprite', false);\n for (const sheet of this.sheets.values()) sheet.img.src = '';\n if (this.lowSheet) this.lowSheet.img.src = '';\n this.sheets.clear();\n }\n\n // ── olaylar ──\n\n private readonly onPointerEnter = (e: PointerEvent): void => {\n this.hovering = true;\n this.lastClientX = e.clientX;\n this.warm();\n this.scheduleRender();\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n this.hovering = true;\n this.lastClientX = e.clientX;\n this.scheduleRender();\n };\n\n private readonly onPointerLeave = (): void => {\n this.hovering = false;\n this.tooltip.removeAttribute('data-visible');\n };\n\n /** İlk ihtiyaç anında (hover / oynatma) kaynağı hazırla — kurulumda hiçbir şey indirilmiyor. */\n private readonly warm = (): void => {\n if (this.warmed || this.destroyed) return;\n this.warmed = true;\n // Küçük sheet bağlantı hızından bağımsız hemen iner.\n if (this.options.lowRes?.url) this.lowSheet = this.createSheet(this.options.lowRes.url, () => this.hovering && this.scheduleRender());\n if (this.options.vtt) {\n void this.loadVtt();\n return;\n }\n const duration = this.ctx.videoEl.duration;\n const t = Number.isFinite(duration) ? this.ctx.videoEl.currentTime : 0;\n // Şablonlu/çok parçalı modda sheet süresi henüz bilinmiyorsa ilk sheet'ten öğrenilecek.\n void this.ensureSheet(this.sheetUrl(this.isMultiSheet() && this.sheetDuration() === null ? 0 : this.sheetIndexAt(t)));\n };\n\n private scheduleRender(): void {\n if (this.rafId !== null) return;\n this.rafId = requestAnimationFrame(() => {\n this.rafId = null;\n this.render();\n });\n }\n\n // ── çizim ──\n\n private render(): void {\n if (!this.hovering || this.destroyed) return;\n const duration = this.ctx.videoEl.duration;\n if (!Number.isFinite(duration) || duration <= 0) return;\n\n const seconds = this.ctx.seekBar.ratioAtClientX(this.lastClientX) * duration;\n const label = this.ctx.seekBar.markerLabelAt?.(this.lastClientX);\n this.timeEl.textContent = label ? `${label} · ${formatTime(seconds)}` : formatTime(seconds);\n\n // Asıl kare hazır değilse küçük sheet'ten doğru zamanın karesi; o da yoksa son kare ekranda kalır.\n const hi = this.isNetworkEligible() ? this.frameAt(seconds, duration) : null;\n if (hi) this.lastFrameWidth = hi.w;\n const frame = hi ?? this.lowResFrameAt(seconds, duration);\n const img = hi ? this.sheets.get(hi.url)!.img : this.lowSheet?.img;\n if (frame && img) {\n // Hedef genişlik: displayWidth → kare genişliği; küçük kare aynı boyuta büyütülür.\n const target = (this.options.displayWidth ?? (hi ? hi.w : this.options.width || this.lastFrameWidth || frame.w)) * this.scale();\n const k = target / frame.w;\n this.imageEl.style.display = '';\n this.imageEl.toggleAttribute('data-lowres', !hi);\n this.imageEl.style.width = `${target}px`;\n this.imageEl.style.height = `${frame.h * k}px`;\n this.imageEl.style.backgroundImage = `url(\"${frame.url}\")`;\n this.imageEl.style.backgroundSize = `${img.naturalWidth * k}px ${img.naturalHeight * k}px`;\n this.imageEl.style.backgroundPosition = `${-frame.x * k}px ${-frame.y * k}px`;\n } else if (!this.imageEl.style.backgroundImage) {\n // Henüz hiçbir kare yüklenmedi — yalnızca zaman (yükleme bitince yeniden çizilir).\n this.imageEl.style.display = 'none';\n }\n\n // Kenarlarda taşmasın: imleci ortala ama seek bar sınırlarında kal.\n this.tooltip.setAttribute('data-visible', '');\n const barRect = this.ctx.seekBar.el.getBoundingClientRect();\n const tipWidth = this.tooltip.offsetWidth;\n const x = Math.min(Math.max(this.lastClientX - barRect.left - tipWidth / 2, 0), Math.max(barRect.width - tipWidth, 0));\n this.tooltip.style.transform = `translateX(${x}px)`;\n }\n\n private scale(): number {\n const responsive = this.options.responsive;\n const playerWidth = this.ctx.playerWidth();\n return responsive && playerWidth && playerWidth < responsive ? playerWidth / responsive : 1;\n }\n\n private isNetworkEligible(): boolean {\n const nav = navigator as Navigator & { connection?: { downlink?: number } };\n const downlink = nav.connection?.downlink;\n const anyReady = Array.from(this.sheets.values()).some((s) => s.ready);\n return downlink === undefined || downlink >= (this.options.downlink ?? 2) || anyReady;\n }\n\n // ── kare çözümleme ──\n\n /** `lowRes` sheet'inden saniyedeki kare (hazır değilse null). */\n private lowResFrameAt(seconds: number, duration: number): Frame | null {\n const o = this.options.lowRes;\n const img = this.lowSheet?.ready ? this.lowSheet.img : null;\n if (!o || !img || !o.width || !o.height) return null;\n const columns = Math.max(1, Math.floor(img.naturalWidth / o.width));\n const count = columns * Math.max(1, Math.floor(img.naturalHeight / o.height));\n const interval = o.interval || duration / count;\n const i = Math.min(count - 1, Math.max(0, Math.floor(seconds / interval)));\n return { url: o.url, x: (i % columns) * o.width, y: Math.floor(i / columns) * o.height, w: o.width, h: o.height };\n }\n\n /** Saniyedeki kareyi döner; gereken sheet hazır değilse yüklemeyi başlatıp null döner (yüklenince render tekrar çağrılır). */\n private frameAt(seconds: number, duration: number): Frame | null {\n return this.options.vtt ? this.vttFrameAt(seconds) : this.gridFrameAt(seconds, duration);\n }\n\n private isMultiSheet(): boolean {\n return !!this.options.sheets?.length || SHEET_TEMPLATE.test(this.options.url ?? '');\n }\n\n /** Tek sheet → Infinity (tüm video); çok parçalı → verilen ya da ilk sheet'ten hesaplanan süre; henüz bilinmiyorsa null. */\n private sheetDuration(): number | null {\n if (!this.isMultiSheet()) return Infinity;\n return this.options.sheetDuration ?? this.derivedSheetDuration;\n }\n\n private sheetIndexAt(seconds: number): number {\n const d = this.sheetDuration();\n if (d === null || d === Infinity) return 0;\n // floor (ceil DEĞİL): tam sınırda (ör. 60. sn) bir SONRAKİ sheet'in ilk karesi.\n let index = Math.floor(Math.max(0, seconds) / d);\n if (this.options.sheets?.length) index = Math.min(index, this.options.sheets.length - 1);\n return index;\n }\n\n /** 0 tabanlı sheet index'inden URL. */\n private sheetUrl(index: number): string {\n if (this.options.sheets?.length) return this.options.sheets[Math.min(index, this.options.sheets.length - 1)]!;\n const url = this.options.url ?? '';\n const number = index + (this.options.firstSheetIndex ?? 1);\n return url.replace(SHEET_TEMPLATE, (_m, _p, width?: string) => String(number).padStart(width ? Number(width) : 0, '0'));\n }\n\n private gridFrameAt(seconds: number, duration: number): Frame | null {\n const { width, height } = this.options;\n if (!width || !height) return null;\n const interval = this.options.interval || 1;\n\n const sheetDuration = this.sheetDuration();\n if (sheetDuration === null) {\n // Çok parçalı ama süre bilinmiyor — ilk sheet yüklenince hesaplanacak.\n void this.ensureSheet(this.sheetUrl(0));\n return null;\n }\n\n const lastIndex = sheetDuration === Infinity ? 0 : this.sheetIndexAt(Math.max(0, duration - 0.001));\n const index = Math.min(this.sheetIndexAt(seconds), lastIndex);\n const url = this.sheetUrl(index);\n this.preloadAround(index, lastIndex);\n\n const sheet = this.sheets.get(url);\n if (!sheet?.ready) {\n void this.ensureSheet(url);\n return null;\n }\n this.touch(url);\n\n // Her sheet'in KENDİ boyutu (son sheet daha kısa olabilir).\n const columns = Math.max(1, Math.floor(sheet.img.naturalWidth / width));\n const rows = Math.max(1, Math.floor(sheet.img.naturalHeight / height));\n const local = sheetDuration === Infinity ? seconds : seconds - index * sheetDuration;\n const frameIndex = Math.min(Math.max(0, Math.floor(local / interval)), columns * rows - 1);\n return { url, x: (frameIndex % columns) * width, y: Math.floor(frameIndex / columns) * height, w: width, h: height };\n }\n\n private preloadAround(index: number, lastIndex: number): void {\n const n = this.options.preloadSheets ?? 1;\n for (let d = 1; d <= n; d++) {\n if (index + d <= lastIndex) void this.ensureSheet(this.sheetUrl(index + d));\n if (index - d >= 0) void this.ensureSheet(this.sheetUrl(index - d));\n }\n }\n\n private vttFrameAt(seconds: number): Frame | null {\n if (!this.vttCues) {\n void this.loadVtt();\n return null;\n }\n const cues = this.vttCues;\n if (!cues.length) return null;\n // İkili arama — saatlerce süren videolarda binlerce cue olabilir.\n let lo = 0;\n let hi = cues.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if (cues[mid]!.start <= seconds) lo = mid;\n else hi = mid - 1;\n }\n const cue = cues[lo]!;\n const neighbours = [cues[lo + 1], cues[lo - 1]].filter((c): c is VttCue => !!c && c.url !== cue.url);\n neighbours.forEach((c) => void this.ensureSheet(c.url));\n\n const sheet = this.sheets.get(cue.url);\n if (!sheet?.ready) {\n void this.ensureSheet(cue.url);\n return null;\n }\n this.touch(cue.url);\n const rect = cue.rect ?? { x: 0, y: 0, w: sheet.img.naturalWidth, h: sheet.img.naturalHeight };\n return { url: cue.url, ...rect };\n }\n\n // ── yükleme / cache ──\n\n private ensureSheet(url: string): Promise<void> {\n if (!url) return Promise.resolve();\n const existing = this.sheets.get(url);\n if (existing) return existing.promise;\n\n const sheet = this.createSheet(url, (img) => {\n this.learnSheetDuration(img);\n if (this.hovering) this.scheduleRender();\n });\n this.sheets.set(url, sheet);\n this.evict();\n return sheet.promise;\n }\n\n /** Görseli yükler; decode bitmeden hazır sayılmaz (sheet geçişinde titreme olmasın). */\n private createSheet(url: string, onReady: (img: HTMLImageElement) => void): Sheet {\n const img = new Image();\n img.decoding = 'async';\n const sheet: Sheet = { img, ready: false, failed: false, promise: Promise.resolve() };\n sheet.promise = new Promise<void>((resolve) => {\n img.onload = () => {\n const done = () => {\n if (this.destroyed) return resolve();\n sheet.ready = true;\n onReady(img);\n resolve();\n };\n img.decode ? img.decode().then(done, done) : done();\n };\n img.onerror = () => {\n sheet.failed = true;\n resolve();\n };\n });\n img.src = url;\n return sheet;\n }\n\n /** Çok parçalı modda `sheetDuration` verilmediyse ilk yüklenen sheet'in ızgara kapasitesinden hesapla. */\n private learnSheetDuration(img: HTMLImageElement): void {\n if (this.derivedSheetDuration !== null || this.options.vtt || !this.isMultiSheet() || this.options.sheetDuration) return;\n const { width, height } = this.options;\n if (!width || !height) return;\n const capacity = Math.max(1, Math.floor(img.naturalWidth / width)) * Math.max(1, Math.floor(img.naturalHeight / height));\n this.derivedSheetDuration = capacity * (this.options.interval || 1);\n }\n\n /** LRU: kullanılan sheet'i sona taşı. */\n private touch(url: string): void {\n const sheet = this.sheets.get(url);\n if (!sheet) return;\n this.sheets.delete(url);\n this.sheets.set(url, sheet);\n }\n\n private evict(): void {\n while (this.sheets.size > MAX_CACHED_SHEETS) {\n const oldest = this.sheets.keys().next().value as string;\n const sheet = this.sheets.get(oldest)!;\n sheet.img.onload = null;\n sheet.img.onerror = null;\n this.sheets.delete(oldest);\n }\n }\n\n private loadVtt(): Promise<void> {\n if (this.vttLoading) return this.vttLoading;\n const vttUrl = this.options.vtt!;\n this.vttLoading = fetch(vttUrl)\n .then((r) => {\n if (!r.ok) throw new Error(`HTTP ${r.status}`);\n return r.text();\n })\n .then((text) => {\n if (this.destroyed) return;\n this.vttCues = parseThumbnailVtt(text, new URL(vttUrl, document.baseURI).href);\n if (this.vttCues.length) void this.ensureSheet(this.vttCues[0]!.url);\n if (this.hovering) this.scheduleRender();\n })\n .catch((err) => {\n console.warn('[HopePlayer sprite-thumbnails] VTT yüklenemedi:', err);\n this.vttCues = [];\n });\n return this.vttLoading;\n }\n}\n\n/** \"01:02:03.500\" / \"02:03.500\" → saniye. */\nfunction parseVttTime(value: string): number {\n const parts = value.trim().split(':').map(Number);\n return parts.reduce((acc, n) => acc * 60 + n, 0);\n}\n\n/** WebVTT thumbnail dosyası → sıralı cue listesi. Görsel yolları VTT dosyasına göre çözümlenir. */\nexport function parseThumbnailVtt(text: string, baseUrl: string): VttCue[] {\n const cues: VttCue[] = [];\n const blocks = text.replace(/\\r/g, '').split(/\\n\\n+/);\n for (const block of blocks) {\n const lines = block.split('\\n').filter(Boolean);\n const timingIndex = lines.findIndex((l) => l.includes('-->'));\n if (timingIndex === -1) continue;\n const [startStr, endStr] = lines[timingIndex]!.split('-->');\n const target = lines[timingIndex + 1]?.trim();\n if (!startStr || !endStr || !target) continue;\n\n const [path, hash] = target.split('#');\n const match = hash?.match(/xywh=(\\d+),(\\d+),(\\d+),(\\d+)/);\n cues.push({\n start: parseVttTime(startStr),\n end: parseVttTime(endStr.trim().split(/\\s+/)[0]!),\n url: new URL(path!, baseUrl).href,\n rect: match ? { x: +match[1]!, y: +match[2]!, w: +match[3]!, h: +match[4]! } : null,\n });\n }\n return cues.sort((a, b) => a.start - b.start);\n}\n","import { SpriteThumbnails, type SpriteThumbnailsPlayerContext } from './SpriteThumbnails';\nimport type { SpriteThumbnailsOptions } from '../../types';\n\nexport function installSpriteThumbnails(ctx: SpriteThumbnailsPlayerContext, options: SpriteThumbnailsOptions): SpriteThumbnails {\n return new SpriteThumbnails(ctx, options);\n}\n\nexport { SpriteThumbnails };\nexport type { SpriteThumbnailsPlayerContext };\n"],"names":["MAX_CACHED_SHEETS","SHEET_TEMPLATE","SpriteThumbnails","ctx","options","__publicField","e","_a","duration","t","sheet","seconds","label","_b","formatTime","hi","frame","img","_c","target","k","barRect","tipWidth","x","responsive","playerWidth","downlink","anyReady","s","o","columns","count","interval","i","d","index","url","number","_m","_p","width","height","sheetDuration","lastIndex","rows","local","frameIndex","n","cues","lo","mid","cue","c","rect","existing","onReady","resolve","done","capacity","oldest","vttUrl","r","text","parseThumbnailVtt","err","parseVttTime","value","acc","baseUrl","blocks","block","lines","timingIndex","l","startStr","endStr","path","hash","match","a","b","installSpriteThumbnails"],"mappings":"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"}
|
|
@@ -37,7 +37,7 @@ class x {
|
|
|
37
37
|
for (let r = 0; r < t.buffered.length; r++)
|
|
38
38
|
t.buffered.start(r) <= t.currentTime + 0.5 && t.buffered.end(r) > t.currentTime && (u = t.buffered.end(r) - t.currentTime);
|
|
39
39
|
const f = [
|
|
40
|
-
[e.statsEngine, l.engine + (l.reason ? ` (${l.reason})` : "")],
|
|
40
|
+
[e.statsEngine, l.engine + (l.drm ? ` · ${l.drm}` : "") + (l.reason ? ` (${l.reason})` : "")],
|
|
41
41
|
[e.statsResolution, `${t.videoWidth}×${t.videoHeight} / ${Math.round(h.width * c)}×${Math.round(h.height * c)}`],
|
|
42
42
|
[e.statsQuality, i ? `${i.height}p · ${Math.round(i.bitrate / 1e3)} kbps${s.autoLevelEnabled ? " · auto" : ""}` : "—"],
|
|
43
43
|
[e.statsCodecs, i && [i.videoCodec, i.audioCodec].filter(Boolean).join(", ") || "—"],
|
|
@@ -67,4 +67,4 @@ export {
|
|
|
67
67
|
x as StatsPanel,
|
|
68
68
|
$ as installStats
|
|
69
69
|
};
|
|
70
|
-
//# sourceMappingURL=statsPanel-
|
|
70
|
+
//# sourceMappingURL=statsPanel-D0DtoFgS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statsPanel-D0DtoFgS.js","sources":["../../src/plugins/stats/StatsPanel.ts","../../src/plugins/stats/index.ts"],"sourcesContent":["import type { HopeLocaleStrings } from '../../i18n/types';\nimport type { PlaybackEngineInfo } from '../../hls/SourceManager';\n\n/** hls.js instance'ından okunan alanlar — tam tipi içe aktarmamak için. */\ninterface HlsStatsSource {\n currentLevel: number;\n autoLevelEnabled: boolean;\n levels: { height: number; width: number; bitrate: number; videoCodec?: string; audioCodec?: string; details?: { live: boolean } }[];\n bandwidthEstimate: number;\n latency: number;\n config: { maxBufferLength: number };\n}\n\nexport interface StatsPlayerContext {\n videoEl: HTMLVideoElement;\n containerEl: HTMLElement;\n i18n: HopeLocaleStrings;\n version: string;\n getEngine(): PlaybackEngineInfo;\n getHls(): HlsStatsSource | null;\n}\n\nconst REFRESH_MS = 500;\n\n/** Sağ tık menüsündeki \"İstatistikler\" — player üstünde canlı teknik bilgi paneli (YouTube'daki \"Stats for nerds\" gibi). */\nexport class StatsPanel {\n private readonly el: HTMLDivElement;\n private readonly titleEl: HTMLSpanElement;\n private readonly closeBtn: HTMLButtonElement;\n private readonly body: HTMLDListElement;\n private timer: ReturnType<typeof setInterval> | null = null;\n\n constructor(private readonly ctx: StatsPlayerContext) {\n this.el = document.createElement('div');\n this.el.className = 'hp-stats';\n this.el.setAttribute('part', 'stats-panel');\n this.el.setAttribute('role', 'dialog');\n\n const header = document.createElement('div');\n header.className = 'hp-stats-header';\n this.titleEl = document.createElement('span');\n this.closeBtn = document.createElement('button');\n this.closeBtn.type = 'button';\n this.closeBtn.className = 'hp-stats-close';\n this.closeBtn.innerHTML =\n '<svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" aria-hidden=\"true\"><path d=\"M6 6l12 12M18 6L6 18\"/></svg>';\n this.closeBtn.addEventListener('click', () => this.hide());\n header.append(this.titleEl, this.closeBtn);\n\n this.body = document.createElement('dl');\n this.body.className = 'hp-stats-body';\n this.el.append(header, this.body);\n // Panel tıklamaları videoyu oynat/duraklat yapmasın.\n this.el.addEventListener('pointerdown', (e) => e.stopPropagation());\n this.el.addEventListener('click', (e) => e.stopPropagation());\n this.refreshLabels();\n }\n\n get isVisible(): boolean {\n return this.el.isConnected;\n }\n\n show(): void {\n if (!this.isVisible) this.ctx.containerEl.appendChild(this.el);\n this.render();\n if (!this.timer) this.timer = setInterval(() => this.render(), REFRESH_MS);\n }\n\n hide(): void {\n if (this.timer) clearInterval(this.timer);\n this.timer = null;\n this.el.remove();\n }\n\n toggle(force?: boolean): void {\n if (force ?? !this.isVisible) this.show();\n else this.hide();\n }\n\n refreshLabels(): void {\n this.titleEl.textContent = this.ctx.i18n.statsTitle;\n this.closeBtn.setAttribute('aria-label', this.ctx.i18n.statsClose);\n if (this.isVisible) this.render();\n }\n\n destroy(): void {\n this.hide();\n }\n\n private render(): void {\n const { videoEl: v, i18n: t } = this.ctx;\n const hls = this.ctx.getHls();\n const engine = this.ctx.getEngine();\n const level = hls && hls.currentLevel >= 0 ? hls.levels[hls.currentLevel] : undefined;\n const quality = v.getVideoPlaybackQuality?.();\n const rect = v.getBoundingClientRect();\n const dpr = window.devicePixelRatio || 1;\n\n let ahead = 0;\n for (let i = 0; i < v.buffered.length; i++) {\n if (v.buffered.start(i) <= v.currentTime + 0.5 && v.buffered.end(i) > v.currentTime) ahead = v.buffered.end(i) - v.currentTime;\n }\n\n const rows: [string, string][] = [\n [t.statsEngine, engine.engine + (engine.drm ? ` · ${engine.drm}` : '') + (engine.reason ? ` (${engine.reason})` : '')],\n [t.statsResolution, `${v.videoWidth}×${v.videoHeight} / ${Math.round(rect.width * dpr)}×${Math.round(rect.height * dpr)}`],\n [t.statsQuality, level ? `${level.height}p · ${Math.round(level.bitrate / 1000)} kbps${hls!.autoLevelEnabled ? ' · auto' : ''}` : '—'],\n [t.statsCodecs, level ? [level.videoCodec, level.audioCodec].filter(Boolean).join(', ') || '—' : '—'],\n [t.statsBandwidth, hls ? `${(hls.bandwidthEstimate / 1e6).toFixed(2)} Mbps` : '—'],\n [t.statsBuffer, `${ahead.toFixed(1)} s`],\n [t.statsDropped, quality ? `${quality.droppedVideoFrames} / ${quality.totalVideoFrames}` : '—'],\n // hls.js `latency`'yi VOD'da da hesaplıyor (süre - konum) — yalnızca canlı yayında anlamlı.\n [t.statsLatency, level?.details?.live && Number.isFinite(hls!.latency) ? `${hls!.latency.toFixed(1)} s` : '—'],\n [t.statsSpeedVolume, `${v.playbackRate}× · ${v.muted ? 0 : Math.round(v.volume * 100)}%`],\n [t.statsSource, v.currentSrc && !v.currentSrc.startsWith('blob:') ? v.currentSrc : v.currentSrc ? 'MediaSource (hls.js)' : '—'],\n [t.statsVersion, `HopeCorePlayer ${this.ctx.version}`],\n ];\n this.body.replaceChildren(\n ...rows.flatMap(([k, val]) => {\n const dt = document.createElement('dt');\n dt.textContent = k;\n const dd = document.createElement('dd');\n dd.textContent = val;\n dd.title = val;\n return [dt, dd];\n })\n );\n }\n}\n","import { StatsPanel, type StatsPlayerContext } from './StatsPanel';\n\nexport function installStats(ctx: StatsPlayerContext): StatsPanel {\n return new StatsPanel(ctx);\n}\n\nexport { StatsPanel };\nexport type { StatsPlayerContext };\n"],"names":["StatsPanel","ctx","__publicField","header","e","force","_a","_b","v","t","hls","engine","level","quality","rect","dpr","ahead","i","rows","k","val","dt","dd","installStats"],"mappings":"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"}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
var E = Object.defineProperty;
|
|
2
|
-
var w = (
|
|
3
|
-
var
|
|
4
|
-
const
|
|
2
|
+
var w = (l, e, t) => e in l ? E(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
|
|
3
|
+
var r = (l, e, t) => w(l, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
const f = "hope_sticky_dismissed_until", v = "hope_sticky_dismissed_forever";
|
|
5
5
|
class k {
|
|
6
6
|
constructor() {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
r(this, "items", /* @__PURE__ */ new Map());
|
|
8
|
+
r(this, "activeKey", null);
|
|
9
|
+
r(this, "observer", null);
|
|
10
|
+
r(this, "lastUserGestureAt", 0);
|
|
11
|
+
r(this, "lastGestureType", null);
|
|
12
|
+
r(this, "gestureListenersAttached", !1);
|
|
13
|
+
r(this, "dismissedUntil", 0);
|
|
14
|
+
r(this, "dismissedForever", !1);
|
|
15
|
+
r(this, "dismissLoaded", !1);
|
|
16
16
|
}
|
|
17
17
|
register(e, t) {
|
|
18
18
|
var p;
|
|
@@ -59,11 +59,11 @@ class k {
|
|
|
59
59
|
}
|
|
60
60
|
};
|
|
61
61
|
this.items.set(e.key, n), this.ensureObserver().observe(a);
|
|
62
|
-
const
|
|
63
|
-
e.videoEl.addEventListener("play",
|
|
62
|
+
const i = () => this.handlePlay(n), o = () => this.handlePauseOrEnded(n, "pause"), c = () => this.handlePauseOrEnded(n, "ended"), d = () => this.handleAdStart(n), u = () => this.handleAdEnd(n);
|
|
63
|
+
e.videoEl.addEventListener("play", i), e.videoEl.addEventListener("pause", o), e.videoEl.addEventListener("ended", c), e.hostEl.addEventListener("hp:adstart", d), e.hostEl.addEventListener("hp:adend", u), !e.videoEl.paused && !e.videoEl.ended && this.handlePlay(n);
|
|
64
64
|
const h = () => {
|
|
65
65
|
var y;
|
|
66
|
-
n.state.sticky && this.unstick(e.key, "destroy"), e.videoEl.removeEventListener("play",
|
|
66
|
+
n.state.sticky && this.unstick(e.key, "destroy"), e.videoEl.removeEventListener("play", i), e.videoEl.removeEventListener("pause", o), e.videoEl.removeEventListener("ended", c), e.hostEl.removeEventListener("hp:adstart", d), e.hostEl.removeEventListener("hp:adend", u), (y = this.observer) == null || y.unobserve(a), a.remove(), this.items.delete(e.key);
|
|
67
67
|
};
|
|
68
68
|
return h.refreshLabels = () => {
|
|
69
69
|
n.state.closeBtnEl && n.state.closeBtnEl.setAttribute("aria-label", e.i18n.close);
|
|
@@ -159,7 +159,8 @@ class k {
|
|
|
159
159
|
}
|
|
160
160
|
// ── stick / unstick ──
|
|
161
161
|
maybeStick(e, t) {
|
|
162
|
-
|
|
162
|
+
var n, i;
|
|
163
|
+
if ((i = (n = e.ctx).isSuspended) != null && i.call(n) || (e.state.userPaused && Date.now() - e.state.userPausedAt > 3e4 && (e.state.userPaused = !1, e.state.userPausedAt = 0), !e.state.hasEverBeenInView) || !e.state.hasEverBeenInViewWhilePlaying || e.state.userPaused) return;
|
|
163
164
|
const a = Date.now();
|
|
164
165
|
e.options.dismissMode === "never" && this.dismissedForever || e.options.dismissMode === "cooldown" && this.dismissedUntil && a < this.dismissedUntil || e.options.requirePlaying && !e.state.playing || e.state.sticky || e.options.minPlayMs > 0 && !e.state.minPlaySatisfied || (e.options.onlyOneSticky && this.activeKey && this.activeKey !== e.ctx.key && this.pauseAndUnstick(this.activeKey, "replaced"), this.stick(e));
|
|
165
166
|
}
|
|
@@ -169,8 +170,8 @@ class k {
|
|
|
169
170
|
if (!e.state.placeholderEl) {
|
|
170
171
|
const n = document.createElement("div");
|
|
171
172
|
n.setAttribute("data-hope-sticky-placeholder", "1");
|
|
172
|
-
const
|
|
173
|
-
n.style.height = `${
|
|
173
|
+
const i = t.getBoundingClientRect();
|
|
174
|
+
n.style.height = `${i.height}px`, (a = t.parentNode) == null || a.insertBefore(n, t), e.state.placeholderEl = n;
|
|
174
175
|
}
|
|
175
176
|
if (t.setAttribute("data-sticky", "1"), t.setAttribute("data-sticky-corner", s), e.options.closeButton && !e.state.closeBtnEl) {
|
|
176
177
|
const n = document.createElement("button");
|
|
@@ -181,11 +182,11 @@ class k {
|
|
|
181
182
|
e.state.sticky = !0, this.activeKey = e.ctx.key, e.ctx.hostEl.dispatchEvent(new CustomEvent("hp:sticky", { detail: { sticky: !0, corner: s } }));
|
|
182
183
|
}
|
|
183
184
|
unstick(e, t) {
|
|
184
|
-
var n,
|
|
185
|
+
var n, i;
|
|
185
186
|
const s = this.items.get(e);
|
|
186
187
|
if (!s) return;
|
|
187
188
|
const a = s.ctx.wrapperEl;
|
|
188
|
-
a.removeAttribute("data-sticky"), a.removeAttribute("data-sticky-corner"), (n = s.state.closeBtnEl) == null || n.remove(), s.state.closeBtnEl = null, (
|
|
189
|
+
a.removeAttribute("data-sticky"), a.removeAttribute("data-sticky-corner"), (n = s.state.closeBtnEl) == null || n.remove(), s.state.closeBtnEl = null, (i = s.state.placeholderEl) == null || i.remove(), s.state.placeholderEl = null, s.state.sticky = !1, this.activeKey === e && (this.activeKey = null), s.ctx.hostEl.dispatchEvent(new CustomEvent("hp:sticky", { detail: { sticky: !1 } }));
|
|
189
190
|
}
|
|
190
191
|
pauseAndUnstick(e, t) {
|
|
191
192
|
const s = this.items.get(e);
|
|
@@ -199,7 +200,7 @@ class k {
|
|
|
199
200
|
this.dismissLoaded = !0;
|
|
200
201
|
try {
|
|
201
202
|
const e = window.localStorage;
|
|
202
|
-
this.dismissedUntil = Number(e.getItem(
|
|
203
|
+
this.dismissedUntil = Number(e.getItem(f) || 0) || 0, this.dismissedForever = e.getItem(v) === "1";
|
|
203
204
|
} catch {
|
|
204
205
|
}
|
|
205
206
|
}
|
|
@@ -210,7 +211,7 @@ class k {
|
|
|
210
211
|
if (e.dismissMode === "never") {
|
|
211
212
|
this.dismissedForever = !0;
|
|
212
213
|
try {
|
|
213
|
-
t == null || t.setItem(
|
|
214
|
+
t == null || t.setItem(v, "1");
|
|
214
215
|
} catch {
|
|
215
216
|
}
|
|
216
217
|
return;
|
|
@@ -218,16 +219,16 @@ class k {
|
|
|
218
219
|
const s = Date.now() + e.cooldownMinutes * 6e4;
|
|
219
220
|
this.dismissedUntil = s;
|
|
220
221
|
try {
|
|
221
|
-
t == null || t.setItem(
|
|
222
|
+
t == null || t.setItem(f, String(s));
|
|
222
223
|
} catch {
|
|
223
224
|
}
|
|
224
225
|
}
|
|
225
226
|
}
|
|
226
227
|
const A = new k();
|
|
227
|
-
function P(
|
|
228
|
-
return A.register(
|
|
228
|
+
function P(l, e) {
|
|
229
|
+
return A.register(l, e);
|
|
229
230
|
}
|
|
230
231
|
export {
|
|
231
232
|
P as installSticky
|
|
232
233
|
};
|
|
233
|
-
//# sourceMappingURL=sticky-
|
|
234
|
+
//# sourceMappingURL=sticky-BDStzjBM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sticky-BDStzjBM.js","sources":["../../src/plugins/sticky/StickyManager.ts","../../src/plugins/sticky/index.ts"],"sourcesContent":["import type { StickyCorner, StickyOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface StickyPlayerContext {\n key: string;\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** Sticky olarak köşeye taşınacak element — genelde hostEl'in kendisi (bkz. options.wrapperSelector). */\n wrapperEl: HTMLElement;\n /**\n * Kapat butonu wrapperEl'e değil shadow root içine eklenir — wrapperEl varsayılan olarak host;\n * slot olmadığı için light DOM child'ı render edilmez.\n */\n closeButtonMountEl: HTMLElement;\n isAdActive(): boolean;\n /** true iken köşeye yapışmaz (ör. video Document PiP penceresinde). */\n isSuspended?(): boolean;\n i18n: HopeLocaleStrings;\n}\n\n/** `register()`'ın döndürdüğü unregister fonksiyonu — dil sonradan değişince close butonunun statik etiketini tazelemek için `refreshLabels` da taşıyor (bkz. loop-section'daki aynı \"fonksiyona metod ekleme\" deseni). */\nexport type StickyUnregister = (() => void) & { refreshLabels?: () => void };\n\ninterface StickyItemState {\n inView: boolean;\n playing: boolean;\n sticky: boolean;\n hasEverBeenInView: boolean;\n hasEverBeenInViewWhilePlaying: boolean;\n watchMsInView: number;\n lastTickAt: number;\n minPlaySatisfied: boolean;\n userPaused: boolean;\n userPausedAt: number;\n adStartedOnce: boolean;\n contentStartedOnce: boolean;\n blockResumeUntil: number;\n programmaticPauseUntil: number;\n placeholderEl: HTMLElement | null;\n closeBtnEl: HTMLElement | null;\n}\n\ninterface StickyItem {\n ctx: StickyPlayerContext;\n options: Required<Omit<StickyOptions, 'wrapperSelector'>>;\n state: StickyItemState;\n /** wrapperEl'in doğal konumundaki görünmez işaretçi — IntersectionObserver bunu izler (sticky olunca wrapper yer değiştirir). */\n sentinelEl: HTMLElement;\n}\n\nconst GESTURE_WINDOW_MS = 1200;\nconst USER_PAUSED_MAX_MS = 30000;\nconst PROGRAMMATIC_PAUSE_MS = 800;\nconst BLOCK_RESUME_MS = 1200;\nconst STORAGE_KEY = 'hope_sticky_dismissed_until';\nconst STORAGE_KEY_FOREVER = 'hope_sticky_dismissed_forever';\n\n/** Sayfadaki tüm sticky player'ları koordine eden modül seviyesi singleton (aynı anda tek sticky). */\nclass StickyManagerImpl {\n private readonly items = new Map<string, StickyItem>();\n private activeKey: string | null = null;\n private observer: IntersectionObserver | null = null;\n\n private lastUserGestureAt = 0;\n private lastGestureType: 'play' | 'pause' | 'other' | null = null;\n private gestureListenersAttached = false;\n\n private dismissedUntil = 0;\n private dismissedForever = false;\n private dismissLoaded = false;\n\n register(ctx: StickyPlayerContext, options: StickyOptions): StickyUnregister {\n this.ensureGestureListeners();\n this.loadDismissState();\n\n const resolved: StickyItem['options'] = {\n enabled: options.enabled ?? true,\n corner: options.corner ?? 'br',\n requirePlaying: options.requirePlaying ?? true,\n minPlayMs: options.minPlayMs ?? 800,\n onlyOneSticky: options.onlyOneSticky ?? true,\n closeActiveStickyOnAnotherPlay: options.closeActiveStickyOnAnotherPlay ?? true,\n userGestureWindowMs: options.userGestureWindowMs ?? GESTURE_WINDOW_MS,\n adCanTriggerSticky: options.adCanTriggerSticky ?? 'preroll-only',\n dismissMode: options.dismissMode ?? 'cooldown',\n cooldownMinutes: options.cooldownMinutes ?? 5,\n storage: options.storage ?? 'local',\n closeButton: options.closeButton ?? true,\n };\n\n if (!resolved.enabled) return () => {};\n\n const sentinel = document.createElement('div');\n sentinel.setAttribute('aria-hidden', 'true');\n sentinel.style.cssText = 'position:relative;width:1px;height:1px;pointer-events:none;opacity:0;';\n ctx.wrapperEl.parentNode?.insertBefore(sentinel, ctx.wrapperEl);\n\n const item: StickyItem = {\n ctx,\n options: resolved,\n sentinelEl: sentinel,\n state: {\n inView: true,\n playing: false,\n sticky: false,\n hasEverBeenInView: false,\n hasEverBeenInViewWhilePlaying: false,\n watchMsInView: 0,\n lastTickAt: 0,\n minPlaySatisfied: false,\n userPaused: false,\n userPausedAt: 0,\n adStartedOnce: false,\n contentStartedOnce: false,\n blockResumeUntil: 0,\n programmaticPauseUntil: 0,\n placeholderEl: null,\n closeBtnEl: null,\n },\n };\n this.items.set(ctx.key, item);\n\n this.ensureObserver().observe(sentinel);\n\n const onPlay = () => this.handlePlay(item);\n const onPause = () => this.handlePauseOrEnded(item, 'pause');\n const onEnded = () => this.handlePauseOrEnded(item, 'ended');\n const onAdStart = () => this.handleAdStart(item);\n const onAdEnd = () => this.handleAdEnd(item);\n\n ctx.videoEl.addEventListener('play', onPlay);\n ctx.videoEl.addEventListener('pause', onPause);\n ctx.videoEl.addEventListener('ended', onEnded);\n ctx.hostEl.addEventListener('hp:adstart', onAdStart);\n ctx.hostEl.addEventListener('hp:adend', onAdEnd);\n\n // Plugin dinamik yüklendiği için autoplay video'yu bu dinleyiciden önce başlatmış olabilir —\n // kaçırılan 'play'i telafi et, yoksa requirePlaying sticky'yi hiç açmaz.\n if (!ctx.videoEl.paused && !ctx.videoEl.ended) {\n this.handlePlay(item);\n }\n\n const unregister: StickyUnregister = () => {\n if (item.state.sticky) this.unstick(ctx.key, 'destroy');\n ctx.videoEl.removeEventListener('play', onPlay);\n ctx.videoEl.removeEventListener('pause', onPause);\n ctx.videoEl.removeEventListener('ended', onEnded);\n ctx.hostEl.removeEventListener('hp:adstart', onAdStart);\n ctx.hostEl.removeEventListener('hp:adend', onAdEnd);\n this.observer?.unobserve(sentinel);\n sentinel.remove();\n this.items.delete(ctx.key);\n };\n unregister.refreshLabels = () => {\n if (item.state.closeBtnEl) {\n item.state.closeBtnEl.setAttribute('aria-label', ctx.i18n.close);\n }\n };\n return unregister;\n }\n\n // ── gesture tracking (tüm sayfa için tek dinleyici) ──\n\n private ensureGestureListeners(): void {\n if (this.gestureListenersAttached || typeof window === 'undefined') return;\n this.gestureListenersAttached = true;\n\n window.addEventListener(\n 'pointerdown',\n (e) => {\n this.lastUserGestureAt = Date.now();\n // composedPath()[0]: Shadow DOM'da e.target host'a retarget edilir; gerçek iç butonu almak için.\n const target = (e.composedPath()[0] ?? e.target) as HTMLElement | null;\n const btn = target?.closest?.('button,[role=\"button\"]') as HTMLElement | null;\n if (btn?.querySelector('.hp-icon-pause')) this.lastGestureType = 'pause';\n else if (btn?.querySelector('.hp-icon-play')) this.lastGestureType = 'play';\n else this.lastGestureType = 'other';\n },\n { capture: true, passive: true }\n );\n window.addEventListener(\n 'keydown',\n () => {\n this.lastUserGestureAt = Date.now();\n this.lastGestureType = 'other';\n },\n { capture: true }\n );\n }\n\n // ── intersection observer (tüm sticky item'lar için tek instance) ──\n\n private ensureObserver(): IntersectionObserver {\n if (this.observer) return this.observer;\n this.observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n const item = [...this.items.values()].find((i) => i.sentinelEl === entry.target);\n if (!item) continue;\n this.onIntersect(item, entry);\n }\n },\n { threshold: [0.35], rootMargin: '0px 0px -20% 0px' }\n );\n return this.observer;\n }\n\n private onIntersect(item: StickyItem, entry: IntersectionObserverEntry): void {\n this.accumulateWatch(item);\n const inView = entry.isIntersecting && entry.intersectionRatio >= 0.35;\n item.state.inView = inView;\n\n if (inView) {\n item.state.hasEverBeenInView = true;\n if (item.state.playing) item.state.hasEverBeenInViewWhilePlaying = true;\n if (item.state.sticky) this.unstick(item.ctx.key, 'back_in_view');\n } else {\n if (!item.state.hasEverBeenInView) return;\n const isActive = item.state.playing;\n if (item.options.requirePlaying && !isActive) return;\n this.maybeStick(item, 'out_of_view');\n }\n }\n\n // ── player event handlers ──\n\n private handlePlay(item: StickyItem): void {\n if (item.state.blockResumeUntil && Date.now() < item.state.blockResumeUntil) {\n item.ctx.videoEl.pause();\n item.state.playing = false;\n return;\n }\n if (item.ctx.isAdActive()) return;\n\n item.state.contentStartedOnce = true;\n const wasPlaying = item.state.playing;\n item.state.playing = true;\n if (!wasPlaying) {\n item.state.lastTickAt = Date.now();\n item.state.watchMsInView = 0;\n }\n if (item.state.inView) item.state.hasEverBeenInViewWhilePlaying = true;\n\n const gestureWindow = item.options.userGestureWindowMs;\n let userInitiated = Date.now() - this.lastUserGestureAt <= gestureWindow;\n if (this.lastGestureType === 'pause') userInitiated = false;\n if (item.state.userPaused && Date.now() - item.state.userPausedAt <= 1500) userInitiated = false;\n\n if (userInitiated) {\n item.state.userPaused = false;\n item.state.userPausedAt = 0;\n this.lastGestureType = 'play';\n }\n\n this.handleBecameActive(item, 'content', userInitiated);\n }\n\n private handlePauseOrEnded(item: StickyItem, kind: 'pause' | 'ended'): void {\n this.accumulateWatch(item);\n if (item.ctx.isAdActive()) {\n item.state.playing = true;\n return;\n }\n item.state.playing = false;\n\n const now = Date.now();\n if (item.state.programmaticPauseUntil && now < item.state.programmaticPauseUntil) {\n item.state.programmaticPauseUntil = 0;\n item.state.userPaused = false;\n item.state.userPausedAt = 0;\n return;\n }\n\n if (kind === 'pause') {\n const isUserPause = now - this.lastUserGestureAt <= item.options.userGestureWindowMs;\n if (isUserPause) {\n item.state.userPaused = true;\n item.state.userPausedAt = now;\n this.lastGestureType = 'pause';\n }\n } else if (item.state.sticky) {\n this.unstick(item.ctx.key, 'ended');\n }\n }\n\n private handleAdStart(item: StickyItem): void {\n const mode = item.options.adCanTriggerSticky;\n const isCurrentlySticky = this.activeKey === item.ctx.key;\n const isFirstAdEver = !item.state.adStartedOnce;\n item.state.adStartedOnce = true;\n item.state.lastTickAt = Date.now();\n item.state.playing = true;\n\n let allow = false;\n if (mode === 'always') allow = true;\n else if (mode === 'never') allow = false;\n else allow = isCurrentlySticky || (isFirstAdEver && !item.state.contentStartedOnce);\n\n if (!allow) return;\n this.handleBecameActive(item, 'ad', false);\n }\n\n private handleAdEnd(item: StickyItem): void {\n this.accumulateWatch(item);\n item.state.playing = !item.ctx.videoEl.paused && !item.ctx.videoEl.ended;\n item.state.lastTickAt = Date.now();\n }\n\n private handleBecameActive(item: StickyItem, source: 'content' | 'ad', userInitiated: boolean): void {\n item.state.playing = true;\n if (userInitiated) {\n item.state.userPaused = false;\n item.state.userPausedAt = 0;\n this.lastGestureType = 'play';\n }\n\n const now = Date.now();\n if (!item.state.lastTickAt) item.state.lastTickAt = now;\n if (item.state.inView) {\n item.state.hasEverBeenInView = true;\n item.state.hasEverBeenInViewWhilePlaying = true;\n }\n\n if (item.options.closeActiveStickyOnAnotherPlay && userInitiated && this.activeKey && this.activeKey !== item.ctx.key) {\n this.pauseAndUnstick(this.activeKey, 'another_played');\n }\n\n if (!item.state.inView) this.maybeStick(item, source === 'ad' ? 'play_ad' : 'play');\n }\n\n private accumulateWatch(item: StickyItem): void {\n const now = Date.now();\n const last = item.state.lastTickAt || now;\n item.state.lastTickAt = now;\n if (!item.state.playing || !item.state.inView) return;\n\n item.state.watchMsInView += now - last;\n if (!item.state.minPlaySatisfied && item.options.minPlayMs > 0 && item.state.watchMsInView >= item.options.minPlayMs) {\n item.state.minPlaySatisfied = true;\n }\n }\n\n // ── stick / unstick ──\n\n private maybeStick(item: StickyItem, _trigger: string): void {\n if (item.ctx.isSuspended?.()) return;\n const maxMs = USER_PAUSED_MAX_MS;\n if (item.state.userPaused && Date.now() - item.state.userPausedAt > maxMs) {\n item.state.userPaused = false;\n item.state.userPausedAt = 0;\n }\n\n if (!item.state.hasEverBeenInView) return;\n if (!item.state.hasEverBeenInViewWhilePlaying) return;\n if (item.state.userPaused) return;\n\n const now = Date.now();\n if (item.options.dismissMode === 'never' && this.dismissedForever) return;\n if (item.options.dismissMode === 'cooldown' && this.dismissedUntil && now < this.dismissedUntil) return;\n\n if (item.options.requirePlaying && !item.state.playing) return;\n if (item.state.sticky) return;\n if (item.options.minPlayMs > 0 && !item.state.minPlaySatisfied) return;\n\n if (item.options.onlyOneSticky && this.activeKey && this.activeKey !== item.ctx.key) {\n this.pauseAndUnstick(this.activeKey, 'replaced');\n }\n\n this.stick(item);\n }\n\n private stick(item: StickyItem): void {\n const wrapper = item.ctx.wrapperEl;\n const corner = item.options.corner;\n\n if (!item.state.placeholderEl) {\n const ph = document.createElement('div');\n ph.setAttribute('data-hope-sticky-placeholder', '1');\n const rect = wrapper.getBoundingClientRect();\n ph.style.height = `${rect.height}px`;\n wrapper.parentNode?.insertBefore(ph, wrapper);\n item.state.placeholderEl = ph;\n }\n\n wrapper.setAttribute('data-sticky', '1');\n wrapper.setAttribute('data-sticky-corner', corner);\n\n if (item.options.closeButton && !item.state.closeBtnEl) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.setAttribute('part', 'sticky-close-button');\n btn.setAttribute('aria-label', item.ctx.i18n.close);\n btn.className =\n 'hp:absolute hp:top-1 hp:right-1 hp:z-30 hp:flex hp:items-center hp:justify-center hp:w-6 hp:h-6 ' +\n 'hp:rounded-full hp:bg-black/60 hp:text-white hp:border-0 hp:cursor-pointer';\n btn.innerHTML = '<i class=\"hp-icon hp-icon-close\" aria-hidden=\"true\"></i>';\n btn.addEventListener('click', () => {\n this.applyGlobalDismiss(item.options);\n this.pauseAndUnstick(item.ctx.key, 'closed');\n });\n item.ctx.closeButtonMountEl.appendChild(btn);\n item.state.closeBtnEl = btn;\n }\n\n item.state.sticky = true;\n this.activeKey = item.ctx.key;\n item.ctx.hostEl.dispatchEvent(new CustomEvent('hp:sticky', { detail: { sticky: true, corner } }));\n }\n\n private unstick(key: string, _reason: string): void {\n const item = this.items.get(key);\n if (!item) return;\n\n const wrapper = item.ctx.wrapperEl;\n wrapper.removeAttribute('data-sticky');\n wrapper.removeAttribute('data-sticky-corner');\n\n item.state.closeBtnEl?.remove();\n item.state.closeBtnEl = null;\n item.state.placeholderEl?.remove();\n item.state.placeholderEl = null;\n\n item.state.sticky = false;\n if (this.activeKey === key) this.activeKey = null;\n item.ctx.hostEl.dispatchEvent(new CustomEvent('hp:sticky', { detail: { sticky: false } }));\n }\n\n private pauseAndUnstick(key: string, reason: string): void {\n const item = this.items.get(key);\n if (!item) return;\n\n const now = Date.now();\n item.state.blockResumeUntil = now + BLOCK_RESUME_MS;\n item.state.programmaticPauseUntil = now + PROGRAMMATIC_PAUSE_MS;\n\n item.ctx.videoEl.pause();\n item.state.playing = false;\n this.unstick(key, reason);\n }\n\n // ── global dismiss (localStorage/sessionStorage) ──\n\n private loadDismissState(): void {\n if (this.dismissLoaded) return;\n this.dismissLoaded = true;\n try {\n const st = window.localStorage;\n this.dismissedUntil = Number(st.getItem(STORAGE_KEY) || 0) || 0;\n this.dismissedForever = st.getItem(STORAGE_KEY_FOREVER) === '1';\n } catch {\n /* storage erişilemez (gizli mod vb.) — sessizce yoksay */\n }\n }\n\n private applyGlobalDismiss(options: StickyItem['options']): void {\n if (options.dismissMode === 'none') return;\n const storage = options.storage === 'memory' ? null : options.storage === 'session' ? window.sessionStorage : window.localStorage;\n\n if (options.dismissMode === 'never') {\n this.dismissedForever = true;\n try {\n storage?.setItem(STORAGE_KEY_FOREVER, '1');\n } catch {\n /* no-op */\n }\n return;\n }\n\n const until = Date.now() + options.cooldownMinutes * 60000;\n this.dismissedUntil = until;\n try {\n storage?.setItem(STORAGE_KEY, String(until));\n } catch {\n /* no-op */\n }\n }\n}\n\nexport const stickyManager = new StickyManagerImpl();\nexport type { StickyCorner };\n","import { stickyManager, type StickyPlayerContext, type StickyUnregister } from './StickyManager';\nimport type { StickyOptions } from '../../types';\n\n/** Dönen fonksiyon unregister/cleanup — HopePlayerElement.disconnectedCallback'te çağrılmalı. `refreshLabels()` da taşır (dil değişince close butonu için). */\nexport function installSticky(ctx: StickyPlayerContext, options: StickyOptions): StickyUnregister {\n return stickyManager.register(ctx, options);\n}\n\nexport type { StickyPlayerContext, StickyUnregister };\n"],"names":["STORAGE_KEY","STORAGE_KEY_FOREVER","StickyManagerImpl","__publicField","ctx","options","_a","resolved","sentinel","item","onPlay","onPause","onEnded","onAdStart","onAdEnd","unregister","target","btn","entries","entry","i","inView","isActive","wasPlaying","gestureWindow","userInitiated","kind","now","mode","isCurrentlySticky","isFirstAdEver","allow","source","last","_trigger","_b","wrapper","corner","ph","rect","key","_reason","reason","st","storage","until","stickyManager","installSticky"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var A = Object.defineProperty;
|
|
2
2
|
var N = (h, t, e) => t in h ? A(h, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : h[t] = e;
|
|
3
3
|
var r = (h, t, e) => N(h, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
-
import { c as b } from "./player-
|
|
4
|
+
import { c as b } from "./player-D2_HRzot.js";
|
|
5
5
|
const P = {
|
|
6
6
|
startIndex: 0,
|
|
7
7
|
loop: !0,
|
|
@@ -331,4 +331,4 @@ export {
|
|
|
331
331
|
L as HopeStory,
|
|
332
332
|
M as installStory
|
|
333
333
|
};
|
|
334
|
-
//# sourceMappingURL=story-
|
|
334
|
+
//# sourceMappingURL=story-CodA2dfn.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"story-BLBij82f.js","sources":["../../src/plugins/story/HopeStory.ts","../../src/plugins/story/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { PlayableItem, StoryOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface StoryPlayerContext {\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** .video-area — story aktifken 9:16'ya çevrilir (data-story attribute ile), destroy'da geri alınır. */\n videoAreaEl: HTMLElement;\n /** Gerçek player gövdesi (.media-layer + chrome + center-play-button) — orta pane'e taşınır, destroy'da geri alınır. */\n playerBodyEls: HTMLElement[];\n loadSource(src: string, type?: string): Promise<void>;\n setPoster(url: string): void;\n requestFreshAd(prerollTag?: string): void;\n i18n: HopeLocaleStrings;\n}\n\ntype Dir = 'next' | 'prev';\n\nconst DEFAULTS: Required<Omit<StoryOptions, 'items' | 'adTagPreroll' | 'gestures' | 'ui'>> = {\n startIndex: 0,\n loop: true,\n autoplayNext: true,\n preferHls: true,\n transitionMs: 380,\n adsOnItemChange: true,\n};\n\n/** Dikey video akışı (Shorts/Story): tek <video>, item değişiminde kaynak değişir. */\nexport class HopeStory {\n private readonly options: Required<Omit<StoryOptions, 'items' | 'adTagPreroll' | 'gestures' | 'ui'>>;\n private readonly gestureOpts: Required<NonNullable<StoryOptions['gestures']>>;\n private readonly uiOpts: Required<NonNullable<StoryOptions['ui']>>;\n private readonly items: PlayableItem[];\n\n private index: number;\n private destroyed = false;\n private switching = false;\n /** Geçiş sürerken gelen buton / klavye isteği — yok sayılmaz, geçiş bitince uygulanır (yalnızca sonuncusu). */\n private pendingNav: { dir: Dir; userInitiated: boolean } | null = null;\n private listOpen = false;\n private userHasStartedPlayback = false;\n private lastAdsIndex: number | null = null;\n private wheelAccum = 0;\n private lastNavAt = 0;\n private drag: { startY: number; startX: number; dy: number; active: boolean; id: number } | null = null;\n\n private readonly els: {\n viewport: HTMLElement;\n track: HTMLElement;\n panePrev: HTMLElement;\n paneCurrent: HTMLElement;\n paneNext: HTMLElement;\n overlay: HTMLElement;\n counter: HTMLElement;\n titleEl: HTMLElement;\n spotEl: HTMLElement;\n dots: HTMLElement;\n progressBar: HTMLElement;\n upBtn: HTMLButtonElement;\n downBtn: HTMLButtonElement;\n listBtn: HTMLButtonElement;\n panel: HTMLElement;\n grid: HTMLElement;\n };\n\n constructor(\n private readonly ctx: StoryPlayerContext,\n private readonly rawOptions: StoryOptions\n ) {\n this.options = { ...DEFAULTS, ...rawOptions };\n this.gestureOpts = {\n swipe: true,\n swipeThreshold: 0.12,\n wheel: true,\n wheelThreshold: 42,\n wheelCooldownMs: 620,\n keyboard: true,\n ...rawOptions.gestures,\n };\n this.uiOpts = { counter: true, title: true, spot: true, dots: true, progress: true, ...rawOptions.ui };\n this.items = Array.isArray(rawOptions.items) ? rawOptions.items : [];\n this.index = this.clamp(this.options.startIndex);\n\n this.els = this.buildDom();\n this.bindEvents();\n this.syncUi();\n this.preloadNeighbours();\n\n if (this.items.length) void this.loadItem(this.index, { isStart: true });\n }\n\n refreshLabels(): void {\n this.els.upBtn.setAttribute('aria-label', this.ctx.i18n.storyPrev);\n this.els.downBtn.setAttribute('aria-label', this.ctx.i18n.storyNext);\n this.els.listBtn.setAttribute('aria-label', this.ctx.i18n.storyAllVideos);\n this.renderList(this.els.grid);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n this.ctx.videoEl.removeEventListener('ended', this.onEnded);\n this.ctx.videoEl.removeEventListener('playing', this.onPlaying);\n this.ctx.videoEl.removeEventListener('play', this.onFirstPlay);\n this.ctx.videoEl.removeEventListener('timeupdate', this.onTimeUpdate);\n this.els.viewport.removeEventListener('wheel', this.onWheel);\n this.els.viewport.removeEventListener('pointerdown', this.onPointerDown);\n window.removeEventListener('pointermove', this.onPointerMove);\n window.removeEventListener('pointerup', this.onPointerUp);\n document.removeEventListener('keydown', this.onKeyDown);\n\n // player gövdesini .video-area'ya geri taşı, story DOM'unu kaldır.\n this.ctx.playerBodyEls.forEach((el) => this.ctx.videoAreaEl.appendChild(el));\n this.ctx.videoAreaEl.removeAttribute('data-story');\n this.els.viewport.remove();\n this.els.panel.remove();\n }\n\n // ── public api ──\n\n next(userInitiated = true): void {\n if (this.switching) {\n this.pendingNav = { dir: 'next', userInitiated };\n return;\n }\n const target = this.index + 1;\n if (target >= this.items.length) {\n if (!this.options.loop) return;\n void this.goTo(0, 'next', userInitiated);\n return;\n }\n void this.goTo(target, 'next', userInitiated);\n }\n\n prev(userInitiated = true): void {\n if (this.switching) {\n this.pendingNav = { dir: 'prev', userInitiated };\n return;\n }\n const target = this.index - 1;\n if (target < 0) {\n if (!this.options.loop) return;\n void this.goTo(this.items.length - 1, 'prev', userInitiated);\n return;\n }\n void this.goTo(target, 'prev', userInitiated);\n }\n\n async goTo(target: number, direction: Dir | null = null, userInitiated = true): Promise<void> {\n if (this.destroyed || this.switching) return;\n const i = this.clamp(target);\n if (i === this.index) return;\n\n const dir = direction || (i > this.index ? 'next' : 'prev');\n this.switching = true;\n try {\n this.fillPane(dir, this.items[i]);\n await this.animate(dir);\n this.index = i;\n this.syncUi();\n await this.loadItem(i, { userInitiated });\n this.preloadNeighbours();\n } finally {\n this.switching = false;\n }\n // Hızlı art arda dokunuş (ör. iki kez \"önceki\"): ikincisi kaybolmasın — hedef şimdiki konumdan hesaplanır.\n const pending = this.pendingNav;\n this.pendingNav = null;\n if (pending && !this.destroyed) pending.dir === 'next' ? this.next(pending.userInitiated) : this.prev(pending.userInitiated);\n }\n\n toggleList(force?: boolean): void {\n this.listOpen = typeof force === 'boolean' ? force : !this.listOpen;\n this.els.panel.setAttribute('aria-hidden', this.listOpen ? 'false' : 'true');\n this.els.listBtn.setAttribute('aria-expanded', this.listOpen ? 'true' : 'false');\n // translate-x/-y utility yerine inline transform: Shadow DOM'da tek eksenli Tailwind translate 'none' oluyor.\n this.els.panel.style.transform = this.listOpen ? 'translateX(0)' : 'translateX(100%)';\n }\n\n // ── dom ──\n\n private buildDom() {\n this.ctx.videoAreaEl.setAttribute('data-story', '1');\n\n const viewport = document.createElement('div');\n viewport.className = 'hp:absolute hp:inset-0 hp:overflow-hidden hp:touch-none';\n viewport.setAttribute('tabindex', '0');\n\n const track = document.createElement('div');\n track.className = 'hp:relative hp:w-full';\n track.style.height = '300%';\n track.style.transform = 'translate3d(0,-33.3333%,0)';\n track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n\n const panePrev = this.createPane();\n const paneCurrent = document.createElement('div');\n paneCurrent.className = 'hp:absolute hp:inset-x-0 hp:h-1/3';\n paneCurrent.style.top = '33.3333%';\n const paneNext = this.createPane();\n paneNext.style.top = '66.6667%';\n\n // Gerçek player gövdesini orta pane'e taşı.\n this.ctx.playerBodyEls.forEach((el) => paneCurrent.appendChild(el));\n\n track.append(panePrev, paneCurrent, paneNext);\n viewport.appendChild(track);\n\n const overlay = document.createElement('div');\n overlay.className = 'hp:absolute hp:inset-0 hp:z-20 hp:pointer-events-none hp:flex hp:flex-col hp:justify-between hp:p-3';\n\n const progressBar = document.createElement('div');\n progressBar.className = 'hp:h-0.5 hp:bg-white/30 hp:rounded-full hp:overflow-hidden';\n const progressFill = document.createElement('div');\n progressFill.className = 'hp:h-full hp:bg-accent hp:w-0';\n progressBar.appendChild(progressFill);\n\n const meta = document.createElement('div');\n meta.className = 'hp:flex hp:flex-col hp:gap-0.5 hp:text-white hp:drop-shadow hp:mt-2 hp:pointer-events-auto';\n const counter = document.createElement('span');\n counter.setAttribute('part', 'story-counter');\n counter.className = 'hp:text-xs hp:opacity-80';\n const titleEl = document.createElement('strong');\n titleEl.className = 'hp:text-sm';\n const spotEl = document.createElement('span');\n spotEl.className = 'hp:text-xs hp:opacity-80';\n meta.append(counter, titleEl, spotEl);\n\n const dots = document.createElement('div');\n dots.className = 'hp:absolute hp:right-2 hp:top-1/2 hp-center-y hp:flex hp:flex-col hp:gap-1 hp:pointer-events-none';\n\n const navWrap = document.createElement('div');\n navWrap.className = 'hp:flex hp:flex-col hp:gap-2 hp:self-end hp:pointer-events-auto hp:mb-16';\n const upBtn = this.navBtn('chevron-left', this.ctx.i18n.storyPrev);\n upBtn.style.transform = 'rotate(90deg)';\n const downBtn = this.navBtn('chevron-left', this.ctx.i18n.storyNext);\n downBtn.style.transform = 'rotate(-90deg)';\n navWrap.append(upBtn, downBtn);\n\n const listBtn = document.createElement('button');\n listBtn.type = 'button';\n listBtn.setAttribute('aria-label', this.ctx.i18n.storyAllVideos);\n listBtn.setAttribute('aria-expanded', 'false');\n // Konum tailwind.css `.hp-story-list-btn` — dar (dikey) player'da üst bara (ayarlar/PiP) taşınan butonların altında.\n listBtn.className =\n 'hp-story-list-btn hp:absolute hp:flex hp:items-center hp:justify-center hp:w-9 hp:h-9 hp:rounded-full ' +\n 'hp:bg-black/40 hp:text-white hp:border-0 hp:cursor-pointer hp:pointer-events-auto';\n listBtn.setAttribute('part', 'story-list-button');\n listBtn.appendChild(createIcon('grid', 'hp:text-base'));\n\n overlay.append(progressBar, meta, dots, navWrap, listBtn);\n\n const panel = document.createElement('aside');\n panel.className =\n 'hp:absolute hp:inset-y-0 hp:right-0 hp:w-72 hp:max-w-[80%] hp:bg-surface-elev hp:z-30 hp:overflow-y-auto hp:p-3 ' +\n 'hp:transition-transform hp:duration-300';\n panel.style.transform = 'translateX(100%)';\n panel.setAttribute('aria-hidden', 'true');\n const grid = document.createElement('div');\n grid.className = 'hp:flex hp:flex-col hp:gap-2 hp:mt-8';\n panel.appendChild(grid);\n\n this.ctx.videoAreaEl.append(viewport, overlay, panel);\n\n this.renderList(grid);\n\n return {\n viewport, track, panePrev, paneCurrent, paneNext, overlay,\n counter, titleEl, spotEl, dots, progressBar: progressFill,\n upBtn, downBtn, listBtn, panel, grid,\n };\n }\n\n private createPane(): HTMLElement {\n const pane = document.createElement('div');\n pane.className = 'hp:absolute hp:inset-x-0 hp:h-1/3 hp:bg-cover hp:bg-center hp:bg-black';\n return pane;\n }\n\n private navBtn(iconName: string, label: string): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.setAttribute('aria-label', label);\n btn.className =\n 'hp:flex hp:items-center hp:justify-center hp:w-8 hp:h-8 hp:rounded-full hp:bg-black/40 hp:text-white hp:border-0 hp:cursor-pointer';\n btn.appendChild(createIcon(iconName, 'hp:text-sm'));\n return btn;\n }\n\n private fillPane(dir: Dir, item: PlayableItem | undefined): void {\n const pane = dir === 'next' ? this.els.paneNext : this.els.panePrev;\n const img = item?.image || '';\n pane.style.backgroundImage = img ? `url(\"${img}\")` : 'none';\n }\n\n private animate(dir: Dir): Promise<void> {\n const track = this.els.track;\n return new Promise((resolve) => {\n let done = false;\n const finish = () => {\n if (done) return;\n done = true;\n track.removeEventListener('transitionend', finish);\n clearTimeout(timer);\n track.style.transition = 'none';\n track.style.transform = 'translate3d(0,-33.3333%,0)';\n void track.offsetHeight;\n track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n resolve();\n };\n track.addEventListener('transitionend', finish);\n const timer = setTimeout(finish, this.options.transitionMs + 120);\n track.style.transform = dir === 'next' ? 'translate3d(0,-66.6667%,0)' : 'translate3d(0,0,0)';\n });\n }\n\n // ── source / playback ──\n\n private async loadItem(i: number, opts: { userInitiated?: boolean; isStart?: boolean } = {}): Promise<void> {\n const item = this.items[i];\n if (!item) return;\n\n const mode = this.resolveMode(item);\n const payload = this.buildPayload(item, mode);\n if (!payload) return;\n\n this.ctx.videoEl.pause();\n if (item.image) this.ctx.setPoster(item.image);\n await this.ctx.loadSource(payload.src, payload.type);\n\n if (this.options.adsOnItemChange && this.lastAdsIndex !== i) {\n this.lastAdsIndex = i;\n this.ctx.requestFreshAd(item.adTagPreroll || this.rawOptions.adTagPreroll);\n }\n\n if (this.shouldAutoPlay(opts)) {\n try {\n await this.ctx.videoEl.play();\n } catch {\n /* autoplay engellendi */\n }\n }\n }\n\n private shouldAutoPlay({ userInitiated, isStart }: { userInitiated?: boolean; isStart?: boolean }): boolean {\n if (isStart) return !!this.ctx.videoEl.autoplay;\n if (userInitiated) return true;\n return this.options.autoplayNext && this.userHasStartedPlayback;\n }\n\n private resolveMode(item: PlayableItem): 'hls' | 'mp4' {\n const hasHls = this.hasMode(item, 'hls');\n const hasMp4 = this.hasMode(item, 'mp4');\n if (this.options.preferHls) return hasHls ? 'hls' : hasMp4 ? 'mp4' : 'hls';\n return hasMp4 ? 'mp4' : hasHls ? 'hls' : 'mp4';\n }\n\n private hasMode(item: PlayableItem, mode: 'hls' | 'mp4'): boolean {\n return Array.isArray(item[mode]) && item[mode]!.some((v) => v?.src);\n }\n\n private buildPayload(item: PlayableItem, mode: 'hls' | 'mp4'): { src: string; type?: string } | null {\n const list = (item[mode] || []).filter((v) => v?.src);\n if (!list.length) return null;\n const src = mode === 'mp4' ? list.find((v) => v.selected) || list[0] : list[0];\n return { src: src!.src, type: src!.type || (mode === 'hls' ? 'application/x-mpegURL' : 'video/mp4') };\n }\n\n // ── preload ──\n\n private preloadNeighbours(): void {\n const nav = navigator as Navigator & { connection?: { saveData?: boolean } };\n if (nav.connection?.saveData) return;\n\n [this.wrapIndex(this.index + 1), this.wrapIndex(this.index - 1)].forEach((i) => {\n if (i === this.index) return;\n const item = this.items[i];\n if (item?.image) {\n const img = new Image();\n img.decoding = 'async';\n img.src = item.image;\n }\n });\n }\n\n // ── ui sync ──\n\n private syncUi(): void {\n const item = this.items[this.index];\n const total = this.items.length;\n\n if (this.uiOpts.counter) this.els.counter.textContent = `${this.index + 1} / ${total}`;\n if (this.uiOpts.title) this.els.titleEl.textContent = item?.title || '';\n if (this.uiOpts.spot) this.els.spotEl.textContent = item?.spot || '';\n\n this.fillPane('prev', this.items[this.wrapIndex(this.index - 1)]);\n this.fillPane('next', this.items[this.wrapIndex(this.index + 1)]);\n\n const atStart = !this.options.loop && this.index === 0;\n const atEnd = !this.options.loop && this.index === total - 1;\n this.els.upBtn.disabled = atStart;\n this.els.downBtn.disabled = atEnd;\n\n if (this.uiOpts.dots) {\n if (this.els.dots.children.length !== total) {\n this.els.dots.innerHTML = '';\n for (let i = 0; i < total; i++) {\n const dot = document.createElement('i');\n dot.className = 'hp:block hp:w-1 hp:h-1 hp:rounded-full hp:bg-white/40';\n this.els.dots.appendChild(dot);\n }\n }\n Array.from(this.els.dots.children).forEach((el, i) => {\n (el as HTMLElement).className = `hp:block hp:w-1 hp:h-1 hp:rounded-full ${i === this.index ? 'hp:bg-white' : 'hp:bg-white/40'}`;\n });\n }\n\n this.setActiveThumb();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:itemchange', { detail: { index: this.index, source: 'story' } }));\n }\n\n private renderList(grid: HTMLElement): void {\n grid.innerHTML = '';\n this.items.forEach((item, i) => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'hp:flex hp:items-center hp:gap-2 hp:w-full hp:p-1.5 hp:rounded hp:text-left hp:text-on-surface hp:bg-transparent hp:border-0 hp:cursor-pointer hp:hover:bg-on-surface/5';\n btn.dataset.index = String(i);\n if (item.image) {\n const img = document.createElement('img');\n img.src = item.image;\n img.loading = 'lazy';\n img.className = 'hp:w-14 hp:aspect-[9/16] hp:object-cover hp:rounded hp:shrink-0';\n btn.appendChild(img);\n }\n const title = document.createElement('span');\n title.className = 'hp:text-xs hp:truncate';\n title.textContent = item.title || this.ctx.i18n.videoFallbackTitle(i);\n btn.appendChild(title);\n btn.addEventListener('click', () => {\n this.toggleList(false);\n void this.goTo(i);\n });\n grid.appendChild(btn);\n });\n }\n\n private setActiveThumb(): void {\n Array.from(this.els.grid.children).forEach((el, i) => {\n el.classList.toggle('hp:bg-accent/15', i === this.index);\n });\n }\n\n // ── events ──\n\n private bindEvents(): void {\n this.ctx.videoEl.addEventListener('ended', this.onEnded);\n this.ctx.videoEl.addEventListener('playing', this.onPlaying);\n this.ctx.videoEl.addEventListener('play', this.onFirstPlay);\n if (this.uiOpts.progress) this.ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n\n this.els.upBtn.addEventListener('click', () => this.prev());\n this.els.downBtn.addEventListener('click', () => this.next());\n this.els.listBtn.addEventListener('click', () => this.toggleList());\n\n this.els.grid.parentElement?.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Escape') this.toggleList(false);\n });\n\n if (this.gestureOpts.wheel) this.els.viewport.addEventListener('wheel', this.onWheel, { passive: false });\n if (this.gestureOpts.swipe) {\n this.els.viewport.addEventListener('pointerdown', this.onPointerDown);\n window.addEventListener('pointermove', this.onPointerMove, { passive: false });\n window.addEventListener('pointerup', this.onPointerUp);\n }\n if (this.gestureOpts.keyboard) document.addEventListener('keydown', this.onKeyDown);\n }\n\n private readonly onEnded = (): void => {\n if (!this.options.autoplayNext) return;\n if (!this.options.loop && this.index === this.items.length - 1) return;\n this.next(false);\n };\n\n private readonly onPlaying = (): void => {};\n\n private readonly onFirstPlay = (): void => {\n this.userHasStartedPlayback = true;\n };\n\n private readonly onTimeUpdate = (): void => {\n const dur = this.ctx.videoEl.duration || 0;\n const cur = this.ctx.videoEl.currentTime || 0;\n this.els.progressBar.style.width = dur > 0 ? `${Math.min(100, (cur / dur) * 100)}%` : '0%';\n };\n\n private readonly onWheel = (e: WheelEvent): void => {\n if (this.switching) {\n e.preventDefault();\n return;\n }\n const dir: Dir = e.deltaY > 0 ? 'next' : 'prev';\n if (!this.canGo(dir)) return;\n e.preventDefault();\n\n const now = Date.now();\n if (now - this.lastNavAt < this.gestureOpts.wheelCooldownMs) return;\n this.wheelAccum += e.deltaY;\n if (Math.abs(this.wheelAccum) < this.gestureOpts.wheelThreshold) return;\n this.wheelAccum = 0;\n this.lastNavAt = now;\n dir === 'next' ? this.next() : this.prev();\n };\n\n private readonly onPointerDown = (e: PointerEvent): void => {\n if (this.switching || this.listOpen) return;\n if (e.pointerType === 'mouse' && e.button !== 0) return;\n this.drag = { startY: e.clientY, startX: e.clientX, dy: 0, active: false, id: e.pointerId };\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n const drag = this.drag;\n if (!drag || e.pointerId !== drag.id) return;\n const dy = e.clientY - drag.startY;\n const dx = e.clientX - drag.startX;\n\n if (!drag.active) {\n if (Math.abs(dy) < 10 || Math.abs(dy) < Math.abs(dx)) return;\n drag.active = true;\n this.els.track.style.transition = 'none';\n }\n e.preventDefault();\n\n const h = this.els.viewport.clientHeight || 1;\n const resisted = this.canGo(dy < 0 ? 'next' : 'prev') ? dy : dy * 0.25;\n drag.dy = resisted;\n\n const pct = -33.3333 + (resisted / h) * 33.3333;\n this.els.track.style.transform = `translate3d(0, ${pct}%, 0)`;\n };\n\n private readonly onPointerUp = (): void => {\n const drag = this.drag;\n this.drag = null;\n if (!drag?.active) return;\n\n const h = this.els.viewport.clientHeight || 1;\n const ratio = Math.abs(drag.dy) / h;\n const dir: Dir = drag.dy < 0 ? 'next' : 'prev';\n\n this.els.track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n if (ratio >= this.gestureOpts.swipeThreshold && this.canGo(dir)) {\n this.els.track.style.transform = 'translate3d(0,-33.3333%,0)';\n dir === 'next' ? this.next() : this.prev();\n } else {\n this.els.track.style.transform = 'translate3d(0,-33.3333%,0)';\n }\n };\n\n private readonly onKeyDown = (e: KeyboardEvent): void => {\n if (this.destroyed) return;\n if (e.key === 'Escape' && this.listOpen) {\n this.toggleList(false);\n return;\n }\n const tag = document.activeElement?.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA') return;\n if (!this.isInViewport()) return;\n\n if (e.key === 'ArrowDown' || e.key === 'PageDown' || e.key === 'j') {\n e.preventDefault();\n this.next();\n } else if (e.key === 'ArrowUp' || e.key === 'PageUp' || e.key === 'k') {\n e.preventDefault();\n this.prev();\n }\n };\n\n // ── helpers ──\n\n private canGo(dir: Dir): boolean {\n if (this.options.loop) return this.items.length > 1;\n return dir === 'next' ? this.index < this.items.length - 1 : this.index > 0;\n }\n\n private isInViewport(): boolean {\n const r = this.ctx.hostEl.getBoundingClientRect();\n return r.bottom > 0 && r.top < (window.innerHeight || 0);\n }\n\n private clamp(i: number): number {\n if (!Number.isFinite(i) || !this.items.length) return 0;\n return Math.max(0, Math.min(this.items.length - 1, Math.trunc(i)));\n }\n\n private wrapIndex(i: number): number {\n const n = this.items.length;\n if (!n) return 0;\n if (this.options.loop) return ((i % n) + n) % n;\n return this.clamp(i);\n }\n}\n","import { HopeStory, type StoryPlayerContext } from './HopeStory';\nimport type { StoryOptions } from '../../types';\n\nexport function installStory(ctx: StoryPlayerContext, options: StoryOptions): HopeStory {\n return new HopeStory(ctx, options);\n}\n\nexport { HopeStory };\nexport type { StoryPlayerContext };\n"],"names":["DEFAULTS","HopeStory","ctx","rawOptions","__publicField","dur","cur","e","dir","now","drag","dy","dx","h","resisted","pct","ratio","tag","_a","el","userInitiated","target","direction","pending","force","viewport","track","panePrev","paneCurrent","paneNext","overlay","progressBar","progressFill","meta","counter","titleEl","spotEl","dots","navWrap","upBtn","downBtn","listBtn","createIcon","panel","grid","pane","iconName","label","btn","item","img","resolve","done","finish","timer","i","opts","mode","payload","isStart","hasHls","hasMp4","v","list","src","total","atStart","atEnd","dot","title","r","n","installStory","options"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"story-CodA2dfn.js","sources":["../../src/plugins/story/HopeStory.ts","../../src/plugins/story/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { PlayableItem, StoryOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface StoryPlayerContext {\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** .video-area — story aktifken 9:16'ya çevrilir (data-story attribute ile), destroy'da geri alınır. */\n videoAreaEl: HTMLElement;\n /** Gerçek player gövdesi (.media-layer + chrome + center-play-button) — orta pane'e taşınır, destroy'da geri alınır. */\n playerBodyEls: HTMLElement[];\n loadSource(src: string, type?: string): Promise<void>;\n setPoster(url: string): void;\n requestFreshAd(prerollTag?: string): void;\n i18n: HopeLocaleStrings;\n}\n\ntype Dir = 'next' | 'prev';\n\nconst DEFAULTS: Required<Omit<StoryOptions, 'items' | 'adTagPreroll' | 'gestures' | 'ui'>> = {\n startIndex: 0,\n loop: true,\n autoplayNext: true,\n preferHls: true,\n transitionMs: 380,\n adsOnItemChange: true,\n};\n\n/** Dikey video akışı (Shorts/Story): tek <video>, item değişiminde kaynak değişir. */\nexport class HopeStory {\n private readonly options: Required<Omit<StoryOptions, 'items' | 'adTagPreroll' | 'gestures' | 'ui'>>;\n private readonly gestureOpts: Required<NonNullable<StoryOptions['gestures']>>;\n private readonly uiOpts: Required<NonNullable<StoryOptions['ui']>>;\n private readonly items: PlayableItem[];\n\n private index: number;\n private destroyed = false;\n private switching = false;\n /** Geçiş sürerken gelen buton / klavye isteği — yok sayılmaz, geçiş bitince uygulanır (yalnızca sonuncusu). */\n private pendingNav: { dir: Dir; userInitiated: boolean } | null = null;\n private listOpen = false;\n private userHasStartedPlayback = false;\n private lastAdsIndex: number | null = null;\n private wheelAccum = 0;\n private lastNavAt = 0;\n private drag: { startY: number; startX: number; dy: number; active: boolean; id: number } | null = null;\n\n private readonly els: {\n viewport: HTMLElement;\n track: HTMLElement;\n panePrev: HTMLElement;\n paneCurrent: HTMLElement;\n paneNext: HTMLElement;\n overlay: HTMLElement;\n counter: HTMLElement;\n titleEl: HTMLElement;\n spotEl: HTMLElement;\n dots: HTMLElement;\n progressBar: HTMLElement;\n upBtn: HTMLButtonElement;\n downBtn: HTMLButtonElement;\n listBtn: HTMLButtonElement;\n panel: HTMLElement;\n grid: HTMLElement;\n };\n\n constructor(\n private readonly ctx: StoryPlayerContext,\n private readonly rawOptions: StoryOptions\n ) {\n this.options = { ...DEFAULTS, ...rawOptions };\n this.gestureOpts = {\n swipe: true,\n swipeThreshold: 0.12,\n wheel: true,\n wheelThreshold: 42,\n wheelCooldownMs: 620,\n keyboard: true,\n ...rawOptions.gestures,\n };\n this.uiOpts = { counter: true, title: true, spot: true, dots: true, progress: true, ...rawOptions.ui };\n this.items = Array.isArray(rawOptions.items) ? rawOptions.items : [];\n this.index = this.clamp(this.options.startIndex);\n\n this.els = this.buildDom();\n this.bindEvents();\n this.syncUi();\n this.preloadNeighbours();\n\n if (this.items.length) void this.loadItem(this.index, { isStart: true });\n }\n\n refreshLabels(): void {\n this.els.upBtn.setAttribute('aria-label', this.ctx.i18n.storyPrev);\n this.els.downBtn.setAttribute('aria-label', this.ctx.i18n.storyNext);\n this.els.listBtn.setAttribute('aria-label', this.ctx.i18n.storyAllVideos);\n this.renderList(this.els.grid);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n this.ctx.videoEl.removeEventListener('ended', this.onEnded);\n this.ctx.videoEl.removeEventListener('playing', this.onPlaying);\n this.ctx.videoEl.removeEventListener('play', this.onFirstPlay);\n this.ctx.videoEl.removeEventListener('timeupdate', this.onTimeUpdate);\n this.els.viewport.removeEventListener('wheel', this.onWheel);\n this.els.viewport.removeEventListener('pointerdown', this.onPointerDown);\n window.removeEventListener('pointermove', this.onPointerMove);\n window.removeEventListener('pointerup', this.onPointerUp);\n document.removeEventListener('keydown', this.onKeyDown);\n\n // player gövdesini .video-area'ya geri taşı, story DOM'unu kaldır.\n this.ctx.playerBodyEls.forEach((el) => this.ctx.videoAreaEl.appendChild(el));\n this.ctx.videoAreaEl.removeAttribute('data-story');\n this.els.viewport.remove();\n this.els.panel.remove();\n }\n\n // ── public api ──\n\n next(userInitiated = true): void {\n if (this.switching) {\n this.pendingNav = { dir: 'next', userInitiated };\n return;\n }\n const target = this.index + 1;\n if (target >= this.items.length) {\n if (!this.options.loop) return;\n void this.goTo(0, 'next', userInitiated);\n return;\n }\n void this.goTo(target, 'next', userInitiated);\n }\n\n prev(userInitiated = true): void {\n if (this.switching) {\n this.pendingNav = { dir: 'prev', userInitiated };\n return;\n }\n const target = this.index - 1;\n if (target < 0) {\n if (!this.options.loop) return;\n void this.goTo(this.items.length - 1, 'prev', userInitiated);\n return;\n }\n void this.goTo(target, 'prev', userInitiated);\n }\n\n async goTo(target: number, direction: Dir | null = null, userInitiated = true): Promise<void> {\n if (this.destroyed || this.switching) return;\n const i = this.clamp(target);\n if (i === this.index) return;\n\n const dir = direction || (i > this.index ? 'next' : 'prev');\n this.switching = true;\n try {\n this.fillPane(dir, this.items[i]);\n await this.animate(dir);\n this.index = i;\n this.syncUi();\n await this.loadItem(i, { userInitiated });\n this.preloadNeighbours();\n } finally {\n this.switching = false;\n }\n // Hızlı art arda dokunuş (ör. iki kez \"önceki\"): ikincisi kaybolmasın — hedef şimdiki konumdan hesaplanır.\n const pending = this.pendingNav;\n this.pendingNav = null;\n if (pending && !this.destroyed) pending.dir === 'next' ? this.next(pending.userInitiated) : this.prev(pending.userInitiated);\n }\n\n toggleList(force?: boolean): void {\n this.listOpen = typeof force === 'boolean' ? force : !this.listOpen;\n this.els.panel.setAttribute('aria-hidden', this.listOpen ? 'false' : 'true');\n this.els.listBtn.setAttribute('aria-expanded', this.listOpen ? 'true' : 'false');\n // translate-x/-y utility yerine inline transform: Shadow DOM'da tek eksenli Tailwind translate 'none' oluyor.\n this.els.panel.style.transform = this.listOpen ? 'translateX(0)' : 'translateX(100%)';\n }\n\n // ── dom ──\n\n private buildDom() {\n this.ctx.videoAreaEl.setAttribute('data-story', '1');\n\n const viewport = document.createElement('div');\n viewport.className = 'hp:absolute hp:inset-0 hp:overflow-hidden hp:touch-none';\n viewport.setAttribute('tabindex', '0');\n\n const track = document.createElement('div');\n track.className = 'hp:relative hp:w-full';\n track.style.height = '300%';\n track.style.transform = 'translate3d(0,-33.3333%,0)';\n track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n\n const panePrev = this.createPane();\n const paneCurrent = document.createElement('div');\n paneCurrent.className = 'hp:absolute hp:inset-x-0 hp:h-1/3';\n paneCurrent.style.top = '33.3333%';\n const paneNext = this.createPane();\n paneNext.style.top = '66.6667%';\n\n // Gerçek player gövdesini orta pane'e taşı.\n this.ctx.playerBodyEls.forEach((el) => paneCurrent.appendChild(el));\n\n track.append(panePrev, paneCurrent, paneNext);\n viewport.appendChild(track);\n\n const overlay = document.createElement('div');\n overlay.className = 'hp:absolute hp:inset-0 hp:z-20 hp:pointer-events-none hp:flex hp:flex-col hp:justify-between hp:p-3';\n\n const progressBar = document.createElement('div');\n progressBar.className = 'hp:h-0.5 hp:bg-white/30 hp:rounded-full hp:overflow-hidden';\n const progressFill = document.createElement('div');\n progressFill.className = 'hp:h-full hp:bg-accent hp:w-0';\n progressBar.appendChild(progressFill);\n\n const meta = document.createElement('div');\n meta.className = 'hp:flex hp:flex-col hp:gap-0.5 hp:text-white hp:drop-shadow hp:mt-2 hp:pointer-events-auto';\n const counter = document.createElement('span');\n counter.setAttribute('part', 'story-counter');\n counter.className = 'hp:text-xs hp:opacity-80';\n const titleEl = document.createElement('strong');\n titleEl.className = 'hp:text-sm';\n const spotEl = document.createElement('span');\n spotEl.className = 'hp:text-xs hp:opacity-80';\n meta.append(counter, titleEl, spotEl);\n\n const dots = document.createElement('div');\n dots.className = 'hp:absolute hp:right-2 hp:top-1/2 hp-center-y hp:flex hp:flex-col hp:gap-1 hp:pointer-events-none';\n\n const navWrap = document.createElement('div');\n navWrap.className = 'hp:flex hp:flex-col hp:gap-2 hp:self-end hp:pointer-events-auto hp:mb-16';\n const upBtn = this.navBtn('chevron-left', this.ctx.i18n.storyPrev);\n upBtn.style.transform = 'rotate(90deg)';\n const downBtn = this.navBtn('chevron-left', this.ctx.i18n.storyNext);\n downBtn.style.transform = 'rotate(-90deg)';\n navWrap.append(upBtn, downBtn);\n\n const listBtn = document.createElement('button');\n listBtn.type = 'button';\n listBtn.setAttribute('aria-label', this.ctx.i18n.storyAllVideos);\n listBtn.setAttribute('aria-expanded', 'false');\n // Konum tailwind.css `.hp-story-list-btn` — dar (dikey) player'da üst bara (ayarlar/PiP) taşınan butonların altında.\n listBtn.className =\n 'hp-story-list-btn hp:absolute hp:flex hp:items-center hp:justify-center hp:w-9 hp:h-9 hp:rounded-full ' +\n 'hp:bg-black/40 hp:text-white hp:border-0 hp:cursor-pointer hp:pointer-events-auto';\n listBtn.setAttribute('part', 'story-list-button');\n listBtn.appendChild(createIcon('grid', 'hp:text-base'));\n\n overlay.append(progressBar, meta, dots, navWrap, listBtn);\n\n const panel = document.createElement('aside');\n panel.className =\n 'hp:absolute hp:inset-y-0 hp:right-0 hp:w-72 hp:max-w-[80%] hp:bg-surface-elev hp:z-30 hp:overflow-y-auto hp:p-3 ' +\n 'hp:transition-transform hp:duration-300';\n panel.style.transform = 'translateX(100%)';\n panel.setAttribute('aria-hidden', 'true');\n const grid = document.createElement('div');\n grid.className = 'hp:flex hp:flex-col hp:gap-2 hp:mt-8';\n panel.appendChild(grid);\n\n this.ctx.videoAreaEl.append(viewport, overlay, panel);\n\n this.renderList(grid);\n\n return {\n viewport, track, panePrev, paneCurrent, paneNext, overlay,\n counter, titleEl, spotEl, dots, progressBar: progressFill,\n upBtn, downBtn, listBtn, panel, grid,\n };\n }\n\n private createPane(): HTMLElement {\n const pane = document.createElement('div');\n pane.className = 'hp:absolute hp:inset-x-0 hp:h-1/3 hp:bg-cover hp:bg-center hp:bg-black';\n return pane;\n }\n\n private navBtn(iconName: string, label: string): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.setAttribute('aria-label', label);\n btn.className =\n 'hp:flex hp:items-center hp:justify-center hp:w-8 hp:h-8 hp:rounded-full hp:bg-black/40 hp:text-white hp:border-0 hp:cursor-pointer';\n btn.appendChild(createIcon(iconName, 'hp:text-sm'));\n return btn;\n }\n\n private fillPane(dir: Dir, item: PlayableItem | undefined): void {\n const pane = dir === 'next' ? this.els.paneNext : this.els.panePrev;\n const img = item?.image || '';\n pane.style.backgroundImage = img ? `url(\"${img}\")` : 'none';\n }\n\n private animate(dir: Dir): Promise<void> {\n const track = this.els.track;\n return new Promise((resolve) => {\n let done = false;\n const finish = () => {\n if (done) return;\n done = true;\n track.removeEventListener('transitionend', finish);\n clearTimeout(timer);\n track.style.transition = 'none';\n track.style.transform = 'translate3d(0,-33.3333%,0)';\n void track.offsetHeight;\n track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n resolve();\n };\n track.addEventListener('transitionend', finish);\n const timer = setTimeout(finish, this.options.transitionMs + 120);\n track.style.transform = dir === 'next' ? 'translate3d(0,-66.6667%,0)' : 'translate3d(0,0,0)';\n });\n }\n\n // ── source / playback ──\n\n private async loadItem(i: number, opts: { userInitiated?: boolean; isStart?: boolean } = {}): Promise<void> {\n const item = this.items[i];\n if (!item) return;\n\n const mode = this.resolveMode(item);\n const payload = this.buildPayload(item, mode);\n if (!payload) return;\n\n this.ctx.videoEl.pause();\n if (item.image) this.ctx.setPoster(item.image);\n await this.ctx.loadSource(payload.src, payload.type);\n\n if (this.options.adsOnItemChange && this.lastAdsIndex !== i) {\n this.lastAdsIndex = i;\n this.ctx.requestFreshAd(item.adTagPreroll || this.rawOptions.adTagPreroll);\n }\n\n if (this.shouldAutoPlay(opts)) {\n try {\n await this.ctx.videoEl.play();\n } catch {\n /* autoplay engellendi */\n }\n }\n }\n\n private shouldAutoPlay({ userInitiated, isStart }: { userInitiated?: boolean; isStart?: boolean }): boolean {\n if (isStart) return !!this.ctx.videoEl.autoplay;\n if (userInitiated) return true;\n return this.options.autoplayNext && this.userHasStartedPlayback;\n }\n\n private resolveMode(item: PlayableItem): 'hls' | 'mp4' {\n const hasHls = this.hasMode(item, 'hls');\n const hasMp4 = this.hasMode(item, 'mp4');\n if (this.options.preferHls) return hasHls ? 'hls' : hasMp4 ? 'mp4' : 'hls';\n return hasMp4 ? 'mp4' : hasHls ? 'hls' : 'mp4';\n }\n\n private hasMode(item: PlayableItem, mode: 'hls' | 'mp4'): boolean {\n return Array.isArray(item[mode]) && item[mode]!.some((v) => v?.src);\n }\n\n private buildPayload(item: PlayableItem, mode: 'hls' | 'mp4'): { src: string; type?: string } | null {\n const list = (item[mode] || []).filter((v) => v?.src);\n if (!list.length) return null;\n const src = mode === 'mp4' ? list.find((v) => v.selected) || list[0] : list[0];\n return { src: src!.src, type: src!.type || (mode === 'hls' ? 'application/x-mpegURL' : 'video/mp4') };\n }\n\n // ── preload ──\n\n private preloadNeighbours(): void {\n const nav = navigator as Navigator & { connection?: { saveData?: boolean } };\n if (nav.connection?.saveData) return;\n\n [this.wrapIndex(this.index + 1), this.wrapIndex(this.index - 1)].forEach((i) => {\n if (i === this.index) return;\n const item = this.items[i];\n if (item?.image) {\n const img = new Image();\n img.decoding = 'async';\n img.src = item.image;\n }\n });\n }\n\n // ── ui sync ──\n\n private syncUi(): void {\n const item = this.items[this.index];\n const total = this.items.length;\n\n if (this.uiOpts.counter) this.els.counter.textContent = `${this.index + 1} / ${total}`;\n if (this.uiOpts.title) this.els.titleEl.textContent = item?.title || '';\n if (this.uiOpts.spot) this.els.spotEl.textContent = item?.spot || '';\n\n this.fillPane('prev', this.items[this.wrapIndex(this.index - 1)]);\n this.fillPane('next', this.items[this.wrapIndex(this.index + 1)]);\n\n const atStart = !this.options.loop && this.index === 0;\n const atEnd = !this.options.loop && this.index === total - 1;\n this.els.upBtn.disabled = atStart;\n this.els.downBtn.disabled = atEnd;\n\n if (this.uiOpts.dots) {\n if (this.els.dots.children.length !== total) {\n this.els.dots.innerHTML = '';\n for (let i = 0; i < total; i++) {\n const dot = document.createElement('i');\n dot.className = 'hp:block hp:w-1 hp:h-1 hp:rounded-full hp:bg-white/40';\n this.els.dots.appendChild(dot);\n }\n }\n Array.from(this.els.dots.children).forEach((el, i) => {\n (el as HTMLElement).className = `hp:block hp:w-1 hp:h-1 hp:rounded-full ${i === this.index ? 'hp:bg-white' : 'hp:bg-white/40'}`;\n });\n }\n\n this.setActiveThumb();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:itemchange', { detail: { index: this.index, source: 'story' } }));\n }\n\n private renderList(grid: HTMLElement): void {\n grid.innerHTML = '';\n this.items.forEach((item, i) => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'hp:flex hp:items-center hp:gap-2 hp:w-full hp:p-1.5 hp:rounded hp:text-left hp:text-on-surface hp:bg-transparent hp:border-0 hp:cursor-pointer hp:hover:bg-on-surface/5';\n btn.dataset.index = String(i);\n if (item.image) {\n const img = document.createElement('img');\n img.src = item.image;\n img.loading = 'lazy';\n img.className = 'hp:w-14 hp:aspect-[9/16] hp:object-cover hp:rounded hp:shrink-0';\n btn.appendChild(img);\n }\n const title = document.createElement('span');\n title.className = 'hp:text-xs hp:truncate';\n title.textContent = item.title || this.ctx.i18n.videoFallbackTitle(i);\n btn.appendChild(title);\n btn.addEventListener('click', () => {\n this.toggleList(false);\n void this.goTo(i);\n });\n grid.appendChild(btn);\n });\n }\n\n private setActiveThumb(): void {\n Array.from(this.els.grid.children).forEach((el, i) => {\n el.classList.toggle('hp:bg-accent/15', i === this.index);\n });\n }\n\n // ── events ──\n\n private bindEvents(): void {\n this.ctx.videoEl.addEventListener('ended', this.onEnded);\n this.ctx.videoEl.addEventListener('playing', this.onPlaying);\n this.ctx.videoEl.addEventListener('play', this.onFirstPlay);\n if (this.uiOpts.progress) this.ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n\n this.els.upBtn.addEventListener('click', () => this.prev());\n this.els.downBtn.addEventListener('click', () => this.next());\n this.els.listBtn.addEventListener('click', () => this.toggleList());\n\n this.els.grid.parentElement?.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Escape') this.toggleList(false);\n });\n\n if (this.gestureOpts.wheel) this.els.viewport.addEventListener('wheel', this.onWheel, { passive: false });\n if (this.gestureOpts.swipe) {\n this.els.viewport.addEventListener('pointerdown', this.onPointerDown);\n window.addEventListener('pointermove', this.onPointerMove, { passive: false });\n window.addEventListener('pointerup', this.onPointerUp);\n }\n if (this.gestureOpts.keyboard) document.addEventListener('keydown', this.onKeyDown);\n }\n\n private readonly onEnded = (): void => {\n if (!this.options.autoplayNext) return;\n if (!this.options.loop && this.index === this.items.length - 1) return;\n this.next(false);\n };\n\n private readonly onPlaying = (): void => {};\n\n private readonly onFirstPlay = (): void => {\n this.userHasStartedPlayback = true;\n };\n\n private readonly onTimeUpdate = (): void => {\n const dur = this.ctx.videoEl.duration || 0;\n const cur = this.ctx.videoEl.currentTime || 0;\n this.els.progressBar.style.width = dur > 0 ? `${Math.min(100, (cur / dur) * 100)}%` : '0%';\n };\n\n private readonly onWheel = (e: WheelEvent): void => {\n if (this.switching) {\n e.preventDefault();\n return;\n }\n const dir: Dir = e.deltaY > 0 ? 'next' : 'prev';\n if (!this.canGo(dir)) return;\n e.preventDefault();\n\n const now = Date.now();\n if (now - this.lastNavAt < this.gestureOpts.wheelCooldownMs) return;\n this.wheelAccum += e.deltaY;\n if (Math.abs(this.wheelAccum) < this.gestureOpts.wheelThreshold) return;\n this.wheelAccum = 0;\n this.lastNavAt = now;\n dir === 'next' ? this.next() : this.prev();\n };\n\n private readonly onPointerDown = (e: PointerEvent): void => {\n if (this.switching || this.listOpen) return;\n if (e.pointerType === 'mouse' && e.button !== 0) return;\n this.drag = { startY: e.clientY, startX: e.clientX, dy: 0, active: false, id: e.pointerId };\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n const drag = this.drag;\n if (!drag || e.pointerId !== drag.id) return;\n const dy = e.clientY - drag.startY;\n const dx = e.clientX - drag.startX;\n\n if (!drag.active) {\n if (Math.abs(dy) < 10 || Math.abs(dy) < Math.abs(dx)) return;\n drag.active = true;\n this.els.track.style.transition = 'none';\n }\n e.preventDefault();\n\n const h = this.els.viewport.clientHeight || 1;\n const resisted = this.canGo(dy < 0 ? 'next' : 'prev') ? dy : dy * 0.25;\n drag.dy = resisted;\n\n const pct = -33.3333 + (resisted / h) * 33.3333;\n this.els.track.style.transform = `translate3d(0, ${pct}%, 0)`;\n };\n\n private readonly onPointerUp = (): void => {\n const drag = this.drag;\n this.drag = null;\n if (!drag?.active) return;\n\n const h = this.els.viewport.clientHeight || 1;\n const ratio = Math.abs(drag.dy) / h;\n const dir: Dir = drag.dy < 0 ? 'next' : 'prev';\n\n this.els.track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n if (ratio >= this.gestureOpts.swipeThreshold && this.canGo(dir)) {\n this.els.track.style.transform = 'translate3d(0,-33.3333%,0)';\n dir === 'next' ? this.next() : this.prev();\n } else {\n this.els.track.style.transform = 'translate3d(0,-33.3333%,0)';\n }\n };\n\n private readonly onKeyDown = (e: KeyboardEvent): void => {\n if (this.destroyed) return;\n if (e.key === 'Escape' && this.listOpen) {\n this.toggleList(false);\n return;\n }\n const tag = document.activeElement?.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA') return;\n if (!this.isInViewport()) return;\n\n if (e.key === 'ArrowDown' || e.key === 'PageDown' || e.key === 'j') {\n e.preventDefault();\n this.next();\n } else if (e.key === 'ArrowUp' || e.key === 'PageUp' || e.key === 'k') {\n e.preventDefault();\n this.prev();\n }\n };\n\n // ── helpers ──\n\n private canGo(dir: Dir): boolean {\n if (this.options.loop) return this.items.length > 1;\n return dir === 'next' ? this.index < this.items.length - 1 : this.index > 0;\n }\n\n private isInViewport(): boolean {\n const r = this.ctx.hostEl.getBoundingClientRect();\n return r.bottom > 0 && r.top < (window.innerHeight || 0);\n }\n\n private clamp(i: number): number {\n if (!Number.isFinite(i) || !this.items.length) return 0;\n return Math.max(0, Math.min(this.items.length - 1, Math.trunc(i)));\n }\n\n private wrapIndex(i: number): number {\n const n = this.items.length;\n if (!n) return 0;\n if (this.options.loop) return ((i % n) + n) % n;\n return this.clamp(i);\n }\n}\n","import { HopeStory, type StoryPlayerContext } from './HopeStory';\nimport type { StoryOptions } from '../../types';\n\nexport function installStory(ctx: StoryPlayerContext, options: StoryOptions): HopeStory {\n return new HopeStory(ctx, options);\n}\n\nexport { HopeStory };\nexport type { StoryPlayerContext };\n"],"names":["DEFAULTS","HopeStory","ctx","rawOptions","__publicField","dur","cur","e","dir","now","drag","dy","dx","h","resisted","pct","ratio","tag","_a","el","userInitiated","target","direction","pending","force","viewport","track","panePrev","paneCurrent","paneNext","overlay","progressBar","progressFill","meta","counter","titleEl","spotEl","dots","navWrap","upBtn","downBtn","listBtn","createIcon","panel","grid","pane","iconName","label","btn","item","img","resolve","done","finish","timer","i","opts","mode","payload","isStart","hasHls","hasMp4","v","list","src","total","atStart","atEnd","dot","title","r","n","installStory","options"],"mappings":"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"}
|