mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
refactor(react): replace prototype-walking and inferred class props (#1376)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
interface Attachable {
|
||||
attach(target: EventTarget): void;
|
||||
detach(): void;
|
||||
}
|
||||
|
||||
export function attachMediaElement<T extends HTMLVideoElement>(media: Attachable): (element: T | null) => void {
|
||||
return (element: T | null) => {
|
||||
if (element) {
|
||||
media.attach(element);
|
||||
} else {
|
||||
media.detach();
|
||||
}
|
||||
// React 19+ accepts a cleanup function as the return value
|
||||
return () => media.detach();
|
||||
};
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import type { Media } from '@videojs/core';
|
||||
|
||||
type AnyClass = abstract new (...args: any[]) => any;
|
||||
|
||||
function getSettableProps(DelegateClass: AnyClass): Set<string> {
|
||||
const props = new Set<string>();
|
||||
for (let proto = DelegateClass.prototype; proto && proto !== Object.prototype; proto = Object.getPrototypeOf(proto)) {
|
||||
for (const key of Object.getOwnPropertyNames(proto)) {
|
||||
const desc = Object.getOwnPropertyDescriptor(proto, key);
|
||||
if (desc?.set) props.add(key);
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
export function mediaProps(media: Media, DelegateClass: AnyClass, props: Record<string, any>) {
|
||||
const delegateKeys = getSettableProps(DelegateClass);
|
||||
const rest: Record<string, any> = {};
|
||||
|
||||
for (const key of Object.keys(props)) {
|
||||
if (delegateKeys.has(key)) {
|
||||
const value = props[key];
|
||||
if ((media as any)[key] !== value) {
|
||||
(media as any)[key] = value;
|
||||
}
|
||||
} else {
|
||||
rest[key] = props[key];
|
||||
}
|
||||
}
|
||||
|
||||
return rest;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
'use client';
|
||||
|
||||
import type { MediaEngineHost } from '@videojs/core';
|
||||
import type { RefCallback } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export function useAttachMedia<T extends HTMLMediaElement>(media: MediaEngineHost): RefCallback<T> {
|
||||
return useCallback(
|
||||
(element: T | null) => {
|
||||
if (element) media.attach?.(element);
|
||||
else media.detach?.();
|
||||
return () => media.detach?.();
|
||||
},
|
||||
[media]
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { isUndefined } from '@videojs/utils/predicate';
|
||||
|
||||
export function useSyncProps<Props extends object, Rest extends Record<string, unknown>>(
|
||||
target: Props,
|
||||
props: Partial<Props> & Rest,
|
||||
defaults: Props
|
||||
): Omit<Rest, keyof Props> {
|
||||
const rest: Record<string, unknown> = {};
|
||||
|
||||
for (const key in props) {
|
||||
if (key in defaults) {
|
||||
const value = isUndefined(props[key]) ? (defaults as Record<string, unknown>)[key] : props[key];
|
||||
if (target[key as keyof typeof target] !== value) target[key as keyof typeof target] = value as any;
|
||||
} else {
|
||||
rest[key] = props[key];
|
||||
}
|
||||
}
|
||||
|
||||
return rest as Omit<Rest, keyof Props>;
|
||||
}
|
||||
Reference in New Issue
Block a user