@hopeplayer/core 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/index-BBmuCtKu.js.map +1 -1
- package/dist/chunks/{index-q5DsrT-Q.js → index-BR31cEYA.js} +2 -2
- package/dist/chunks/index-BR31cEYA.js.map +1 -0
- package/dist/chunks/{index-DiCkShCE.js → index-BjmWoP4E.js} +80 -70
- package/dist/chunks/index-BjmWoP4E.js.map +1 -0
- package/dist/chunks/{index-B4ujPVcl.js → index-CEmsL1uT.js} +2 -2
- package/dist/chunks/{index-B4ujPVcl.js.map → index-CEmsL1uT.js.map} +1 -1
- package/dist/chunks/{index-CQqGn9as.js → index-CZK3TwzR.js} +2 -2
- package/dist/chunks/index-CZK3TwzR.js.map +1 -0
- package/dist/chunks/{index-BFgqg05L.js → index-DadIEuQc.js} +2 -2
- package/dist/chunks/{index-BFgqg05L.js.map → index-DadIEuQc.js.map} +1 -1
- package/dist/chunks/index-glxDu2eJ.js.map +1 -1
- package/dist/chunks/{index-DXf2Al1x.js → index-lrAXde76.js} +2 -2
- package/dist/chunks/{index-DXf2Al1x.js.map → index-lrAXde76.js.map} +1 -1
- package/dist/hls/SourceManager.d.ts +5 -2
- package/dist/hls/SourceManager.d.ts.map +1 -1
- package/dist/hope-player.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/index-CQqGn9as.js.map +0 -1
- package/dist/chunks/index-DiCkShCE.js.map +0 -1
- package/dist/chunks/index-q5DsrT-Q.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-B4ujPVcl.js","sources":["../../src/plugins/playlist/PlaylistRunner.ts","../../src/plugins/playlist/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { PlayableItem, PlaylistOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface PlaylistPlayerContext {\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** Liste UI'ının monte edileceği, shadow root içindeki panel. */\n panelEl: HTMLElement;\n loadSource(src: string, type?: string): Promise<void>;\n setPoster(url: string): void;\n /** AdsController varsa retry/VMAP durumunu sıfırlayıp item'ın (varsa) kendi adTagPreroll'üyle yeniden reklam ister — yoksa no-op. */\n requestFreshAd(prerollTag?: string): void;\n i18n: HopeLocaleStrings;\n}\n\ntype SourceMode = 'hls' | 'mp4';\n\ninterface Attempt {\n id: number;\n index: number;\n mode: SourceMode;\n tried: Set<SourceMode>;\n mp4Index: number;\n}\n\nconst DEFAULTS: Required<Omit<PlaylistOptions, 'items' | 'adTagPreroll' | 'ui'>> = {\n startMode: 'after_current',\n startIndex: 0,\n loop: false,\n autoplayNext: true,\n preferHls: true,\n adsOnItemChange: true,\n};\n\n/** Tek player üzerinde sıralı oynatma listesi (startMode, loop, hata fallback zinciri). */\nexport class PlaylistRunner {\n private readonly options: Required<Omit<PlaylistOptions, 'items' | 'adTagPreroll' | 'ui'>>;\n private readonly items: PlayableItem[];\n\n private index: number;\n private destroyed = false;\n private switching = false;\n private playlistActive = false;\n private startPendingAfterCurrent = false;\n private attemptId = 0;\n private attempt: Attempt | null = null;\n private lastErrorAt = 0;\n private lastAdsIndex: number | null = null;\n private lastDispatchedIndex: number | null = null;\n private userHasStartedPlayback = false;\n\n private readonly ui: {\n root: HTMLElement;\n titleEl: HTMLElement;\n listEl: HTMLElement;\n prevBtn: HTMLButtonElement;\n nextBtn: HTMLButtonElement;\n itemEls: Array<{ li: HTMLElement; titleRow: HTMLElement; progressFill: HTMLElement | null; timeEl: HTMLElement | null }>;\n };\n\n constructor(\n private readonly ctx: PlaylistPlayerContext,\n private readonly rawOptions: PlaylistOptions\n ) {\n this.options = { ...DEFAULTS, ...rawOptions };\n this.items = Array.isArray(rawOptions.items) ? rawOptions.items : [];\n this.index = this.clampIndex(this.options.startIndex);\n\n this.ui = this.buildUi();\n this.bindPlayerEvents();\n this.init();\n }\n\n // ── lifecycle ──\n\n private init(): void {\n if (!this.items.length) return;\n\n if (this.options.startMode === 'after_current') {\n this.startPendingAfterCurrent = true;\n this.playlistActive = false;\n this.setActive(this.index);\n return;\n }\n\n this.playlistActive = true;\n void this.loadAndPlay(this.index, { userInitiated: false, isPlaylistStart: true });\n }\n\n refreshLabels(): void {\n this.ui.titleEl.textContent = this.playlistTitleText();\n this.ui.prevBtn.setAttribute('aria-label', this.ctx.i18n.playlistPrev);\n this.ui.nextBtn.setAttribute('aria-label', this.ctx.i18n.playlistNext);\n this.ui.itemEls.forEach((entry, idx) => {\n const item = this.items[idx];\n if (item && !item.title) entry.titleRow.textContent = this.ctx.i18n.videoFallbackTitle(idx);\n });\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.ctx.videoEl.removeEventListener('ended', this.onEnded);\n this.ctx.videoEl.removeEventListener('error', this.onError);\n this.ctx.videoEl.removeEventListener('play', this.onUserPlay);\n this.ui.root.remove();\n }\n\n // ── public api ──\n\n start(opts: { index?: number } = {}): void {\n if (this.destroyed || !this.items.length) return;\n this.startPendingAfterCurrent = false;\n this.playlistActive = true;\n this.index = this.clampIndex(opts.index ?? this.index);\n this.setActive(this.index);\n void this.loadAndPlay(this.index, { userInitiated: false, isPlaylistStart: true });\n }\n\n next(): void {\n if (this.destroyed || !this.items.length) return;\n if (!this.playlistActive) return this.start({ index: this.index });\n\n if (this.index < this.items.length - 1) this.index++;\n else if (this.options.loop) this.index = 0;\n else return;\n\n this.setActive(this.index);\n void this.loadAndPlay(this.index, { userInitiated: true });\n }\n\n prev(): void {\n if (this.destroyed || !this.items.length) return;\n if (!this.playlistActive) return this.start({ index: this.index });\n if (this.index === 0) return;\n this.index--;\n this.setActive(this.index);\n void this.loadAndPlay(this.index, { userInitiated: true });\n }\n\n setIndex(i: number): void {\n if (this.destroyed || !this.items.length) return;\n this.index = this.clampIndex(i);\n this.setActive(this.index);\n if (!this.playlistActive) return this.start({ index: this.index });\n void this.loadAndPlay(this.index, { userInitiated: true });\n }\n\n getIndex(): number {\n return this.index;\n }\n\n isActive(): boolean {\n return this.playlistActive;\n }\n\n // ── player events ──\n\n private bindPlayerEvents(): void {\n this.ctx.videoEl.addEventListener('ended', this.onEnded);\n this.ctx.videoEl.addEventListener('error', this.onError);\n this.ctx.videoEl.addEventListener('play', this.onUserPlay);\n this.ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n }\n\n private readonly onUserPlay = (): void => {\n this.userHasStartedPlayback = true;\n };\n\n private readonly onEnded = (): void => {\n if (this.startPendingAfterCurrent && !this.playlistActive) {\n this.startPendingAfterCurrent = false;\n this.playlistActive = true;\n this.setActive(this.index);\n void this.loadAndPlay(this.index, { userInitiated: true, isPlaylistStart: true });\n return;\n }\n if (this.playlistActive) this.next();\n };\n\n private readonly onError = (): void => {\n if (this.destroyed || !this.playlistActive) return;\n const now = Date.now();\n if (now - this.lastErrorAt < 200) return;\n this.lastErrorAt = now;\n void this.fallbackOrSkip();\n };\n\n private readonly onTimeUpdate = (): void => {\n this.updateProgress();\n };\n\n // ── core load ──\n\n private async loadAndPlay(\n i: number,\n opts: { userInitiated?: boolean; forceMode?: SourceMode | null; forceMp4Index?: number | null; isFallback?: boolean; isPlaylistStart?: boolean } = {}\n ): Promise<void> {\n if (this.destroyed || this.switching || !this.playlistActive) return;\n this.switching = true;\n\n const item = this.items[i];\n if (!item) {\n this.switching = false;\n return;\n }\n const attemptId = ++this.attemptId;\n const mode = opts.forceMode ?? this.resolveMode(item);\n\n let tried = new Set<SourceMode>([mode]);\n let mp4Index = opts.forceMp4Index ?? 0;\n if (opts.isFallback && this.attempt?.index === i && this.attempt?.tried) {\n tried = new Set(this.attempt.tried);\n tried.add(mode);\n if (opts.forceMp4Index == null) mp4Index = this.attempt.mp4Index ?? 0;\n }\n this.attempt = { id: attemptId, index: i, mode, tried, mp4Index };\n\n try {\n const payload = this.buildPayload(item, mode, mp4Index);\n if (!payload) throw new Error('No playable source');\n\n this.setActive(i);\n this.ctx.videoEl.pause();\n if (item.image) this.ctx.setPoster(item.image);\n await this.ctx.loadSource(payload.src, payload.type);\n\n if (this.options.adsOnItemChange) this.maybeRequestAds(i, item, !!opts.isFallback);\n\n if (this.shouldAutoPlay(!!opts.userInitiated)) {\n try {\n await this.ctx.videoEl.play();\n } catch {\n /* autoplay engellendi — sessizce geç */\n }\n }\n this.updateProgress();\n } finally {\n this.switching = false;\n }\n }\n\n private async fallbackOrSkip(): Promise<void> {\n if (this.destroyed || !this.attempt) return;\n const item = this.items[this.attempt.index];\n if (!item) return;\n\n if (this.attempt.mode === 'mp4') {\n const mp4List = (item.mp4 || []).filter((v) => v?.src);\n const nextMp4 = (this.attempt.mp4Index ?? 0) + 1;\n if (nextMp4 < mp4List.length) {\n await this.loadAndPlay(this.attempt.index, { forceMode: 'mp4', forceMp4Index: nextMp4, isFallback: true });\n return;\n }\n }\n\n const otherMode: SourceMode = this.attempt.mode === 'hls' ? 'mp4' : 'hls';\n if (this.hasMode(item, otherMode) && !this.attempt.tried.has(otherMode)) {\n await this.loadAndPlay(this.attempt.index, { forceMode: otherMode, isFallback: true });\n return;\n }\n\n this.next();\n }\n\n // ── ads ──\n\n private maybeRequestAds(index: number, item: PlayableItem, _isFallback: boolean): void {\n if (this.lastAdsIndex === index) return;\n this.lastAdsIndex = index;\n this.ctx.requestFreshAd(item.adTagPreroll || this.rawOptions.adTagPreroll);\n }\n\n // ── sources ──\n\n private resolveMode(item: PlayableItem): SourceMode {\n if (this.options.preferHls) return this.hasMode(item, 'hls') ? 'hls' : this.hasMode(item, 'mp4') ? 'mp4' : 'hls';\n return this.hasMode(item, 'mp4') ? 'mp4' : this.hasMode(item, 'hls') ? 'hls' : 'mp4';\n }\n\n private hasMode(item: PlayableItem, mode: SourceMode): boolean {\n return Array.isArray(item[mode]) && item[mode]!.some((v) => v?.src);\n }\n\n private buildPayload(item: PlayableItem, mode: SourceMode, mp4Index = 0): { src: string; type?: string } | null {\n const list = (item[mode] || []).filter((v) => v?.src);\n if (!list.length) return null;\n\n let src;\n if (mode === 'mp4') {\n src = mp4Index > 0 ? list[mp4Index] || list[0] : list.find((v) => v.selected) || list[0];\n } else {\n src = list[0];\n }\n return { src: src!.src, type: src!.type || (mode === 'hls' ? 'application/x-mpegURL' : 'video/mp4') };\n }\n\n private shouldAutoPlay(userInitiated: boolean): boolean {\n if (userInitiated) return true;\n return this.options.autoplayNext && this.userHasStartedPlayback;\n }\n\n private clampIndex(i: number): number {\n if (!Number.isFinite(i) || !this.items.length) return 0;\n return Math.max(0, Math.min(this.items.length - 1, Math.trunc(i)));\n }\n\n // ── ui ──\n\n private buildUi() {\n const ui = this.rawOptions.ui ?? {};\n const root = document.createElement('div');\n root.setAttribute('part', 'playlist-panel');\n root.className = 'hp:flex hp:flex-col hp:gap-2 hp:p-3 hp:bg-surface-elev hp:max-h-80 hp:overflow-y-auto';\n\n const header = document.createElement('div');\n header.className = 'hp:flex hp:items-center hp:justify-between hp:gap-2 hp:mb-1';\n\n const titleEl = document.createElement('div');\n titleEl.className = 'hp:text-sm hp:font-semibold hp:text-on-surface';\n titleEl.textContent = this.playlistTitleText();\n header.appendChild(titleEl);\n\n const navWrap = document.createElement('div');\n navWrap.className = 'hp:flex hp:gap-1';\n const prevBtn = this.navButton('chevron-left', this.ctx.i18n.playlistPrev, () => this.prev());\n const nextBtn = this.navButton('chevron-left', this.ctx.i18n.playlistNext, () => this.next());\n nextBtn.style.transform = 'rotate(180deg)';\n navWrap.append(prevBtn, nextBtn);\n header.appendChild(navWrap);\n\n root.appendChild(header);\n\n const listEl = document.createElement('ul');\n listEl.className = 'hp:flex hp:flex-col hp:gap-1 hp:list-none hp:m-0 hp:p-0';\n root.appendChild(listEl);\n\n const itemEls: Array<{ li: HTMLElement; titleRow: HTMLElement; progressFill: HTMLElement | null; timeEl: HTMLElement | null }> = [];\n this.items.forEach((item, idx) => {\n const li = document.createElement('li');\n li.className =\n 'hp:flex hp:items-center hp:gap-2 hp:p-2 hp:rounded hp:cursor-pointer hp:text-on-surface-muted hp:text-sm ' +\n 'hp:hover:bg-on-surface/5 hp:data-[active=true]:bg-accent/15 hp:data-[active=true]:text-on-surface';\n\n if (item.image) {\n const img = document.createElement('img');\n img.src = item.image;\n img.loading = 'lazy';\n img.className = 'hp:w-16 hp:aspect-video hp:object-cover hp:rounded hp:shrink-0';\n li.appendChild(img);\n }\n\n const body = document.createElement('div');\n body.className = 'hp:flex-1 hp:min-w-0';\n const titleRow = document.createElement('div');\n titleRow.className = 'hp:truncate hp:font-medium';\n titleRow.textContent = item.title || this.ctx.i18n.videoFallbackTitle(idx);\n body.appendChild(titleRow);\n\n let progressFill: HTMLElement | null = null;\n let timeEl: HTMLElement | null = null;\n if (ui.showMeta !== false) {\n const metaRow = document.createElement('div');\n metaRow.className = 'hp:flex hp:items-center hp:gap-2 hp:text-xs hp:opacity-70 hp:mt-0.5';\n timeEl = document.createElement('span');\n timeEl.textContent = '';\n metaRow.appendChild(timeEl);\n\n const bar = document.createElement('div');\n bar.className = 'hp:flex-1 hp:h-0.5 hp:bg-on-surface/20 hp:rounded-full hp:overflow-hidden';\n progressFill = document.createElement('div');\n progressFill.className = 'hp:h-full hp:bg-accent';\n progressFill.style.width = '0%';\n bar.appendChild(progressFill);\n metaRow.appendChild(bar);\n body.appendChild(metaRow);\n }\n\n li.appendChild(body);\n li.addEventListener('click', () => this.setIndex(idx));\n listEl.appendChild(li);\n itemEls.push({ li, titleRow, progressFill, timeEl });\n });\n\n this.ctx.panelEl.appendChild(root);\n return { root, titleEl, listEl, prevBtn, nextBtn, itemEls };\n }\n\n private playlistTitleText(): string {\n const ui = this.rawOptions.ui ?? {};\n const title = ui.title || this.ctx.i18n.playlistTitle;\n return ui.showCount === false ? title : `${title} (${this.items.length})`;\n }\n\n private navButton(iconName: string, label: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.setAttribute('aria-label', label);\n btn.className = 'hp:flex hp:items-center hp:justify-center hp:w-6 hp:h-6 hp:text-on-surface hp:bg-transparent hp:border-0 hp:cursor-pointer';\n btn.appendChild(createIcon(iconName, 'hp:text-sm'));\n btn.addEventListener('click', onClick);\n return btn;\n }\n\n private setActive(index: number): void {\n this.ui.itemEls.forEach((entry, idx) => {\n if (idx === index) entry.li.setAttribute('data-active', 'true');\n else entry.li.removeAttribute('data-active');\n });\n // loadAndPlay() hem anlık UI geri bildirimi için önceden (next/prev/setIndex\n // içinden) hem de kaynak gerçekten yüklendiğinde setActive() çağırıyor —\n // aynı index için event'i yalnızca BİR kez yaymak için guard.\n if (this.lastDispatchedIndex !== index) {\n this.lastDispatchedIndex = index;\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:itemchange', { detail: { index, source: 'playlist' } }));\n }\n }\n\n private updateProgress(): void {\n const active = this.ui.itemEls[this.index];\n if (!active) return;\n const duration = this.ctx.videoEl.duration;\n const current = this.ctx.videoEl.currentTime;\n if (active.timeEl) active.timeEl.textContent = this.formatTime(current);\n if (active.progressFill && Number.isFinite(duration) && duration > 0) {\n active.progressFill.style.width = `${Math.min(100, (current / duration) * 100)}%`;\n }\n }\n\n private formatTime(sec: number): string {\n const s = Math.max(0, Math.floor(sec || 0));\n const m = Math.floor(s / 60);\n const r = s % 60;\n return `${m}:${String(r).padStart(2, '0')}`;\n }\n}\n","import { PlaylistRunner, type PlaylistPlayerContext } from './PlaylistRunner';\nimport type { PlaylistOptions } from '../../types';\n\nexport function installPlaylist(ctx: PlaylistPlayerContext, options: PlaylistOptions): PlaylistRunner {\n return new PlaylistRunner(ctx, options);\n}\n\nexport { PlaylistRunner };\nexport type { PlaylistPlayerContext };\n"],"names":["DEFAULTS","PlaylistRunner","ctx","rawOptions","__publicField","now","entry","idx","item","opts","i","attemptId","mode","tried","mp4Index","_a","_b","payload","mp4List","v","nextMp4","otherMode","index","_isFallback","list","src","userInitiated","ui","root","header","titleEl","navWrap","prevBtn","nextBtn","listEl","itemEls","li","img","body","titleRow","progressFill","timeEl","metaRow","bar","title","iconName","label","onClick","btn","createIcon","active","duration","current","sec","s","m","r","installPlaylist","options"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-CEmsL1uT.js","sources":["../../src/plugins/playlist/PlaylistRunner.ts","../../src/plugins/playlist/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { PlayableItem, PlaylistOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface PlaylistPlayerContext {\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** Liste UI'ının monte edileceği, shadow root içindeki panel. */\n panelEl: HTMLElement;\n loadSource(src: string, type?: string): Promise<void>;\n setPoster(url: string): void;\n /** AdsController varsa retry/VMAP durumunu sıfırlayıp item'ın (varsa) kendi adTagPreroll'üyle yeniden reklam ister — yoksa no-op. */\n requestFreshAd(prerollTag?: string): void;\n i18n: HopeLocaleStrings;\n}\n\ntype SourceMode = 'hls' | 'mp4';\n\ninterface Attempt {\n id: number;\n index: number;\n mode: SourceMode;\n tried: Set<SourceMode>;\n mp4Index: number;\n}\n\nconst DEFAULTS: Required<Omit<PlaylistOptions, 'items' | 'adTagPreroll' | 'ui'>> = {\n startMode: 'after_current',\n startIndex: 0,\n loop: false,\n autoplayNext: true,\n preferHls: true,\n adsOnItemChange: true,\n};\n\n/** Tek player üzerinde sıralı oynatma listesi (startMode, loop, hata fallback zinciri). */\nexport class PlaylistRunner {\n private readonly options: Required<Omit<PlaylistOptions, 'items' | 'adTagPreroll' | 'ui'>>;\n private readonly items: PlayableItem[];\n\n private index: number;\n private destroyed = false;\n private switching = false;\n private playlistActive = false;\n private startPendingAfterCurrent = false;\n private attemptId = 0;\n private attempt: Attempt | null = null;\n private lastErrorAt = 0;\n private lastAdsIndex: number | null = null;\n private lastDispatchedIndex: number | null = null;\n private userHasStartedPlayback = false;\n\n private readonly ui: {\n root: HTMLElement;\n titleEl: HTMLElement;\n listEl: HTMLElement;\n prevBtn: HTMLButtonElement;\n nextBtn: HTMLButtonElement;\n itemEls: Array<{ li: HTMLElement; titleRow: HTMLElement; progressFill: HTMLElement | null; timeEl: HTMLElement | null }>;\n };\n\n constructor(\n private readonly ctx: PlaylistPlayerContext,\n private readonly rawOptions: PlaylistOptions\n ) {\n this.options = { ...DEFAULTS, ...rawOptions };\n this.items = Array.isArray(rawOptions.items) ? rawOptions.items : [];\n this.index = this.clampIndex(this.options.startIndex);\n\n this.ui = this.buildUi();\n this.bindPlayerEvents();\n this.init();\n }\n\n // ── lifecycle ──\n\n private init(): void {\n if (!this.items.length) return;\n\n if (this.options.startMode === 'after_current') {\n this.startPendingAfterCurrent = true;\n this.playlistActive = false;\n this.setActive(this.index);\n return;\n }\n\n this.playlistActive = true;\n void this.loadAndPlay(this.index, { userInitiated: false, isPlaylistStart: true });\n }\n\n refreshLabels(): void {\n this.ui.titleEl.textContent = this.playlistTitleText();\n this.ui.prevBtn.setAttribute('aria-label', this.ctx.i18n.playlistPrev);\n this.ui.nextBtn.setAttribute('aria-label', this.ctx.i18n.playlistNext);\n this.ui.itemEls.forEach((entry, idx) => {\n const item = this.items[idx];\n if (item && !item.title) entry.titleRow.textContent = this.ctx.i18n.videoFallbackTitle(idx);\n });\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.ctx.videoEl.removeEventListener('ended', this.onEnded);\n this.ctx.videoEl.removeEventListener('error', this.onError);\n this.ctx.videoEl.removeEventListener('play', this.onUserPlay);\n this.ui.root.remove();\n }\n\n // ── public api ──\n\n start(opts: { index?: number } = {}): void {\n if (this.destroyed || !this.items.length) return;\n this.startPendingAfterCurrent = false;\n this.playlistActive = true;\n this.index = this.clampIndex(opts.index ?? this.index);\n this.setActive(this.index);\n void this.loadAndPlay(this.index, { userInitiated: false, isPlaylistStart: true });\n }\n\n next(): void {\n if (this.destroyed || !this.items.length) return;\n if (!this.playlistActive) return this.start({ index: this.index });\n\n if (this.index < this.items.length - 1) this.index++;\n else if (this.options.loop) this.index = 0;\n else return;\n\n this.setActive(this.index);\n void this.loadAndPlay(this.index, { userInitiated: true });\n }\n\n prev(): void {\n if (this.destroyed || !this.items.length) return;\n if (!this.playlistActive) return this.start({ index: this.index });\n if (this.index === 0) return;\n this.index--;\n this.setActive(this.index);\n void this.loadAndPlay(this.index, { userInitiated: true });\n }\n\n setIndex(i: number): void {\n if (this.destroyed || !this.items.length) return;\n this.index = this.clampIndex(i);\n this.setActive(this.index);\n if (!this.playlistActive) return this.start({ index: this.index });\n void this.loadAndPlay(this.index, { userInitiated: true });\n }\n\n getIndex(): number {\n return this.index;\n }\n\n isActive(): boolean {\n return this.playlistActive;\n }\n\n // ── player events ──\n\n private bindPlayerEvents(): void {\n this.ctx.videoEl.addEventListener('ended', this.onEnded);\n this.ctx.videoEl.addEventListener('error', this.onError);\n this.ctx.videoEl.addEventListener('play', this.onUserPlay);\n this.ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n }\n\n private readonly onUserPlay = (): void => {\n this.userHasStartedPlayback = true;\n };\n\n private readonly onEnded = (): void => {\n if (this.startPendingAfterCurrent && !this.playlistActive) {\n this.startPendingAfterCurrent = false;\n this.playlistActive = true;\n this.setActive(this.index);\n void this.loadAndPlay(this.index, { userInitiated: true, isPlaylistStart: true });\n return;\n }\n if (this.playlistActive) this.next();\n };\n\n private readonly onError = (): void => {\n if (this.destroyed || !this.playlistActive) return;\n const now = Date.now();\n if (now - this.lastErrorAt < 200) return;\n this.lastErrorAt = now;\n void this.fallbackOrSkip();\n };\n\n private readonly onTimeUpdate = (): void => {\n this.updateProgress();\n };\n\n // ── core load ──\n\n private async loadAndPlay(\n i: number,\n opts: { userInitiated?: boolean; forceMode?: SourceMode | null; forceMp4Index?: number | null; isFallback?: boolean; isPlaylistStart?: boolean } = {}\n ): Promise<void> {\n if (this.destroyed || this.switching || !this.playlistActive) return;\n this.switching = true;\n\n const item = this.items[i];\n if (!item) {\n this.switching = false;\n return;\n }\n const attemptId = ++this.attemptId;\n const mode = opts.forceMode ?? this.resolveMode(item);\n\n let tried = new Set<SourceMode>([mode]);\n let mp4Index = opts.forceMp4Index ?? 0;\n if (opts.isFallback && this.attempt?.index === i && this.attempt?.tried) {\n tried = new Set(this.attempt.tried);\n tried.add(mode);\n if (opts.forceMp4Index == null) mp4Index = this.attempt.mp4Index ?? 0;\n }\n this.attempt = { id: attemptId, index: i, mode, tried, mp4Index };\n\n try {\n const payload = this.buildPayload(item, mode, mp4Index);\n if (!payload) throw new Error('No playable source');\n\n this.setActive(i);\n this.ctx.videoEl.pause();\n if (item.image) this.ctx.setPoster(item.image);\n await this.ctx.loadSource(payload.src, payload.type);\n\n if (this.options.adsOnItemChange) this.maybeRequestAds(i, item, !!opts.isFallback);\n\n if (this.shouldAutoPlay(!!opts.userInitiated)) {\n try {\n await this.ctx.videoEl.play();\n } catch {\n /* autoplay engellendi — sessizce geç */\n }\n }\n this.updateProgress();\n } finally {\n this.switching = false;\n }\n }\n\n private async fallbackOrSkip(): Promise<void> {\n if (this.destroyed || !this.attempt) return;\n const item = this.items[this.attempt.index];\n if (!item) return;\n\n if (this.attempt.mode === 'mp4') {\n const mp4List = (item.mp4 || []).filter((v) => v?.src);\n const nextMp4 = (this.attempt.mp4Index ?? 0) + 1;\n if (nextMp4 < mp4List.length) {\n await this.loadAndPlay(this.attempt.index, { forceMode: 'mp4', forceMp4Index: nextMp4, isFallback: true });\n return;\n }\n }\n\n const otherMode: SourceMode = this.attempt.mode === 'hls' ? 'mp4' : 'hls';\n if (this.hasMode(item, otherMode) && !this.attempt.tried.has(otherMode)) {\n await this.loadAndPlay(this.attempt.index, { forceMode: otherMode, isFallback: true });\n return;\n }\n\n this.next();\n }\n\n // ── ads ──\n\n private maybeRequestAds(index: number, item: PlayableItem, _isFallback: boolean): void {\n if (this.lastAdsIndex === index) return;\n this.lastAdsIndex = index;\n this.ctx.requestFreshAd(item.adTagPreroll || this.rawOptions.adTagPreroll);\n }\n\n // ── sources ──\n\n private resolveMode(item: PlayableItem): SourceMode {\n if (this.options.preferHls) return this.hasMode(item, 'hls') ? 'hls' : this.hasMode(item, 'mp4') ? 'mp4' : 'hls';\n return this.hasMode(item, 'mp4') ? 'mp4' : this.hasMode(item, 'hls') ? 'hls' : 'mp4';\n }\n\n private hasMode(item: PlayableItem, mode: SourceMode): boolean {\n return Array.isArray(item[mode]) && item[mode]!.some((v) => v?.src);\n }\n\n private buildPayload(item: PlayableItem, mode: SourceMode, mp4Index = 0): { src: string; type?: string } | null {\n const list = (item[mode] || []).filter((v) => v?.src);\n if (!list.length) return null;\n\n let src;\n if (mode === 'mp4') {\n src = mp4Index > 0 ? list[mp4Index] || list[0] : list.find((v) => v.selected) || list[0];\n } else {\n src = list[0];\n }\n return { src: src!.src, type: src!.type || (mode === 'hls' ? 'application/x-mpegURL' : 'video/mp4') };\n }\n\n private shouldAutoPlay(userInitiated: boolean): boolean {\n if (userInitiated) return true;\n return this.options.autoplayNext && this.userHasStartedPlayback;\n }\n\n private clampIndex(i: number): number {\n if (!Number.isFinite(i) || !this.items.length) return 0;\n return Math.max(0, Math.min(this.items.length - 1, Math.trunc(i)));\n }\n\n // ── ui ──\n\n private buildUi() {\n const ui = this.rawOptions.ui ?? {};\n const root = document.createElement('div');\n root.setAttribute('part', 'playlist-panel');\n root.className = 'hp:flex hp:flex-col hp:gap-2 hp:p-3 hp:bg-surface-elev hp:max-h-80 hp:overflow-y-auto';\n\n const header = document.createElement('div');\n header.className = 'hp:flex hp:items-center hp:justify-between hp:gap-2 hp:mb-1';\n\n const titleEl = document.createElement('div');\n titleEl.className = 'hp:text-sm hp:font-semibold hp:text-on-surface';\n titleEl.textContent = this.playlistTitleText();\n header.appendChild(titleEl);\n\n const navWrap = document.createElement('div');\n navWrap.className = 'hp:flex hp:gap-1';\n const prevBtn = this.navButton('chevron-left', this.ctx.i18n.playlistPrev, () => this.prev());\n const nextBtn = this.navButton('chevron-left', this.ctx.i18n.playlistNext, () => this.next());\n nextBtn.style.transform = 'rotate(180deg)';\n navWrap.append(prevBtn, nextBtn);\n header.appendChild(navWrap);\n\n root.appendChild(header);\n\n const listEl = document.createElement('ul');\n listEl.className = 'hp:flex hp:flex-col hp:gap-1 hp:list-none hp:m-0 hp:p-0';\n root.appendChild(listEl);\n\n const itemEls: Array<{ li: HTMLElement; titleRow: HTMLElement; progressFill: HTMLElement | null; timeEl: HTMLElement | null }> = [];\n this.items.forEach((item, idx) => {\n const li = document.createElement('li');\n li.className =\n 'hp:flex hp:items-center hp:gap-2 hp:p-2 hp:rounded hp:cursor-pointer hp:text-on-surface-muted hp:text-sm ' +\n 'hp:hover:bg-on-surface/5 hp:data-[active=true]:bg-accent/15 hp:data-[active=true]:text-on-surface';\n\n if (item.image) {\n const img = document.createElement('img');\n img.src = item.image;\n img.loading = 'lazy';\n img.className = 'hp:w-16 hp:aspect-video hp:object-cover hp:rounded hp:shrink-0';\n li.appendChild(img);\n }\n\n const body = document.createElement('div');\n body.className = 'hp:flex-1 hp:min-w-0';\n const titleRow = document.createElement('div');\n titleRow.className = 'hp:truncate hp:font-medium';\n titleRow.textContent = item.title || this.ctx.i18n.videoFallbackTitle(idx);\n body.appendChild(titleRow);\n\n let progressFill: HTMLElement | null = null;\n let timeEl: HTMLElement | null = null;\n if (ui.showMeta !== false) {\n const metaRow = document.createElement('div');\n metaRow.className = 'hp:flex hp:items-center hp:gap-2 hp:text-xs hp:opacity-70 hp:mt-0.5';\n timeEl = document.createElement('span');\n timeEl.textContent = '';\n metaRow.appendChild(timeEl);\n\n const bar = document.createElement('div');\n bar.className = 'hp:flex-1 hp:h-0.5 hp:bg-on-surface/20 hp:rounded-full hp:overflow-hidden';\n progressFill = document.createElement('div');\n progressFill.className = 'hp:h-full hp:bg-accent';\n progressFill.style.width = '0%';\n bar.appendChild(progressFill);\n metaRow.appendChild(bar);\n body.appendChild(metaRow);\n }\n\n li.appendChild(body);\n li.addEventListener('click', () => this.setIndex(idx));\n listEl.appendChild(li);\n itemEls.push({ li, titleRow, progressFill, timeEl });\n });\n\n this.ctx.panelEl.appendChild(root);\n return { root, titleEl, listEl, prevBtn, nextBtn, itemEls };\n }\n\n private playlistTitleText(): string {\n const ui = this.rawOptions.ui ?? {};\n const title = ui.title || this.ctx.i18n.playlistTitle;\n return ui.showCount === false ? title : `${title} (${this.items.length})`;\n }\n\n private navButton(iconName: string, label: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.setAttribute('aria-label', label);\n btn.className = 'hp:flex hp:items-center hp:justify-center hp:w-6 hp:h-6 hp:text-on-surface hp:bg-transparent hp:border-0 hp:cursor-pointer';\n btn.appendChild(createIcon(iconName, 'hp:text-sm'));\n btn.addEventListener('click', onClick);\n return btn;\n }\n\n private setActive(index: number): void {\n this.ui.itemEls.forEach((entry, idx) => {\n if (idx === index) entry.li.setAttribute('data-active', 'true');\n else entry.li.removeAttribute('data-active');\n });\n // loadAndPlay() hem anlık UI geri bildirimi için önceden (next/prev/setIndex\n // içinden) hem de kaynak gerçekten yüklendiğinde setActive() çağırıyor —\n // aynı index için event'i yalnızca BİR kez yaymak için guard.\n if (this.lastDispatchedIndex !== index) {\n this.lastDispatchedIndex = index;\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:itemchange', { detail: { index, source: 'playlist' } }));\n }\n }\n\n private updateProgress(): void {\n const active = this.ui.itemEls[this.index];\n if (!active) return;\n const duration = this.ctx.videoEl.duration;\n const current = this.ctx.videoEl.currentTime;\n if (active.timeEl) active.timeEl.textContent = this.formatTime(current);\n if (active.progressFill && Number.isFinite(duration) && duration > 0) {\n active.progressFill.style.width = `${Math.min(100, (current / duration) * 100)}%`;\n }\n }\n\n private formatTime(sec: number): string {\n const s = Math.max(0, Math.floor(sec || 0));\n const m = Math.floor(s / 60);\n const r = s % 60;\n return `${m}:${String(r).padStart(2, '0')}`;\n }\n}\n","import { PlaylistRunner, type PlaylistPlayerContext } from './PlaylistRunner';\nimport type { PlaylistOptions } from '../../types';\n\nexport function installPlaylist(ctx: PlaylistPlayerContext, options: PlaylistOptions): PlaylistRunner {\n return new PlaylistRunner(ctx, options);\n}\n\nexport { PlaylistRunner };\nexport type { PlaylistPlayerContext };\n"],"names":["DEFAULTS","PlaylistRunner","ctx","rawOptions","__publicField","now","entry","idx","item","opts","i","attemptId","mode","tried","mp4Index","_a","_b","payload","mp4List","v","nextMp4","otherMode","index","_isFallback","list","src","userInitiated","ui","root","header","titleEl","navWrap","prevBtn","nextBtn","listEl","itemEls","li","img","body","titleRow","progressFill","timeEl","metaRow","bar","title","iconName","label","onClick","btn","createIcon","active","duration","current","sec","s","m","r","installPlaylist","options"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var m = Object.defineProperty;
|
|
2
2
|
var v = (r, t, e) => t in r ? m(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
|
|
3
3
|
var n = (r, t, e) => v(r, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
-
import { f as E } from "./index-
|
|
4
|
+
import { f as E } from "./index-BjmWoP4E.js";
|
|
5
5
|
class u {
|
|
6
6
|
constructor(t, e) {
|
|
7
7
|
n(this, "chapters", []);
|
|
@@ -60,4 +60,4 @@ export {
|
|
|
60
60
|
u as Segments,
|
|
61
61
|
g as installSegments
|
|
62
62
|
};
|
|
63
|
-
//# sourceMappingURL=index-
|
|
63
|
+
//# sourceMappingURL=index-CZK3TwzR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-CZK3TwzR.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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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var A = Object.defineProperty;
|
|
2
2
|
var P = (h, t, e) => t in h ? A(h, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : h[t] = e;
|
|
3
3
|
var r = (h, t, e) => P(h, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
-
import { c as E } from "./index-
|
|
4
|
+
import { c as E } from "./index-BjmWoP4E.js";
|
|
5
5
|
const L = {
|
|
6
6
|
startIndex: 0,
|
|
7
7
|
loop: !0,
|
|
@@ -319,4 +319,4 @@ export {
|
|
|
319
319
|
N as HopeStory,
|
|
320
320
|
M as installStory
|
|
321
321
|
};
|
|
322
|
-
//# sourceMappingURL=index-
|
|
322
|
+
//# sourceMappingURL=index-DadIEuQc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-BFgqg05L.js","sources":["../../src/plugins/story/HopeStory.ts","../../src/plugins/story/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { PlayableItem, StoryOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface StoryPlayerContext {\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** .video-area — story aktifken 9:16'ya çevrilir (data-story attribute ile), destroy'da geri alınır. */\n videoAreaEl: HTMLElement;\n /** Gerçek player gövdesi (.media-layer + chrome + center-play-button) — orta pane'e taşınır, destroy'da geri alınır. */\n playerBodyEls: HTMLElement[];\n loadSource(src: string, type?: string): Promise<void>;\n setPoster(url: string): void;\n requestFreshAd(prerollTag?: string): void;\n i18n: HopeLocaleStrings;\n}\n\ntype Dir = 'next' | 'prev';\n\nconst DEFAULTS: Required<Omit<StoryOptions, 'items' | 'adTagPreroll' | 'gestures' | 'ui'>> = {\n startIndex: 0,\n loop: true,\n autoplayNext: true,\n preferHls: true,\n transitionMs: 380,\n adsOnItemChange: true,\n};\n\n/** Dikey video akışı (Shorts/Story): tek <video>, item değişiminde kaynak değişir. */\nexport class HopeStory {\n private readonly options: Required<Omit<StoryOptions, 'items' | 'adTagPreroll' | 'gestures' | 'ui'>>;\n private readonly gestureOpts: Required<NonNullable<StoryOptions['gestures']>>;\n private readonly uiOpts: Required<NonNullable<StoryOptions['ui']>>;\n private readonly items: PlayableItem[];\n\n private index: number;\n private destroyed = false;\n private switching = false;\n private listOpen = false;\n private userHasStartedPlayback = false;\n private lastAdsIndex: number | null = null;\n private wheelAccum = 0;\n private lastNavAt = 0;\n private drag: { startY: number; startX: number; dy: number; active: boolean; id: number } | null = null;\n\n private readonly els: {\n viewport: HTMLElement;\n track: HTMLElement;\n panePrev: HTMLElement;\n paneCurrent: HTMLElement;\n paneNext: HTMLElement;\n overlay: HTMLElement;\n counter: HTMLElement;\n titleEl: HTMLElement;\n spotEl: HTMLElement;\n dots: HTMLElement;\n progressBar: HTMLElement;\n upBtn: HTMLButtonElement;\n downBtn: HTMLButtonElement;\n listBtn: HTMLButtonElement;\n panel: HTMLElement;\n grid: HTMLElement;\n };\n\n constructor(\n private readonly ctx: StoryPlayerContext,\n private readonly rawOptions: StoryOptions\n ) {\n this.options = { ...DEFAULTS, ...rawOptions };\n this.gestureOpts = {\n swipe: true,\n swipeThreshold: 0.12,\n wheel: true,\n wheelThreshold: 42,\n wheelCooldownMs: 620,\n keyboard: true,\n ...rawOptions.gestures,\n };\n this.uiOpts = { counter: true, title: true, spot: true, dots: true, progress: true, ...rawOptions.ui };\n this.items = Array.isArray(rawOptions.items) ? rawOptions.items : [];\n this.index = this.clamp(this.options.startIndex);\n\n this.els = this.buildDom();\n this.bindEvents();\n this.syncUi();\n this.preloadNeighbours();\n\n if (this.items.length) void this.loadItem(this.index, { isStart: true });\n }\n\n refreshLabels(): void {\n this.els.upBtn.setAttribute('aria-label', this.ctx.i18n.storyPrev);\n this.els.downBtn.setAttribute('aria-label', this.ctx.i18n.storyNext);\n this.els.listBtn.setAttribute('aria-label', this.ctx.i18n.storyAllVideos);\n this.renderList(this.els.grid);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n this.ctx.videoEl.removeEventListener('ended', this.onEnded);\n this.ctx.videoEl.removeEventListener('playing', this.onPlaying);\n this.ctx.videoEl.removeEventListener('play', this.onFirstPlay);\n this.ctx.videoEl.removeEventListener('timeupdate', this.onTimeUpdate);\n this.els.viewport.removeEventListener('wheel', this.onWheel);\n this.els.viewport.removeEventListener('pointerdown', this.onPointerDown);\n window.removeEventListener('pointermove', this.onPointerMove);\n window.removeEventListener('pointerup', this.onPointerUp);\n document.removeEventListener('keydown', this.onKeyDown);\n\n // player gövdesini .video-area'ya geri taşı, story DOM'unu kaldır.\n this.ctx.playerBodyEls.forEach((el) => this.ctx.videoAreaEl.appendChild(el));\n this.ctx.videoAreaEl.removeAttribute('data-story');\n this.els.viewport.remove();\n this.els.panel.remove();\n }\n\n // ── public api ──\n\n next(userInitiated = true): void {\n const target = this.index + 1;\n if (target >= this.items.length) {\n if (!this.options.loop) return;\n void this.goTo(0, 'next', userInitiated);\n return;\n }\n void this.goTo(target, 'next', userInitiated);\n }\n\n prev(userInitiated = true): void {\n const target = this.index - 1;\n if (target < 0) {\n if (!this.options.loop) return;\n void this.goTo(this.items.length - 1, 'prev', userInitiated);\n return;\n }\n void this.goTo(target, 'prev', userInitiated);\n }\n\n async goTo(target: number, direction: Dir | null = null, userInitiated = true): Promise<void> {\n if (this.destroyed || this.switching) return;\n const i = this.clamp(target);\n if (i === this.index) return;\n\n const dir = direction || (i > this.index ? 'next' : 'prev');\n this.switching = true;\n try {\n this.fillPane(dir, this.items[i]);\n await this.animate(dir);\n this.index = i;\n this.syncUi();\n await this.loadItem(i, { userInitiated });\n this.preloadNeighbours();\n } finally {\n this.switching = false;\n }\n }\n\n toggleList(force?: boolean): void {\n this.listOpen = typeof force === 'boolean' ? force : !this.listOpen;\n this.els.panel.setAttribute('aria-hidden', this.listOpen ? 'false' : 'true');\n this.els.listBtn.setAttribute('aria-expanded', this.listOpen ? 'true' : 'false');\n // translate-x/-y utility yerine inline transform: Shadow DOM'da tek eksenli Tailwind translate 'none' oluyor.\n this.els.panel.style.transform = this.listOpen ? 'translateX(0)' : 'translateX(100%)';\n }\n\n // ── dom ──\n\n private buildDom() {\n this.ctx.videoAreaEl.setAttribute('data-story', '1');\n\n const viewport = document.createElement('div');\n viewport.className = 'hp:absolute hp:inset-0 hp:overflow-hidden hp:touch-none';\n viewport.setAttribute('tabindex', '0');\n\n const track = document.createElement('div');\n track.className = 'hp:relative hp:w-full';\n track.style.height = '300%';\n track.style.transform = 'translate3d(0,-33.3333%,0)';\n track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n\n const panePrev = this.createPane();\n const paneCurrent = document.createElement('div');\n paneCurrent.className = 'hp:absolute hp:inset-x-0 hp:h-1/3';\n paneCurrent.style.top = '33.3333%';\n const paneNext = this.createPane();\n paneNext.style.top = '66.6667%';\n\n // Gerçek player gövdesini orta pane'e taşı.\n this.ctx.playerBodyEls.forEach((el) => paneCurrent.appendChild(el));\n\n track.append(panePrev, paneCurrent, paneNext);\n viewport.appendChild(track);\n\n const overlay = document.createElement('div');\n overlay.className = 'hp:absolute hp:inset-0 hp:z-20 hp:pointer-events-none hp:flex hp:flex-col hp:justify-between hp:p-3';\n\n const progressBar = document.createElement('div');\n progressBar.className = 'hp:h-0.5 hp:bg-white/30 hp:rounded-full hp:overflow-hidden';\n const progressFill = document.createElement('div');\n progressFill.className = 'hp:h-full hp:bg-accent hp:w-0';\n progressBar.appendChild(progressFill);\n\n const meta = document.createElement('div');\n meta.className = 'hp:flex hp:flex-col hp:gap-0.5 hp:text-white hp:drop-shadow hp:mt-2 hp:pointer-events-auto';\n const counter = document.createElement('span');\n counter.setAttribute('part', 'story-counter');\n counter.className = 'hp:text-xs hp:opacity-80';\n const titleEl = document.createElement('strong');\n titleEl.className = 'hp:text-sm';\n const spotEl = document.createElement('span');\n spotEl.className = 'hp:text-xs hp:opacity-80';\n meta.append(counter, titleEl, spotEl);\n\n const dots = document.createElement('div');\n dots.className = 'hp:absolute hp:right-2 hp:top-1/2 hp-center-y hp:flex hp:flex-col hp:gap-1 hp:pointer-events-none';\n\n const navWrap = document.createElement('div');\n navWrap.className = 'hp:flex hp:flex-col hp:gap-2 hp:self-end hp:pointer-events-auto hp:mb-16';\n const upBtn = this.navBtn('chevron-left', this.ctx.i18n.storyPrev);\n upBtn.style.transform = 'rotate(90deg)';\n const downBtn = this.navBtn('chevron-left', this.ctx.i18n.storyNext);\n downBtn.style.transform = 'rotate(-90deg)';\n navWrap.append(upBtn, downBtn);\n\n const listBtn = document.createElement('button');\n listBtn.type = 'button';\n listBtn.setAttribute('aria-label', this.ctx.i18n.storyAllVideos);\n listBtn.setAttribute('aria-expanded', 'false');\n listBtn.className =\n 'hp:absolute hp:top-2 hp:right-2 hp:flex hp:items-center hp:justify-center hp:w-8 hp:h-8 hp:rounded-full ' +\n 'hp:bg-black/40 hp:text-white hp:border-0 hp:cursor-pointer hp:pointer-events-auto';\n listBtn.appendChild(createIcon('settings', 'hp:text-sm'));\n\n overlay.append(progressBar, meta, dots, navWrap, listBtn);\n\n const panel = document.createElement('aside');\n panel.className =\n 'hp:absolute hp:inset-y-0 hp:right-0 hp:w-72 hp:max-w-[80%] hp:bg-surface-elev hp:z-30 hp:overflow-y-auto hp:p-3 ' +\n 'hp:transition-transform hp:duration-300';\n panel.style.transform = 'translateX(100%)';\n panel.setAttribute('aria-hidden', 'true');\n const grid = document.createElement('div');\n grid.className = 'hp:flex hp:flex-col hp:gap-2 hp:mt-8';\n panel.appendChild(grid);\n\n this.ctx.videoAreaEl.append(viewport, overlay, panel);\n\n this.renderList(grid);\n\n return {\n viewport, track, panePrev, paneCurrent, paneNext, overlay,\n counter, titleEl, spotEl, dots, progressBar: progressFill,\n upBtn, downBtn, listBtn, panel, grid,\n };\n }\n\n private createPane(): HTMLElement {\n const pane = document.createElement('div');\n pane.className = 'hp:absolute hp:inset-x-0 hp:h-1/3 hp:bg-cover hp:bg-center hp:bg-black';\n return pane;\n }\n\n private navBtn(iconName: string, label: string): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.setAttribute('aria-label', label);\n btn.className =\n 'hp:flex hp:items-center hp:justify-center hp:w-8 hp:h-8 hp:rounded-full hp:bg-black/40 hp:text-white hp:border-0 hp:cursor-pointer';\n btn.appendChild(createIcon(iconName, 'hp:text-sm'));\n return btn;\n }\n\n private fillPane(dir: Dir, item: PlayableItem | undefined): void {\n const pane = dir === 'next' ? this.els.paneNext : this.els.panePrev;\n const img = item?.image || '';\n pane.style.backgroundImage = img ? `url(\"${img}\")` : 'none';\n }\n\n private animate(dir: Dir): Promise<void> {\n const track = this.els.track;\n return new Promise((resolve) => {\n let done = false;\n const finish = () => {\n if (done) return;\n done = true;\n track.removeEventListener('transitionend', finish);\n clearTimeout(timer);\n track.style.transition = 'none';\n track.style.transform = 'translate3d(0,-33.3333%,0)';\n void track.offsetHeight;\n track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n resolve();\n };\n track.addEventListener('transitionend', finish);\n const timer = setTimeout(finish, this.options.transitionMs + 120);\n track.style.transform = dir === 'next' ? 'translate3d(0,-66.6667%,0)' : 'translate3d(0,0,0)';\n });\n }\n\n // ── source / playback ──\n\n private async loadItem(i: number, opts: { userInitiated?: boolean; isStart?: boolean } = {}): Promise<void> {\n const item = this.items[i];\n if (!item) return;\n\n const mode = this.resolveMode(item);\n const payload = this.buildPayload(item, mode);\n if (!payload) return;\n\n this.ctx.videoEl.pause();\n if (item.image) this.ctx.setPoster(item.image);\n await this.ctx.loadSource(payload.src, payload.type);\n\n if (this.options.adsOnItemChange && this.lastAdsIndex !== i) {\n this.lastAdsIndex = i;\n this.ctx.requestFreshAd(item.adTagPreroll || this.rawOptions.adTagPreroll);\n }\n\n if (this.shouldAutoPlay(opts)) {\n try {\n await this.ctx.videoEl.play();\n } catch {\n /* autoplay engellendi */\n }\n }\n }\n\n private shouldAutoPlay({ userInitiated, isStart }: { userInitiated?: boolean; isStart?: boolean }): boolean {\n if (isStart) return !!this.ctx.videoEl.autoplay;\n if (userInitiated) return true;\n return this.options.autoplayNext && this.userHasStartedPlayback;\n }\n\n private resolveMode(item: PlayableItem): 'hls' | 'mp4' {\n const hasHls = this.hasMode(item, 'hls');\n const hasMp4 = this.hasMode(item, 'mp4');\n if (this.options.preferHls) return hasHls ? 'hls' : hasMp4 ? 'mp4' : 'hls';\n return hasMp4 ? 'mp4' : hasHls ? 'hls' : 'mp4';\n }\n\n private hasMode(item: PlayableItem, mode: 'hls' | 'mp4'): boolean {\n return Array.isArray(item[mode]) && item[mode]!.some((v) => v?.src);\n }\n\n private buildPayload(item: PlayableItem, mode: 'hls' | 'mp4'): { src: string; type?: string } | null {\n const list = (item[mode] || []).filter((v) => v?.src);\n if (!list.length) return null;\n const src = mode === 'mp4' ? list.find((v) => v.selected) || list[0] : list[0];\n return { src: src!.src, type: src!.type || (mode === 'hls' ? 'application/x-mpegURL' : 'video/mp4') };\n }\n\n // ── preload ──\n\n private preloadNeighbours(): void {\n const nav = navigator as Navigator & { connection?: { saveData?: boolean } };\n if (nav.connection?.saveData) return;\n\n [this.wrapIndex(this.index + 1), this.wrapIndex(this.index - 1)].forEach((i) => {\n if (i === this.index) return;\n const item = this.items[i];\n if (item?.image) {\n const img = new Image();\n img.decoding = 'async';\n img.src = item.image;\n }\n });\n }\n\n // ── ui sync ──\n\n private syncUi(): void {\n const item = this.items[this.index];\n const total = this.items.length;\n\n if (this.uiOpts.counter) this.els.counter.textContent = `${this.index + 1} / ${total}`;\n if (this.uiOpts.title) this.els.titleEl.textContent = item?.title || '';\n if (this.uiOpts.spot) this.els.spotEl.textContent = item?.spot || '';\n\n this.fillPane('prev', this.items[this.wrapIndex(this.index - 1)]);\n this.fillPane('next', this.items[this.wrapIndex(this.index + 1)]);\n\n const atStart = !this.options.loop && this.index === 0;\n const atEnd = !this.options.loop && this.index === total - 1;\n this.els.upBtn.disabled = atStart;\n this.els.downBtn.disabled = atEnd;\n\n if (this.uiOpts.dots) {\n if (this.els.dots.children.length !== total) {\n this.els.dots.innerHTML = '';\n for (let i = 0; i < total; i++) {\n const dot = document.createElement('i');\n dot.className = 'hp:block hp:w-1 hp:h-1 hp:rounded-full hp:bg-white/40';\n this.els.dots.appendChild(dot);\n }\n }\n Array.from(this.els.dots.children).forEach((el, i) => {\n (el as HTMLElement).className = `hp:block hp:w-1 hp:h-1 hp:rounded-full ${i === this.index ? 'hp:bg-white' : 'hp:bg-white/40'}`;\n });\n }\n\n this.setActiveThumb();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:itemchange', { detail: { index: this.index, source: 'story' } }));\n }\n\n private renderList(grid: HTMLElement): void {\n grid.innerHTML = '';\n this.items.forEach((item, i) => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'hp:flex hp:items-center hp:gap-2 hp:w-full hp:p-1.5 hp:rounded hp:text-left hp:text-on-surface hp:bg-transparent hp:border-0 hp:cursor-pointer hp:hover:bg-on-surface/5';\n btn.dataset.index = String(i);\n if (item.image) {\n const img = document.createElement('img');\n img.src = item.image;\n img.loading = 'lazy';\n img.className = 'hp:w-14 hp:aspect-[9/16] hp:object-cover hp:rounded hp:shrink-0';\n btn.appendChild(img);\n }\n const title = document.createElement('span');\n title.className = 'hp:text-xs hp:truncate';\n title.textContent = item.title || this.ctx.i18n.videoFallbackTitle(i);\n btn.appendChild(title);\n btn.addEventListener('click', () => {\n this.toggleList(false);\n void this.goTo(i);\n });\n grid.appendChild(btn);\n });\n }\n\n private setActiveThumb(): void {\n Array.from(this.els.grid.children).forEach((el, i) => {\n el.classList.toggle('hp:bg-accent/15', i === this.index);\n });\n }\n\n // ── events ──\n\n private bindEvents(): void {\n this.ctx.videoEl.addEventListener('ended', this.onEnded);\n this.ctx.videoEl.addEventListener('playing', this.onPlaying);\n this.ctx.videoEl.addEventListener('play', this.onFirstPlay);\n if (this.uiOpts.progress) this.ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n\n this.els.upBtn.addEventListener('click', () => this.prev());\n this.els.downBtn.addEventListener('click', () => this.next());\n this.els.listBtn.addEventListener('click', () => this.toggleList());\n\n this.els.grid.parentElement?.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Escape') this.toggleList(false);\n });\n\n if (this.gestureOpts.wheel) this.els.viewport.addEventListener('wheel', this.onWheel, { passive: false });\n if (this.gestureOpts.swipe) {\n this.els.viewport.addEventListener('pointerdown', this.onPointerDown);\n window.addEventListener('pointermove', this.onPointerMove, { passive: false });\n window.addEventListener('pointerup', this.onPointerUp);\n }\n if (this.gestureOpts.keyboard) document.addEventListener('keydown', this.onKeyDown);\n }\n\n private readonly onEnded = (): void => {\n if (!this.options.autoplayNext) return;\n if (!this.options.loop && this.index === this.items.length - 1) return;\n this.next(false);\n };\n\n private readonly onPlaying = (): void => {};\n\n private readonly onFirstPlay = (): void => {\n this.userHasStartedPlayback = true;\n };\n\n private readonly onTimeUpdate = (): void => {\n const dur = this.ctx.videoEl.duration || 0;\n const cur = this.ctx.videoEl.currentTime || 0;\n this.els.progressBar.style.width = dur > 0 ? `${Math.min(100, (cur / dur) * 100)}%` : '0%';\n };\n\n private readonly onWheel = (e: WheelEvent): void => {\n if (this.switching) {\n e.preventDefault();\n return;\n }\n const dir: Dir = e.deltaY > 0 ? 'next' : 'prev';\n if (!this.canGo(dir)) return;\n e.preventDefault();\n\n const now = Date.now();\n if (now - this.lastNavAt < this.gestureOpts.wheelCooldownMs) return;\n this.wheelAccum += e.deltaY;\n if (Math.abs(this.wheelAccum) < this.gestureOpts.wheelThreshold) return;\n this.wheelAccum = 0;\n this.lastNavAt = now;\n dir === 'next' ? this.next() : this.prev();\n };\n\n private readonly onPointerDown = (e: PointerEvent): void => {\n if (this.switching || this.listOpen) return;\n if (e.pointerType === 'mouse' && e.button !== 0) return;\n this.drag = { startY: e.clientY, startX: e.clientX, dy: 0, active: false, id: e.pointerId };\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n const drag = this.drag;\n if (!drag || e.pointerId !== drag.id) return;\n const dy = e.clientY - drag.startY;\n const dx = e.clientX - drag.startX;\n\n if (!drag.active) {\n if (Math.abs(dy) < 10 || Math.abs(dy) < Math.abs(dx)) return;\n drag.active = true;\n this.els.track.style.transition = 'none';\n }\n e.preventDefault();\n\n const h = this.els.viewport.clientHeight || 1;\n const resisted = this.canGo(dy < 0 ? 'next' : 'prev') ? dy : dy * 0.25;\n drag.dy = resisted;\n\n const pct = -33.3333 + (resisted / h) * 33.3333;\n this.els.track.style.transform = `translate3d(0, ${pct}%, 0)`;\n };\n\n private readonly onPointerUp = (): void => {\n const drag = this.drag;\n this.drag = null;\n if (!drag?.active) return;\n\n const h = this.els.viewport.clientHeight || 1;\n const ratio = Math.abs(drag.dy) / h;\n const dir: Dir = drag.dy < 0 ? 'next' : 'prev';\n\n this.els.track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n if (ratio >= this.gestureOpts.swipeThreshold && this.canGo(dir)) {\n this.els.track.style.transform = 'translate3d(0,-33.3333%,0)';\n dir === 'next' ? this.next() : this.prev();\n } else {\n this.els.track.style.transform = 'translate3d(0,-33.3333%,0)';\n }\n };\n\n private readonly onKeyDown = (e: KeyboardEvent): void => {\n if (this.destroyed) return;\n if (e.key === 'Escape' && this.listOpen) {\n this.toggleList(false);\n return;\n }\n const tag = document.activeElement?.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA') return;\n if (!this.isInViewport()) return;\n\n if (e.key === 'ArrowDown' || e.key === 'PageDown' || e.key === 'j') {\n e.preventDefault();\n this.next();\n } else if (e.key === 'ArrowUp' || e.key === 'PageUp' || e.key === 'k') {\n e.preventDefault();\n this.prev();\n }\n };\n\n // ── helpers ──\n\n private canGo(dir: Dir): boolean {\n if (this.options.loop) return this.items.length > 1;\n return dir === 'next' ? this.index < this.items.length - 1 : this.index > 0;\n }\n\n private isInViewport(): boolean {\n const r = this.ctx.hostEl.getBoundingClientRect();\n return r.bottom > 0 && r.top < (window.innerHeight || 0);\n }\n\n private clamp(i: number): number {\n if (!Number.isFinite(i) || !this.items.length) return 0;\n return Math.max(0, Math.min(this.items.length - 1, Math.trunc(i)));\n }\n\n private wrapIndex(i: number): number {\n const n = this.items.length;\n if (!n) return 0;\n if (this.options.loop) return ((i % n) + n) % n;\n return this.clamp(i);\n }\n}\n","import { HopeStory, type StoryPlayerContext } from './HopeStory';\nimport type { StoryOptions } from '../../types';\n\nexport function installStory(ctx: StoryPlayerContext, options: StoryOptions): HopeStory {\n return new HopeStory(ctx, options);\n}\n\nexport { HopeStory };\nexport type { StoryPlayerContext };\n"],"names":["DEFAULTS","HopeStory","ctx","rawOptions","__publicField","dur","cur","e","dir","now","drag","dy","dx","h","resisted","pct","ratio","tag","_a","el","userInitiated","target","direction","force","viewport","track","panePrev","paneCurrent","paneNext","overlay","progressBar","progressFill","meta","counter","titleEl","spotEl","dots","navWrap","upBtn","downBtn","listBtn","createIcon","panel","grid","pane","iconName","label","btn","item","img","resolve","done","finish","timer","i","opts","mode","payload","isStart","hasHls","hasMp4","v","list","src","total","atStart","atEnd","dot","title","r","n","installStory","options"],"mappings":";;;;AAmBA,MAAMA,IAAuF;AAAA,EACzF,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,iBAAiB;AACrB;AAGO,MAAMC,EAAU;AAAA,EAmCnB,YACqBC,GACAC,GACnB;AArCe,IAAAC,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAET,IAAAA,EAAA;AACA,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,kBAAW;AACX,IAAAA,EAAA,gCAAyB;AACzB,IAAAA,EAAA,sBAA8B;AAC9B,IAAAA,EAAA,oBAAa;AACb,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,cAA2F;AAElF,IAAAA,EAAA;AAkaA,IAAAA,EAAA,iBAAU,MAAY;AACnC,MAAK,KAAK,QAAQ,iBACd,CAAC,KAAK,QAAQ,QAAQ,KAAK,UAAU,KAAK,MAAM,SAAS,KAC7D,KAAK,KAAK,EAAK;AAAA,IACnB;AAEiB,IAAAA,EAAA,mBAAY,MAAY;AAAA,IAAC;AAEzB,IAAAA,EAAA,qBAAc,MAAY;AACvC,WAAK,yBAAyB;AAAA,IAClC;AAEiB,IAAAA,EAAA,sBAAe,MAAY;AACxC,YAAMC,IAAM,KAAK,IAAI,QAAQ,YAAY,GACnCC,IAAM,KAAK,IAAI,QAAQ,eAAe;AAC5C,WAAK,IAAI,YAAY,MAAM,QAAQD,IAAM,IAAI,GAAG,KAAK,IAAI,KAAMC,IAAMD,IAAO,GAAG,CAAC,MAAM;AAAA,IAC1F;AAEiB,IAAAD,EAAA,iBAAU,CAACG,MAAwB;AAChD,UAAI,KAAK,WAAW;AAChB,QAAAA,EAAE,eAAA;AACF;AAAA,MACJ;AACA,YAAMC,IAAWD,EAAE,SAAS,IAAI,SAAS;AACzC,UAAI,CAAC,KAAK,MAAMC,CAAG,EAAG;AACtB,MAAAD,EAAE,eAAA;AAEF,YAAME,IAAM,KAAK,IAAA;AACjB,MAAIA,IAAM,KAAK,YAAY,KAAK,YAAY,oBAC5C,KAAK,cAAcF,EAAE,QACjB,OAAK,IAAI,KAAK,UAAU,IAAI,KAAK,YAAY,oBACjD,KAAK,aAAa,GAClB,KAAK,YAAYE,GACjBD,MAAQ,SAAS,KAAK,KAAA,IAAS,KAAK,KAAA;AAAA,IACxC;AAEiB,IAAAJ,EAAA,uBAAgB,CAACG,MAA0B;AACxD,MAAI,KAAK,aAAa,KAAK,YACvBA,EAAE,gBAAgB,WAAWA,EAAE,WAAW,MAC9C,KAAK,OAAO,EAAE,QAAQA,EAAE,SAAS,QAAQA,EAAE,SAAS,IAAI,GAAG,QAAQ,IAAO,IAAIA,EAAE,UAAA;AAAA,IACpF;AAEiB,IAAAH,EAAA,uBAAgB,CAACG,MAA0B;AACxD,YAAMG,IAAO,KAAK;AAClB,UAAI,CAACA,KAAQH,EAAE,cAAcG,EAAK,GAAI;AACtC,YAAMC,IAAKJ,EAAE,UAAUG,EAAK,QACtBE,IAAKL,EAAE,UAAUG,EAAK;AAE5B,UAAI,CAACA,EAAK,QAAQ;AACd,YAAI,KAAK,IAAIC,CAAE,IAAI,MAAM,KAAK,IAAIA,CAAE,IAAI,KAAK,IAAIC,CAAE,EAAG;AACtD,QAAAF,EAAK,SAAS,IACd,KAAK,IAAI,MAAM,MAAM,aAAa;AAAA,MACtC;AACA,MAAAH,EAAE,eAAA;AAEF,YAAMM,IAAI,KAAK,IAAI,SAAS,gBAAgB,GACtCC,IAAW,KAAK,MAAMH,IAAK,IAAI,SAAS,MAAM,IAAIA,IAAKA,IAAK;AAClE,MAAAD,EAAK,KAAKI;AAEV,YAAMC,IAAM,WAAYD,IAAWD,IAAK;AACxC,WAAK,IAAI,MAAM,MAAM,YAAY,kBAAkBE,CAAG;AAAA,IAC1D;AAEiB,IAAAX,EAAA,qBAAc,MAAY;AACvC,YAAMM,IAAO,KAAK;AAElB,UADA,KAAK,OAAO,MACR,EAACA,KAAA,QAAAA,EAAM,QAAQ;AAEnB,YAAMG,IAAI,KAAK,IAAI,SAAS,gBAAgB,GACtCG,IAAQ,KAAK,IAAIN,EAAK,EAAE,IAAIG,GAC5BL,IAAWE,EAAK,KAAK,IAAI,SAAS;AAExC,WAAK,IAAI,MAAM,MAAM,aAAa,aAAa,KAAK,QAAQ,YAAY,WACpEM,KAAS,KAAK,YAAY,kBAAkB,KAAK,MAAMR,CAAG,KAC1D,KAAK,IAAI,MAAM,MAAM,YAAY,8BACjCA,MAAQ,SAAS,KAAK,KAAA,IAAS,KAAK,KAAA,KAEpC,KAAK,IAAI,MAAM,MAAM,YAAY;AAAA,IAEzC;AAEiB,IAAAJ,EAAA,mBAAY,CAACG,MAA2B;;AACrD,UAAI,KAAK,UAAW;AACpB,UAAIA,EAAE,QAAQ,YAAY,KAAK,UAAU;AACrC,aAAK,WAAW,EAAK;AACrB;AAAA,MACJ;AACA,YAAMU,KAAMC,IAAA,SAAS,kBAAT,gBAAAA,EAAwB;AACpC,MAAID,MAAQ,WAAWA,MAAQ,cAC1B,KAAK,mBAENV,EAAE,QAAQ,eAAeA,EAAE,QAAQ,cAAcA,EAAE,QAAQ,OAC3DA,EAAE,eAAA,GACF,KAAK,KAAA,MACEA,EAAE,QAAQ,aAAaA,EAAE,QAAQ,YAAYA,EAAE,QAAQ,SAC9DA,EAAE,eAAA,GACF,KAAK,KAAA;AAAA,IAEb;AAhfqB,SAAA,MAAAL,GACA,KAAA,aAAAC,GAEjB,KAAK,UAAU,EAAE,GAAGH,GAAU,GAAGG,EAAA,GACjC,KAAK,cAAc;AAAA,MACf,OAAO;AAAA,MACP,gBAAgB;AAAA,MAChB,OAAO;AAAA,MACP,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,UAAU;AAAA,MACV,GAAGA,EAAW;AAAA,IAAA,GAElB,KAAK,SAAS,EAAE,SAAS,IAAM,OAAO,IAAM,MAAM,IAAM,MAAM,IAAM,UAAU,IAAM,GAAGA,EAAW,GAAA,GAClG,KAAK,QAAQ,MAAM,QAAQA,EAAW,KAAK,IAAIA,EAAW,QAAQ,CAAA,GAClE,KAAK,QAAQ,KAAK,MAAM,KAAK,QAAQ,UAAU,GAE/C,KAAK,MAAM,KAAK,SAAA,GAChB,KAAK,WAAA,GACL,KAAK,OAAA,GACL,KAAK,kBAAA,GAED,KAAK,MAAM,UAAa,KAAK,SAAS,KAAK,OAAO,EAAE,SAAS,GAAA,CAAM;AAAA,EAC3E;AAAA,EAEA,gBAAsB;AAClB,SAAK,IAAI,MAAM,aAAa,cAAc,KAAK,IAAI,KAAK,SAAS,GACjE,KAAK,IAAI,QAAQ,aAAa,cAAc,KAAK,IAAI,KAAK,SAAS,GACnE,KAAK,IAAI,QAAQ,aAAa,cAAc,KAAK,IAAI,KAAK,cAAc,GACxE,KAAK,WAAW,KAAK,IAAI,IAAI;AAAA,EACjC;AAAA,EAEA,UAAgB;AACZ,IAAI,KAAK,cACT,KAAK,YAAY,IAEjB,KAAK,IAAI,QAAQ,oBAAoB,SAAS,KAAK,OAAO,GAC1D,KAAK,IAAI,QAAQ,oBAAoB,WAAW,KAAK,SAAS,GAC9D,KAAK,IAAI,QAAQ,oBAAoB,QAAQ,KAAK,WAAW,GAC7D,KAAK,IAAI,QAAQ,oBAAoB,cAAc,KAAK,YAAY,GACpE,KAAK,IAAI,SAAS,oBAAoB,SAAS,KAAK,OAAO,GAC3D,KAAK,IAAI,SAAS,oBAAoB,eAAe,KAAK,aAAa,GACvE,OAAO,oBAAoB,eAAe,KAAK,aAAa,GAC5D,OAAO,oBAAoB,aAAa,KAAK,WAAW,GACxD,SAAS,oBAAoB,WAAW,KAAK,SAAS,GAGtD,KAAK,IAAI,cAAc,QAAQ,CAACgB,MAAO,KAAK,IAAI,YAAY,YAAYA,CAAE,CAAC,GAC3E,KAAK,IAAI,YAAY,gBAAgB,YAAY,GACjD,KAAK,IAAI,SAAS,OAAA,GAClB,KAAK,IAAI,MAAM,OAAA;AAAA,EACnB;AAAA;AAAA,EAIA,KAAKC,IAAgB,IAAY;AAC7B,UAAMC,IAAS,KAAK,QAAQ;AAC5B,QAAIA,KAAU,KAAK,MAAM,QAAQ;AAC7B,UAAI,CAAC,KAAK,QAAQ,KAAM;AACxB,MAAK,KAAK,KAAK,GAAG,QAAQD,CAAa;AACvC;AAAA,IACJ;AACA,IAAK,KAAK,KAAKC,GAAQ,QAAQD,CAAa;AAAA,EAChD;AAAA,EAEA,KAAKA,IAAgB,IAAY;AAC7B,UAAMC,IAAS,KAAK,QAAQ;AAC5B,QAAIA,IAAS,GAAG;AACZ,UAAI,CAAC,KAAK,QAAQ,KAAM;AACxB,MAAK,KAAK,KAAK,KAAK,MAAM,SAAS,GAAG,QAAQD,CAAa;AAC3D;AAAA,IACJ;AACA,IAAK,KAAK,KAAKC,GAAQ,QAAQD,CAAa;AAAA,EAChD;AAAA,EAEA,MAAM,KAAKC,GAAgBC,IAAwB,MAAMF,IAAgB,IAAqB;AAC1F,QAAI,KAAK,aAAa,KAAK,UAAW;AACtC,UAAM,IAAI,KAAK,MAAMC,CAAM;AAC3B,QAAI,MAAM,KAAK,MAAO;AAEtB,UAAMb,IAAMc,MAAc,IAAI,KAAK,QAAQ,SAAS;AACpD,SAAK,YAAY;AACjB,QAAI;AACA,WAAK,SAASd,GAAK,KAAK,MAAM,CAAC,CAAC,GAChC,MAAM,KAAK,QAAQA,CAAG,GACtB,KAAK,QAAQ,GACb,KAAK,OAAA,GACL,MAAM,KAAK,SAAS,GAAG,EAAE,eAAAY,GAAe,GACxC,KAAK,kBAAA;AAAA,IACT,UAAA;AACI,WAAK,YAAY;AAAA,IACrB;AAAA,EACJ;AAAA,EAEA,WAAWG,GAAuB;AAC9B,SAAK,WAAW,OAAOA,KAAU,YAAYA,IAAQ,CAAC,KAAK,UAC3D,KAAK,IAAI,MAAM,aAAa,eAAe,KAAK,WAAW,UAAU,MAAM,GAC3E,KAAK,IAAI,QAAQ,aAAa,iBAAiB,KAAK,WAAW,SAAS,OAAO,GAE/E,KAAK,IAAI,MAAM,MAAM,YAAY,KAAK,WAAW,kBAAkB;AAAA,EACvE;AAAA;AAAA,EAIQ,WAAW;AACf,SAAK,IAAI,YAAY,aAAa,cAAc,GAAG;AAEnD,UAAMC,IAAW,SAAS,cAAc,KAAK;AAC7C,IAAAA,EAAS,YAAY,2DACrBA,EAAS,aAAa,YAAY,GAAG;AAErC,UAAMC,IAAQ,SAAS,cAAc,KAAK;AAC1C,IAAAA,EAAM,YAAY,yBAClBA,EAAM,MAAM,SAAS,QACrBA,EAAM,MAAM,YAAY,8BACxBA,EAAM,MAAM,aAAa,aAAa,KAAK,QAAQ,YAAY;AAE/D,UAAMC,IAAW,KAAK,WAAA,GAChBC,IAAc,SAAS,cAAc,KAAK;AAChD,IAAAA,EAAY,YAAY,qCACxBA,EAAY,MAAM,MAAM;AACxB,UAAMC,IAAW,KAAK,WAAA;AACtB,IAAAA,EAAS,MAAM,MAAM,YAGrB,KAAK,IAAI,cAAc,QAAQ,CAACT,MAAOQ,EAAY,YAAYR,CAAE,CAAC,GAElEM,EAAM,OAAOC,GAAUC,GAAaC,CAAQ,GAC5CJ,EAAS,YAAYC,CAAK;AAE1B,UAAMI,IAAU,SAAS,cAAc,KAAK;AAC5C,IAAAA,EAAQ,YAAY;AAEpB,UAAMC,IAAc,SAAS,cAAc,KAAK;AAChD,IAAAA,EAAY,YAAY;AACxB,UAAMC,IAAe,SAAS,cAAc,KAAK;AACjD,IAAAA,EAAa,YAAY,iCACzBD,EAAY,YAAYC,CAAY;AAEpC,UAAMC,IAAO,SAAS,cAAc,KAAK;AACzC,IAAAA,EAAK,YAAY;AACjB,UAAMC,IAAU,SAAS,cAAc,MAAM;AAC7C,IAAAA,EAAQ,aAAa,QAAQ,eAAe,GAC5CA,EAAQ,YAAY;AACpB,UAAMC,IAAU,SAAS,cAAc,QAAQ;AAC/C,IAAAA,EAAQ,YAAY;AACpB,UAAMC,IAAS,SAAS,cAAc,MAAM;AAC5C,IAAAA,EAAO,YAAY,4BACnBH,EAAK,OAAOC,GAASC,GAASC,CAAM;AAEpC,UAAMC,IAAO,SAAS,cAAc,KAAK;AACzC,IAAAA,EAAK,YAAY;AAEjB,UAAMC,IAAU,SAAS,cAAc,KAAK;AAC5C,IAAAA,EAAQ,YAAY;AACpB,UAAMC,IAAQ,KAAK,OAAO,gBAAgB,KAAK,IAAI,KAAK,SAAS;AACjE,IAAAA,EAAM,MAAM,YAAY;AACxB,UAAMC,IAAU,KAAK,OAAO,gBAAgB,KAAK,IAAI,KAAK,SAAS;AACnE,IAAAA,EAAQ,MAAM,YAAY,kBAC1BF,EAAQ,OAAOC,GAAOC,CAAO;AAE7B,UAAMC,IAAU,SAAS,cAAc,QAAQ;AAC/C,IAAAA,EAAQ,OAAO,UACfA,EAAQ,aAAa,cAAc,KAAK,IAAI,KAAK,cAAc,GAC/DA,EAAQ,aAAa,iBAAiB,OAAO,GAC7CA,EAAQ,YACJ,6LAEJA,EAAQ,YAAYC,EAAW,YAAY,YAAY,CAAC,GAExDZ,EAAQ,OAAOC,GAAaE,GAAMI,GAAMC,GAASG,CAAO;AAExD,UAAME,IAAQ,SAAS,cAAc,OAAO;AAC5C,IAAAA,EAAM,YACF,2JAEJA,EAAM,MAAM,YAAY,oBACxBA,EAAM,aAAa,eAAe,MAAM;AACxC,UAAMC,IAAO,SAAS,cAAc,KAAK;AACzC,WAAAA,EAAK,YAAY,wCACjBD,EAAM,YAAYC,CAAI,GAEtB,KAAK,IAAI,YAAY,OAAOnB,GAAUK,GAASa,CAAK,GAEpD,KAAK,WAAWC,CAAI,GAEb;AAAA,MACH,UAAAnB;AAAA,MAAU,OAAAC;AAAA,MAAO,UAAAC;AAAA,MAAU,aAAAC;AAAA,MAAa,UAAAC;AAAA,MAAU,SAAAC;AAAA,MAClD,SAAAI;AAAA,MAAS,SAAAC;AAAA,MAAS,QAAAC;AAAA,MAAQ,MAAAC;AAAA,MAAM,aAAaL;AAAA,MAC7C,OAAAO;AAAA,MAAO,SAAAC;AAAA,MAAS,SAAAC;AAAA,MAAS,OAAAE;AAAA,MAAO,MAAAC;AAAA,IAAA;AAAA,EAExC;AAAA,EAEQ,aAA0B;AAC9B,UAAMC,IAAO,SAAS,cAAc,KAAK;AACzC,WAAAA,EAAK,YAAY,0EACVA;AAAA,EACX;AAAA,EAEQ,OAAOC,GAAkBC,GAAkC;AAC/D,UAAMC,IAAM,SAAS,cAAc,QAAQ;AAC3C,WAAAA,EAAI,OAAO,UACXA,EAAI,aAAa,cAAcD,CAAK,GACpCC,EAAI,YACA,sIACJA,EAAI,YAAYN,EAAWI,GAAU,YAAY,CAAC,GAC3CE;AAAA,EACX;AAAA,EAEQ,SAASvC,GAAUwC,GAAsC;AAC7D,UAAMJ,IAAOpC,MAAQ,SAAS,KAAK,IAAI,WAAW,KAAK,IAAI,UACrDyC,KAAMD,KAAA,gBAAAA,EAAM,UAAS;AAC3B,IAAAJ,EAAK,MAAM,kBAAkBK,IAAM,QAAQA,CAAG,OAAO;AAAA,EACzD;AAAA,EAEQ,QAAQzC,GAAyB;AACrC,UAAMiB,IAAQ,KAAK,IAAI;AACvB,WAAO,IAAI,QAAQ,CAACyB,MAAY;AAC5B,UAAIC,IAAO;AACX,YAAMC,IAAS,MAAM;AACjB,QAAID,MACJA,IAAO,IACP1B,EAAM,oBAAoB,iBAAiB2B,CAAM,GACjD,aAAaC,CAAK,GAClB5B,EAAM,MAAM,aAAa,QACzBA,EAAM,MAAM,YAAY,8BACnBA,EAAM,cACXA,EAAM,MAAM,aAAa,aAAa,KAAK,QAAQ,YAAY,WAC/DyB,EAAA;AAAA,MACJ;AACA,MAAAzB,EAAM,iBAAiB,iBAAiB2B,CAAM;AAC9C,YAAMC,IAAQ,WAAWD,GAAQ,KAAK,QAAQ,eAAe,GAAG;AAChE,MAAA3B,EAAM,MAAM,YAAYjB,MAAQ,SAAS,+BAA+B;AAAA,IAC5E,CAAC;AAAA,EACL;AAAA;AAAA,EAIA,MAAc,SAAS8C,GAAWC,IAAuD,IAAmB;AACxG,UAAMP,IAAO,KAAK,MAAMM,CAAC;AACzB,QAAI,CAACN,EAAM;AAEX,UAAMQ,IAAO,KAAK,YAAYR,CAAI,GAC5BS,IAAU,KAAK,aAAaT,GAAMQ,CAAI;AAC5C,QAAKC,MAEL,KAAK,IAAI,QAAQ,MAAA,GACbT,EAAK,SAAO,KAAK,IAAI,UAAUA,EAAK,KAAK,GAC7C,MAAM,KAAK,IAAI,WAAWS,EAAQ,KAAKA,EAAQ,IAAI,GAE/C,KAAK,QAAQ,mBAAmB,KAAK,iBAAiBH,MACtD,KAAK,eAAeA,GACpB,KAAK,IAAI,eAAeN,EAAK,gBAAgB,KAAK,WAAW,YAAY,IAGzE,KAAK,eAAeO,CAAI;AACxB,UAAI;AACA,cAAM,KAAK,IAAI,QAAQ,KAAA;AAAA,MAC3B,QAAQ;AAAA,MAER;AAAA,EAER;AAAA,EAEQ,eAAe,EAAE,eAAAnC,GAAe,SAAAsC,KAAoE;AACxG,WAAIA,IAAgB,CAAC,CAAC,KAAK,IAAI,QAAQ,WACnCtC,IAAsB,KACnB,KAAK,QAAQ,gBAAgB,KAAK;AAAA,EAC7C;AAAA,EAEQ,YAAY4B,GAAmC;AACnD,UAAMW,IAAS,KAAK,QAAQX,GAAM,KAAK,GACjCY,IAAS,KAAK,QAAQZ,GAAM,KAAK;AACvC,WAAI,KAAK,QAAQ,YAAkBW,IAAS,QAAQC,IAAS,QAAQ,QAC9DA,IAAS,QAAQD,IAAS,QAAQ;AAAA,EAC7C;AAAA,EAEQ,QAAQX,GAAoBQ,GAA8B;AAC9D,WAAO,MAAM,QAAQR,EAAKQ,CAAI,CAAC,KAAKR,EAAKQ,CAAI,EAAG,KAAK,CAACK,MAAMA,KAAA,gBAAAA,EAAG,GAAG;AAAA,EACtE;AAAA,EAEQ,aAAab,GAAoBQ,GAA4D;AACjG,UAAMM,KAAQd,EAAKQ,CAAI,KAAK,IAAI,OAAO,CAACK,MAAMA,KAAA,gBAAAA,EAAG,GAAG;AACpD,QAAI,CAACC,EAAK,OAAQ,QAAO;AACzB,UAAMC,IAAMP,MAAS,SAAQM,EAAK,KAAK,CAACD,MAAMA,EAAE,QAAQ,KAAKC,EAAK,CAAC;AACnE,WAAO,EAAE,KAAKC,EAAK,KAAK,MAAMA,EAAK,SAASP,MAAS,QAAQ,0BAA0B,aAAA;AAAA,EAC3F;AAAA;AAAA,EAIQ,oBAA0B;;AAE9B,KAAItC,IADQ,UACJ,eAAJ,QAAAA,EAAgB,YAEpB,CAAC,KAAK,UAAU,KAAK,QAAQ,CAAC,GAAG,KAAK,UAAU,KAAK,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAACoC,MAAM;AAC5E,UAAIA,MAAM,KAAK,MAAO;AACtB,YAAMN,IAAO,KAAK,MAAMM,CAAC;AACzB,UAAIN,KAAA,QAAAA,EAAM,OAAO;AACb,cAAMC,IAAM,IAAI,MAAA;AAChB,QAAAA,EAAI,WAAW,SACfA,EAAI,MAAMD,EAAK;AAAA,MACnB;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA,EAIQ,SAAe;AACnB,UAAMA,IAAO,KAAK,MAAM,KAAK,KAAK,GAC5BgB,IAAQ,KAAK,MAAM;AAEzB,IAAI,KAAK,OAAO,YAAS,KAAK,IAAI,QAAQ,cAAc,GAAG,KAAK,QAAQ,CAAC,MAAMA,CAAK,KAChF,KAAK,OAAO,UAAO,KAAK,IAAI,QAAQ,eAAchB,KAAA,gBAAAA,EAAM,UAAS,KACjE,KAAK,OAAO,SAAM,KAAK,IAAI,OAAO,eAAcA,KAAA,gBAAAA,EAAM,SAAQ,KAElE,KAAK,SAAS,QAAQ,KAAK,MAAM,KAAK,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAChE,KAAK,SAAS,QAAQ,KAAK,MAAM,KAAK,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC;AAEhE,UAAMiB,IAAU,CAAC,KAAK,QAAQ,QAAQ,KAAK,UAAU,GAC/CC,IAAQ,CAAC,KAAK,QAAQ,QAAQ,KAAK,UAAUF,IAAQ;AAI3D,QAHA,KAAK,IAAI,MAAM,WAAWC,GAC1B,KAAK,IAAI,QAAQ,WAAWC,GAExB,KAAK,OAAO,MAAM;AAClB,UAAI,KAAK,IAAI,KAAK,SAAS,WAAWF,GAAO;AACzC,aAAK,IAAI,KAAK,YAAY;AAC1B,iBAASV,IAAI,GAAGA,IAAIU,GAAOV,KAAK;AAC5B,gBAAMa,IAAM,SAAS,cAAc,GAAG;AACtC,UAAAA,EAAI,YAAY,yDAChB,KAAK,IAAI,KAAK,YAAYA,CAAG;AAAA,QACjC;AAAA,MACJ;AACA,YAAM,KAAK,KAAK,IAAI,KAAK,QAAQ,EAAE,QAAQ,CAAChD,GAAImC,MAAM;AACjD,QAAAnC,EAAmB,YAAY,0CAA0CmC,MAAM,KAAK,QAAQ,gBAAgB,gBAAgB;AAAA,MACjI,CAAC;AAAA,IACL;AAEA,SAAK,eAAA,GACL,KAAK,IAAI,OAAO,cAAc,IAAI,YAAY,iBAAiB,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,QAAQ,QAAA,EAAQ,CAAG,CAAC;AAAA,EACtH;AAAA,EAEQ,WAAWX,GAAyB;AACxC,IAAAA,EAAK,YAAY,IACjB,KAAK,MAAM,QAAQ,CAACK,GAAMM,MAAM;AAC5B,YAAMP,IAAM,SAAS,cAAc,QAAQ;AAI3C,UAHAA,EAAI,OAAO,UACXA,EAAI,YAAY,2KAChBA,EAAI,QAAQ,QAAQ,OAAOO,CAAC,GACxBN,EAAK,OAAO;AACZ,cAAMC,IAAM,SAAS,cAAc,KAAK;AACxC,QAAAA,EAAI,MAAMD,EAAK,OACfC,EAAI,UAAU,QACdA,EAAI,YAAY,mEAChBF,EAAI,YAAYE,CAAG;AAAA,MACvB;AACA,YAAMmB,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,0BAClBA,EAAM,cAAcpB,EAAK,SAAS,KAAK,IAAI,KAAK,mBAAmBM,CAAC,GACpEP,EAAI,YAAYqB,CAAK,GACrBrB,EAAI,iBAAiB,SAAS,MAAM;AAChC,aAAK,WAAW,EAAK,GAChB,KAAK,KAAKO,CAAC;AAAA,MACpB,CAAC,GACDX,EAAK,YAAYI,CAAG;AAAA,IACxB,CAAC;AAAA,EACL;AAAA,EAEQ,iBAAuB;AAC3B,UAAM,KAAK,KAAK,IAAI,KAAK,QAAQ,EAAE,QAAQ,CAAC5B,GAAImC,MAAM;AAClD,MAAAnC,EAAG,UAAU,OAAO,mBAAmBmC,MAAM,KAAK,KAAK;AAAA,IAC3D,CAAC;AAAA,EACL;AAAA;AAAA,EAIQ,aAAmB;;AACvB,SAAK,IAAI,QAAQ,iBAAiB,SAAS,KAAK,OAAO,GACvD,KAAK,IAAI,QAAQ,iBAAiB,WAAW,KAAK,SAAS,GAC3D,KAAK,IAAI,QAAQ,iBAAiB,QAAQ,KAAK,WAAW,GACtD,KAAK,OAAO,YAAU,KAAK,IAAI,QAAQ,iBAAiB,cAAc,KAAK,YAAY,GAE3F,KAAK,IAAI,MAAM,iBAAiB,SAAS,MAAM,KAAK,MAAM,GAC1D,KAAK,IAAI,QAAQ,iBAAiB,SAAS,MAAM,KAAK,MAAM,GAC5D,KAAK,IAAI,QAAQ,iBAAiB,SAAS,MAAM,KAAK,YAAY,IAElEpC,IAAA,KAAK,IAAI,KAAK,kBAAd,QAAAA,EAA6B,iBAAiB,WAAW,CAAC,MAAM;AAC5D,MAAK,EAAoB,QAAQ,YAAU,KAAK,WAAW,EAAK;AAAA,IACpE,IAEI,KAAK,YAAY,SAAO,KAAK,IAAI,SAAS,iBAAiB,SAAS,KAAK,SAAS,EAAE,SAAS,IAAO,GACpG,KAAK,YAAY,UACjB,KAAK,IAAI,SAAS,iBAAiB,eAAe,KAAK,aAAa,GACpE,OAAO,iBAAiB,eAAe,KAAK,eAAe,EAAE,SAAS,IAAO,GAC7E,OAAO,iBAAiB,aAAa,KAAK,WAAW,IAErD,KAAK,YAAY,qBAAmB,iBAAiB,WAAW,KAAK,SAAS;AAAA,EACtF;AAAA;AAAA,EAwGQ,MAAMV,GAAmB;AAC7B,WAAI,KAAK,QAAQ,OAAa,KAAK,MAAM,SAAS,IAC3CA,MAAQ,SAAS,KAAK,QAAQ,KAAK,MAAM,SAAS,IAAI,KAAK,QAAQ;AAAA,EAC9E;AAAA,EAEQ,eAAwB;AAC5B,UAAM6D,IAAI,KAAK,IAAI,OAAO,sBAAA;AAC1B,WAAOA,EAAE,SAAS,KAAKA,EAAE,OAAO,OAAO,eAAe;AAAA,EAC1D;AAAA,EAEQ,MAAMf,GAAmB;AAC7B,WAAI,CAAC,OAAO,SAASA,CAAC,KAAK,CAAC,KAAK,MAAM,SAAe,IAC/C,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,MAAM,SAAS,GAAG,KAAK,MAAMA,CAAC,CAAC,CAAC;AAAA,EACrE;AAAA,EAEQ,UAAUA,GAAmB;AACjC,UAAMgB,IAAI,KAAK,MAAM;AACrB,WAAKA,IACD,KAAK,QAAQ,QAAehB,IAAIgB,IAAKA,KAAKA,IACvC,KAAK,MAAMhB,CAAC,IAFJ;AAAA,EAGnB;AACJ;ACvkBO,SAASiB,EAAarE,GAAyBsE,GAAkC;AACpF,SAAO,IAAIvE,EAAUC,GAAKsE,CAAO;AACrC;"}
|
|
1
|
+
{"version":3,"file":"index-DadIEuQc.js","sources":["../../src/plugins/story/HopeStory.ts","../../src/plugins/story/index.ts"],"sourcesContent":["import { createIcon } from '../../icons/Icon';\nimport type { PlayableItem, StoryOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface StoryPlayerContext {\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** .video-area — story aktifken 9:16'ya çevrilir (data-story attribute ile), destroy'da geri alınır. */\n videoAreaEl: HTMLElement;\n /** Gerçek player gövdesi (.media-layer + chrome + center-play-button) — orta pane'e taşınır, destroy'da geri alınır. */\n playerBodyEls: HTMLElement[];\n loadSource(src: string, type?: string): Promise<void>;\n setPoster(url: string): void;\n requestFreshAd(prerollTag?: string): void;\n i18n: HopeLocaleStrings;\n}\n\ntype Dir = 'next' | 'prev';\n\nconst DEFAULTS: Required<Omit<StoryOptions, 'items' | 'adTagPreroll' | 'gestures' | 'ui'>> = {\n startIndex: 0,\n loop: true,\n autoplayNext: true,\n preferHls: true,\n transitionMs: 380,\n adsOnItemChange: true,\n};\n\n/** Dikey video akışı (Shorts/Story): tek <video>, item değişiminde kaynak değişir. */\nexport class HopeStory {\n private readonly options: Required<Omit<StoryOptions, 'items' | 'adTagPreroll' | 'gestures' | 'ui'>>;\n private readonly gestureOpts: Required<NonNullable<StoryOptions['gestures']>>;\n private readonly uiOpts: Required<NonNullable<StoryOptions['ui']>>;\n private readonly items: PlayableItem[];\n\n private index: number;\n private destroyed = false;\n private switching = false;\n private listOpen = false;\n private userHasStartedPlayback = false;\n private lastAdsIndex: number | null = null;\n private wheelAccum = 0;\n private lastNavAt = 0;\n private drag: { startY: number; startX: number; dy: number; active: boolean; id: number } | null = null;\n\n private readonly els: {\n viewport: HTMLElement;\n track: HTMLElement;\n panePrev: HTMLElement;\n paneCurrent: HTMLElement;\n paneNext: HTMLElement;\n overlay: HTMLElement;\n counter: HTMLElement;\n titleEl: HTMLElement;\n spotEl: HTMLElement;\n dots: HTMLElement;\n progressBar: HTMLElement;\n upBtn: HTMLButtonElement;\n downBtn: HTMLButtonElement;\n listBtn: HTMLButtonElement;\n panel: HTMLElement;\n grid: HTMLElement;\n };\n\n constructor(\n private readonly ctx: StoryPlayerContext,\n private readonly rawOptions: StoryOptions\n ) {\n this.options = { ...DEFAULTS, ...rawOptions };\n this.gestureOpts = {\n swipe: true,\n swipeThreshold: 0.12,\n wheel: true,\n wheelThreshold: 42,\n wheelCooldownMs: 620,\n keyboard: true,\n ...rawOptions.gestures,\n };\n this.uiOpts = { counter: true, title: true, spot: true, dots: true, progress: true, ...rawOptions.ui };\n this.items = Array.isArray(rawOptions.items) ? rawOptions.items : [];\n this.index = this.clamp(this.options.startIndex);\n\n this.els = this.buildDom();\n this.bindEvents();\n this.syncUi();\n this.preloadNeighbours();\n\n if (this.items.length) void this.loadItem(this.index, { isStart: true });\n }\n\n refreshLabels(): void {\n this.els.upBtn.setAttribute('aria-label', this.ctx.i18n.storyPrev);\n this.els.downBtn.setAttribute('aria-label', this.ctx.i18n.storyNext);\n this.els.listBtn.setAttribute('aria-label', this.ctx.i18n.storyAllVideos);\n this.renderList(this.els.grid);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n this.ctx.videoEl.removeEventListener('ended', this.onEnded);\n this.ctx.videoEl.removeEventListener('playing', this.onPlaying);\n this.ctx.videoEl.removeEventListener('play', this.onFirstPlay);\n this.ctx.videoEl.removeEventListener('timeupdate', this.onTimeUpdate);\n this.els.viewport.removeEventListener('wheel', this.onWheel);\n this.els.viewport.removeEventListener('pointerdown', this.onPointerDown);\n window.removeEventListener('pointermove', this.onPointerMove);\n window.removeEventListener('pointerup', this.onPointerUp);\n document.removeEventListener('keydown', this.onKeyDown);\n\n // player gövdesini .video-area'ya geri taşı, story DOM'unu kaldır.\n this.ctx.playerBodyEls.forEach((el) => this.ctx.videoAreaEl.appendChild(el));\n this.ctx.videoAreaEl.removeAttribute('data-story');\n this.els.viewport.remove();\n this.els.panel.remove();\n }\n\n // ── public api ──\n\n next(userInitiated = true): void {\n const target = this.index + 1;\n if (target >= this.items.length) {\n if (!this.options.loop) return;\n void this.goTo(0, 'next', userInitiated);\n return;\n }\n void this.goTo(target, 'next', userInitiated);\n }\n\n prev(userInitiated = true): void {\n const target = this.index - 1;\n if (target < 0) {\n if (!this.options.loop) return;\n void this.goTo(this.items.length - 1, 'prev', userInitiated);\n return;\n }\n void this.goTo(target, 'prev', userInitiated);\n }\n\n async goTo(target: number, direction: Dir | null = null, userInitiated = true): Promise<void> {\n if (this.destroyed || this.switching) return;\n const i = this.clamp(target);\n if (i === this.index) return;\n\n const dir = direction || (i > this.index ? 'next' : 'prev');\n this.switching = true;\n try {\n this.fillPane(dir, this.items[i]);\n await this.animate(dir);\n this.index = i;\n this.syncUi();\n await this.loadItem(i, { userInitiated });\n this.preloadNeighbours();\n } finally {\n this.switching = false;\n }\n }\n\n toggleList(force?: boolean): void {\n this.listOpen = typeof force === 'boolean' ? force : !this.listOpen;\n this.els.panel.setAttribute('aria-hidden', this.listOpen ? 'false' : 'true');\n this.els.listBtn.setAttribute('aria-expanded', this.listOpen ? 'true' : 'false');\n // translate-x/-y utility yerine inline transform: Shadow DOM'da tek eksenli Tailwind translate 'none' oluyor.\n this.els.panel.style.transform = this.listOpen ? 'translateX(0)' : 'translateX(100%)';\n }\n\n // ── dom ──\n\n private buildDom() {\n this.ctx.videoAreaEl.setAttribute('data-story', '1');\n\n const viewport = document.createElement('div');\n viewport.className = 'hp:absolute hp:inset-0 hp:overflow-hidden hp:touch-none';\n viewport.setAttribute('tabindex', '0');\n\n const track = document.createElement('div');\n track.className = 'hp:relative hp:w-full';\n track.style.height = '300%';\n track.style.transform = 'translate3d(0,-33.3333%,0)';\n track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n\n const panePrev = this.createPane();\n const paneCurrent = document.createElement('div');\n paneCurrent.className = 'hp:absolute hp:inset-x-0 hp:h-1/3';\n paneCurrent.style.top = '33.3333%';\n const paneNext = this.createPane();\n paneNext.style.top = '66.6667%';\n\n // Gerçek player gövdesini orta pane'e taşı.\n this.ctx.playerBodyEls.forEach((el) => paneCurrent.appendChild(el));\n\n track.append(panePrev, paneCurrent, paneNext);\n viewport.appendChild(track);\n\n const overlay = document.createElement('div');\n overlay.className = 'hp:absolute hp:inset-0 hp:z-20 hp:pointer-events-none hp:flex hp:flex-col hp:justify-between hp:p-3';\n\n const progressBar = document.createElement('div');\n progressBar.className = 'hp:h-0.5 hp:bg-white/30 hp:rounded-full hp:overflow-hidden';\n const progressFill = document.createElement('div');\n progressFill.className = 'hp:h-full hp:bg-accent hp:w-0';\n progressBar.appendChild(progressFill);\n\n const meta = document.createElement('div');\n meta.className = 'hp:flex hp:flex-col hp:gap-0.5 hp:text-white hp:drop-shadow hp:mt-2 hp:pointer-events-auto';\n const counter = document.createElement('span');\n counter.setAttribute('part', 'story-counter');\n counter.className = 'hp:text-xs hp:opacity-80';\n const titleEl = document.createElement('strong');\n titleEl.className = 'hp:text-sm';\n const spotEl = document.createElement('span');\n spotEl.className = 'hp:text-xs hp:opacity-80';\n meta.append(counter, titleEl, spotEl);\n\n const dots = document.createElement('div');\n dots.className = 'hp:absolute hp:right-2 hp:top-1/2 hp-center-y hp:flex hp:flex-col hp:gap-1 hp:pointer-events-none';\n\n const navWrap = document.createElement('div');\n navWrap.className = 'hp:flex hp:flex-col hp:gap-2 hp:self-end hp:pointer-events-auto hp:mb-16';\n const upBtn = this.navBtn('chevron-left', this.ctx.i18n.storyPrev);\n upBtn.style.transform = 'rotate(90deg)';\n const downBtn = this.navBtn('chevron-left', this.ctx.i18n.storyNext);\n downBtn.style.transform = 'rotate(-90deg)';\n navWrap.append(upBtn, downBtn);\n\n const listBtn = document.createElement('button');\n listBtn.type = 'button';\n listBtn.setAttribute('aria-label', this.ctx.i18n.storyAllVideos);\n listBtn.setAttribute('aria-expanded', 'false');\n listBtn.className =\n 'hp:absolute hp:top-2 hp:right-2 hp:flex hp:items-center hp:justify-center hp:w-8 hp:h-8 hp:rounded-full ' +\n 'hp:bg-black/40 hp:text-white hp:border-0 hp:cursor-pointer hp:pointer-events-auto';\n listBtn.appendChild(createIcon('settings', 'hp:text-sm'));\n\n overlay.append(progressBar, meta, dots, navWrap, listBtn);\n\n const panel = document.createElement('aside');\n panel.className =\n 'hp:absolute hp:inset-y-0 hp:right-0 hp:w-72 hp:max-w-[80%] hp:bg-surface-elev hp:z-30 hp:overflow-y-auto hp:p-3 ' +\n 'hp:transition-transform hp:duration-300';\n panel.style.transform = 'translateX(100%)';\n panel.setAttribute('aria-hidden', 'true');\n const grid = document.createElement('div');\n grid.className = 'hp:flex hp:flex-col hp:gap-2 hp:mt-8';\n panel.appendChild(grid);\n\n this.ctx.videoAreaEl.append(viewport, overlay, panel);\n\n this.renderList(grid);\n\n return {\n viewport, track, panePrev, paneCurrent, paneNext, overlay,\n counter, titleEl, spotEl, dots, progressBar: progressFill,\n upBtn, downBtn, listBtn, panel, grid,\n };\n }\n\n private createPane(): HTMLElement {\n const pane = document.createElement('div');\n pane.className = 'hp:absolute hp:inset-x-0 hp:h-1/3 hp:bg-cover hp:bg-center hp:bg-black';\n return pane;\n }\n\n private navBtn(iconName: string, label: string): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.setAttribute('aria-label', label);\n btn.className =\n 'hp:flex hp:items-center hp:justify-center hp:w-8 hp:h-8 hp:rounded-full hp:bg-black/40 hp:text-white hp:border-0 hp:cursor-pointer';\n btn.appendChild(createIcon(iconName, 'hp:text-sm'));\n return btn;\n }\n\n private fillPane(dir: Dir, item: PlayableItem | undefined): void {\n const pane = dir === 'next' ? this.els.paneNext : this.els.panePrev;\n const img = item?.image || '';\n pane.style.backgroundImage = img ? `url(\"${img}\")` : 'none';\n }\n\n private animate(dir: Dir): Promise<void> {\n const track = this.els.track;\n return new Promise((resolve) => {\n let done = false;\n const finish = () => {\n if (done) return;\n done = true;\n track.removeEventListener('transitionend', finish);\n clearTimeout(timer);\n track.style.transition = 'none';\n track.style.transform = 'translate3d(0,-33.3333%,0)';\n void track.offsetHeight;\n track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n resolve();\n };\n track.addEventListener('transitionend', finish);\n const timer = setTimeout(finish, this.options.transitionMs + 120);\n track.style.transform = dir === 'next' ? 'translate3d(0,-66.6667%,0)' : 'translate3d(0,0,0)';\n });\n }\n\n // ── source / playback ──\n\n private async loadItem(i: number, opts: { userInitiated?: boolean; isStart?: boolean } = {}): Promise<void> {\n const item = this.items[i];\n if (!item) return;\n\n const mode = this.resolveMode(item);\n const payload = this.buildPayload(item, mode);\n if (!payload) return;\n\n this.ctx.videoEl.pause();\n if (item.image) this.ctx.setPoster(item.image);\n await this.ctx.loadSource(payload.src, payload.type);\n\n if (this.options.adsOnItemChange && this.lastAdsIndex !== i) {\n this.lastAdsIndex = i;\n this.ctx.requestFreshAd(item.adTagPreroll || this.rawOptions.adTagPreroll);\n }\n\n if (this.shouldAutoPlay(opts)) {\n try {\n await this.ctx.videoEl.play();\n } catch {\n /* autoplay engellendi */\n }\n }\n }\n\n private shouldAutoPlay({ userInitiated, isStart }: { userInitiated?: boolean; isStart?: boolean }): boolean {\n if (isStart) return !!this.ctx.videoEl.autoplay;\n if (userInitiated) return true;\n return this.options.autoplayNext && this.userHasStartedPlayback;\n }\n\n private resolveMode(item: PlayableItem): 'hls' | 'mp4' {\n const hasHls = this.hasMode(item, 'hls');\n const hasMp4 = this.hasMode(item, 'mp4');\n if (this.options.preferHls) return hasHls ? 'hls' : hasMp4 ? 'mp4' : 'hls';\n return hasMp4 ? 'mp4' : hasHls ? 'hls' : 'mp4';\n }\n\n private hasMode(item: PlayableItem, mode: 'hls' | 'mp4'): boolean {\n return Array.isArray(item[mode]) && item[mode]!.some((v) => v?.src);\n }\n\n private buildPayload(item: PlayableItem, mode: 'hls' | 'mp4'): { src: string; type?: string } | null {\n const list = (item[mode] || []).filter((v) => v?.src);\n if (!list.length) return null;\n const src = mode === 'mp4' ? list.find((v) => v.selected) || list[0] : list[0];\n return { src: src!.src, type: src!.type || (mode === 'hls' ? 'application/x-mpegURL' : 'video/mp4') };\n }\n\n // ── preload ──\n\n private preloadNeighbours(): void {\n const nav = navigator as Navigator & { connection?: { saveData?: boolean } };\n if (nav.connection?.saveData) return;\n\n [this.wrapIndex(this.index + 1), this.wrapIndex(this.index - 1)].forEach((i) => {\n if (i === this.index) return;\n const item = this.items[i];\n if (item?.image) {\n const img = new Image();\n img.decoding = 'async';\n img.src = item.image;\n }\n });\n }\n\n // ── ui sync ──\n\n private syncUi(): void {\n const item = this.items[this.index];\n const total = this.items.length;\n\n if (this.uiOpts.counter) this.els.counter.textContent = `${this.index + 1} / ${total}`;\n if (this.uiOpts.title) this.els.titleEl.textContent = item?.title || '';\n if (this.uiOpts.spot) this.els.spotEl.textContent = item?.spot || '';\n\n this.fillPane('prev', this.items[this.wrapIndex(this.index - 1)]);\n this.fillPane('next', this.items[this.wrapIndex(this.index + 1)]);\n\n const atStart = !this.options.loop && this.index === 0;\n const atEnd = !this.options.loop && this.index === total - 1;\n this.els.upBtn.disabled = atStart;\n this.els.downBtn.disabled = atEnd;\n\n if (this.uiOpts.dots) {\n if (this.els.dots.children.length !== total) {\n this.els.dots.innerHTML = '';\n for (let i = 0; i < total; i++) {\n const dot = document.createElement('i');\n dot.className = 'hp:block hp:w-1 hp:h-1 hp:rounded-full hp:bg-white/40';\n this.els.dots.appendChild(dot);\n }\n }\n Array.from(this.els.dots.children).forEach((el, i) => {\n (el as HTMLElement).className = `hp:block hp:w-1 hp:h-1 hp:rounded-full ${i === this.index ? 'hp:bg-white' : 'hp:bg-white/40'}`;\n });\n }\n\n this.setActiveThumb();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:itemchange', { detail: { index: this.index, source: 'story' } }));\n }\n\n private renderList(grid: HTMLElement): void {\n grid.innerHTML = '';\n this.items.forEach((item, i) => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'hp:flex hp:items-center hp:gap-2 hp:w-full hp:p-1.5 hp:rounded hp:text-left hp:text-on-surface hp:bg-transparent hp:border-0 hp:cursor-pointer hp:hover:bg-on-surface/5';\n btn.dataset.index = String(i);\n if (item.image) {\n const img = document.createElement('img');\n img.src = item.image;\n img.loading = 'lazy';\n img.className = 'hp:w-14 hp:aspect-[9/16] hp:object-cover hp:rounded hp:shrink-0';\n btn.appendChild(img);\n }\n const title = document.createElement('span');\n title.className = 'hp:text-xs hp:truncate';\n title.textContent = item.title || this.ctx.i18n.videoFallbackTitle(i);\n btn.appendChild(title);\n btn.addEventListener('click', () => {\n this.toggleList(false);\n void this.goTo(i);\n });\n grid.appendChild(btn);\n });\n }\n\n private setActiveThumb(): void {\n Array.from(this.els.grid.children).forEach((el, i) => {\n el.classList.toggle('hp:bg-accent/15', i === this.index);\n });\n }\n\n // ── events ──\n\n private bindEvents(): void {\n this.ctx.videoEl.addEventListener('ended', this.onEnded);\n this.ctx.videoEl.addEventListener('playing', this.onPlaying);\n this.ctx.videoEl.addEventListener('play', this.onFirstPlay);\n if (this.uiOpts.progress) this.ctx.videoEl.addEventListener('timeupdate', this.onTimeUpdate);\n\n this.els.upBtn.addEventListener('click', () => this.prev());\n this.els.downBtn.addEventListener('click', () => this.next());\n this.els.listBtn.addEventListener('click', () => this.toggleList());\n\n this.els.grid.parentElement?.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Escape') this.toggleList(false);\n });\n\n if (this.gestureOpts.wheel) this.els.viewport.addEventListener('wheel', this.onWheel, { passive: false });\n if (this.gestureOpts.swipe) {\n this.els.viewport.addEventListener('pointerdown', this.onPointerDown);\n window.addEventListener('pointermove', this.onPointerMove, { passive: false });\n window.addEventListener('pointerup', this.onPointerUp);\n }\n if (this.gestureOpts.keyboard) document.addEventListener('keydown', this.onKeyDown);\n }\n\n private readonly onEnded = (): void => {\n if (!this.options.autoplayNext) return;\n if (!this.options.loop && this.index === this.items.length - 1) return;\n this.next(false);\n };\n\n private readonly onPlaying = (): void => {};\n\n private readonly onFirstPlay = (): void => {\n this.userHasStartedPlayback = true;\n };\n\n private readonly onTimeUpdate = (): void => {\n const dur = this.ctx.videoEl.duration || 0;\n const cur = this.ctx.videoEl.currentTime || 0;\n this.els.progressBar.style.width = dur > 0 ? `${Math.min(100, (cur / dur) * 100)}%` : '0%';\n };\n\n private readonly onWheel = (e: WheelEvent): void => {\n if (this.switching) {\n e.preventDefault();\n return;\n }\n const dir: Dir = e.deltaY > 0 ? 'next' : 'prev';\n if (!this.canGo(dir)) return;\n e.preventDefault();\n\n const now = Date.now();\n if (now - this.lastNavAt < this.gestureOpts.wheelCooldownMs) return;\n this.wheelAccum += e.deltaY;\n if (Math.abs(this.wheelAccum) < this.gestureOpts.wheelThreshold) return;\n this.wheelAccum = 0;\n this.lastNavAt = now;\n dir === 'next' ? this.next() : this.prev();\n };\n\n private readonly onPointerDown = (e: PointerEvent): void => {\n if (this.switching || this.listOpen) return;\n if (e.pointerType === 'mouse' && e.button !== 0) return;\n this.drag = { startY: e.clientY, startX: e.clientX, dy: 0, active: false, id: e.pointerId };\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n const drag = this.drag;\n if (!drag || e.pointerId !== drag.id) return;\n const dy = e.clientY - drag.startY;\n const dx = e.clientX - drag.startX;\n\n if (!drag.active) {\n if (Math.abs(dy) < 10 || Math.abs(dy) < Math.abs(dx)) return;\n drag.active = true;\n this.els.track.style.transition = 'none';\n }\n e.preventDefault();\n\n const h = this.els.viewport.clientHeight || 1;\n const resisted = this.canGo(dy < 0 ? 'next' : 'prev') ? dy : dy * 0.25;\n drag.dy = resisted;\n\n const pct = -33.3333 + (resisted / h) * 33.3333;\n this.els.track.style.transform = `translate3d(0, ${pct}%, 0)`;\n };\n\n private readonly onPointerUp = (): void => {\n const drag = this.drag;\n this.drag = null;\n if (!drag?.active) return;\n\n const h = this.els.viewport.clientHeight || 1;\n const ratio = Math.abs(drag.dy) / h;\n const dir: Dir = drag.dy < 0 ? 'next' : 'prev';\n\n this.els.track.style.transition = `transform ${this.options.transitionMs}ms ease`;\n if (ratio >= this.gestureOpts.swipeThreshold && this.canGo(dir)) {\n this.els.track.style.transform = 'translate3d(0,-33.3333%,0)';\n dir === 'next' ? this.next() : this.prev();\n } else {\n this.els.track.style.transform = 'translate3d(0,-33.3333%,0)';\n }\n };\n\n private readonly onKeyDown = (e: KeyboardEvent): void => {\n if (this.destroyed) return;\n if (e.key === 'Escape' && this.listOpen) {\n this.toggleList(false);\n return;\n }\n const tag = document.activeElement?.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA') return;\n if (!this.isInViewport()) return;\n\n if (e.key === 'ArrowDown' || e.key === 'PageDown' || e.key === 'j') {\n e.preventDefault();\n this.next();\n } else if (e.key === 'ArrowUp' || e.key === 'PageUp' || e.key === 'k') {\n e.preventDefault();\n this.prev();\n }\n };\n\n // ── helpers ──\n\n private canGo(dir: Dir): boolean {\n if (this.options.loop) return this.items.length > 1;\n return dir === 'next' ? this.index < this.items.length - 1 : this.index > 0;\n }\n\n private isInViewport(): boolean {\n const r = this.ctx.hostEl.getBoundingClientRect();\n return r.bottom > 0 && r.top < (window.innerHeight || 0);\n }\n\n private clamp(i: number): number {\n if (!Number.isFinite(i) || !this.items.length) return 0;\n return Math.max(0, Math.min(this.items.length - 1, Math.trunc(i)));\n }\n\n private wrapIndex(i: number): number {\n const n = this.items.length;\n if (!n) return 0;\n if (this.options.loop) return ((i % n) + n) % n;\n return this.clamp(i);\n }\n}\n","import { HopeStory, type StoryPlayerContext } from './HopeStory';\nimport type { StoryOptions } from '../../types';\n\nexport function installStory(ctx: StoryPlayerContext, options: StoryOptions): HopeStory {\n return new HopeStory(ctx, options);\n}\n\nexport { HopeStory };\nexport type { StoryPlayerContext };\n"],"names":["DEFAULTS","HopeStory","ctx","rawOptions","__publicField","dur","cur","e","dir","now","drag","dy","dx","h","resisted","pct","ratio","tag","_a","el","userInitiated","target","direction","force","viewport","track","panePrev","paneCurrent","paneNext","overlay","progressBar","progressFill","meta","counter","titleEl","spotEl","dots","navWrap","upBtn","downBtn","listBtn","createIcon","panel","grid","pane","iconName","label","btn","item","img","resolve","done","finish","timer","i","opts","mode","payload","isStart","hasHls","hasMp4","v","list","src","total","atStart","atEnd","dot","title","r","n","installStory","options"],"mappings":"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"}
|