Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/hooks/useRiveColor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ import type {
ViewModelColorProperty,
ViewModelInstance,
} from '../specs/ViewModel.nitro';
import { type UseRivePropertyResult } from '../types';
import { useRiveProperty } from './useRiveProperty';
import { RiveColor } from '../core/RiveColor';

const COLOR_PROPERTY_OPTIONS = {
getProperty: (vmi: ViewModelInstance, p: string) => vmi.colorProperty(p),
};

export interface UseRiveColorResult {
value: RiveColor | undefined;
setValue: (value: RiveColor | string) => void;
error: Error | null;
}

/**
* Hook for interacting with color ViewModel instance properties.
*
Expand All @@ -21,9 +26,7 @@ const COLOR_PROPERTY_OPTIONS = {
export function useRiveColor(
path: string,
viewModelInstance?: ViewModelInstance | null
): UseRivePropertyResult<RiveColor> & {
setValue: (value: RiveColor | string) => void;
} {
): UseRiveColorResult {
const [rawValue, setRawValue, error] = useRiveProperty<
ViewModelColorProperty,
number
Expand Down
15 changes: 13 additions & 2 deletions src/hooks/useRiveProperty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ export function useRiveProperty<P extends ViewModelProperty, T>(
/** Optional override callback for property events (mainly used by triggers) */
onPropertyEventOverride?: (...args: any[]) => void;
}
): [T | undefined, (value: T) => void, Error | null, P | undefined] {
): [
T | undefined,
(value: T | ((prevValue: T | undefined) => T)) => void,
Error | null,
P | undefined,
] {
const [value, setValue] = useState<T | undefined>(undefined);
const [error, setError] = useState<Error | null>(null);

Expand Down Expand Up @@ -79,14 +84,20 @@ export function useRiveProperty<P extends ViewModelProperty, T>(

// Set the value of the property
const setPropertyValue = useCallback(
(newValue: T) => {
(valueOrUpdater: T | ((prevValue: T | undefined) => T)) => {
if (!property) {
setError(
new Error(
`Cannot set value for property "${path}" because it was not found. Your view model instance may be undefined, or the path may be incorrect.`
)
);
} else {
const newValue =
typeof valueOrUpdater === 'function'
? (valueOrUpdater as (prevValue: T | undefined) => T)(
property.value
)
: valueOrUpdater;
property.value = newValue;
}
},
Expand Down
1 change: 1 addition & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,5 @@ export { useRiveColor } from './hooks/useRiveColor';
export { useRiveTrigger } from './hooks/useRiveTrigger';
export { useRiveFile } from './hooks/useRiveFile';
export { type RiveFileInput } from './hooks/useRiveFile';
export { type SetValueAction } from './types';
export { DataBindMode };
15 changes: 12 additions & 3 deletions src/types.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
/**
* A value or a function that computes a new value from the previous value.
* Similar to React's SetStateAction pattern.
*/
export type SetValueAction<T> = T | ((prevValue: T | undefined) => T);

export interface UseRivePropertyResult<T> {
/**
* The current value of the property.
*/
value: T | undefined;
/**
* Set the value of the property.
* @param value - The value to set the property to.
* Set the value of the property. Accepts either a direct value or
* a function that receives the previous value and returns the new value.
* @example
* setValue(10) // Set to 10
* setValue((prev) => (prev ?? 0) + 5) // Increment by 5
*/
setValue: (value: T) => void;
setValue: (value: SetValueAction<T>) => void;
/**
* The error if the property is not found.
*/
Expand Down
Loading