Skip to content

Commit

Permalink
refactor: removed all the partial type operators and made them option…
Browse files Browse the repository at this point in the history
…al in the types themselves. This makes it easier to in the future has some properties to be mandatory instead of having them all to be optional due to the `Partial` operator.
  • Loading branch information
pepijnverburg committed May 12, 2023
1 parent e23229a commit cb1454b
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 25 deletions.
33 changes: 24 additions & 9 deletions packages/libraries/react/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ export const IN_DEVELOPMENT = false;
*/
export const DEBUG_ENABLED = IN_DEVELOPMENT;

/**
* One second in milliseconds.
*/
export const ONE_SECOND_MS = 1000;

/**
* Whether debugging for this package is enabled.
*/
Expand Down Expand Up @@ -69,16 +74,26 @@ export const DEFAULT_MIN_PITCH = 0.0;
export const DEFAULT_MAX_PITCH = 10.0;

/**
* The default options for the MutationObserver passed from `useClippetObserver`.
* The default time required between mutations to trigger the handler.
*/
export const DEFAULT_MUTATION_OBSERVER_OPTIONS: MutationObserverInit = {
attributes: true,
childList: false,
subtree: false,
attributeFilter: ['style'],
};
export const DEFAULT_MUTATION_OBSERVER_DEBOUNCE_MS = 100;

/**
* The default time required between mutations to trigger a callback.
* The default frame rate per second where the movement should be checked.
*/
export const DEFAULT_MUTATION_OBSERVER_DEBOUNCE_MS = 100;
export const DEFAULT_MOVEMENT_OBSERVER_FRAME_RATE = 10;

/**
* The default frame rate per second where the synchronisation should be checked.
*/
export const DEFAULT_SYNCHRONISATION_OBSERVER_FRAME_RATE = 10;

/**
* The default time it takes after the last change before the sound should be stopped when synchronisation is enabled.
*/
export const DEFAULT_SYNCRONISATION_OBSERVER_STOP_TIMEOUT_MS = 100;

