mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-24 06:31:20 -08:00
refactor(core): CORE-13 type component registries and own control lifetimes
This commit is contained in:
1 parent
9eb7c945ca
commit
697817eceb
68 files changed
+10100
-1925
No files matched your search
@@ -0,0 +1,29 @@
|
||||
import type { ComponentHost, EntryOption } from './types'
|
||||
import { addClass, append, setStyles, tooltip } from '../utils/dom'
|
||||
|
||||
export function renderEntry<Host extends ComponentHost>(element: HTMLDivElement, parent: HTMLElement, kind: string, name: string, id: number, option: EntryOption<Host>): void {
|
||||
addClass(element, `art-${kind}`)
|
||||
addClass(element, `art-${kind}-${name}`)
|
||||
const children = Array.from(parent.children) as HTMLElement[]
|
||||
element.dataset.index = String(option.index || id)
|
||||
const next = children.find(child => Number(child.dataset.index) >= Number(element.dataset.index))
|
||||
if (next)
|
||||
next.insertAdjacentElement('beforebegin', element)
|
||||
else
|
||||
append(parent, element)
|
||||
if (option.html)
|
||||
append(element, option.html)
|
||||
if (option.style)
|
||||
setStyles(element, option.style)
|
||||
if (option.tooltip)
|
||||
tooltip(element, option.tooltip)
|
||||
}
|
||||
|
||||
// Builtin renderers append known element markup or existing icon wrappers.
|
||||
export function appendElement(parent: Element, child: string | Element): HTMLElement {
|
||||
return append(parent, child) as HTMLElement
|
||||
}
|
||||
|
||||
export function queryElement(selector: string, parent: ParentNode): HTMLElement {
|
||||
return parent.querySelector<HTMLElement>(selector)!
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import type ResourceScope from '../lifecycle/scope'
|
||||
import type { ComponentHost } from './types'
|
||||
import { getScope } from '../lifecycle/instance'
|
||||
|
||||
const scopes = new WeakMap<HTMLElement, ResourceScope>()
|
||||
|
||||
export function ownEntry(art: ComponentHost, element: HTMLElement): ResourceScope {
|
||||
const scope = getScope(art).child()
|
||||
scopes.set(element, scope)
|
||||
return scope
|
||||
}
|
||||
|
||||
export function entryScope(element: HTMLElement): ResourceScope {
|
||||
const scope = scopes.get(element)
|
||||
if (!scope)
|
||||
throw new Error('ArtPlayer component has not been registered')
|
||||
return scope
|
||||
}
|
||||
|
||||
export function releaseEntry(element: HTMLElement): void {
|
||||
scopes.get(element)?.dispose()
|
||||
}
|
||||
|
||||
export function proxyEntry<Name extends keyof HTMLElementEventMap>(art: ComponentHost, element: HTMLElement, target: EventTarget, name: Name, callback: (event: HTMLElementEventMap[Name]) => unknown): () => void {
|
||||
const scope = entryScope(element)
|
||||
if (scope.closed)
|
||||
return () => {}
|
||||
const cleanup = art.events.proxy(target, name, (event) => {
|
||||
if (!scope.closed)
|
||||
return callback(event as HTMLElementEventMap[Name])
|
||||
})
|
||||
return scope.add(() => {
|
||||
art.events.remove(cleanup)
|
||||
})
|
||||
}
|
||||
|
||||
export interface SubscriptionHost<Events extends { [Name in keyof Events]: readonly unknown[] }> {
|
||||
on: <Name extends keyof Events>(name: Name, callback: (...args: [...Events[Name]]) => unknown) => unknown
|
||||
off: <Name extends keyof Events>(name: Name, callback: (...args: [...Events[Name]]) => unknown) => unknown
|
||||
}
|
||||
|
||||
export function subscribeEntry<Events extends { [Name in keyof Events]: readonly unknown[] }, Name extends keyof Events>(art: SubscriptionHost<Events>, element: HTMLElement, name: Name, callback: (...args: [...Events[Name]]) => unknown): void {
|
||||
const scope = entryScope(element)
|
||||
if (scope.closed)
|
||||
return
|
||||
const guarded = (...args: [...Events[Name]]) => {
|
||||
if (!scope.closed)
|
||||
return callback(...args)
|
||||
}
|
||||
art.on(name, guarded)
|
||||
scope.add(() => {
|
||||
art.off(name, guarded)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { Cleanup } from '../lifecycle/scope'
|
||||
|
||||
const selections = new WeakMap<Event, () => boolean>()
|
||||
|
||||
export function trackSelection(event: Event, active: () => boolean): Cleanup {
|
||||
selections.set(event, active)
|
||||
return () => {
|
||||
if (selections.get(event) === active)
|
||||
selections.delete(event)
|
||||
}
|
||||
}
|
||||
|
||||
export function captureSelection(event?: Event): () => boolean {
|
||||
return (event && selections.get(event)) || (() => true)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import type Component from '../utils/component'
|
||||
|
||||
export type EventCleanup = () => void
|
||||
|
||||
export interface ComponentHost {
|
||||
template: { $player: HTMLElement }
|
||||
emit: (name: string, ...args: unknown[]) => unknown
|
||||
events: {
|
||||
proxy: (target: EventTarget, name: string, callback: (event: Event) => unknown) => EventCleanup
|
||||
remove: (cleanup: EventCleanup) => void
|
||||
}
|
||||
}
|
||||
|
||||
export interface SelectorItem {
|
||||
html: string | HTMLElement | number
|
||||
value?: string | number
|
||||
default?: boolean
|
||||
readonly $control_option?: SelectorItem[]
|
||||
readonly $control_item?: HTMLDivElement
|
||||
readonly $control_value?: HTMLDivElement
|
||||
}
|
||||
|
||||
export interface EntryOption<Host extends ComponentHost> {
|
||||
html?: string | HTMLElement | number
|
||||
disable?: boolean
|
||||
name?: string
|
||||
index?: number
|
||||
style?: Partial<CSSStyleDeclaration>
|
||||
tooltip?: string | number
|
||||
position?: string
|
||||
selector?: SelectorItem[]
|
||||
click?: (this: Host, component: Component<Host>, event: Event) => unknown
|
||||
mounted?: (this: Host, element: HTMLDivElement) => unknown
|
||||
beforeUnmount?: (this: Host, element: HTMLDivElement) => unknown
|
||||
onSelect?: (this: Host, item: SelectorItem, element: HTMLDivElement, event: Event) => unknown
|
||||
}
|
||||
|
||||
export type EntryInput<Host extends ComponentHost> = EntryOption<Host> | ((art: Host) => EntryOption<Host>)
|
||||
|
||||
export interface Entry<Host extends ComponentHost> {
|
||||
$ref: HTMLDivElement
|
||||
events: EventCleanup[]
|
||||
option: EntryOption<Host>
|
||||
}
|
||||
Reference in new issue
Block a user