refactor(core): CORE-13 type component registries and own control lifetimes

This commit is contained in:
Harvey Zhao committed 2026-09-11 04:54:32 +08:00
1 parent 9eb7c945ca
commit 697817eceb
68 files changed
+10100 -1925

No files matched your search

@@ -1,6 +1,8 @@
import { inverseClass, query, queryAll } from '../utils'
import type { ContextmenuFactory, ContextmenuOption } from './types'
import { controlEvents } from '../control/resources'
import { inverseClass, query } from '../utils'
export default function aspectRatio(option) {
export default function aspectRatio(option: ContextmenuOption): ContextmenuFactory {
return (art) => {
const {
i18n,
@@ -15,19 +17,20 @@ export default function aspectRatio(option) {
...option,
html: `${i18n.get('Aspect Ratio')}: ${html}`,
click: (contextmenu, event) => {
const { value } = event.target.dataset
const value = event.target instanceof HTMLElement ? event.target.dataset.value : undefined
if (value) {
art.aspectRatio = value
contextmenu.show = false
}
},
mounted: ($panel) => {
const { on } = controlEvents(art, $panel)
const $default = query('[data-value="default"]', $panel)
if ($default) {
inverseClass($default, 'art-current')
}
art.on('aspectRatio', (value) => {
const $current = queryAll('span', $panel).find(item => item.dataset.value === value)
on('aspectRatio', (value) => {
const $current = Array.from($panel.querySelectorAll('span')).find(item => item.dataset.value === value)
if ($current) {
inverseClass($current, 'art-current')
}
@@ -1,9 +0,0 @@
export default function close(option) {
return art => ({
...option,
html: art.i18n.get('Close'),
click: (contextmenu) => {
contextmenu.show = false
},
})
}
@@ -0,0 +1,11 @@
import type { ContextmenuFactory, ContextmenuOption } from './types'
export default function close(option: ContextmenuOption): ContextmenuFactory {
return art => ({
...option,
html: art.i18n.get('Close'),
click: (contextmenu) => {
contextmenu.show = false
},
})
}
@@ -1,6 +1,8 @@
import { capitalize, inverseClass, query, queryAll } from '../utils'
import type { ContextmenuFactory, ContextmenuOption } from './types'
import { controlEvents } from '../control/resources'
import { capitalize, inverseClass, query } from '../utils'
export default function flip(option) {
export default function flip(option: ContextmenuOption): ContextmenuFactory {
return (art) => {
const {
i18n,
@@ -13,19 +15,20 @@ export default function flip(option) {
...option,
html: `${i18n.get('Video Flip')}: ${html}`,
click: (contextmenu, event) => {
const { value } = event.target.dataset
const value = event.target instanceof HTMLElement ? event.target.dataset.value : undefined
if (value) {
art.flip = value.toLowerCase()
contextmenu.show = false
}
},
mounted: ($panel) => {
const { on } = controlEvents(art, $panel)
const $default = query('[data-value="normal"]', $panel)
if ($default) {
inverseClass($default, 'art-current')
}
art.on('flip', (value) => {
const $current = queryAll('span', $panel).find(item => item.dataset.value === value)
on('flip', (value) => {
const $current = Array.from($panel.querySelectorAll('span')).find(item => item.dataset.value === value)
if ($current) {
inverseClass($current, 'art-current')
}
@@ -1,3 +1,6 @@
import type { ContextmenuHost } from './types'
import { ownEntry } from '../component/resources'
import { controlEvents } from '../control/resources'
import { getRect, includeFromEvent, isMobile, setStyles } from '../utils'
import Component from '../utils/component'
import aspectRatio from './aspectRatio'
@@ -7,24 +10,25 @@ import info from './info'
import playbackRate from './playbackRate'
import version from './version'
export default class Contextmenu extends Component {
constructor(art) {
export default class Contextmenu extends Component<ContextmenuHost> {
constructor(art: ContextmenuHost) {
super(art)
this.name = 'contextmenu'
this.$parent = art.template.$contextmenu
ownEntry(art, this.$parent)
if (!isMobile) {
this.init()
}
}
init() {
init(): void {
const {
option,
proxy,
template: { $player, $contextmenu },
} = this.art
const { on, proxy } = controlEvents(this.art, $contextmenu)
if (option.playbackRate) {
this.add(
@@ -75,7 +79,7 @@ export default class Contextmenu extends Component {
)
for (let index = 0; index < option.contextmenu.length; index++) {
this.add(option.contextmenu[index])
this.add(option.contextmenu[index]!)
}
proxy($player, 'contextmenu', (event) => {
@@ -112,7 +116,7 @@ export default class Contextmenu extends Component {
}
})
this.art.on('blur', () => {
on('blur', () => {
this.show = false
})
}
@@ -1,4 +1,6 @@
export default function info(option) {
import type { ContextmenuFactory, ContextmenuOption } from './types'
export default function info(option: ContextmenuOption): ContextmenuFactory {
return art => ({
...option,
html: art.i18n.get('Video Info'),
@@ -1,6 +1,8 @@
import { inverseClass, query, queryAll } from '../utils'
import type { ContextmenuFactory, ContextmenuOption } from './types'
import { controlEvents } from '../control/resources'
import { inverseClass, query } from '../utils'
export default function playbackRate(option) {
export default function playbackRate(option: ContextmenuOption): ContextmenuFactory {
return (art) => {
const {
i18n,
@@ -15,18 +17,19 @@ export default function playbackRate(option) {
...option,
html: `${i18n.get('Play Speed')}: ${html}`,
click: (contextmenu, event) => {
const { value } = event.target.dataset
const value = event.target instanceof HTMLElement ? event.target.dataset.value : undefined
if (value) {
art.playbackRate = Number(value)
contextmenu.show = false
}
},
mounted: ($panel) => {
const { on } = controlEvents(art, $panel)
const $default = query('[data-value="1"]', $panel)
if ($default)
inverseClass($default, 'art-current')
art.on('video:ratechange', () => {
const $current = queryAll('span', $panel).find(
on('video:ratechange', () => {
const $current = Array.from($panel.querySelectorAll('span')).find(
item => Number(item.dataset.value) === art.playbackRate,
)
if ($current) {
@@ -0,0 +1,17 @@
import type { SubscriptionHost } from '../component/resources'
import type { ComponentHost, EntryInput, EntryOption } from '../component/types'
import type { UIEvents } from '../control/types'
export interface ContextmenuHost extends ComponentHost, SubscriptionHost<UIEvents> {
template: { $player: HTMLDivElement, $contextmenu: HTMLDivElement }
option: { playbackRate: boolean, aspectRatio: boolean, flip: boolean, contextmenu: EntryInput<ContextmenuHost>[] }
constructor: { CONTEXTMENU: boolean, PLAYBACK_RATE: number[], ASPECT_RATIO: string[], FLIP: string[] }
i18n: { get: (key: string) => string }
info: { show: boolean }
playbackRate: number
aspectRatio: string
flip: string
}
export type ContextmenuOption = EntryOption<ContextmenuHost>
export type ContextmenuFactory = (art: ContextmenuHost) => ContextmenuOption
@@ -1,6 +1,7 @@
import type { ContextmenuOption } from './types'
import { version } from '../../package.json'
export default function (option) {
export default function (option: ContextmenuOption): ContextmenuOption {
return {
...option,
html: `<a href="https://artplayer.org" target="_blank" style="width:100%;">ArtPlayer ${version}</a>`,