/**
* The default amount of movement in pixels required to trigger a sound.
*/
export const DEFAULT_MOVEMENT_OBSERVER_THRESHOLD_PX = 2;
2 changes: 1 addition & 1 deletion packages/libraries/react/src/context/ClippetProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import ClippetContext from './ClippetContext';
*/
export interface ClippetProviderProps {
children?: ReactNode | ReactNode[] | null;
options?: Partial<ClippetProviderOptions>;
options?: ClippetProviderOptions;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/libraries/react/src/hooks/useClippet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { useClippetProvider } from './useClippetProvider';
* @param options Advanced options to customize the behaviour of this single hook.
* @returns Tuple to play and have access to the advanced API to for example stop the sound on request.
*/
export function useClippet(clippet: Clippet, options?: Partial<ClippetOptions>): UseClippet {
export function useClippet(clippet: Clippet, options?: ClippetOptions): UseClippet {
const providerOptions = useClippetProvider();
const {
enablePooling = true,
Expand Down
74 changes: 61 additions & 13 deletions packages/libraries/react/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,29 @@ export interface ClippetContextOptions {
/**
* Flag to identify whether the sounds are globally muted.
*/
isMuted: boolean;
isMuted?: boolean;

/**
* A normalized number to set the global volume of each sound.
* This volume level is multiplied with the volume specific settings of a hook.
*/
volume: number;
volume?: number;

/**
* The minimum volume when a sound is played. Each play request is checked against this volume,
* with the exception when the sound is muted. In that case `mutedVolume` is used.
*/
minVolume: number;
minVolume?: number;

/**
* The maximum volume when a sound is played. Each play request is checked against this volume.
*/
maxVolume: number;
maxVolume?: number;

/**
* The volume used when a sound is muted. This by default is (of course) `0`, but can be adjusted in more advanced situations.
*/
mutedVolume: number;
mutedVolume?: number;

/**
* The global pitch level for all sounds. This pitch level is multiplied with the pitch specific settings of a hook.
Expand All @@ -46,7 +46,7 @@ export interface ClippetContextOptions {
/**
* Global events on the document to play clippets to make it easy to introduce accessibility features application-wide.
*/
windowEvents: ClippetWindowEvent[];
windowEvents?: ClippetWindowEvent[];
}

export type ClippetWindowEventType = keyof WindowEventMap;
Expand All @@ -66,7 +66,7 @@ export interface ClippetWindowEvent {
*/
export interface ClippetWindowEventsOptions {
windowEvents: ClippetWindowEvent[];
providerOptions?: Partial<ClippetProviderOptions>;
providerOptions?: ClippetProviderOptions;
}

/**
Expand All @@ -87,32 +87,80 @@ export interface ClippetOptions {
/**
* Flag to identify whether the sound of this hook should be muted.
*/
isMuted: boolean;
isMuted?: boolean;

/**
* True when the sound should be played regardless of any mute options passed to the provider or hook.
*/
forceUnmute: boolean;
forceUnmute?: boolean;

/**
* A normalized number (between 0 and 1) to adjust the volume of the sound of this hook.
* This number is multiplied with the volume level of the provider making it possible to set a global volume
* and adjust the relative volume for each invidual hook.
*/
volume: number;
volume?: number;

/**
* Flag to identity whether the `Audio` instance should be re-used across unique `useClippet` hook instances.
*/
enablePooling: boolean;
enablePooling?: boolean;
}

/**
* Optional options that can be passed to a `useClippetObserver` hook to fine-tune the behaviour.
*/
export interface ClippetObserverOptions extends ClippetOptions {
mutationObserverOptions?: MutationObserverInit;
syncWithAnimation?: boolean;
/**
* The options to pass along to the `MutationObserver` instance when observing the DOM.
*/
mutations?: MutationObserverInit;
/**
* The options to enable observing movements using the `getClientBoundingRect` state.
*/
movements?: MovementObserverOptions;
/**
* The amount of time in milliseconds a change can be observed and with that a sound can be played.
*/
debounceMs?: number;
/**
* Advanced options to synchronize the observerations done with the playback of the sound.
* This for example allow for a sound to be played when a element moves and stop when it stops moving.
*/
synchronisation?: SynchronisationObserverOptions;
}

/**
* Optional options that can be passed to a `useMovementObserver` hook to fine-tune the behaviour.
*/
export interface MovementObserverOptions {
/**
* Flag to identify whether observing movements is enabled.
*/
enabled?: boolean;
/**
* The minimum movement in pixels to trigger a sound. This can be on both the y and x axis.
*/
threshold?: number;
/**
* The frame rate at which the movement should be checked. This is in frames per second.
*/
frameRate?: number;
}

export interface SynchronisationObserverOptions {
/**
* Flag to identify whether synchronizing the observer with the sound is enabled
*/
enabled?: boolean;
/**
* The amount of time in milliseconds before a sound is stopped when any changes stop.
*/
stopTimeoutMs?: number;
/**
* The frame rate at which any synchronisation should be checked. This is in frames per second.
*/
frameRate?: number;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/libraries/react/src/utilities/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export function stopAudio(audio: ClippetAudio) {
/**
* Helper to get the volume and whether it is muted of a specific clippet.
*/
export function getAudioVolumeTuple(providerOptions: Partial<ClippetProviderOptions>, clippetOptions?: Partial<ClippetOptions>) {
export function getAudioVolumeTuple(providerOptions: ClippetProviderOptions, clippetOptions?: ClippetOptions) {
const {
isMuted: providerIsMuted,
volume: providerVolume = DEFAULT_PROVIDER_VOLUME,
Expand Down
12 changes: 12 additions & 0 deletions packages/libraries/react/src/utilities/timing.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ONE_SECOND_MS } from '../constants';

export function throttle(callback: Function, delay: number) {
let shouldWait = false

Expand Down Expand Up @@ -38,3 +40,13 @@ export function timeHasPassed(date: Date | null | undefined, ms: number) {

return diff > ms;
}

export function getTimeoutMsByFrameRate(frameRate: number) {

// guard: skip invalid frame rates
if (frameRate === 0) {
return 0;
}

return ONE_SECOND_MS / Math.abs(frameRate);
}

0 comments on commit cb1454b

Please sign in to comment.