@hopeplayer/core 1.5.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.
Files changed (105) hide show
  1. package/dist/HopePlayerElement.d.ts +24 -0
  2. package/dist/HopePlayerElement.d.ts.map +1 -1
  3. package/dist/chunks/adTriggers-BIAWe8o4.js +419 -0
  4. package/dist/chunks/adTriggers-BIAWe8o4.js.map +1 -0
  5. package/dist/chunks/{ads-C4tDPsUs.js → ads-DlpHPpR9.js} +2 -2
  6. package/dist/chunks/{ads-C4tDPsUs.js.map → ads-DlpHPpR9.js.map} +1 -1
  7. package/dist/chunks/{cast-Baxvu76A.js → cast-vHyi7oV_.js} +2 -2
  8. package/dist/chunks/{cast-Baxvu76A.js.map → cast-vHyi7oV_.js.map} +1 -1
  9. package/dist/chunks/docPip-wybMVP1H.js +82 -0
  10. package/dist/chunks/docPip-wybMVP1H.js.map +1 -0
  11. package/dist/chunks/heatmap-Bb7neaYU.js +92 -0
  12. package/dist/chunks/heatmap-Bb7neaYU.js.map +1 -0
  13. package/dist/chunks/{history-CvydU0aN.js → history-CwqLXiZi.js} +2 -2
  14. package/dist/chunks/{history-CvydU0aN.js.map → history-CwqLXiZi.js.map} +1 -1
  15. package/dist/chunks/interactive-CgltIneu.js +189 -0
  16. package/dist/chunks/interactive-CgltIneu.js.map +1 -0
  17. package/dist/chunks/{loopSection-CvF4l5uf.js → loopSection-Bwk4W8vz.js} +16 -16
  18. package/dist/chunks/loopSection-Bwk4W8vz.js.map +1 -0
  19. package/dist/chunks/{markers-Dr4-CCxE.js → markers-L69W3kj6.js} +53 -51
  20. package/dist/chunks/markers-L69W3kj6.js.map +1 -0
  21. package/dist/chunks/{player-DV4Hf5Cw.js → player-D2_HRzot.js} +1382 -1158
  22. package/dist/chunks/player-D2_HRzot.js.map +1 -0
  23. package/dist/chunks/{playlist-DJsdK6xm.js → playlist-CHfStNbQ.js} +2 -2
  24. package/dist/chunks/{playlist-DJsdK6xm.js.map → playlist-CHfStNbQ.js.map} +1 -1
  25. package/dist/chunks/plugin-style-CPJELe-i.js +17 -0
  26. package/dist/chunks/plugin-style-CPJELe-i.js.map +1 -0
  27. package/dist/chunks/{pluginHost-GxNfyP5E.js → pluginHost-cN2uGFeG.js} +2 -2
  28. package/dist/chunks/{pluginHost-GxNfyP5E.js.map → pluginHost-cN2uGFeG.js.map} +1 -1
  29. package/dist/chunks/redirectScreen-TIqLdvBY.js +239 -0
  30. package/dist/chunks/redirectScreen-TIqLdvBY.js.map +1 -0
  31. package/dist/chunks/{rewardedUnlock-jFOdzfSq.js → rewardedUnlock-DUqYwXTr.js} +2 -2
  32. package/dist/chunks/{rewardedUnlock-jFOdzfSq.js.map → rewardedUnlock-DUqYwXTr.js.map} +1 -1
  33. package/dist/chunks/segments-Ds-c1b5e.js +66 -0
  34. package/dist/chunks/segments-Ds-c1b5e.js.map +1 -0
  35. package/dist/chunks/{skipSegments-vJMhdiJn.js → skipSegments-ByNoF1qZ.js} +2 -2
  36. package/dist/chunks/{skipSegments-vJMhdiJn.js.map → skipSegments-ByNoF1qZ.js.map} +1 -1
  37. package/dist/chunks/{spriteThumbnails-BoxVY--_.js → spriteThumbnails-Cr9UmkM9.js} +28 -28
  38. package/dist/chunks/spriteThumbnails-Cr9UmkM9.js.map +1 -0
  39. package/dist/chunks/{sticky-D_eLCNFk.js → sticky-BDStzjBM.js} +27 -26
  40. package/dist/chunks/sticky-BDStzjBM.js.map +1 -0
  41. package/dist/chunks/{story-BRkhSDhR.js → story-CodA2dfn.js} +2 -2
  42. package/dist/chunks/{story-BRkhSDhR.js.map → story-CodA2dfn.js.map} +1 -1
  43. package/dist/chunks/transcript-LG7E9UYE.js +186 -0
  44. package/dist/chunks/transcript-LG7E9UYE.js.map +1 -0
  45. package/dist/controls/ContextMenu.d.ts +1 -0
  46. package/dist/controls/ContextMenu.d.ts.map +1 -1
  47. package/dist/controls/ControlBar.d.ts +6 -0
  48. package/dist/controls/ControlBar.d.ts.map +1 -1
  49. package/dist/controls/SeekBar.d.ts +5 -2
  50. package/dist/controls/SeekBar.d.ts.map +1 -1
  51. package/dist/controls/SettingsMenu.d.ts +2 -1
  52. package/dist/controls/SettingsMenu.d.ts.map +1 -1
  53. package/dist/hope-player.js +1 -1
  54. package/dist/i18n/locales/en.d.ts.map +1 -1
  55. package/dist/i18n/locales/tr.d.ts.map +1 -1
  56. package/dist/i18n/types.d.ts +25 -0
  57. package/dist/i18n/types.d.ts.map +1 -1
  58. package/dist/index.d.ts +1 -1
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/plugins/ad-triggers/AdTriggers.d.ts +5 -0
  61. package/dist/plugins/ad-triggers/AdTriggers.d.ts.map +1 -1
  62. package/dist/plugins/doc-pip/DocumentPip.d.ts +44 -0
  63. package/dist/plugins/doc-pip/DocumentPip.d.ts.map +1 -0
  64. package/dist/plugins/doc-pip/index.d.ts +5 -0
  65. package/dist/plugins/doc-pip/index.d.ts.map +1 -0
  66. package/dist/plugins/heatmap/Heatmap.d.ts +36 -0
  67. package/dist/plugins/heatmap/Heatmap.d.ts.map +1 -0
  68. package/dist/plugins/heatmap/index.d.ts +6 -0
  69. package/dist/plugins/heatmap/index.d.ts.map +1 -0
  70. package/dist/plugins/interactive/Interactive.d.ts +45 -0
  71. package/dist/plugins/interactive/Interactive.d.ts.map +1 -0
  72. package/dist/plugins/interactive/index.d.ts +6 -0
  73. package/dist/plugins/interactive/index.d.ts.map +1 -0
  74. package/dist/plugins/markers/MarkProgress.d.ts +3 -1
  75. package/dist/plugins/markers/MarkProgress.d.ts.map +1 -1
  76. package/dist/plugins/redirect-screen/RedirectScreen.d.ts +3 -1
  77. package/dist/plugins/redirect-screen/RedirectScreen.d.ts.map +1 -1
  78. package/dist/plugins/segments/Segments.d.ts +1 -0
  79. package/dist/plugins/segments/Segments.d.ts.map +1 -1
  80. package/dist/plugins/sprite-thumbnails/SpriteThumbnails.d.ts +1 -0
  81. package/dist/plugins/sprite-thumbnails/SpriteThumbnails.d.ts.map +1 -1
  82. package/dist/plugins/sticky/StickyManager.d.ts +2 -0
  83. package/dist/plugins/sticky/StickyManager.d.ts.map +1 -1
  84. package/dist/plugins/transcript/Transcript.d.ts +65 -0
  85. package/dist/plugins/transcript/Transcript.d.ts.map +1 -0
  86. package/dist/plugins/transcript/index.d.ts +6 -0
  87. package/dist/plugins/transcript/index.d.ts.map +1 -0
  88. package/dist/subtitles/attachTracks.d.ts +6 -0
  89. package/dist/subtitles/attachTracks.d.ts.map +1 -1
  90. package/dist/types/index.d.ts +164 -12
  91. package/dist/types/index.d.ts.map +1 -1
  92. package/dist/utils/plugin-style.d.ts +5 -0
  93. package/dist/utils/plugin-style.d.ts.map +1 -0
  94. package/package.json +1 -1
  95. package/dist/chunks/adTriggers-DXmtF4t2.js +0 -410
  96. package/dist/chunks/adTriggers-DXmtF4t2.js.map +0 -1
  97. package/dist/chunks/loopSection-CvF4l5uf.js.map +0 -1
  98. package/dist/chunks/markers-Dr4-CCxE.js.map +0 -1
  99. package/dist/chunks/player-DV4Hf5Cw.js.map +0 -1
  100. package/dist/chunks/redirectScreen-BT_26-5g.js +0 -208
  101. package/dist/chunks/redirectScreen-BT_26-5g.js.map +0 -1
  102. package/dist/chunks/segments--hl_QVrI.js +0 -63
  103. package/dist/chunks/segments--hl_QVrI.js.map +0 -1
  104. package/dist/chunks/spriteThumbnails-BoxVY--_.js.map +0 -1
  105. package/dist/chunks/sticky-D_eLCNFk.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"history-CvydU0aN.js","sources":["../../src/plugins/history/PlaybackHistory.ts","../../src/plugins/history/index.ts"],"sourcesContent":["import type { HistoryOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { formatTime } from '../../utils/format-time';\nimport { seekWhenReady } from '../shared/seekWhenReady';\n\nexport interface HistoryPlayerContext {\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n overlayContainerEl: HTMLElement;\n i18n: HopeLocaleStrings;\n /** Şu an yüklü kaynağın adresi (hls.js'te blob değil gerçek .m3u8) — `id` verilmezse videonun anahtarı. */\n currentSrc(): string | null;\n isAdActive(): boolean;\n /** `options.muted` — otomatik oynatma için sessiz istendiyse hatırlanan \"sesli\" durumu onu bozmasın. */\n mutedRequested(): boolean;\n /** QR ile devam (`?vtime=`) bu sayfa açılışında bir konum getirdiyse — ilk yüklemede o kazanır. */\n linkTimePresent: boolean;\n}\n\nconst POSITIONS_KEY = 'hp-history-positions';\nconst VOLUME_KEY = 'hp-history-volume';\n/** Bu kadar saniye izlenmeden konum kaydedilmez (yanlışlıkla açılan video). */\nconst DEFAULT_MIN_WATCHED = 10;\n/** Sona bu kadar kala \"bitti\" sayılır — kayıt silinir, sonraki açılışta baştan başlar. */\nconst DEFAULT_END_MARGIN = 15;\nconst DEFAULT_MAX_ENTRIES = 50;\nconst DEFAULT_TTL_DAYS = 30;\n/** Oynarken konum en fazla bu sıklıkla yazılır (ms). */\nconst SAVE_EVERY_MS = 5000;\nconst NOTICE_MS = 6000;\n\ninterface Entry {\n t: number;\n d: number;\n at: number;\n}\n\n/**\n * Zaman ve ses geçmişi: video yarıda bırakılırsa bir sonraki açılışta kaldığı yerden başlar (\"Kaldığınız yerden devam:\n * 0:42 · Baştan başla\" bildirimiyle); ses seviyesi ve sessiz durumu sitede hatırlanır. Kayıtlar tarayıcıda (localStorage).\n * Canlı yayında, reklam sırasında ve sona yakın konumda kayıt yapılmaz.\n */\nexport class PlaybackHistory {\n private key: string | null = null;\n private lastSaveAt = 0;\n private noticeEl: HTMLDivElement | null = null;\n private noticeTimer: ReturnType<typeof setTimeout> | null = null;\n private skipNextRestore: boolean;\n private readonly position: boolean;\n private readonly volume: boolean;\n private readonly minWatched: number;\n private readonly endMargin: number;\n\n constructor(\n private readonly ctx: HistoryPlayerContext,\n private readonly options: HistoryOptions\n ) {\n this.position = options.position !== false;\n this.volume = options.volume !== false;\n this.minWatched = options.minWatched ?? DEFAULT_MIN_WATCHED;\n this.endMargin = options.endMargin ?? DEFAULT_END_MARGIN;\n this.skipNextRestore = ctx.linkTimePresent;\n\n const v = ctx.videoEl;\n if (this.volume) {\n this.restoreVolume();\n v.addEventListener('volumechange', this.saveVolume);\n }\n if (this.position) {\n v.addEventListener('loadedmetadata', this.onLoadedMetadata);\n v.addEventListener('timeupdate', this.onTimeUpdate);\n v.addEventListener('pause', this.savePosition);\n v.addEventListener('seeked', this.savePosition);\n v.addEventListener('ended', this.onEnded);\n window.addEventListener('pagehide', this.savePosition);\n document.addEventListener('visibilitychange', this.onVisibility);\n if (v.readyState >= 1) this.onLoadedMetadata();\n }\n }\n\n destroy(): void {\n const v = this.ctx.videoEl;\n this.savePosition();\n v.removeEventListener('volumechange', this.saveVolume);\n v.removeEventListener('loadedmetadata', this.onLoadedMetadata);\n v.removeEventListener('timeupdate', this.onTimeUpdate);\n v.removeEventListener('pause', this.savePosition);\n v.removeEventListener('seeked', this.savePosition);\n v.removeEventListener('ended', this.onEnded);\n window.removeEventListener('pagehide', this.savePosition);\n document.removeEventListener('visibilitychange', this.onVisibility);\n this.hideNotice();\n }\n\n refreshLabels(): void {\n this.hideNotice();\n }\n\n // ── Konum ──\n\n private videoKey(): string | null {\n if (this.options.id) return `id:${this.options.id}`;\n const src = this.ctx.currentSrc();\n if (!src || src.startsWith('blob:') || src.startsWith('data:')) return null;\n try {\n const u = new URL(src, location.href);\n u.hash = '';\n return u.href;\n } catch {\n return src;\n }\n }\n\n private readonly onLoadedMetadata = (): void => {\n const v = this.ctx.videoEl;\n this.key = this.videoKey();\n this.lastSaveAt = 0;\n if (!this.key || !Number.isFinite(v.duration)) return;\n // Link ile gelen konum (QR ile devam) yalnızca bu açılışta kazanır.\n if (this.skipNextRestore) {\n this.skipNextRestore = false;\n return;\n }\n // Başka bir şey zaten sarmışsa (ör. kaynak değişiminde korunan konum) dokunma.\n if (v.currentTime > 1) return;\n const entry = this.entries()[this.key];\n if (!entry || entry.t < this.minWatched || entry.t > v.duration - this.endMargin) return;\n seekWhenReady(v, entry.t, { attempts: 2 });\n this.showNotice(entry.t);\n this.emit('resumed', entry.t);\n };\n\n private readonly onTimeUpdate = (): void => {\n if (Date.now() - this.lastSaveAt < SAVE_EVERY_MS) return;\n this.savePosition();\n };\n\n private readonly onVisibility = (): void => {\n if (document.visibilityState === 'hidden') this.savePosition();\n };\n\n private readonly savePosition = (): void => {\n const v = this.ctx.videoEl;\n if (!this.key || this.ctx.isAdActive() || v.seeking) return;\n const d = v.duration;\n if (!Number.isFinite(d) || d <= 0) return; // canlı yayın\n this.lastSaveAt = Date.now();\n const t = v.currentTime;\n const all = this.entries();\n if (t >= d - this.endMargin) delete all[this.key];\n else if (t >= this.minWatched) all[this.key] = { t: Math.floor(t), d: Math.round(d), at: Date.now() };\n else return;\n this.store(all);\n };\n\n private readonly onEnded = (): void => {\n if (!this.key) return;\n const all = this.entries();\n delete all[this.key];\n this.store(all);\n };\n\n /** Süresi geçenleri at, en yeni `maxEntries` kaydı tut. */\n private store(all: Record<string, Entry>): void {\n const ttl = (this.options.ttlDays ?? DEFAULT_TTL_DAYS) * 86_400_000;\n const max = this.options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n const now = Date.now();\n const kept = Object.entries(all)\n .filter(([, e]) => now - e.at < ttl)\n .sort((a, b) => b[1].at - a[1].at)\n .slice(0, max);\n write(POSITIONS_KEY, Object.fromEntries(kept));\n }\n\n private entries(): Record<string, Entry> {\n const raw = read<Record<string, Entry>>(POSITIONS_KEY);\n return raw && typeof raw === 'object' ? raw : {};\n }\n\n // ── Ses ──\n\n private restoreVolume(): void {\n const saved = read<{ volume: number; muted: boolean }>(VOLUME_KEY);\n if (!saved || typeof saved.volume !== 'number') return;\n const v = this.ctx.videoEl;\n v.volume = Math.min(1, Math.max(0, saved.volume));\n // Sessiz otomatik oynatma istendiyse (options.muted) \"sesli\" kaydı onu bozmasın; kullanıcı sessize aldıysa korunur.\n v.muted = this.ctx.mutedRequested() || !!saved.muted;\n }\n\n private readonly saveVolume = (): void => {\n if (this.ctx.isAdActive()) return;\n const v = this.ctx.videoEl;\n write(VOLUME_KEY, { volume: Math.round(v.volume * 100) / 100, muted: v.muted });\n };\n\n // ── Bildirim ──\n\n private showNotice(time: number): void {\n if (this.options.notice === false) return;\n this.hideNotice();\n const t = this.ctx.i18n;\n const el = document.createElement('div');\n el.className = 'hp-history-notice';\n el.setAttribute('part', 'history-notice');\n el.setAttribute('role', 'status');\n const text = document.createElement('span');\n text.textContent = t.historyResumed(formatTime(time));\n const restart = document.createElement('button');\n restart.type = 'button';\n restart.className = 'hp-history-restart';\n restart.textContent = t.historyRestart;\n restart.addEventListener('click', () => {\n const v = this.ctx.videoEl;\n v.currentTime = 0;\n if (this.key) {\n const all = this.entries();\n delete all[this.key];\n this.store(all);\n }\n this.emit('restart', 0);\n this.hideNotice();\n });\n el.append(text, restart);\n // Bildirimdeki tıklama oynat / duraklat'a geçmesin.\n for (const ev of ['pointerdown', 'mousedown', 'mouseup', 'touchstart', 'touchend', 'click', 'dblclick'] as const) el.addEventListener(ev, (e) => e.stopPropagation());\n this.ctx.overlayContainerEl.appendChild(el);\n this.noticeEl = el;\n this.noticeTimer = setTimeout(() => this.hideNotice(), NOTICE_MS);\n }\n\n private hideNotice(): void {\n if (this.noticeTimer) clearTimeout(this.noticeTimer);\n this.noticeTimer = null;\n this.noticeEl?.remove();\n this.noticeEl = null;\n }\n\n private emit(state: 'resumed' | 'restart', time: number): void {\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:history', { detail: { state, time, id: this.key } }));\n }\n}\n\nfunction read<T>(key: string): T | null {\n try {\n return JSON.parse(localStorage.getItem(key) ?? 'null') as T | null;\n } catch {\n return null;\n }\n}\n\nfunction write(key: string, value: unknown): void {\n try {\n localStorage.setItem(key, JSON.stringify(value));\n } catch {\n /* gizli sekme / kota dolu — geçmiş yalnızca bu oturumda yok */\n }\n}\n","import { PlaybackHistory, type HistoryPlayerContext } from './PlaybackHistory';\nimport type { HistoryOptions } from '../../types';\n\nexport function installHistory(ctx: HistoryPlayerContext, options: HistoryOptions): PlaybackHistory {\n return new PlaybackHistory(ctx, options);\n}\n\nexport { PlaybackHistory };\nexport type { HistoryPlayerContext };\n"],"names":["POSITIONS_KEY","VOLUME_KEY","DEFAULT_MIN_WATCHED","DEFAULT_END_MARGIN","DEFAULT_MAX_ENTRIES","DEFAULT_TTL_DAYS","SAVE_EVERY_MS","NOTICE_MS","PlaybackHistory","ctx","options","__publicField","v","entry","seekWhenReady","d","t","all","write","src","u","ttl","max","now","kept","e","b","raw","read","saved","time","el","text","formatTime","restart","ev","_a","state","key","value","installHistory"],"mappings":"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"}
