feat(core): add play button component (#383)

This commit is contained in:
rahim
2026-02-04 00:33:14 +11:00
committed by GitHub
parent 9fa172e8a4
commit 9cfab264d8
41 changed files with 2083 additions and 38 deletions
+26
View File
@@ -0,0 +1,26 @@
import { isUndefined } from '../predicate';
/** Makes all properties optional and explicitly allows undefined values. */
type PartialWithUndefined<T> = { [K in keyof T]?: T[K] | undefined };
/**
* Creates a new object with default values filled in for undefined properties.
*
* @example
* ```ts
* const props = { label: undefined, disabled: true };
* const defaultProps = { label: '', disabled: false };
* defaults(props, defaultProps); // { label: '', disabled: true }
* ```
*/
export function defaults<T extends object>(object: PartialWithUndefined<T>, defaultValues: T): T {
const result = { ...defaultValues };
for (const key in object) {
if (!isUndefined(object[key])) {
result[key as keyof T] = object[key] as T[keyof T];
}
}
return result;
}
+1
View File
@@ -1 +1,2 @@
export { defaults } from './defaults';
export { pick } from './pick';
@@ -0,0 +1,72 @@
import { describe, expect, it } from 'vitest';
import { defaults } from '../defaults';
describe('defaults', () => {
it('fills undefined values with defaults', () => {
const result = defaults({ a: undefined, b: 2 }, { a: 1, b: 0 });
expect(result).toEqual({ a: 1, b: 2 });
});
it('preserves defined values', () => {
const result = defaults({ a: 'custom', b: 'also custom' }, { a: 'default', b: 'default' });
expect(result).toEqual({ a: 'custom', b: 'also custom' });
});
it('returns all defaults for empty object', () => {
const result = defaults({}, { a: 1, b: 2 });
expect(result).toEqual({ a: 1, b: 2 });
});
it('preserves falsy values (false)', () => {
const result = defaults({ enabled: false }, { enabled: true });
expect(result).toEqual({ enabled: false });
});
it('preserves falsy values (0)', () => {
const result = defaults({ count: 0 }, { count: 10 });
expect(result).toEqual({ count: 0 });
});
it('preserves falsy values (empty string)', () => {
const result = defaults({ label: '' }, { label: 'default' });
expect(result).toEqual({ label: '' });
});
it('preserves null values', () => {
const result = defaults<{ value: string | null }>({ value: null }, { value: 'default' });
expect(result).toEqual({ value: null });
});
it('handles mixed defined and undefined values', () => {
const result = defaults({ label: 'custom', disabled: undefined }, { label: 'default', disabled: false });
expect(result).toEqual({ label: 'custom', disabled: false });
});
it('does not mutate the input object', () => {
const input = { a: undefined };
const defaultValues = { a: 1, b: 2 };
defaults(input, defaultValues);
expect(input).toEqual({ a: undefined });
expect(defaultValues).toEqual({ a: 1, b: 2 });
});
it('does not mutate the default values object', () => {
const input = { a: 'custom' };
const defaultValues = { a: 'default', b: 'default' };
const result = defaults(input, defaultValues);
expect(defaultValues).toEqual({ a: 'default', b: 'default' });
expect(result).not.toBe(defaultValues);
});
it('handles nested objects (shallow)', () => {
const nested = { x: 1 };
const result = defaults({ config: undefined }, { config: nested });
expect(result.config).toBe(nested);
});
});