refactor(packages)!: replace DelegateMixin & ProxyMixin with MediaHost base classes (#1292)

This commit is contained in:
Wesley Luyten
2026-04-14 00:18:11 -05:00
committed by GitHub
parent f609373cd7
commit 8f1653efcd
91 changed files with 2840 additions and 1816 deletions
+1
View File
@@ -1,3 +1,4 @@
export { defaults } from './defaults';
export { omit } from './omit';
export { pick } from './pick';
export { shallowEqual } from './shallow-equal';
+18
View File
@@ -0,0 +1,18 @@
/**
* Creates a new object without the specified keys.
*
* @example
* const obj = { a: 1, b: 2, c: 3 };
* omit(obj, ['b']); // { a: 1, c: 3 }
*/
export function omit<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: readonly K[]): Omit<T, K> {
const result = {} as Record<string, unknown>;
for (const key in obj) {
if (!keys.includes(key as unknown as K)) {
result[key] = obj[key];
}
}
return result as Omit<T, K>;
}
+3 -1
View File
@@ -9,7 +9,9 @@ export function pick<T extends Record<string, unknown>, K extends keyof T>(obj:
const result = {} as Pick<T, K>;
for (const key of keys) {
result[key] = obj[key];
if (Object.hasOwn(obj, key)) {
result[key] = obj[key];
}
}
return result;
@@ -0,0 +1,88 @@
import { describe, expect, it } from 'vitest';
import { omit } from '../omit';
describe('omit', () => {
it('removes specified keys from object', () => {
const obj = { a: 1, b: 2, c: 3 };
expect(omit(obj, ['b'])).toEqual({ a: 1, c: 3 });
});
it('removes multiple keys', () => {
const obj = { a: 1, b: 2, c: 3 };
expect(omit(obj, ['a', 'c'])).toEqual({ b: 2 });
});
it('returns copy of object for empty keys array', () => {
const obj = { a: 1, b: 2 };
const result = omit(obj, []);
expect(result).toEqual({ a: 1, b: 2 });
expect(result).not.toBe(obj);
});
it('ignores non-existent keys', () => {
const obj = { a: 1, b: 2 };
expect(omit(obj, ['nonexistent' as keyof typeof obj])).toEqual({ a: 1, b: 2 });
});
it('returns empty object when all keys are removed', () => {
const obj = { a: 1, b: 2 };
expect(omit(obj, ['a', 'b'])).toEqual({});
});
it('handles nested objects (shallow copy)', () => {
const nested = { a: { x: 1 }, b: { y: 2 }, c: 3 };
const result = omit(nested, ['c']);
expect(result).toEqual({ a: { x: 1 }, b: { y: 2 } });
expect((result as any).a).toBe(nested.a);
});
it('preserves value types', () => {
const obj = {
str: 'hello',
num: 42,
bool: true,
arr: [1, 2, 3],
nil: null,
undef: undefined,
};
const result = omit(obj, ['str']);
expect(result).toEqual({
num: 42,
bool: true,
arr: [1, 2, 3],
nil: null,
undef: undefined,
});
});
it('works with readonly keys array', () => {
const obj = { a: 1, b: 2, c: 3 };
const keys = ['a', 'c'] as const;
expect(omit(obj, keys)).toEqual({ b: 2 });
});
it('filters attrs that are MediaHost props from element attributes', () => {
const elementAttrs = {
src: 'video.mp4',
autoplay: '',
class: 'player',
'current-time': '10',
'playback-rate': '1.5',
muted: '',
};
const mediaPropAttrs = ['current-time', 'playback-rate', 'muted'] as const;
const result = omit(elementAttrs, mediaPropAttrs);
expect(result).toEqual({ src: 'video.mp4', autoplay: '', class: 'player' });
expect(result).not.toHaveProperty('current-time');
expect(result).not.toHaveProperty('playback-rate');
expect(result).not.toHaveProperty('muted');
});
});
@@ -57,4 +57,29 @@ describe('pick', () => {
expect(pick(obj, keys)).toEqual({ a: 1, c: 3 });
});
it('does not include non-existent keys as undefined properties', () => {
const obj = { a: 1 };
const result = pick(obj, ['a', 'b' as keyof typeof obj]);
expect(Object.keys(result)).toEqual(['a']);
expect(result).not.toHaveProperty('b');
});
it('filters element attributes to only allowed media attributes', () => {
const elementAttrs: Record<string, string> = {
src: 'video.mp4',
autoplay: '',
class: 'player',
style: 'width: 100%',
};
const allowedAttrs = ['src', 'autoplay', 'controls', 'muted', 'loop'];
const result = pick(elementAttrs, allowedAttrs);
expect(result).toEqual({ src: 'video.mp4', autoplay: '' });
expect(result).not.toHaveProperty('class');
expect(result).not.toHaveProperty('style');
expect(result).not.toHaveProperty('controls');
});
});