1
+ {"version":3,"file":"history-CwqLXiZi.js","sources":["../../src/plugins/history/PlaybackHistory.ts","../../src/plugins/history/index.ts"],"sourcesContent":["import type { HistoryOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { formatTime } from '../../utils/format-time';\nimport { seekWhenReady } from '../shared/seekWhenReady';\n\nexport interface HistoryPlayerContext {\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n overlayContainerEl: HTMLElement;\n i18n: HopeLocaleStrings;\n /** Şu an yüklü kaynağın adresi (hls.js'te blob değil gerçek .m3u8) — `id` verilmezse videonun anahtarı. */\n currentSrc(): string | null;\n isAdActive(): boolean;\n /** `options.muted` — otomatik oynatma için sessiz istendiyse hatırlanan \"sesli\" durumu onu bozmasın. */\n mutedRequested(): boolean;\n /** QR ile devam (`?vtime=`) bu sayfa açılışında bir konum getirdiyse — ilk yüklemede o kazanır. */\n linkTimePresent: boolean;\n}\n\nconst POSITIONS_KEY = 'hp-history-positions';\nconst VOLUME_KEY = 'hp-history-volume';\n/** Bu kadar saniye izlenmeden konum kaydedilmez (yanlışlıkla açılan video). */\nconst DEFAULT_MIN_WATCHED = 10;\n/** Sona bu kadar kala \"bitti\" sayılır — kayıt silinir, sonraki açılışta baştan başlar. */\nconst DEFAULT_END_MARGIN = 15;\nconst DEFAULT_MAX_ENTRIES = 50;\nconst DEFAULT_TTL_DAYS = 30;\n/** Oynarken konum en fazla bu sıklıkla yazılır (ms). */\nconst SAVE_EVERY_MS = 5000;\nconst NOTICE_MS = 6000;\n\ninterface Entry {\n t: number;\n d: number;\n at: number;\n}\n\n/**\n * Zaman ve ses geçmişi: video yarıda bırakılırsa bir sonraki açılışta kaldığı yerden başlar (\"Kaldığınız yerden devam:\n * 0:42 · Baştan başla\" bildirimiyle); ses seviyesi ve sessiz durumu sitede hatırlanır. Kayıtlar tarayıcıda (localStorage).\n * Canlı yayında, reklam sırasında ve sona yakın konumda kayıt yapılmaz.\n */\nexport class PlaybackHistory {\n private key: string | null = null;\n private lastSaveAt = 0;\n private noticeEl: HTMLDivElement | null = null;\n private noticeTimer: ReturnType<typeof setTimeout> | null = null;\n private skipNextRestore: boolean;\n private readonly position: boolean;\n private readonly volume: boolean;\n private readonly minWatched: number;\n private readonly endMargin: number;\n\n constructor(\n private readonly ctx: HistoryPlayerContext,\n private readonly options: HistoryOptions\n ) {\n this.position = options.position !== false;\n this.volume = options.volume !== false;\n this.minWatched = options.minWatched ?? DEFAULT_MIN_WATCHED;\n this.endMargin = options.endMargin ?? DEFAULT_END_MARGIN;\n this.skipNextRestore = ctx.linkTimePresent;\n\n const v = ctx.videoEl;\n if (this.volume) {\n this.restoreVolume();\n v.addEventListener('volumechange', this.saveVolume);\n }\n if (this.position) {\n v.addEventListener('loadedmetadata', this.onLoadedMetadata);\n v.addEventListener('timeupdate', this.onTimeUpdate);\n v.addEventListener('pause', this.savePosition);\n v.addEventListener('seeked', this.savePosition);\n v.addEventListener('ended', this.onEnded);\n window.addEventListener('pagehide', this.savePosition);\n document.addEventListener('visibilitychange', this.onVisibility);\n if (v.readyState >= 1) this.onLoadedMetadata();\n }\n }\n\n destroy(): void {\n const v = this.ctx.videoEl;\n this.savePosition();\n v.removeEventListener('volumechange', this.saveVolume);\n v.removeEventListener('loadedmetadata', this.onLoadedMetadata);\n v.removeEventListener('timeupdate', this.onTimeUpdate);\n v.removeEventListener('pause', this.savePosition);\n v.removeEventListener('seeked', this.savePosition);\n v.removeEventListener('ended', this.onEnded);\n window.removeEventListener('pagehide', this.savePosition);\n document.removeEventListener('visibilitychange', this.onVisibility);\n this.hideNotice();\n }\n\n refreshLabels(): void {\n this.hideNotice();\n }\n\n // ── Konum ──\n\n private videoKey(): string | null {\n if (this.options.id) return `id:${this.options.id}`;\n const src = this.ctx.currentSrc();\n if (!src || src.startsWith('blob:') || src.startsWith('data:')) return null;\n try {\n const u = new URL(src, location.href);\n u.hash = '';\n return u.href;\n } catch {\n return src;\n }\n }\n\n private readonly onLoadedMetadata = (): void => {\n const v = this.ctx.videoEl;\n this.key = this.videoKey();\n this.lastSaveAt = 0;\n if (!this.key || !Number.isFinite(v.duration)) return;\n // Link ile gelen konum (QR ile devam) yalnızca bu açılışta kazanır.\n if (this.skipNextRestore) {\n this.skipNextRestore = false;\n return;\n }\n // Başka bir şey zaten sarmışsa (ör. kaynak değişiminde korunan konum) dokunma.\n if (v.currentTime > 1) return;\n const entry = this.entries()[this.key];\n if (!entry || entry.t < this.minWatched || entry.t > v.duration - this.endMargin) return;\n seekWhenReady(v, entry.t, { attempts: 2 });\n this.showNotice(entry.t);\n this.emit('resumed', entry.t);\n };\n\n private readonly onTimeUpdate = (): void => {\n if (Date.now() - this.lastSaveAt < SAVE_EVERY_MS) return;\n this.savePosition();\n };\n\n private readonly onVisibility = (): void => {\n if (document.visibilityState === 'hidden') this.savePosition();\n };\n\n private readonly savePosition = (): void => {\n const v = this.ctx.videoEl;\n if (!this.key || this.ctx.isAdActive() || v.seeking) return;\n const d = v.duration;\n if (!Number.isFinite(d) || d <= 0) return; // canlı yayın\n this.lastSaveAt = Date.now();\n const t = v.currentTime;\n const all = this.entries();\n if (t >= d - this.endMargin) delete all[this.key];\n else if (t >= this.minWatched) all[this.key] = { t: Math.floor(t), d: Math.round(d), at: Date.now() };\n else return;\n this.store(all);\n };\n\n private readonly onEnded = (): void => {\n if (!this.key) return;\n const all = this.entries();\n delete all[this.key];\n this.store(all);\n };\n\n /** Süresi geçenleri at, en yeni `maxEntries` kaydı tut. */\n private store(all: Record<string, Entry>): void {\n const ttl = (this.options.ttlDays ?? DEFAULT_TTL_DAYS) * 86_400_000;\n const max = this.options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n const now = Date.now();\n const kept = Object.entries(all)\n .filter(([, e]) => now - e.at < ttl)\n .sort((a, b) => b[1].at - a[1].at)\n .slice(0, max);\n write(POSITIONS_KEY, Object.fromEntries(kept));\n }\n\n private entries(): Record<string, Entry> {\n const raw = read<Record<string, Entry>>(POSITIONS_KEY);\n return raw && typeof raw === 'object' ? raw : {};\n }\n\n // ── Ses ──\n\n private restoreVolume(): void {\n const saved = read<{ volume: number; muted: boolean }>(VOLUME_KEY);\n if (!saved || typeof saved.volume !== 'number') return;\n const v = this.ctx.videoEl;\n v.volume = Math.min(1, Math.max(0, saved.volume));\n // Sessiz otomatik oynatma istendiyse (options.muted) \"sesli\" kaydı onu bozmasın; kullanıcı sessize aldıysa korunur.\n v.muted = this.ctx.mutedRequested() || !!saved.muted;\n }\n\n private readonly saveVolume = (): void => {\n if (this.ctx.isAdActive()) return;\n const v = this.ctx.videoEl;\n write(VOLUME_KEY, { volume: Math.round(v.volume * 100) / 100, muted: v.muted });\n };\n\n // ── Bildirim ──\n\n private showNotice(time: number): void {\n if (this.options.notice === false) return;\n this.hideNotice();\n const t = this.ctx.i18n;\n const el = document.createElement('div');\n el.className = 'hp-history-notice';\n el.setAttribute('part', 'history-notice');\n el.setAttribute('role', 'status');\n const text = document.createElement('span');\n text.textContent = t.historyResumed(formatTime(time));\n const restart = document.createElement('button');\n restart.type = 'button';\n restart.className = 'hp-history-restart';\n restart.textContent = t.historyRestart;\n restart.addEventListener('click', () => {\n const v = this.ctx.videoEl;\n v.currentTime = 0;\n if (this.key) {\n const all = this.entries();\n delete all[this.key];\n this.store(all);\n }\n this.emit('restart', 0);\n this.hideNotice();\n });\n el.append(text, restart);\n // Bildirimdeki tıklama oynat / duraklat'a geçmesin.\n for (const ev of ['pointerdown', 'mousedown', 'mouseup', 'touchstart', 'touchend', 'click', 'dblclick'] as const) el.addEventListener(ev, (e) => e.stopPropagation());\n this.ctx.overlayContainerEl.appendChild(el);\n this.noticeEl = el;\n this.noticeTimer = setTimeout(() => this.hideNotice(), NOTICE_MS);\n }\n\n private hideNotice(): void {\n if (this.noticeTimer) clearTimeout(this.noticeTimer);\n this.noticeTimer = null;\n this.noticeEl?.remove();\n this.noticeEl = null;\n }\n\n private emit(state: 'resumed' | 'restart', time: number): void {\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:history', { detail: { state, time, id: this.key } }));\n }\n}\n\nfunction read<T>(key: string): T | null {\n try {\n return JSON.parse(localStorage.getItem(key) ?? 'null') as T | null;\n } catch {\n return null;\n }\n}\n\nfunction write(key: string, value: unknown): void {\n try {\n localStorage.setItem(key, JSON.stringify(value));\n } catch {\n /* gizli sekme / kota dolu — geçmiş yalnızca bu oturumda yok */\n }\n}\n","import { PlaybackHistory, type HistoryPlayerContext } from './PlaybackHistory';\nimport type { HistoryOptions } from '../../types';\n\nexport function installHistory(ctx: HistoryPlayerContext, options: HistoryOptions): PlaybackHistory {\n return new PlaybackHistory(ctx, options);\n}\n\nexport { PlaybackHistory };\nexport type { HistoryPlayerContext };\n"],"names":["POSITIONS_KEY","VOLUME_KEY","DEFAULT_MIN_WATCHED","DEFAULT_END_MARGIN","DEFAULT_MAX_ENTRIES","DEFAULT_TTL_DAYS","SAVE_EVERY_MS","NOTICE_MS","PlaybackHistory","ctx","options","__publicField","v","entry","seekWhenReady","d","t","all","write","src","u","ttl","max","now","kept","e","b","raw","read","saved","time","el","text","formatTime","restart","ev","_a","state","key","value","installHistory"],"mappings":"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"}
@@ -0,0 +1,189 @@
1
+ var A = Object.defineProperty;
2
+ var z = (p, t, i) => t in p ? A(p, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : p[t] = i;
3
+ var d = (p, t, i) => z(p, typeof t != "symbol" ? t + "" : t, i);
4
+ import { c as L } from "./player-D2_HRzot.js";
5
+ import { a as S } from "./plugin-style-CPJELe-i.js";
6
+ const q = '.hp-ia{position:absolute;z-index:24;width:min(320px,calc(100% - 24px));max-height:calc(100% - 100px);overflow-y:auto;box-sizing:border-box;padding:12px;border:1px solid rgba(255,255,255,.12);border-radius:12px;background:#0e0e12e0;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);color:#fff;box-shadow:0 16px 36px -14px #000000d9;font:13px/1.4 system-ui,-apple-system,sans-serif;animation:hp-redirect-in .3s cubic-bezier(.2,.8,.2,1)}.hp-ia[data-position=top-right]{top:12px;right:12px}.hp-ia[data-position=top-left]{top:12px;left:12px}.hp-ia[data-position=bottom-right]{right:12px;bottom:76px}.hp-ia[data-position=bottom-left]{left:12px;bottom:76px}.hp-ia[data-position=center]{top:50%;left:50%;transform:translate(-50%,-50%);animation:hp-redirect-fade .25s ease-out}.video-area[data-chrome-hidden] .hp-ia[data-position^=bottom]{bottom:12px}.video-area[data-compact] .hp-ia{width:calc(100% - 16px);max-height:calc(100% - 64px);padding:10px}.video-area[data-compact] .hp-ia[data-position$=right],.video-area[data-compact] .hp-ia[data-position$=left]{left:8px;right:8px}.video-area[data-compact] .hp-ia[data-position^=top]{top:8px}.video-area[data-compact] .hp-ia[data-position^=bottom]{bottom:56px}.hp-ia-close{position:absolute;top:8px;right:8px;display:grid;place-items:center;width:24px;height:24px;padding:0;border:0;border-radius:999px;background:#ffffff1f;color:#fff;font-size:12px;cursor:pointer}.hp-ia-close:hover{background:#ffffff3d}.hp-ia-label{display:block;margin-bottom:4px;color:var(--hp-color-accent, #fff);font:700 10px/1.2 system-ui,-apple-system,sans-serif;letter-spacing:.1em;text-transform:uppercase}.hp-ia-question{margin:0 28px 10px 0;font-weight:600;font-size:14px}.hp-ia-choices{display:grid;gap:6px}.hp-ia-choice{position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;overflow:hidden;padding:8px 10px;border:1px solid rgba(255,255,255,.16);border-radius:8px;background:#ffffff0f;color:#fff;font:inherit;text-align:start;cursor:pointer;transition:background .15s,border-color .15s}.hp-ia-choice:hover:not(:disabled){background:#ffffff24}.hp-ia-choice:disabled{cursor:default}.hp-ia-choice[data-result]:before{content:"";position:absolute;inset:0 auto 0 0;width:var(--hp-ia-pct, 0%);background:#ffffff24;transition:width .6s cubic-bezier(.2,.8,.2,1)}.hp-ia-choice>span{position:relative}.hp-ia-choice[data-picked]{border-color:var(--hp-color-accent, #fff)}.hp-ia-choice[data-correct]{border-color:#2fbf71;background:#2fbf7138}.hp-ia-choice[data-wrong]{border-color:#e5484d;background:#e5484d38}.hp-ia-pct{flex:none;font-weight:600;font-variant-numeric:tabular-nums}.hp-ia-status{margin:8px 0 0;font-size:12.5px;opacity:.85}.hp-ia-status:empty{display:none}.hp-ia[data-type=product],.hp-ia[data-type=link]{padding:0}.hp-ia-card{display:flex;gap:10px;padding:8px 34px 8px 8px;color:#fff;text-decoration:none}.hp-ia-image{flex:none;width:72px;height:72px;border-radius:8px;object-fit:cover;background:#111}.hp-ia-body{display:flex;flex-direction:column;gap:2px;min-width:0}.hp-ia-body .hp-ia-label{margin-bottom:0}.hp-ia-title{display:-webkit-box;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-weight:600}.hp-ia-sub{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;opacity:.7;font-size:12px}.hp-ia-price{display:flex;gap:6px;align-items:baseline}.hp-ia-price s{opacity:.55;font-size:12px}.hp-ia-cta{align-self:flex-start;margin-top:4px;padding:5px 12px;border-radius:999px;background:var(--hp-color-accent, #fff);color:var(--hp-color-on-accent, #000);font-weight:600;font-size:12px}.hp-ia-card:hover .hp-ia-cta{filter:brightness(.92)}.hp-ia-choice:focus-visible,.hp-ia-close:focus-visible,.hp-ia-card:focus-visible{outline:2px solid var(--hp-color-accent, #fff);outline-offset:2px}.hp-seek-marker.hp-ia-marker{background:var(--hp-ia-marker-color, #f5c518)}@media(prefers-reduced-motion:reduce){.hp-ia,.hp-ia-choice[data-result]:before{animation:none;transition:none}}', E = "hp-interactive:", C = 1.5;
7
+ function T(p, t) {
8
+ return typeof p == "string" ? { id: String(t), text: p } : { id: p.id ?? String(t), text: p.text };
9
+ }
10
+ function n(p, t, i) {
11
+ const e = document.createElement(p);
12
+ return e.className = t, i !== void 0 && (e.textContent = i), e;
13
+ }
14
+ class $ {
15
+ constructor(t, i) {
16
+ d(this, "entries", []);
17
+ d(this, "active", null);
18
+ d(this, "markers", []);
19
+ d(this, "closeTimer", null);
20
+ d(this, "drawMarkers", () => {
21
+ for (const i of this.markers) i.remove();
22
+ this.markers = [];
23
+ const t = this.ctx.videoEl.duration;
24
+ if (!(this.options.markers === !1 || !Number.isFinite(t) || t <= 0))
25
+ for (const i of this.entries) {
26
+ if (i.item.time < 0 || i.item.time > t) continue;
27
+ const e = this.ctx.addSeekBarMarker(i.item.time / t, "hp-ia-marker", "question" in i.item ? i.item.question : i.item.title), o = i.item.markerColor ?? this.options.markerColor;
28
+ o && (e.style.backgroundColor = o), this.markers.push(e);
29
+ }
30
+ });
31
+ /** Yeni kaynak: oturum durumu sıfırlanır. */
32
+ d(this, "onEmptied", () => {
33
+ this.hide(null);
34
+ for (const t of this.entries) t.done = !1;
35
+ });
36
+ d(this, "onAdStart", () => {
37
+ this.active && !this.active.answered && this.hide("timeout");
38
+ });
39
+ /** Geri sarınca sonraki öğeler yeniden gösterilebilir (cevaplanmış anket / quiz yine sorulmaz). */
40
+ d(this, "onSeeked", () => {
41
+ var i;
42
+ const t = this.ctx.videoEl.currentTime;
43
+ for (const e of this.entries) e.item.time > t + 0.1 && e !== ((i = this.active) == null ? void 0 : i.entry) && (e.done = !1);
44
+ this.onTime();
45
+ });
46
+ d(this, "onTime", () => {
47
+ const t = this.ctx.videoEl.currentTime, i = this.active;
48
+ if (i)
49
+ if (t < i.entry.item.time - 0.5) this.hide("seek");
50
+ else if (!i.answered && t >= i.shownAt + this.duration(i.entry.item)) this.hide("timeout");
51
+ else if (i.answered && this.entries.some((e) => !e.done && t >= e.item.time && t - e.item.time <= C)) this.hide(null);
52
+ else return;
53
+ if (!this.ctx.isAdActive()) {
54
+ for (const e of this.entries)
55
+ if (!(e.done || t < e.item.time) && (e.done = !0, !(t - e.item.time > C || this.remembered(e)))) {
56
+ this.show(e, t);
57
+ return;
58
+ }
59
+ }
60
+ });
61
+ this.ctx = t, this.options = i, S(t.overlayEl, "interactive", q), this.entries = i.items.map((o, s) => ({ item: o, id: o.id ?? `i${s}`, done: !1 }));
62
+ const e = t.videoEl;
63
+ e.addEventListener("timeupdate", this.onTime), e.addEventListener("seeked", this.onSeeked), e.addEventListener("loadedmetadata", this.drawMarkers), e.addEventListener("emptied", this.onEmptied), t.hostEl.addEventListener("hp:adstart", this.onAdStart), e.readyState >= 1 && this.drawMarkers();
64
+ }
65
+ /** Yalnızca fonksiyonlar değişti (ör. React'te her render'da yeni onAnswer). */
66
+ setOptions(t) {
67
+ this.options = t;
68
+ }
69
+ refreshLabels() {
70
+ var t, i;
71
+ (i = (t = this.active) == null ? void 0 : t.el.querySelector(".hp-ia-close")) == null || i.setAttribute("aria-label", this.ctx.i18n.interactiveClose);
72
+ }
73
+ destroy() {
74
+ const t = this.ctx.videoEl;
75
+ t.removeEventListener("timeupdate", this.onTime), t.removeEventListener("seeked", this.onSeeked), t.removeEventListener("loadedmetadata", this.drawMarkers), t.removeEventListener("emptied", this.onEmptied), this.ctx.hostEl.removeEventListener("hp:adstart", this.onAdStart), this.hide(null);
76
+ for (const i of this.markers) i.remove();
77
+ this.markers = [];
78
+ }
79
+ emit(t, i, e = {}) {
80
+ return this.ctx.hostEl.dispatchEvent(
81
+ new CustomEvent("hp:interactive", { detail: { state: t, id: i.id, type: i.item.type, ...e }, cancelable: t === "click" })
82
+ );
83
+ }
84
+ remembered(t) {
85
+ if (this.options.rememberAnswers === !1 || t.item.type !== "poll" && t.item.type !== "quiz") return !1;
86
+ try {
87
+ return localStorage.getItem(E + t.id) !== null;
88
+ } catch {
89
+ return !1;
90
+ }
91
+ }
92
+ remember(t, i) {
93
+ if (this.options.rememberAnswers !== !1)
94
+ try {
95
+ localStorage.setItem(E + t.id, String(i));
96
+ } catch {
97
+ }
98
+ }
99
+ duration(t) {
100
+ return t.duration ?? (t.type === "poll" || t.type === "quiz" ? 15 : 8);
101
+ }
102
+ show(t, i) {
103
+ const e = t.item, o = n("div", "hp-ia");
104
+ o.setAttribute("part", `interactive interactive-${e.type}`), o.setAttribute("data-type", e.type), o.setAttribute("data-position", e.position ?? (e.type === "poll" || e.type === "quiz" ? "top-right" : "bottom-right")), o.setAttribute("role", "group");
105
+ for (const a of ["pointerdown", "click", "dblclick"]) o.addEventListener(a, (f) => f.stopPropagation());
106
+ if (o.addEventListener("keydown", (a) => a.stopPropagation()), e.dismissible !== !1) {
107
+ const a = n("button", "hp-ia-close");
108
+ a.type = "button", a.setAttribute("aria-label", this.ctx.i18n.interactiveClose), a.appendChild(L("close")), a.addEventListener("click", () => this.hide("user")), o.appendChild(a);
109
+ }
110
+ e.type === "poll" || e.type === "quiz" ? this.buildQuestion(o, t) : this.buildCard(o, t, e), this.ctx.overlayEl.appendChild(o);
111
+ const s = this.ctx.videoEl, r = !!e.pause && !s.paused;
112
+ r && s.pause(), this.active = { entry: t, el: o, shownAt: i, pausedByUs: r, answered: !1 }, this.emit("shown", t);
113
+ }
114
+ buildQuestion(t, i) {
115
+ const e = i.item, o = this.ctx.i18n;
116
+ t.appendChild(n("span", "hp-ia-label", e.type === "poll" ? o.interactivePoll : o.interactiveQuiz));
117
+ const s = n("p", "hp-ia-question", e.question);
118
+ s.id = `hp-ia-q-${i.id}`, t.setAttribute("aria-labelledby", s.id), t.appendChild(s);
119
+ const r = n("div", "hp-ia-choices"), a = e.choices.map(T), f = a.map((v, u) => {
120
+ const c = n("button", "hp-ia-choice");
121
+ return c.type = "button", c.appendChild(n("span", "hp-ia-choice-text", v.text)), c.addEventListener("click", () => void this.answer(i, u, a[u].id, f)), r.appendChild(c), c;
122
+ });
123
+ t.appendChild(r);
124
+ const l = n("p", "hp-ia-status");
125
+ l.setAttribute("aria-live", "polite"), t.appendChild(l);
126
+ }
127
+ async answer(t, i, e, o) {
128
+ var v, u, c, g, y, k;
129
+ const s = this.active;
130
+ if (!s || s.entry !== t || s.answered) return;
131
+ s.answered = !0;
132
+ const r = t.item, a = r.type === "quiz" ? i === r.answer : void 0;
133
+ this.remember(t, i);
134
+ for (const m of o) m.disabled = !0;
135
+ (v = o[i]) == null || v.setAttribute("data-picked", "");
136
+ const f = s.el.querySelector(".hp-ia-status");
137
+ this.emit("answer", t, { choice: i, choiceId: e, ...a !== void 0 ? { correct: a } : {} });
138
+ let l;
139
+ try {
140
+ l = await ((c = (u = this.options).onAnswer) == null ? void 0 : c.call(u, { item: r, id: t.id, choice: i, choiceId: e, correct: a }));
141
+ } catch {
142
+ l = void 0;
143
+ }
144
+ if (((g = this.active) == null ? void 0 : g.entry) === t) {
145
+ if (r.type === "quiz")
146
+ (y = o[r.answer]) == null || y.setAttribute("data-correct", ""), a || (k = o[i]) == null || k.setAttribute("data-wrong", ""), f && (f.textContent = `${a ? this.ctx.i18n.interactiveCorrect : this.ctx.i18n.interactiveWrong}${r.explanation ? ` ${r.explanation}` : ""}`);
147
+ else {
148
+ const m = Array.isArray(l) ? l : r.results ? r.results.map((x, h) => x + (h === i ? 1 : 0)) : null;
149
+ if (m) {
150
+ const x = m.reduce((h, b) => h + (Number.isFinite(b) && b > 0 ? b : 0), 0) || 1;
151
+ o.forEach((h, b) => {
152
+ const w = Math.round((m[b] ?? 0) / x * 100);
153
+ h.style.setProperty("--hp-ia-pct", `${w}%`), h.setAttribute("data-result", ""), h.appendChild(n("span", "hp-ia-pct", this.ctx.i18n.interactiveVotes(w)));
154
+ });
155
+ }
156
+ }
157
+ this.closeTimer = setTimeout(() => this.hide(null), r.type === "quiz" ? 5e3 : 3500);
158
+ }
159
+ }
160
+ buildCard(t, i, e) {
161
+ const o = this.ctx.i18n, s = n("a", "hp-ia-card");
162
+ if (s.href = e.url, e.newTab !== !1 && (s.target = "_blank", s.rel = "noopener"), e.image) {
163
+ const a = n("img", "hp-ia-image");
164
+ a.src = e.image, a.alt = "", a.decoding = "async", a.addEventListener("error", () => a.remove()), s.appendChild(a);
165
+ }
166
+ const r = n("span", "hp-ia-body");
167
+ if (e.sponsored && r.appendChild(n("span", "hp-ia-label", o.interactiveSponsored)), r.appendChild(n("span", "hp-ia-title", e.title)), e.subtitle && r.appendChild(n("span", "hp-ia-sub", e.subtitle)), e.price || e.oldPrice) {
168
+ const a = n("span", "hp-ia-price");
169
+ e.price && a.appendChild(n("strong", "", e.price)), e.oldPrice && a.appendChild(n("s", "", e.oldPrice)), r.appendChild(a);
170
+ }
171
+ r.appendChild(n("span", "hp-ia-cta", e.cta ?? (e.type === "product" ? o.interactiveBuy : o.interactiveGo))), s.appendChild(r), s.addEventListener("click", (a) => {
172
+ this.emit("click", i, { url: e.url }) || a.preventDefault();
173
+ }), t.setAttribute("aria-label", e.title), t.appendChild(s);
174
+ }
175
+ hide(t) {
176
+ this.closeTimer && clearTimeout(this.closeTimer), this.closeTimer = null;
177
+ const i = this.active;
178
+ i && (this.active = null, i.el.remove(), t && this.emit("dismiss", i.entry, { reason: t }), i.pausedByUs && t !== "seek" && this.ctx.videoEl.play().catch(() => {
179
+ }));
180
+ }
181
+ }
182
+ function I(p, t) {
183
+ return new $(p, t);
184
+ }
185
+ export {
186
+ $ as Interactive,
187
+ I as installInteractive
188
+ };
189
+ //# sourceMappingURL=interactive-CgltIneu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive-CgltIneu.js","sources":["../../src/plugins/interactive/Interactive.ts","../../src/plugins/interactive/index.ts"],"sourcesContent":["import type { InteractiveCard, InteractiveChoice, InteractiveItem, InteractiveOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { createIcon } from '../../icons/Icon';\nimport { adoptStyle } from '../../utils/plugin-style';\nimport css from './interactive.css?inline';\n\nexport interface InteractivePlayerContext {\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n overlayEl: HTMLElement;\n i18n: HopeLocaleStrings;\n isAdActive(): boolean;\n addSeekBarMarker(ratio: number, extraClass?: string, label?: string): HTMLElement;\n}\n\ninterface Entry {\n item: InteractiveItem;\n id: string;\n /** Bu oturumda gösterildi (ileri geri sarınca tekrar sorulmaz). */\n done: boolean;\n}\n\nconst STORE = 'hp-interactive:';\n/** Bu kadar saniye geç kalınırsa (ileri sarma) öğe atlanır. */\nconst LATE = 1.5;\n\nfunction choiceOf(c: string | InteractiveChoice, i: number): { id: string; text: string } {\n return typeof c === 'string' ? { id: String(i), text: c } : { id: c.id ?? String(i), text: c.text };\n}\n\nfunction el<K extends keyof HTMLElementTagNameMap>(tag: K, className: string, text?: string): HTMLElementTagNameMap[K] {\n const e = document.createElement(tag);\n e.className = className;\n if (text !== undefined) e.textContent = text;\n return e;\n}\n\n/**\n * Etkileşimli içerik: belirli saniyelerde anket, quiz, ürün ya da bağlantı kartı. Zamanlama videonun zamanıyla\n * işler (duraklatınca süre durur); ileri sarılıp geçilen öğe gösterilmez. Cevaplanan anket / quiz izleyiciye bir daha\n * sorulmaz (localStorage). Reklam oynarken gizlenir.\n */\nexport class Interactive {\n private entries: Entry[] = [];\n private active: { entry: Entry; el: HTMLElement; shownAt: number; pausedByUs: boolean; answered: boolean } | null = null;\n private markers: HTMLElement[] = [];\n private closeTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n private readonly ctx: InteractivePlayerContext,\n private options: InteractiveOptions\n ) {\n adoptStyle(ctx.overlayEl, 'interactive', css);\n this.entries = options.items.map((item, i) => ({ item, id: item.id ?? `i${i}`, done: false }));\n const v = ctx.videoEl;\n v.addEventListener('timeupdate', this.onTime);\n v.addEventListener('seeked', this.onSeeked);\n v.addEventListener('loadedmetadata', this.drawMarkers);\n v.addEventListener('emptied', this.onEmptied);\n ctx.hostEl.addEventListener('hp:adstart', this.onAdStart);\n if (v.readyState >= 1) this.drawMarkers();\n }\n\n /** Yalnızca fonksiyonlar değişti (ör. React'te her render'da yeni onAnswer). */\n setOptions(options: InteractiveOptions): void {\n this.options = options;\n }\n\n refreshLabels(): void {\n // Açık öğenin metinleri bir sonraki gösterimde dilden okunur; açık olanın kapat etiketi güncellenir.\n this.active?.el.querySelector('.hp-ia-close')?.setAttribute('aria-label', this.ctx.i18n.interactiveClose);\n }\n\n destroy(): void {\n const v = this.ctx.videoEl;\n v.removeEventListener('timeupdate', this.onTime);\n v.removeEventListener('seeked', this.onSeeked);\n v.removeEventListener('loadedmetadata', this.drawMarkers);\n v.removeEventListener('emptied', this.onEmptied);\n this.ctx.hostEl.removeEventListener('hp:adstart', this.onAdStart);\n this.hide(null);\n for (const m of this.markers) m.remove();\n this.markers = [];\n }\n\n private emit(state: 'shown' | 'answer' | 'click' | 'dismiss', entry: Entry, extra: Record<string, unknown> = {}): boolean {\n return this.ctx.hostEl.dispatchEvent(\n new CustomEvent('hp:interactive', { detail: { state, id: entry.id, type: entry.item.type, ...extra }, cancelable: state === 'click' })\n );\n }\n\n private readonly drawMarkers = (): void => {\n for (const m of this.markers) m.remove();\n this.markers = [];\n const d = this.ctx.videoEl.duration;\n if (this.options.markers === false || !Number.isFinite(d) || d <= 0) return;\n for (const e of this.entries) {\n if (e.item.time < 0 || e.item.time > d) continue;\n const m = this.ctx.addSeekBarMarker(e.item.time / d, 'hp-ia-marker', 'question' in e.item ? e.item.question : e.item.title);\n const color = e.item.markerColor ?? this.options.markerColor;\n if (color) m.style.backgroundColor = color;\n this.markers.push(m);\n }\n };\n\n /** Yeni kaynak: oturum durumu sıfırlanır. */\n private readonly onEmptied = (): void => {\n this.hide(null);\n for (const e of this.entries) e.done = false;\n };\n\n private readonly onAdStart = (): void => {\n // Reklam açık öğeyi örtmesin — kapat, reklamdan sonra tekrar gösterilmez.\n if (this.active && !this.active.answered) this.hide('timeout');\n };\n\n private remembered(entry: Entry): boolean {\n if (this.options.rememberAnswers === false || (entry.item.type !== 'poll' && entry.item.type !== 'quiz')) return false;\n try {\n return localStorage.getItem(STORE + entry.id) !== null;\n } catch {\n return false;\n }\n }\n\n private remember(entry: Entry, choice: number): void {\n if (this.options.rememberAnswers === false) return;\n try {\n localStorage.setItem(STORE + entry.id, String(choice));\n } catch {\n /* depolama kapalı */\n }\n }\n\n private duration(item: InteractiveItem): number {\n return item.duration ?? (item.type === 'poll' || item.type === 'quiz' ? 15 : 8);\n }\n\n /** Geri sarınca sonraki öğeler yeniden gösterilebilir (cevaplanmış anket / quiz yine sorulmaz). */\n private readonly onSeeked = (): void => {\n const t = this.ctx.videoEl.currentTime;\n for (const e of this.entries) if (e.item.time > t + 0.1 && e !== this.active?.entry) e.done = false;\n this.onTime();\n };\n\n private readonly onTime = (): void => {\n const t = this.ctx.videoEl.currentTime;\n const a = this.active;\n if (a) {\n // Geri sarıldı ya da süresi doldu (cevaplanmış anket sonucu kendi zamanlayıcısıyla kapanır).\n if (t < a.entry.item.time - 0.5) this.hide('seek');\n else if (!a.answered && t >= a.shownAt + this.duration(a.entry.item)) this.hide('timeout');\n // Sonuç gösterilirken sıradaki öğenin zamanı geldi — sonucu kapat, yenisini göster.\n else if (a.answered && this.entries.some((e) => !e.done && t >= e.item.time && t - e.item.time <= LATE)) this.hide(null);\n else return;\n }\n if (this.ctx.isAdActive()) return;\n for (const e of this.entries) {\n if (e.done || t < e.item.time) continue;\n e.done = true;\n // İleri sarılıp geçildiyse ya da daha önce cevaplandıysa gösterme.\n if (t - e.item.time > LATE || this.remembered(e)) continue;\n this.show(e, t);\n return;\n }\n };\n\n private show(entry: Entry, t: number): void {\n const item = entry.item;\n const box = el('div', 'hp-ia');\n box.setAttribute('part', `interactive interactive-${item.type}`);\n box.setAttribute('data-type', item.type);\n box.setAttribute('data-position', item.position ?? (item.type === 'poll' || item.type === 'quiz' ? 'top-right' : 'bottom-right'));\n box.setAttribute('role', 'group');\n for (const ev of ['pointerdown', 'click', 'dblclick'] as const) box.addEventListener(ev, (e) => e.stopPropagation());\n box.addEventListener('keydown', (e) => e.stopPropagation());\n\n if (item.dismissible !== false) {\n const close = el('button', 'hp-ia-close');\n close.type = 'button';\n close.setAttribute('aria-label', this.ctx.i18n.interactiveClose);\n close.appendChild(createIcon('close'));\n close.addEventListener('click', () => this.hide('user'));\n box.appendChild(close);\n }\n\n if (item.type === 'poll' || item.type === 'quiz') this.buildQuestion(box, entry);\n else this.buildCard(box, entry, item);\n\n this.ctx.overlayEl.appendChild(box);\n const v = this.ctx.videoEl;\n const pausedByUs = !!item.pause && !v.paused;\n if (pausedByUs) v.pause();\n this.active = { entry, el: box, shownAt: t, pausedByUs, answered: false };\n this.emit('shown', entry);\n }\n\n private buildQuestion(box: HTMLElement, entry: Entry): void {\n const item = entry.item as Extract<InteractiveItem, { type: 'poll' | 'quiz' }>;\n const i18n = this.ctx.i18n;\n box.appendChild(el('span', 'hp-ia-label', item.type === 'poll' ? i18n.interactivePoll : i18n.interactiveQuiz));\n const q = el('p', 'hp-ia-question', item.question);\n q.id = `hp-ia-q-${entry.id}`;\n box.setAttribute('aria-labelledby', q.id);\n box.appendChild(q);\n const list = el('div', 'hp-ia-choices');\n const choices = item.choices.map(choiceOf);\n const buttons = choices.map((c, i) => {\n const b = el('button', 'hp-ia-choice');\n b.type = 'button';\n b.appendChild(el('span', 'hp-ia-choice-text', c.text));\n b.addEventListener('click', () => void this.answer(entry, i, choices[i]!.id, buttons));\n list.appendChild(b);\n return b;\n });\n box.appendChild(list);\n const status = el('p', 'hp-ia-status');\n status.setAttribute('aria-live', 'polite');\n box.appendChild(status);\n }\n\n private async answer(entry: Entry, choice: number, choiceId: string, buttons: HTMLButtonElement[]): Promise<void> {\n const a = this.active;\n if (!a || a.entry !== entry || a.answered) return;\n a.answered = true;\n const item = entry.item as Extract<InteractiveItem, { type: 'poll' | 'quiz' }>;\n const correct = item.type === 'quiz' ? choice === item.answer : undefined;\n this.remember(entry, choice);\n for (const b of buttons) b.disabled = true;\n buttons[choice]?.setAttribute('data-picked', '');\n const status = a.el.querySelector<HTMLElement>('.hp-ia-status');\n this.emit('answer', entry, { choice, choiceId, ...(correct !== undefined ? { correct } : {}) });\n\n let results: number[] | void | undefined;\n try {\n results = await this.options.onAnswer?.({ item, id: entry.id, choice, choiceId, correct });\n } catch {\n results = undefined;\n }\n if (this.active?.entry !== entry) return;\n\n if (item.type === 'quiz') {\n buttons[item.answer]?.setAttribute('data-correct', '');\n if (!correct) buttons[choice]?.setAttribute('data-wrong', '');\n if (status) status.textContent = `${correct ? this.ctx.i18n.interactiveCorrect : this.ctx.i18n.interactiveWrong}${item.explanation ? ` ${item.explanation}` : ''}`;\n } else {\n // Sonuç: onAnswer'ın döndürdüğü, yoksa verilen dağılım + bu oy.\n const base = Array.isArray(results) ? results : item.results ? item.results.map((n, i) => n + (i === choice ? 1 : 0)) : null;\n if (base) {\n const total = base.reduce((s, n) => s + (Number.isFinite(n) && n > 0 ? n : 0), 0) || 1;\n buttons.forEach((b, i) => {\n const pct = Math.round(((base[i] ?? 0) / total) * 100);\n b.style.setProperty('--hp-ia-pct', `${pct}%`);\n b.setAttribute('data-result', '');\n b.appendChild(el('span', 'hp-ia-pct', this.ctx.i18n.interactiveVotes(pct)));\n });\n }\n }\n // Sonuç birkaç saniye görünür, sonra kapanır (duraklattıysak oynatma devam eder).\n this.closeTimer = setTimeout(() => this.hide(null), item.type === 'quiz' ? 5000 : 3500);\n }\n\n private buildCard(box: HTMLElement, entry: Entry, item: InteractiveCard): void {\n const i18n = this.ctx.i18n;\n const link = el('a', 'hp-ia-card');\n link.href = item.url;\n if (item.newTab !== false) {\n link.target = '_blank';\n link.rel = 'noopener';\n }\n if (item.image) {\n const img = el('img', 'hp-ia-image');\n img.src = item.image;\n img.alt = '';\n img.decoding = 'async';\n img.addEventListener('error', () => img.remove());\n link.appendChild(img);\n }\n const body = el('span', 'hp-ia-body');\n if (item.sponsored) body.appendChild(el('span', 'hp-ia-label', i18n.interactiveSponsored));\n body.appendChild(el('span', 'hp-ia-title', item.title));\n if (item.subtitle) body.appendChild(el('span', 'hp-ia-sub', item.subtitle));\n if (item.price || item.oldPrice) {\n const price = el('span', 'hp-ia-price');\n if (item.price) price.appendChild(el('strong', '', item.price));\n if (item.oldPrice) price.appendChild(el('s', '', item.oldPrice));\n body.appendChild(price);\n }\n body.appendChild(el('span', 'hp-ia-cta', item.cta ?? (item.type === 'product' ? i18n.interactiveBuy : i18n.interactiveGo)));\n link.appendChild(body);\n link.addEventListener('click', (e) => {\n // preventDefault → entegratör kendisi açar (sepete ekle, SPA router).\n if (!this.emit('click', entry, { url: item.url })) e.preventDefault();\n });\n box.setAttribute('aria-label', item.title);\n box.appendChild(link);\n }\n\n private hide(reason: 'user' | 'timeout' | 'seek' | null): void {\n if (this.closeTimer) clearTimeout(this.closeTimer);\n this.closeTimer = null;\n const a = this.active;\n if (!a) return;\n this.active = null;\n a.el.remove();\n if (reason) this.emit('dismiss', a.entry, { reason });\n if (a.pausedByUs && reason !== 'seek') void this.ctx.videoEl.play().catch(() => {});\n }\n}\n","import { Interactive, type InteractivePlayerContext } from './Interactive';\nimport type { InteractiveOptions } from '../../types';\n\nexport function installInteractive(ctx: InteractivePlayerContext, options: InteractiveOptions): Interactive {\n return new Interactive(ctx, options);\n}\n\nexport { Interactive };\nexport type { InteractivePlayerContext };\n"],"names":["STORE","LATE","choiceOf","c","i","el","tag","className","text","Interactive","ctx","options","__publicField","m","d","e","color","_a","a","adoptStyle","css","item","v","_b","state","entry","extra","choice","t","box","ev","close","createIcon","pausedByUs","i18n","q","list","choices","buttons","b","status","choiceId","correct","results","_c","_d","_e","_f","base","n","total","s","pct","link","img","body","price","reason","installInteractive"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  var v = Object.defineProperty;
2
2
  var m = (i, t, e) => t in i ? v(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
3
3
  var o = (i, t, e) => m(i, typeof t != "symbol" ? t + "" : t, e);
4
- class E {
4
+ class k {
5
5
  constructor(t, e, s = {}) {
6
6
  o(this, "seconds");
7
7
  o(this, "loopStart", null);
@@ -14,8 +14,8 @@ class E {
14
14
  }
15
15
  /** currentTime'dan geriye doğru tam N saniyelik bir aralığı döngüye alır (video başına yakınsa ileri doğru taşar). */
16
16
  enableLastN(t) {
17
- const e = this.video.currentTime, s = this.video.duration, n = t || this.seconds;
18
- this.loopStart = Math.max(0, e - n), this.loopEnd = Math.min(Number.isFinite(s) ? s : 1 / 0, this.loopStart + n), this.activate(), this.updateMarkers();
17
+ const e = this.video.currentTime, s = this.video.duration, r = t || this.seconds;
18
+ this.loopStart = Math.max(0, e - r), this.loopEnd = Math.min(Number.isFinite(s) ? s : 1 / 0, this.loopStart + r), this.activate(), this.updateMarkers();
19
19
  }
20
20
  setStart(t) {
21
21
  this.loopStart = t ?? this.video.currentTime, this.updateMarkers();
@@ -44,32 +44,32 @@ class E {
44
44
  updateMarkers() {
45
45
  this.markers.clearMarkers();
46
46
  const t = this.video.duration;
47
- !t || !Number.isFinite(t) || (this.loopStart !== null && this.markers.addMarker(this.loopStart / t, "hp:bg-accent"), this.loopEnd !== null && this.markers.addMarker(this.loopEnd / t, "hp:bg-accent"));
47
+ !t || !Number.isFinite(t) || (this.loopStart !== null && this.markers.addMarker(this.loopStart / t, "hp-seek-marker-loop"), this.loopEnd !== null && this.markers.addMarker(this.loopEnd / t, "hp-seek-marker-loop"));
48
48
  }
49
49
  }
50
50
  function S(i, t) {
51
- const e = new E(i.videoEl, i.markers, t), { btn: s } = i.addControlButton(i.i18n.loop, "loop", () => {
52
- e.toggle(), n();
53
- }), n = () => {
51
+ const e = new k(i.videoEl, i.markers, t), { btn: s } = i.addControlButton(i.i18n.loop, "loop", () => {
52
+ e.toggle(), r();
53
+ }), r = () => {
54
54
  s.classList.toggle("hp:text-accent", e.active);
55
55
  };
56
56
  e.refreshLabels = () => {
57
57
  s.setAttribute("aria-label", i.i18n.loop);
58
58
  };
59
- const a = (r) => {
60
- if (r.button !== 1) return;
61
- r.preventDefault();
62
- const l = i.seekBarEl.getBoundingClientRect(), u = Math.min(1, Math.max(0, (r.clientX - l.left) / l.width)), d = i.videoEl.duration, h = Number.isFinite(d) ? u * d : void 0, c = e.getState();
63
- c.active ? e.disable() : c.loopStart === null ? e.setStart(h) : e.setEnd(h), n();
59
+ const a = (n) => {
60
+ if (n.button !== 1) return;
61
+ n.preventDefault();
62
+ const l = i.seekBarEl.getBoundingClientRect(), c = Math.min(1, Math.max(0, (n.clientX - l.left) / l.width)), d = i.videoEl.duration, h = Number.isFinite(d) ? c * d : void 0, p = e.getState();
63
+ p.active ? e.disable() : p.loopStart === null ? e.setStart(h) : e.setEnd(h), r();
64
64
  };
65
65
  i.seekBarEl.addEventListener("mousedown", a);
66
- const p = e.destroy.bind(e);
66
+ const u = e.destroy.bind(e);
67
67
  return e.destroy = () => {
68
- i.seekBarEl.removeEventListener("mousedown", a), p();
68
+ i.seekBarEl.removeEventListener("mousedown", a), u();
69
69
  }, e;
70
70
  }
71
71
  export {
72
- E as LoopSection,
72
+ k as LoopSection,
73
73
  S as installLoopSection
74
74
  };
75
- //# sourceMappingURL=loopSection-CvF4l5uf.js.map
75
+ //# sourceMappingURL=loopSection-Bwk4W8vz.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopSection-Bwk4W8vz.js","sources":["../../src/plugins/loop-section/LoopSection.ts","../../src/plugins/loop-section/index.ts"],"sourcesContent":["import type { LoopSectionOptions } from '../../types';\n\nexport interface LoopSeekBarMarkers {\n addMarker(ratio: number, extraClass?: string): HTMLDivElement;\n clearMarkers(): void;\n}\n\nexport interface LoopSectionState {\n active: boolean;\n loopStart: number | null;\n loopEnd: number | null;\n}\n\n/** A/B döngü motoru. */\nexport class LoopSection {\n private readonly seconds: number;\n loopStart: number | null = null;\n loopEnd: number | null = null;\n active = false;\n\n constructor(\n private readonly video: HTMLVideoElement,\n private readonly markers: LoopSeekBarMarkers,\n options: LoopSectionOptions = {}\n ) {\n this.seconds = options.seconds || 10;\n }\n\n /** currentTime'dan geriye doğru tam N saniyelik bir aralığı döngüye alır (video başına yakınsa ileri doğru taşar). */\n enableLastN(secs?: number): void {\n const now = this.video.currentTime;\n const duration = this.video.duration;\n const s = secs || this.seconds;\n this.loopStart = Math.max(0, now - s);\n this.loopEnd = Math.min(Number.isFinite(duration) ? duration : Infinity, this.loopStart + s);\n this.activate();\n this.updateMarkers();\n }\n\n setStart(time?: number): void {\n this.loopStart = time ?? this.video.currentTime;\n this.updateMarkers();\n }\n\n setEnd(time?: number): void {\n this.loopEnd = time ?? this.video.currentTime;\n if (this.loopStart !== null && this.loopEnd > this.loopStart) {\n this.activate();\n this.updateMarkers();\n }\n }\n\n toggle(): void {\n if (this.active) this.disable();\n else this.enableLastN();\n }\n\n disable(): void {\n this.active = false;\n this.loopStart = null;\n this.loopEnd = null;\n this.video.removeEventListener('timeupdate', this.onTimeUpdate);\n this.markers.clearMarkers();\n }\n\n getState(): LoopSectionState {\n return { active: this.active, loopStart: this.loopStart, loopEnd: this.loopEnd };\n }\n\n /** `installLoopSection` bunu gerçek buton etiketini tazeleyen bir implementasyonla override eder (bkz. index.ts) — `destroy`'un üzerine yazılma deseniyle aynı. */\n refreshLabels(): void {\n /* no-op varsayılan */\n }\n\n destroy(): void {\n this.disable();\n }\n\n private activate(): void {\n this.active = true;\n this.video.removeEventListener('timeupdate', this.onTimeUpdate);\n this.video.addEventListener('timeupdate', this.onTimeUpdate);\n }\n\n private readonly onTimeUpdate = (): void => {\n if (this.loopEnd !== null && this.video.currentTime >= this.loopEnd) {\n this.video.currentTime = this.loopStart ?? 0;\n }\n };\n\n private updateMarkers(): void {\n this.markers.clearMarkers();\n const duration = this.video.duration;\n if (!duration || !Number.isFinite(duration)) return;\n\n if (this.loopStart !== null) {\n this.markers.addMarker(this.loopStart / duration, 'hp-seek-marker-loop');\n }\n if (this.loopEnd !== null) {\n this.markers.addMarker(this.loopEnd / duration, 'hp-seek-marker-loop');\n }\n }\n}\n","import { LoopSection, type LoopSeekBarMarkers } from './LoopSection';\nimport type { LoopSectionOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface LoopSectionPlayerContext {\n videoEl: HTMLVideoElement;\n seekBarEl: HTMLElement;\n markers: LoopSeekBarMarkers;\n addControlButton(label: string, iconName: string, onClick: () => void): { btn: HTMLButtonElement; icon: HTMLElement };\n i18n: HopeLocaleStrings;\n}\n\n/** Döngü motorunu kurar: kontrol çubuğuna toggle butonu, seek bar'da orta-tık ile A → B → kapat. */\nexport function installLoopSection(ctx: LoopSectionPlayerContext, options: LoopSectionOptions): LoopSection {\n const engine = new LoopSection(ctx.videoEl, ctx.markers, options);\n\n const { btn } = ctx.addControlButton(ctx.i18n.loop, 'loop', () => {\n engine.toggle();\n refresh();\n });\n\n const refresh = (): void => {\n btn.classList.toggle('hp:text-accent', engine.active);\n };\n\n engine.refreshLabels = () => {\n btn.setAttribute('aria-label', ctx.i18n.loop);\n };\n\n const onSeekBarMiddleClick = (e: MouseEvent): void => {\n if (e.button !== 1) return;\n e.preventDefault();\n\n const rect = ctx.seekBarEl.getBoundingClientRect();\n const ratio = Math.min(1, Math.max(0, (e.clientX - rect.left) / rect.width));\n const duration = ctx.videoEl.duration;\n const clickTime = Number.isFinite(duration) ? ratio * duration : undefined;\n\n const state = engine.getState();\n if (state.active) engine.disable();\n else if (state.loopStart === null) engine.setStart(clickTime);\n else engine.setEnd(clickTime);\n\n refresh();\n };\n ctx.seekBarEl.addEventListener('mousedown', onSeekBarMiddleClick);\n\n const originalDestroy = engine.destroy.bind(engine);\n engine.destroy = () => {\n ctx.seekBarEl.removeEventListener('mousedown', onSeekBarMiddleClick);\n originalDestroy();\n };\n\n return engine;\n}\n\nexport { LoopSection };\nexport type { LoopSeekBarMarkers };\n"],"names":["LoopSection","video","markers","options","__publicField","secs","now","duration","s","time","installLoopSection","ctx","engine","btn","refresh","onSeekBarMiddleClick","e","rect","ratio","clickTime","state","originalDestroy"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  var u = Object.defineProperty;
2
- var m = (p, e, t) => e in p ? u(p, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : p[e] = t;
3
- var o = (p, e, t) => m(p, typeof e != "symbol" ? e + "" : e, t);
4
- import { c as b } from "./player-DV4Hf5Cw.js";
5
- const f = {
2
+ var m = (h, e, t) => e in h ? u(h, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : h[e] = t;
3
+ var s = (h, e, t) => m(h, typeof e != "symbol" ? e + "" : e, t);
4
+ import { c as f } from "./player-D2_HRzot.js";
5
+ const b = {
6
6
  enabled: !1,
7
7
  mode: "rich",
8
8
  text: "",
@@ -21,33 +21,35 @@ const f = {
21
21
  }, k = { enabled: !1, url: "", method: "GET", includeMarker: !1 };
22
22
  class v {
23
23
  constructor(e, t) {
24
- o(this, "markers");
25
- o(this, "popupGlobal");
26
- o(this, "pingGlobal");
27
- o(this, "triggerOnSeek");
28
- o(this, "seekJumpThresholdSec");
29
- o(this, "seekIgnoreWindowMs");
30
- o(this, "hitSet", /* @__PURE__ */ new Set());
31
- o(this, "lastHitAt", /* @__PURE__ */ new Map());
32
- o(this, "lastTime", 0);
33
- o(this, "isSeeking", !1);
34
- o(this, "ignoreUntilTs", 0);
35
- o(this, "popupEl", null);
36
- o(this, "onLoadedMetadata", () => {
24
+ s(this, "markers");
25
+ s(this, "popupGlobal");
26
+ s(this, "pingGlobal");
27
+ s(this, "triggerOnSeek");
28
+ s(this, "seekJumpThresholdSec");
29
+ s(this, "seekIgnoreWindowMs");
30
+ /** `options.color` — öğede renk yoksa. */
31
+ s(this, "defaultColor");
32
+ s(this, "hitSet", /* @__PURE__ */ new Set());
33
+ s(this, "lastHitAt", /* @__PURE__ */ new Map());
34
+ s(this, "lastTime", 0);
35
+ s(this, "isSeeking", !1);
36
+ s(this, "ignoreUntilTs", 0);
37
+ s(this, "popupEl", null);
38
+ s(this, "onLoadedMetadata", () => {
37
39
  const e = this.ctx.videoEl.duration;
38
40
  !Number.isFinite(e) || e <= 0 || (this.markers.forEach((t) => {
39
41
  if (t.el) return;
40
- const i = this.ctx.addSeekBarMarker(t.time / e);
41
- t.color && (i.style.backgroundColor = t.color), t.label && (i.title = t.label), t.el = i;
42
+ const i = this.ctx.addSeekBarMarker(t.time / e, "", t.label);
43
+ t.color && (i.style.backgroundColor = t.color), t.el = i;
42
44
  }), this.lastTime = this.ctx.videoEl.currentTime || 0);
43
45
  });
44
- o(this, "onSeeking", () => {
46
+ s(this, "onSeeking", () => {
45
47
  this.isSeeking = !0, this.ignoreUntilTs = Date.now() + this.seekIgnoreWindowMs, this.lastTime = this.ctx.videoEl.currentTime || 0;
46
48
  });
47
- o(this, "onSeeked", () => {
49
+ s(this, "onSeeked", () => {
48
50
  this.lastTime = this.ctx.videoEl.currentTime || 0, this.isSeeking = !1, this.ignoreUntilTs = Date.now() + this.seekIgnoreWindowMs;
49
51
  });
50
- o(this, "onTimeUpdate", () => {
52
+ s(this, "onTimeUpdate", () => {
51
53
  const e = Date.now();
52
54
  if (e < this.ignoreUntilTs || this.isSeeking) return;
53
55
  const t = this.ctx.videoEl.currentTime;
@@ -56,22 +58,22 @@ class v {
56
58
  this.lastTime = t;
57
59
  return;
58
60
  }
59
- for (const n of this.markers) {
60
- const a = `${n.time}-${n.idx}`;
61
- if (n.once && this.hitSet.has(a)) continue;
62
- if (!n.once) {
61
+ for (const o of this.markers) {
62
+ const a = `${o.time}-${o.idx}`;
63
+ if (o.once && this.hitSet.has(a)) continue;
64
+ if (!o.once) {
63
65
  const r = this.lastHitAt.get(a) || 0;
64
- if (e - r < n.cooldownMs) continue;
66
+ if (e - r < o.cooldownMs) continue;
65
67
  }
66
- if (!(this.lastTime < n.time && t >= n.time - n.tolerance)) continue;
67
- n.once ? this.hitSet.add(a) : this.lastHitAt.set(a, e), n.pauseOnHit && this.ctx.videoEl.pause(), this.firePing(n), this.fireAction(n);
68
- const s = n.popup ? { ...this.popupGlobal, ...n.popup } : this.popupGlobal;
69
- s.enabled && (this.ctx.videoEl.pause(), this.showPopup(s));
68
+ if (!(this.lastTime < o.time && t >= o.time - o.tolerance)) continue;
69
+ o.once ? this.hitSet.add(a) : this.lastHitAt.set(a, e), o.pauseOnHit && this.ctx.videoEl.pause(), this.firePing(o), this.fireAction(o);
70
+ const n = o.popup ? { ...this.popupGlobal, ...o.popup } : this.popupGlobal;
71
+ n.enabled && (this.ctx.videoEl.pause(), this.showPopup(n));
70
72
  break;
71
73
  }
72
74
  this.lastTime = t;
73
75
  });
74
- this.ctx = e, this.triggerOnSeek = t.triggerOnSeek === !0, this.seekJumpThresholdSec = t.seekJumpThresholdSec ?? 1, this.seekIgnoreWindowMs = t.seekIgnoreWindowMs ?? 250, this.popupGlobal = { ...f, ...t.popup }, this.pingGlobal = { ...k, ...t.ping }, this.markers = (t.items || []).map((i, n) => this.normalize(i, n)).filter((i) => Number.isFinite(i.time) && i.time >= 0).sort((i, n) => i.time - n.time), e.videoEl.addEventListener("loadedmetadata", this.onLoadedMetadata), e.videoEl.addEventListener("timeupdate", this.onTimeUpdate), e.videoEl.addEventListener("seeking", this.onSeeking), e.videoEl.addEventListener("seeked", this.onSeeked), e.videoEl.readyState >= 1 && this.onLoadedMetadata();
76
+ this.ctx = e, this.triggerOnSeek = t.triggerOnSeek === !0, this.seekJumpThresholdSec = t.seekJumpThresholdSec ?? 1, this.seekIgnoreWindowMs = t.seekIgnoreWindowMs ?? 250, this.popupGlobal = { ...b, ...t.popup }, this.pingGlobal = { ...k, ...t.ping }, this.defaultColor = t.color, this.markers = (t.items || []).map((i, o) => this.normalize(i, o)).filter((i) => Number.isFinite(i.time) && i.time >= 0).sort((i, o) => i.time - o.time), e.videoEl.addEventListener("loadedmetadata", this.onLoadedMetadata), e.videoEl.addEventListener("timeupdate", this.onTimeUpdate), e.videoEl.addEventListener("seeking", this.onSeeking), e.videoEl.addEventListener("seeked", this.onSeeked), e.videoEl.readyState >= 1 && this.onLoadedMetadata();
75
77
  }
76
78
  /** Popup lazy oluşturulup yeniden kullanılıyor (`ensurePopup`) — zaten açıksa close butonunun statik etiketini tazeler. */
77
79
  refreshLabels() {
@@ -90,7 +92,7 @@ class v {
90
92
  return {
91
93
  idx: t,
92
94
  time: Number(e.time),
93
- color: e.color,
95
+ color: e.color ?? this.defaultColor,
94
96
  label: e.label ?? "",
95
97
  pauseOnHit: e.pauseOnHit ?? !0,
96
98
  once: e.once ?? !0,
@@ -145,8 +147,8 @@ class v {
145
147
  if (typeof i == "function")
146
148
  try {
147
149
  i({ marker: e, payload: t.payload });
148
- } catch (n) {
149
- console.warn("[HopePlayer markers] custom action fonksiyonu hata verdi:", n);
150
+ } catch (o) {
151
+ console.warn("[HopePlayer markers] custom action fonksiyonu hata verdi:", o);
150
152
  }
151
153
  else
152
154
  console.warn("[HopePlayer markers] custom action fonksiyonu bulunamadı: window." + t.name);
@@ -160,17 +162,17 @@ class v {
160
162
  const t = document.createElement("div");
161
163
  t.className = "hp:relative hp:max-w-[85%] hp:bg-surface-elev hp:text-on-surface hp:rounded-lg hp:p-4 hp:text-center hp:shadow-xl", t.setAttribute("role", "dialog"), t.setAttribute("aria-modal", "true");
162
164
  const i = document.createElement("button");
163
- i.type = "button", i.setAttribute("aria-label", this.ctx.i18n.close), i.className = "hp:absolute hp:top-1 hp:right-1 hp:w-6 hp:h-6 hp:flex hp:items-center hp:justify-center hp:bg-transparent hp:border-0 hp:cursor-pointer hp:text-on-surface", i.appendChild(b("close", "hp:text-sm"));
164
- const n = document.createElement("div");
165
- n.className = "hp:hidden hp:mb-2";
165
+ i.type = "button", i.setAttribute("aria-label", this.ctx.i18n.close), i.className = "hp:absolute hp:top-1 hp:right-1 hp:w-6 hp:h-6 hp:flex hp:items-center hp:justify-center hp:bg-transparent hp:border-0 hp:cursor-pointer hp:text-on-surface", i.appendChild(f("close", "hp:text-sm"));
166
+ const o = document.createElement("div");
167
+ o.className = "hp:hidden hp:mb-2";
166
168
  const a = document.createElement("img");
167
- a.className = "hp:max-w-full hp:rounded", n.appendChild(a);
169
+ a.className = "hp:max-w-full hp:rounded", o.appendChild(a);
168
170
  const l = document.createElement("div");
169
171
  l.className = "hp:text-sm hp:mb-2";
170
- const s = document.createElement("a");
171
- s.target = "_blank", s.rel = "noopener noreferrer", s.className = "hp:hidden hp:text-accent hp:underline hp:text-sm hp:block hp:mb-2";
172
+ const n = document.createElement("a");
173
+ n.target = "_blank", n.rel = "noopener noreferrer", n.className = "hp:hidden hp:text-accent hp:underline hp:text-sm hp:block hp:mb-2";
172
174
  const r = document.createElement("button");
173
- return r.type = "button", r.className = "hp:hidden hp:px-4 hp:py-1.5 hp:rounded hp:bg-accent hp:text-on-accent hp:border-0 hp:cursor-pointer hp:text-sm", t.append(i, n, l, s, r), e.appendChild(t), this.ctx.overlayContainerEl.appendChild(e), this.popupEl = e, e;
175
+ return r.type = "button", r.className = "hp:hidden hp:px-4 hp:py-1.5 hp:rounded hp:bg-accent hp:text-on-accent hp:border-0 hp:cursor-pointer hp:text-sm", t.append(i, o, l, n, r), e.appendChild(t), this.ctx.overlayContainerEl.appendChild(e), this.popupEl = e, e;
174
176
  }
175
177
  hidePopup() {
176
178
  var e, t;
@@ -181,25 +183,25 @@ class v {
181
183
  });
182
184
  }
183
185
  showPopup(e) {
184
- const t = this.ensurePopup(), i = t.querySelector("div.hp\\:text-sm.hp\\:mb-2:not(.hp\\:hidden)"), n = t.querySelector("div.hp\\:mb-2"), a = t.querySelector("img"), l = t.querySelector("a"), s = t.querySelectorAll("button")[1], r = t.querySelector("button");
186
+ const t = this.ensurePopup(), i = t.querySelector("div.hp\\:text-sm.hp\\:mb-2:not(.hp\\:hidden)"), o = t.querySelector("div.hp\\:mb-2"), a = t.querySelector("img"), l = t.querySelector("a"), n = t.querySelectorAll("button")[1], r = t.querySelector("button");
185
187
  r && (r.style.display = e.showClose === !1 ? "none" : ""), i && (i.textContent = e.text || "");
186
188
  const c = e.mode === "rich";
187
- n && a && (c && e.imageUrl ? (n.classList.remove("hp:hidden"), a.src = e.imageUrl, a.alt = e.imageAlt || "") : (n.classList.add("hp:hidden"), a.removeAttribute("src"))), l && (c && e.linkUrl ? (l.classList.remove("hp:hidden"), l.href = e.linkUrl, l.textContent = e.linkText || this.ctx.i18n.markerLearnMore) : (l.classList.add("hp:hidden"), l.removeAttribute("href"))), s && (e.showContinue ? (s.classList.remove("hp:hidden"), s.textContent = e.continueText || this.ctx.i18n.markerContinue) : s.classList.add("hp:hidden"));
188
- const h = r == null ? void 0 : r.cloneNode(!0);
189
- r && h && r.replaceWith(h);
190
- const d = s == null ? void 0 : s.cloneNode(!0);
191
- s && d && s.replaceWith(d), h == null || h.addEventListener("click", () => {
189
+ o && a && (c && e.imageUrl ? (o.classList.remove("hp:hidden"), a.src = e.imageUrl, a.alt = e.imageAlt || "") : (o.classList.add("hp:hidden"), a.removeAttribute("src"))), l && (c && e.linkUrl ? (l.classList.remove("hp:hidden"), l.href = e.linkUrl, l.textContent = e.linkText || this.ctx.i18n.markerLearnMore) : (l.classList.add("hp:hidden"), l.removeAttribute("href"))), n && (e.showContinue ? (n.classList.remove("hp:hidden"), n.textContent = e.continueText || this.ctx.i18n.markerContinue) : n.classList.add("hp:hidden"));
190
+ const p = r == null ? void 0 : r.cloneNode(!0);
191
+ r && p && r.replaceWith(p);
192
+ const d = n == null ? void 0 : n.cloneNode(!0);
193
+ n && d && n.replaceWith(d), p == null || p.addEventListener("click", () => {
192
194
  this.hidePopup(), e.autoplayOnClose && this.safePlay();
193
195
  }), d == null || d.addEventListener("click", () => {
194
196
  this.hidePopup(), e.autoplayOnContinue && this.safePlay();
195
197
  }), t.classList.remove("hp:hidden"), t.classList.add("hp:flex");
196
198
  }
197
199
  }
198
- function y(p, e) {
199
- return new v(p, e);
200
+ function y(h, e) {
201
+ return new v(h, e);
200
202
  }
201
203
  export {
202
204
  v as MarkProgress,
203
205
  y as installMarkers
204
206
  };
205
- //# sourceMappingURL=markers-Dr4-CCxE.js.map
207
+ //# sourceMappingURL=markers-L69W3kj6.js.map