@hopeplayer/core 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index-BBmuCtKu.js","sources":["../../src/plugins/geo-checker/GeoChecker.ts","../../src/plugins/geo-checker/index.ts"],"sourcesContent":["import type { GeoCheckerOptions } from '../../types';\r\nimport type { GatePlayerContext } from '../shared/GatePlayerContext';\r\n\r\nconst EU_COUNTRIES = [\r\n 'EU', 'AD', 'AL', 'AT', 'BA', 'BE', 'BG', 'BY', 'CH', 'CS', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FO', 'FR', 'FX', 'GB', 'GI',\r\n 'GR', 'HR', 'HU', 'IE', 'IS', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MD', 'MK', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SI',\r\n 'SJ', 'SK', 'SM', 'UA', 'VA',\r\n];\r\nconst MENA_COUNTRIES = [\r\n 'DZ', 'BH', 'EG', 'IR', 'IQ', 'JO', 'KW', 'LB', 'LY', 'MA', 'OM', 'QA', 'SA', 'PS', 'SD', 'SY', 'TN', 'AE', 'YE',\r\n 'IL', 'DJ', 'TD', 'SO', 'MR', 'NL',\r\n];\r\n\r\n/** Ücretsiz, API anahtarı gerektirmeyen, CORS'a açık IP-coğrafya servisi. */\r\nconst DEFAULT_API_URL = 'https://get.geojs.io/v1/ip/geo.json';\r\n/** geojs'te ülke KODU (`\"TR\"`) — `country` alanı ülke ADI (`\"Türkiye\"`). */\r\nconst DEFAULT_PARAMETER = 'country_code';\r\n\r\n/**\n * IP-coğrafyasına göre erişim kontrolü. API'ye ulaşılamazsa erişime izin verir (fail-open) —\n * güvenlik değil, lisans/yayın bölgesi uyumluluğu.\n */\r\nexport class GeoChecker {\r\n private readonly loadingEl: HTMLElement;\r\n private destroyed = false;\r\n\r\n constructor(\r\n private readonly ctx: GatePlayerContext,\r\n private readonly options: GeoCheckerOptions\r\n ) {\r\n ctx.blockChrome();\r\n ctx.videoEl.addEventListener('play', this.onPlayWhileBlocked);\r\n\r\n this.loadingEl = document.createElement('div');\r\n this.loadingEl.setAttribute('part', 'geo-loading');\r\n this.loadingEl.className = 'hp:absolute hp:inset-0 hp:z-40 hp:flex hp:items-center hp:justify-center hp:bg-surface';\r\n this.loadingEl.innerHTML =\r\n '<div class=\"hp:w-8 hp:h-8 hp:rounded-full hp:border-2 hp:border-on-surface/30 hp:border-t-accent hp:animate-spin\"></div>';\r\n ctx.overlayContainerEl.appendChild(this.loadingEl);\r\n\r\n void this.check();\r\n }\r\n\r\n /** Uyarı ekranı bir kez (kalıcı olarak) render ediliyor — burada tazelenecek reaktif bir etiket yok, diğer gate plugin'leriyle TUTARLI bir çağrı yüzeyi için var. */\r\n refreshLabels(): void {\r\n /* no-op */\r\n }\r\n\r\n destroy(): void {\r\n this.destroyed = true;\r\n this.ctx.videoEl.removeEventListener('play', this.onPlayWhileBlocked);\r\n this.loadingEl.remove();\r\n }\r\n\r\n private readonly onPlayWhileBlocked = (): void => {\r\n this.ctx.videoEl.pause();\r\n };\r\n\r\n /** Varsayılan geojs: ülke kodu country_code'da (country alanı ülke adı). */\r\n private async resolveCountry(): Promise<string> {\r\n if (this.options.getCountry) return String((await this.options.getCountry()) ?? '');\r\n\r\n const response = await fetch(this.options.apiUrl || DEFAULT_API_URL);\r\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\r\n const data: unknown = await response.json();\r\n const value = (this.options.parameter || DEFAULT_PARAMETER)\r\n .split('.')\r\n .reduce<unknown>((obj, key) => (obj && typeof obj === 'object' ? (obj as Record<string, unknown>)[key] : undefined), data);\r\n return typeof value === 'string' ? value : '';\r\n }\r\n\r\n private async check(): Promise<void> {\r\n let allowed = true;\r\n let userCountry = '';\r\n\r\n try {\r\n userCountry = (await this.resolveCountry()).trim().toUpperCase();\r\n\r\n let allowList = this.options.allowedCountries || [];\r\n if (this.options.region === 'EU') allowList = EU_COUNTRIES;\r\n else if (this.options.region === 'MENA') allowList = MENA_COUNTRIES;\r\n\r\n allowed = allowList.some((code) => code.trim().toUpperCase() === userCountry);\r\n } catch (err) {\r\n console.warn('[HopePlayer geo-checker] IP sorgusu başarısız, erişime izin veriliyor:', err);\r\n allowed = true;\r\n }\r\n\r\n if (this.destroyed) return;\r\n this.loadingEl.remove();\r\n\r\n if (allowed) {\r\n this.ctx.videoEl.removeEventListener('play', this.onPlayWhileBlocked);\r\n this.ctx.unblockChrome();\r\n return;\r\n }\r\n\r\n this.showWarning(userCountry);\r\n }\r\n\r\n private showWarning(country: string): void {\r\n const el = document.createElement('div');\r\n el.setAttribute('part', 'geo-warning');\r\n el.className = 'hp:absolute hp:inset-0 hp:z-40 hp:flex hp:flex-col hp:items-center hp:justify-center hp:gap-2 hp:bg-surface hp:text-on-surface hp:text-center hp:p-4';\r\n\r\n const messages = this.options.warningMessages?.length ? this.options.warningMessages : [this.ctx.i18n.geoDefaultWarning];\r\n for (const msg of messages) {\r\n const p = document.createElement('p');\r\n p.className = 'hp:text-sm hp:m-0';\r\n p.textContent = msg;\r\n el.appendChild(p);\r\n }\r\n\r\n const countryEl = document.createElement('span');\r\n countryEl.className = 'hp:text-xs hp:opacity-60';\r\n countryEl.textContent = country || this.ctx.i18n.geoUnknownCountry;\r\n el.appendChild(countryEl);\r\n\r\n this.ctx.overlayContainerEl.appendChild(el);\r\n // Erişim kalıcı olarak kapalı — unblockChrome() ÇAĞRILMIYOR.\r\n }\r\n}\r\n","import { GeoChecker } from './GeoChecker';\nimport type { GatePlayerContext } from '../shared/GatePlayerContext';\nimport type { GeoCheckerOptions } from '../../types';\n\nexport function installGeoChecker(ctx: GatePlayerContext, options: GeoCheckerOptions): GeoChecker {\n return new GeoChecker(ctx, options);\n}\n\nexport { GeoChecker };\nexport type { GatePlayerContext };\n"],"names":["EU_COUNTRIES","MENA_COUNTRIES","DEFAULT_API_URL","DEFAULT_PARAMETER","GeoChecker","ctx","options","__publicField","response","data","value","obj","key","allowed","userCountry","allowList","code","err","country","_a","el","messages","msg","p","countryEl","installGeoChecker"],"mappings":"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"}
1
+ {"version":3,"file":"index-BBmuCtKu.js","sources":["../../src/plugins/geo-checker/GeoChecker.ts","../../src/plugins/geo-checker/index.ts"],"sourcesContent":["import type { GeoCheckerOptions } from '../../types';\nimport type { GatePlayerContext } from '../shared/GatePlayerContext';\n\nconst EU_COUNTRIES = [\n 'EU', 'AD', 'AL', 'AT', 'BA', 'BE', 'BG', 'BY', 'CH', 'CS', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FO', 'FR', 'FX', 'GB', 'GI',\n 'GR', 'HR', 'HU', 'IE', 'IS', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MD', 'MK', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SI',\n 'SJ', 'SK', 'SM', 'UA', 'VA',\n];\nconst MENA_COUNTRIES = [\n 'DZ', 'BH', 'EG', 'IR', 'IQ', 'JO', 'KW', 'LB', 'LY', 'MA', 'OM', 'QA', 'SA', 'PS', 'SD', 'SY', 'TN', 'AE', 'YE',\n 'IL', 'DJ', 'TD', 'SO', 'MR', 'NL',\n];\n\n/** Ücretsiz, API anahtarı gerektirmeyen, CORS'a açık IP-coğrafya servisi. */\nconst DEFAULT_API_URL = 'https://get.geojs.io/v1/ip/geo.json';\n/** geojs'te ülke KODU (`\"TR\"`) — `country` alanı ülke ADI (`\"Türkiye\"`). */\nconst DEFAULT_PARAMETER = 'country_code';\n\n/**\n * IP-coğrafyasına göre erişim kontrolü. API'ye ulaşılamazsa erişime izin verir (fail-open) —\n * güvenlik değil, lisans/yayın bölgesi uyumluluğu.\n */\nexport class GeoChecker {\n private readonly loadingEl: HTMLElement;\n private destroyed = false;\n\n constructor(\n private readonly ctx: GatePlayerContext,\n private readonly options: GeoCheckerOptions\n ) {\n ctx.blockChrome();\n ctx.videoEl.addEventListener('play', this.onPlayWhileBlocked);\n\n this.loadingEl = document.createElement('div');\n this.loadingEl.setAttribute('part', 'geo-loading');\n this.loadingEl.className = 'hp:absolute hp:inset-0 hp:z-40 hp:flex hp:items-center hp:justify-center hp:bg-surface';\n this.loadingEl.innerHTML =\n '<div class=\"hp:w-8 hp:h-8 hp:rounded-full hp:border-2 hp:border-on-surface/30 hp:border-t-accent hp:animate-spin\"></div>';\n ctx.overlayContainerEl.appendChild(this.loadingEl);\n\n void this.check();\n }\n\n /** Uyarı ekranı bir kez (kalıcı olarak) render ediliyor — burada tazelenecek reaktif bir etiket yok, diğer gate plugin'leriyle TUTARLI bir çağrı yüzeyi için var. */\n refreshLabels(): void {\n /* no-op */\n }\n\n destroy(): void {\n this.destroyed = true;\n this.ctx.videoEl.removeEventListener('play', this.onPlayWhileBlocked);\n this.loadingEl.remove();\n }\n\n private readonly onPlayWhileBlocked = (): void => {\n this.ctx.videoEl.pause();\n };\n\n /** Varsayılan geojs: ülke kodu country_code'da (country alanı ülke adı). */\n private async resolveCountry(): Promise<string> {\n if (this.options.getCountry) return String((await this.options.getCountry()) ?? '');\n\n const response = await fetch(this.options.apiUrl || DEFAULT_API_URL);\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n const data: unknown = await response.json();\n const value = (this.options.parameter || DEFAULT_PARAMETER)\n .split('.')\n .reduce<unknown>((obj, key) => (obj && typeof obj === 'object' ? (obj as Record<string, unknown>)[key] : undefined), data);\n return typeof value === 'string' ? value : '';\n }\n\n private async check(): Promise<void> {\n let allowed = true;\n let userCountry = '';\n\n try {\n userCountry = (await this.resolveCountry()).trim().toUpperCase();\n\n let allowList = this.options.allowedCountries || [];\n if (this.options.region === 'EU') allowList = EU_COUNTRIES;\n else if (this.options.region === 'MENA') allowList = MENA_COUNTRIES;\n\n allowed = allowList.some((code) => code.trim().toUpperCase() === userCountry);\n } catch (err) {\n console.warn('[HopePlayer geo-checker] IP sorgusu başarısız, erişime izin veriliyor:', err);\n allowed = true;\n }\n\n if (this.destroyed) return;\n this.loadingEl.remove();\n\n if (allowed) {\n this.ctx.videoEl.removeEventListener('play', this.onPlayWhileBlocked);\n this.ctx.unblockChrome();\n return;\n }\n\n this.showWarning(userCountry);\n }\n\n private showWarning(country: string): void {\n const el = document.createElement('div');\n el.setAttribute('part', 'geo-warning');\n el.className = 'hp:absolute hp:inset-0 hp:z-40 hp:flex hp:flex-col hp:items-center hp:justify-center hp:gap-2 hp:bg-surface hp:text-on-surface hp:text-center hp:p-4';\n\n const messages = this.options.warningMessages?.length ? this.options.warningMessages : [this.ctx.i18n.geoDefaultWarning];\n for (const msg of messages) {\n const p = document.createElement('p');\n p.className = 'hp:text-sm hp:m-0';\n p.textContent = msg;\n el.appendChild(p);\n }\n\n const countryEl = document.createElement('span');\n countryEl.className = 'hp:text-xs hp:opacity-60';\n countryEl.textContent = country || this.ctx.i18n.geoUnknownCountry;\n el.appendChild(countryEl);\n\n this.ctx.overlayContainerEl.appendChild(el);\n // Erişim kalıcı olarak kapalı — unblockChrome() ÇAĞRILMIYOR.\n }\n}\n","import { GeoChecker } from './GeoChecker';\nimport type { GatePlayerContext } from '../shared/GatePlayerContext';\nimport type { GeoCheckerOptions } from '../../types';\n\nexport function installGeoChecker(ctx: GatePlayerContext, options: GeoCheckerOptions): GeoChecker {\n return new GeoChecker(ctx, options);\n}\n\nexport { GeoChecker };\nexport type { GatePlayerContext };\n"],"names":["EU_COUNTRIES","MENA_COUNTRIES","DEFAULT_API_URL","DEFAULT_PARAMETER","GeoChecker","ctx","options","__publicField","response","data","value","obj","key","allowed","userCountry","allowList","code","err","country","_a","el","messages","msg","p","countryEl","installGeoChecker"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index-CQqGn9as.js","sources":["../../src/plugins/segments/Segments.ts","../../src/plugins/segments/index.ts"],"sourcesContent":["import type { SegmentItem } from '../../types';\r\nimport type { SeekBarChapterRange } from '../../controls/SeekBar';\r\nimport { formatTime } from '../../utils/format-time';\r\n\r\nexport interface SegmentsPlayerContext {\r\n videoEl: HTMLVideoElement;\r\n /** Chapter modunu destekleyen seek bar — parçalara bölme/zaman eşlemesi onda. */\r\n seekBar: {\r\n readonly el: HTMLElement;\r\n setChapters(ranges: SeekBarChapterRange[]): HTMLElement[];\r\n suppressHoverTime(key: string, suppressed: boolean): void;\r\n clearChapters(): void;\r\n ratioAtClientX(clientX: number): number;\r\n };\r\n}\r\n\r\ninterface Chapter {\r\n start: number;\r\n end: number;\r\n text?: string;\r\n color?: string;\r\n}\r\n\r\n/**\n * YouTube tarzı bölümler: seek bar parçalara bölünür (SeekBar.setChapters), hover'da bölüm adı + zaman.\n * Zaman çizgisi her zaman tam kaplanır (boşluklar adsız bölüm, son bölüm sona uzar).\n */\r\nexport class Segments {\r\n private chapters: Chapter[] = [];\r\n private chapterEls: HTMLElement[] = [];\r\n private hoverIndex = -1;\r\n private readonly tooltipEl: HTMLDivElement;\r\n private readonly titleEl: HTMLDivElement;\r\n private readonly timeEl: HTMLDivElement;\r\n\r\n constructor(\r\n private readonly ctx: SegmentsPlayerContext,\r\n private readonly segments: SegmentItem[]\r\n ) {\r\n this.tooltipEl = document.createElement('div');\r\n this.tooltipEl.className = 'hp-chapter-tooltip';\r\n this.tooltipEl.setAttribute('part', 'segment-tooltip');\r\n this.titleEl = document.createElement('div');\r\n this.titleEl.className = 'hp-chapter-tooltip-title';\r\n this.timeEl = document.createElement('div');\r\n this.timeEl.className = 'hp-chapter-tooltip-time';\r\n this.tooltipEl.append(this.titleEl, this.timeEl);\r\n ctx.seekBar.el.appendChild(this.tooltipEl);\r\n // Popup zamanı zaten gösteriyor — seek bar'ın varsayılan hover zamanı ikinci kez yazmasın.\r\n ctx.seekBar.suppressHoverTime('segments', true);\r\n\r\n ctx.seekBar.el.addEventListener('pointermove', this.onPointerMove);\r\n ctx.seekBar.el.addEventListener('pointerleave', this.onPointerLeave);\r\n ctx.videoEl.addEventListener('loadedmetadata', this.onLoadedMetadata);\r\n if (ctx.videoEl.readyState >= 1) this.onLoadedMetadata();\r\n }\r\n\r\n destroy(): void {\r\n this.ctx.videoEl.removeEventListener('loadedmetadata', this.onLoadedMetadata);\r\n this.ctx.seekBar.el.removeEventListener('pointermove', this.onPointerMove);\r\n this.ctx.seekBar.el.removeEventListener('pointerleave', this.onPointerLeave);\r\n this.ctx.seekBar.clearChapters();\r\n this.ctx.seekBar.suppressHoverTime('segments', false);\r\n this.tooltipEl.remove();\r\n this.chapterEls = [];\r\n this.chapters = [];\r\n }\r\n\r\n private readonly onLoadedMetadata = (): void => {\r\n const duration = this.ctx.videoEl.duration;\r\n if (!Number.isFinite(duration) || duration <= 0) return;\r\n\r\n this.chapters = buildChapters(this.segments, duration);\r\n this.chapterEls = this.ctx.seekBar.setChapters(\r\n this.chapters.map((c) => ({ start: c.start / duration, end: c.end / duration, color: c.color }))\r\n );\r\n };\r\n\r\n private readonly onPointerMove = (e: PointerEvent): void => {\r\n const duration = this.ctx.videoEl.duration;\r\n if (!this.chapters.length || !Number.isFinite(duration) || duration <= 0) return;\r\n\r\n const time = this.ctx.seekBar.ratioAtClientX(e.clientX) * duration;\r\n let index = this.chapters.findIndex((c) => time < c.end);\r\n if (index === -1) index = this.chapters.length - 1;\r\n this.setHover(index);\r\n\r\n const chapter = this.chapters[index]!;\r\n this.titleEl.textContent = chapter.text ?? '';\r\n this.titleEl.style.display = chapter.text ? '' : 'none';\r\n this.timeEl.textContent = formatTime(time);\r\n\r\n // sprite-thumbnails önizlemesi de seek bar'ın hemen üstünde açılıyor —\r\n // görünürse popup onun ÜSTÜNE çıkıyor (üst üste binmesin).\r\n const sprite = this.ctx.seekBar.el.querySelector<HTMLElement>('[part=\"sprite-tooltip\"]');\r\n const spriteH = sprite && sprite.hasAttribute('data-visible') && sprite.offsetHeight > 0 ? sprite.offsetHeight + 8 : 0;\r\n this.tooltipEl.style.bottom = spriteH ? `calc(100% + 6px + ${spriteH}px)` : '';\r\n // Sprite önizlemesi zamanı zaten kendi altında gösteriyor — aynı zaman iki kez yazılmasın.\r\n this.timeEl.style.display = spriteH ? 'none' : '';\r\n\r\n // Popup imleci ortalar ama seek bar kenarlarından taşmaz.\r\n const barRect = this.ctx.seekBar.el.getBoundingClientRect();\r\n this.tooltipEl.setAttribute('data-visible', '');\r\n const tipWidth = this.tooltipEl.offsetWidth;\r\n const x = Math.min(Math.max(e.clientX - barRect.left - tipWidth / 2, 0), Math.max(barRect.width - tipWidth, 0));\r\n this.tooltipEl.style.transform = `translateX(${x}px)`;\r\n };\r\n\r\n private readonly onPointerLeave = (): void => {\r\n this.setHover(-1);\r\n this.tooltipEl.removeAttribute('data-visible');\r\n };\r\n\r\n private setHover(index: number): void {\r\n if (index === this.hoverIndex) return;\r\n this.chapterEls[this.hoverIndex]?.removeAttribute('data-hover');\r\n this.hoverIndex = index;\r\n this.chapterEls[index]?.setAttribute('data-hover', '');\r\n }\r\n}\r\n\r\n/** Segmentleri sıralar, boşlukları adsız bölümle doldurur, son bölümü video sonuna uzatır — sonuç 0→duration'ı kesintisiz kaplar. */\r\nfunction buildChapters(segments: SegmentItem[], duration: number): Chapter[] {\r\n const sorted = segments\r\n .filter((s) => Number.isFinite(s.start) && s.start < duration)\r\n .slice()\r\n .sort((a, b) => a.start - b.start);\r\n\r\n const chapters: Chapter[] = [];\r\n let cursor = 0;\r\n for (const seg of sorted) {\r\n const start = Math.max(seg.start, cursor);\r\n const end = Math.min(Number.isFinite(seg.end) ? seg.end : duration, duration);\r\n if (end <= start) continue;\r\n if (start > cursor) chapters.push({ start: cursor, end: start });\r\n chapters.push({ start, end, text: seg.text, color: seg.color });\r\n cursor = end;\r\n }\r\n if (!chapters.length) return [];\r\n if (cursor < duration) chapters[chapters.length - 1]!.end = duration;\r\n return chapters;\r\n}\r\n","import { Segments, type SegmentsPlayerContext } from './Segments';\nimport type { SegmentItem } from '../../types';\n\nexport function installSegments(ctx: SegmentsPlayerContext, items: SegmentItem[]): Segments {\n return new Segments(ctx, items);\n}\n\nexport { Segments };\nexport type { SegmentsPlayerContext };\n"],"names":["Segments","ctx","segments","__publicField","duration","buildChapters","c","e","time","index","chapter","formatTime","sprite","spriteH","barRect","tipWidth","x","_a","_b","sorted","a","b","chapters","cursor","seg","start","end","installSegments","items"],"mappings":"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"}
1
+ {"version":3,"file":"index-CQqGn9as.js","sources":["../../src/plugins/segments/Segments.ts","../../src/plugins/segments/index.ts"],"sourcesContent":["import type { SegmentItem } from '../../types';\nimport type { SeekBarChapterRange } from '../../controls/SeekBar';\nimport { formatTime } from '../../utils/format-time';\n\nexport interface SegmentsPlayerContext {\n videoEl: HTMLVideoElement;\n /** Chapter modunu destekleyen seek bar — parçalara bölme/zaman eşlemesi onda. */\n seekBar: {\n readonly el: HTMLElement;\n setChapters(ranges: SeekBarChapterRange[]): HTMLElement[];\n suppressHoverTime(key: string, suppressed: boolean): void;\n clearChapters(): void;\n ratioAtClientX(clientX: number): number;\n };\n}\n\ninterface Chapter {\n start: number;\n end: number;\n text?: string;\n color?: string;\n}\n\n/**\n * YouTube tarzı bölümler: seek bar parçalara bölünür (SeekBar.setChapters), hover'da bölüm adı + zaman.\n * Zaman çizgisi her zaman tam kaplanır (boşluklar adsız bölüm, son bölüm sona uzar).\n */\nexport class Segments {\n private chapters: Chapter[] = [];\n private chapterEls: HTMLElement[] = [];\n private hoverIndex = -1;\n private readonly tooltipEl: HTMLDivElement;\n private readonly titleEl: HTMLDivElement;\n private readonly timeEl: HTMLDivElement;\n\n constructor(\n private readonly ctx: SegmentsPlayerContext,\n private readonly segments: SegmentItem[]\n ) {\n this.tooltipEl = document.createElement('div');\n this.tooltipEl.className = 'hp-chapter-tooltip';\n this.tooltipEl.setAttribute('part', 'segment-tooltip');\n this.titleEl = document.createElement('div');\n this.titleEl.className = 'hp-chapter-tooltip-title';\n this.timeEl = document.createElement('div');\n this.timeEl.className = 'hp-chapter-tooltip-time';\n this.tooltipEl.append(this.titleEl, this.timeEl);\n ctx.seekBar.el.appendChild(this.tooltipEl);\n // Popup zamanı zaten gösteriyor — seek bar'ın varsayılan hover zamanı ikinci kez yazmasın.\n ctx.seekBar.suppressHoverTime('segments', true);\n\n ctx.seekBar.el.addEventListener('pointermove', this.onPointerMove);\n ctx.seekBar.el.addEventListener('pointerleave', this.onPointerLeave);\n ctx.videoEl.addEventListener('loadedmetadata', this.onLoadedMetadata);\n if (ctx.videoEl.readyState >= 1) this.onLoadedMetadata();\n }\n\n destroy(): void {\n this.ctx.videoEl.removeEventListener('loadedmetadata', this.onLoadedMetadata);\n this.ctx.seekBar.el.removeEventListener('pointermove', this.onPointerMove);\n this.ctx.seekBar.el.removeEventListener('pointerleave', this.onPointerLeave);\n this.ctx.seekBar.clearChapters();\n this.ctx.seekBar.suppressHoverTime('segments', false);\n this.tooltipEl.remove();\n this.chapterEls = [];\n this.chapters = [];\n }\n\n private readonly onLoadedMetadata = (): void => {\n const duration = this.ctx.videoEl.duration;\n if (!Number.isFinite(duration) || duration <= 0) return;\n\n this.chapters = buildChapters(this.segments, duration);\n this.chapterEls = this.ctx.seekBar.setChapters(\n this.chapters.map((c) => ({ start: c.start / duration, end: c.end / duration, color: c.color }))\n );\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n const duration = this.ctx.videoEl.duration;\n if (!this.chapters.length || !Number.isFinite(duration) || duration <= 0) return;\n\n const time = this.ctx.seekBar.ratioAtClientX(e.clientX) * duration;\n let index = this.chapters.findIndex((c) => time < c.end);\n if (index === -1) index = this.chapters.length - 1;\n this.setHover(index);\n\n const chapter = this.chapters[index]!;\n this.titleEl.textContent = chapter.text ?? '';\n this.titleEl.style.display = chapter.text ? '' : 'none';\n this.timeEl.textContent = formatTime(time);\n\n // sprite-thumbnails önizlemesi de seek bar'ın hemen üstünde açılıyor —\n // görünürse popup onun ÜSTÜNE çıkıyor (üst üste binmesin).\n const sprite = this.ctx.seekBar.el.querySelector<HTMLElement>('[part=\"sprite-tooltip\"]');\n const spriteH = sprite && sprite.hasAttribute('data-visible') && sprite.offsetHeight > 0 ? sprite.offsetHeight + 8 : 0;\n this.tooltipEl.style.bottom = spriteH ? `calc(100% + 6px + ${spriteH}px)` : '';\n // Sprite önizlemesi zamanı zaten kendi altında gösteriyor — aynı zaman iki kez yazılmasın.\n this.timeEl.style.display = spriteH ? 'none' : '';\n\n // Popup imleci ortalar ama seek bar kenarlarından taşmaz.\n const barRect = this.ctx.seekBar.el.getBoundingClientRect();\n this.tooltipEl.setAttribute('data-visible', '');\n const tipWidth = this.tooltipEl.offsetWidth;\n const x = Math.min(Math.max(e.clientX - barRect.left - tipWidth / 2, 0), Math.max(barRect.width - tipWidth, 0));\n this.tooltipEl.style.transform = `translateX(${x}px)`;\n };\n\n private readonly onPointerLeave = (): void => {\n this.setHover(-1);\n this.tooltipEl.removeAttribute('data-visible');\n };\n\n private setHover(index: number): void {\n if (index === this.hoverIndex) return;\n this.chapterEls[this.hoverIndex]?.removeAttribute('data-hover');\n this.hoverIndex = index;\n this.chapterEls[index]?.setAttribute('data-hover', '');\n }\n}\n\n/** Segmentleri sıralar, boşlukları adsız bölümle doldurur, son bölümü video sonuna uzatır — sonuç 0→duration'ı kesintisiz kaplar. */\nfunction buildChapters(segments: SegmentItem[], duration: number): Chapter[] {\n const sorted = segments\n .filter((s) => Number.isFinite(s.start) && s.start < duration)\n .slice()\n .sort((a, b) => a.start - b.start);\n\n const chapters: Chapter[] = [];\n let cursor = 0;\n for (const seg of sorted) {\n const start = Math.max(seg.start, cursor);\n const end = Math.min(Number.isFinite(seg.end) ? seg.end : duration, duration);\n if (end <= start) continue;\n if (start > cursor) chapters.push({ start: cursor, end: start });\n chapters.push({ start, end, text: seg.text, color: seg.color });\n cursor = end;\n }\n if (!chapters.length) return [];\n if (cursor < duration) chapters[chapters.length - 1]!.end = duration;\n return chapters;\n}\n","import { Segments, type SegmentsPlayerContext } from './Segments';\nimport type { SegmentItem } from '../../types';\n\nexport function installSegments(ctx: SegmentsPlayerContext, items: SegmentItem[]): Segments {\n return new Segments(ctx, items);\n}\n\nexport { Segments };\nexport type { SegmentsPlayerContext };\n"],"names":["Segments","ctx","segments","__publicField","duration","buildChapters","c","e","time","index","chapter","formatTime","sprite","spriteH","barRect","tipWidth","x","_a","_b","sorted","a","b","chapters","cursor","seg","start","end","installSegments","items"],"mappings":"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"}