Skip to content

Commit 721ed78

Browse files
committed
feat: add useViewModelInstanceList hook
1 parent eef56fb commit 721ed78

2 files changed

Lines changed: 107 additions & 0 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { useCallback } from 'react';
2+
import { ViewModelInstance, ViewModelInstanceList } from '@rive-app/canvas';
3+
import { UseViewModelInstanceListResult } from '../types';
4+
import { useViewModelInstanceProperty } from './useViewModelInstanceProperty';
5+
6+
/**
7+
* Hook for interacting with list properties of a ViewModelInstance.
8+
*
9+
* @param path - Path to the property (e.g. "items" or "nested/items")
10+
* @param viewModelInstance - The ViewModelInstance containing the list property
11+
* @returns An object with the list length and manipulation functions
12+
*/
13+
export default function useViewModelInstanceList(
14+
path: string,
15+
viewModelInstance?: ViewModelInstance | null
16+
): UseViewModelInstanceListResult {
17+
18+
const result = useViewModelInstanceProperty<ViewModelInstanceList, number, Omit<UseViewModelInstanceListResult, 'length'>>(
19+
path,
20+
viewModelInstance,
21+
{
22+
getProperty: useCallback((vm, p) => vm.list(p), []),
23+
getValue: useCallback((prop) => prop.length, []),
24+
defaultValue: 0,
25+
buildPropertyOperations: useCallback((safePropertyAccess) => ({
26+
addInstance: (instance: ViewModelInstance) => {
27+
safePropertyAccess(prop => prop.addInstance(instance));
28+
},
29+
addInstanceAt: (instance: ViewModelInstance, index: number): boolean => {
30+
let result = false;
31+
safePropertyAccess(prop => {
32+
result = prop.addInstanceAt(instance, index);
33+
});
34+
return result;
35+
},
36+
removeInstance: (instance: ViewModelInstance) => {
37+
safePropertyAccess(prop => prop.removeInstance(instance));
38+
},
39+
removeInstanceAt: (index: number) => {
40+
safePropertyAccess(prop => prop.removeInstanceAt(index));
41+
},
42+
getInstanceAt: (index: number): ViewModelInstance | null => {
43+
let result: ViewModelInstance | null = null;
44+
safePropertyAccess(prop => {
45+
result = prop.instanceAt(index);
46+
});
47+
return result;
48+
},
49+
swap: (a: number, b: number) => {
50+
safePropertyAccess(prop => prop.swap(a, b));
51+
}
52+
}), [])
53+
}
54+
);
55+
56+
return {
57+
length: result.value ?? 0,
58+
addInstance: result.addInstance,
59+
addInstanceAt: result.addInstanceAt,
60+
removeInstance: result.removeInstance,
61+
removeInstanceAt: result.removeInstanceAt,
62+
getInstanceAt: result.getInstanceAt,
63+
swap: result.swap
64+
};
65+
}

src/types.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
RiveFile,
55
RiveFileParameters,
66
RiveParameters,
7+
ViewModelInstance,
78
} from '@rive-app/canvas';
89
import { ComponentProps, RefCallback } from 'react';
910

@@ -196,4 +197,45 @@ export type UseViewModelInstanceImageResult = {
196197
* @param value - The image to set.
197198
*/
198199
setValue: (value: RiveRenderImage | null) => void;
200+
};
201+
202+
export type UseViewModelInstanceListResult = {
203+
/**
204+
* The current length of the list.
205+
*/
206+
length: number;
207+
/**
208+
* Add an instance to the end of the list.
209+
* @param instance - The ViewModelInstance to add.
210+
*/
211+
addInstance: (instance: ViewModelInstance) => void;
212+
/**
213+
* Add an instance at a specific index in the list.
214+
* @param instance - The ViewModelInstance to add.
215+
* @param index - The index to add the instance at.
216+
* @returns True if the instance was successfully added, false otherwise.
217+
*/
218+
addInstanceAt: (instance: ViewModelInstance, index: number) => boolean;
219+
/**
220+
* Remove an instance from the list.
221+
* @param instance - The ViewModelInstance to remove.
222+
*/
223+
removeInstance: (instance: ViewModelInstance) => void;
224+
/**
225+
* Remove an instance at a specific index from the list.
226+
* @param index - The index to remove the instance from.
227+
*/
228+
removeInstanceAt: (index: number) => void;
229+
/**
230+
* Get an instance at a specific index from the list.
231+
* @param index - The index to get the instance from.
232+
* @returns The ViewModelInstance at the index, or null if not found.
233+
*/
234+
getInstanceAt: (index: number) => ViewModelInstance | null;
235+
/**
236+
* Swap two instances in the list.
237+
* @param a - The first index.
238+
* @param b - The second index.
239+
*/
240+
swap: (a: number, b: number) => void;
199241
};

0 commit comments

Comments
 (0)