@shopify/react-native-skia 0.1.143 → 0.1.145
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cpp/api/JsiSkPaint.h +6 -0
- package/lib/commonjs/renderer/Canvas.js +17 -7
- package/lib/commonjs/renderer/Canvas.js.map +1 -1
- package/lib/commonjs/renderer/DependencyManager.js +144 -36
- package/lib/commonjs/renderer/DependencyManager.js.map +1 -1
- package/lib/commonjs/renderer/HostConfig.js +1 -1
- package/lib/commonjs/renderer/HostConfig.js.map +1 -1
- package/lib/commonjs/renderer/components/backdrop/BackdropFilter.js.map +1 -1
- package/lib/commonjs/renderer/nodes/Declaration.js +2 -3
- package/lib/commonjs/renderer/nodes/Declaration.js.map +1 -1
- package/lib/commonjs/renderer/nodes/Drawing.js +3 -7
- package/lib/commonjs/renderer/nodes/Drawing.js.map +1 -1
- package/lib/commonjs/renderer/nodes/Node.js +9 -7
- package/lib/commonjs/renderer/nodes/Node.js.map +1 -1
- package/lib/commonjs/renderer/processors/Animations/Animations.js +3 -22
- package/lib/commonjs/renderer/processors/Animations/Animations.js.map +1 -1
- package/lib/commonjs/skia/types/Paint/Paint.js.map +1 -1
- package/lib/commonjs/skia/web/Host.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkPaint.js +4 -0
- package/lib/commonjs/skia/web/JsiSkPaint.js.map +1 -1
- package/lib/module/renderer/Canvas.js +17 -6
- package/lib/module/renderer/Canvas.js.map +1 -1
- package/lib/module/renderer/DependencyManager.js +140 -33
- package/lib/module/renderer/DependencyManager.js.map +1 -1
- package/lib/module/renderer/HostConfig.js +1 -1
- package/lib/module/renderer/HostConfig.js.map +1 -1
- package/lib/module/renderer/components/backdrop/BackdropFilter.js.map +1 -1
- package/lib/module/renderer/nodes/Declaration.js +3 -4
- package/lib/module/renderer/nodes/Declaration.js.map +1 -1
- package/lib/module/renderer/nodes/Drawing.js +3 -6
- package/lib/module/renderer/nodes/Drawing.js.map +1 -1
- package/lib/module/renderer/nodes/Node.js +9 -7
- package/lib/module/renderer/nodes/Node.js.map +1 -1
- package/lib/module/renderer/processors/Animations/Animations.js +1 -16
- package/lib/module/renderer/processors/Animations/Animations.js.map +1 -1
- package/lib/module/skia/types/Paint/Paint.js.map +1 -1
- package/lib/module/skia/web/Host.js.map +1 -1
- package/lib/module/skia/web/JsiSkPaint.js +4 -0
- package/lib/module/skia/web/JsiSkPaint.js.map +1 -1
- package/lib/typescript/src/renderer/Canvas.d.ts +1 -1
- package/lib/typescript/src/renderer/DependencyManager.d.ts +40 -14
- package/lib/typescript/src/renderer/nodes/Declaration.d.ts +2 -2
- package/lib/typescript/src/renderer/nodes/Drawing.d.ts +2 -2
- package/lib/typescript/src/renderer/nodes/Node.d.ts +3 -2
- package/lib/typescript/src/renderer/processors/Animations/Animations.d.ts +0 -1
- package/lib/typescript/src/skia/types/Paint/Paint.d.ts +5 -0
- package/lib/typescript/src/skia/web/Host.d.ts +1 -1
- package/lib/typescript/src/skia/web/JsiSkPaint.d.ts +1 -0
- package/libs/ios/libskia.xcframework/Info.plist +5 -5
- package/libs/ios/libskia.xcframework/ios-arm64_arm64e/libskia.a +0 -0
- package/libs/ios/libskia.xcframework/ios-arm64_arm64e_x86_64-simulator/libskia.a +0 -0
- package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e/libskshaper.a +0 -0
- package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e_x86_64-simulator/libskshaper.a +0 -0
- package/libs/ios/libsvg.xcframework/ios-arm64_arm64e/libsvg.a +0 -0
- package/libs/ios/libsvg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsvg.a +0 -0
- package/package.json +1 -1
- package/src/renderer/Canvas.tsx +19 -7
- package/src/renderer/DependencyManager.tsx +170 -39
- package/src/renderer/HostConfig.ts +1 -1
- package/src/renderer/components/backdrop/BackdropFilter.tsx +1 -1
- package/src/renderer/nodes/Declaration.tsx +6 -8
- package/src/renderer/nodes/Drawing.tsx +5 -7
- package/src/renderer/nodes/Node.ts +11 -9
- package/src/renderer/processors/Animations/Animations.ts +2 -15
- package/src/skia/types/Paint/Paint.ts +6 -0
- package/src/skia/web/Host.ts +1 -1
- package/src/skia/web/JsiSkPaint.ts +4 -0
package/src/renderer/Canvas.tsx
CHANGED
@@ -20,6 +20,7 @@ import { SkiaView, useDrawCallback } from "../views";
|
|
20
20
|
import type { TouchHandler } from "../views";
|
21
21
|
import { useValue } from "../values/hooks/useValue";
|
22
22
|
import { Skia } from "../skia/Skia";
|
23
|
+
import type { SkiaValue } from "../values";
|
23
24
|
|
24
25
|
import { debug as hostDebug, skHostConfig } from "./HostConfig";
|
25
26
|
// import { debugTree } from "./nodes";
|
@@ -38,8 +39,7 @@ skiaReconciler.injectIntoDevTools({
|
|
38
39
|
const render = (element: ReactNode, root: OpaqueRoot, container: Container) => {
|
39
40
|
skiaReconciler.updateContainer(element, root, null, () => {
|
40
41
|
hostDebug("updateContainer");
|
41
|
-
|
42
|
-
container.depMgr.subscribe();
|
42
|
+
container.depMgr.update();
|
43
43
|
});
|
44
44
|
};
|
45
45
|
|
@@ -60,9 +60,19 @@ export const Canvas = forwardRef<SkiaView, CanvasProps>(
|
|
60
60
|
const [tick, setTick] = useState(0);
|
61
61
|
const redraw = useCallback(() => setTick((t) => t + 1), []);
|
62
62
|
|
63
|
+
const registerValues = useCallback(
|
64
|
+
(values: Array<SkiaValue<unknown>>) => {
|
65
|
+
if (ref.current === null) {
|
66
|
+
throw new Error("Canvas ref is not set");
|
67
|
+
}
|
68
|
+
return ref.current.registerValues(values);
|
69
|
+
},
|
70
|
+
[ref]
|
71
|
+
);
|
72
|
+
|
63
73
|
const container = useMemo(
|
64
|
-
() => new Container(new DependencyManager(
|
65
|
-
[redraw,
|
74
|
+
() => new Container(new DependencyManager(registerValues), redraw),
|
75
|
+
[redraw, registerValues]
|
66
76
|
);
|
67
77
|
|
68
78
|
const root = useMemo(
|
@@ -78,6 +88,8 @@ export const Canvas = forwardRef<SkiaView, CanvasProps>(
|
|
78
88
|
);
|
79
89
|
}, [children, root, redraw, container, canvasCtx]);
|
80
90
|
|
91
|
+
const paint = useMemo(() => Skia.Paint(), []);
|
92
|
+
|
81
93
|
// Draw callback
|
82
94
|
const onDraw = useDrawCallback(
|
83
95
|
(canvas, info) => {
|
@@ -92,7 +104,7 @@ export const Canvas = forwardRef<SkiaView, CanvasProps>(
|
|
92
104
|
) {
|
93
105
|
canvasCtx.size.current = { width, height };
|
94
106
|
}
|
95
|
-
|
107
|
+
paint.reset();
|
96
108
|
const ctx = {
|
97
109
|
width,
|
98
110
|
height,
|
@@ -101,7 +113,7 @@ export const Canvas = forwardRef<SkiaView, CanvasProps>(
|
|
101
113
|
paint,
|
102
114
|
opacity: 1,
|
103
115
|
ref,
|
104
|
-
center:
|
116
|
+
center: { x: width / 2, y: height / 2 },
|
105
117
|
Skia,
|
106
118
|
};
|
107
119
|
container.draw(ctx);
|
@@ -112,7 +124,7 @@ export const Canvas = forwardRef<SkiaView, CanvasProps>(
|
|
112
124
|
useEffect(() => {
|
113
125
|
return () => {
|
114
126
|
skiaReconciler.updateContainer(null, root, null, () => {
|
115
|
-
container.depMgr.
|
127
|
+
container.depMgr.remove();
|
116
128
|
});
|
117
129
|
};
|
118
130
|
}, [container, root]);
|
@@ -1,62 +1,193 @@
|
|
1
|
-
import type { RefObject } from "react";
|
2
|
-
|
3
|
-
import type { SkiaView } from "../views";
|
4
1
|
import type { SkiaValue } from "../values";
|
5
2
|
|
6
|
-
import { isSelector, isValue } from "./processors";
|
7
3
|
import type { Node } from "./nodes";
|
4
|
+
import type { AnimatedProps } from "./processors";
|
5
|
+
import { isSelector, isValue } from "./processors";
|
6
|
+
import { mapKeys } from "./typeddash";
|
8
7
|
|
9
8
|
type Unsubscribe = () => void;
|
10
|
-
type
|
9
|
+
type Mutator = (value: unknown) => void;
|
10
|
+
|
11
|
+
type SubscriptionState = {
|
12
|
+
nodes: Map<Node, Mutator[]>;
|
13
|
+
unsubscribe: null | Unsubscribe;
|
14
|
+
};
|
11
15
|
|
12
16
|
export class DependencyManager {
|
13
|
-
|
14
|
-
subscriptions: Map<
|
15
|
-
|
16
|
-
{ values: SkiaValue<unknown>[]; unsubscribe: null | Unsubscribe }
|
17
|
-
> = new Map();
|
18
|
-
|
19
|
-
constructor(ref: RefObject<SkiaView>) {
|
20
|
-
this.ref = ref;
|
21
|
-
}
|
17
|
+
registerValues: (values: Array<SkiaValue<unknown>>) => () => void;
|
18
|
+
subscriptions: Map<SkiaValue<unknown>, SubscriptionState> = new Map();
|
19
|
+
unregisterDependantValues: null | Unsubscribe = null;
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
}
|
28
|
-
this.subscriptions.delete(node);
|
21
|
+
constructor(
|
22
|
+
registerValues: (values: Array<SkiaValue<unknown>>) => () => void
|
23
|
+
) {
|
24
|
+
this.registerValues = registerValues;
|
29
25
|
}
|
30
26
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
27
|
+
/**
|
28
|
+
* Call to unsubscribe all value listeners from the given node based
|
29
|
+
* on the current list of subscriptions for the node. This function
|
30
|
+
* is typically called when the node is unmounted or when one or more
|
31
|
+
* properties have changed.
|
32
|
+
* @param node Node to unsubscribe value listeners from
|
33
|
+
*/
|
34
|
+
unsubscribeNode(node: Node) {
|
35
|
+
const subscriptions = Array.from(this.subscriptions.values()).filter((p) =>
|
36
|
+
p.nodes.has(node)
|
37
|
+
);
|
35
38
|
|
36
|
-
if (
|
37
|
-
|
39
|
+
if (subscriptions) {
|
40
|
+
subscriptions.forEach((si) => {
|
41
|
+
// Delete node from subscription
|
42
|
+
si.nodes.delete(node);
|
43
|
+
|
44
|
+
// Remove subscription if there are no listeneres left on the value
|
45
|
+
if (si.nodes.size === 0) {
|
46
|
+
// There are no more nodes subscribing to this value, we can call
|
47
|
+
// unsubscribe on it.
|
48
|
+
if (!si.unsubscribe) {
|
49
|
+
throw new Error("Failed to unsubscribe to value subscription");
|
50
|
+
}
|
51
|
+
si.unsubscribe && si.unsubscribe();
|
52
|
+
|
53
|
+
// Remove from subscription states as well
|
54
|
+
const element = Array.from(this.subscriptions.entries()).find(
|
55
|
+
([_, sub]) => sub === si
|
56
|
+
);
|
57
|
+
if (!element) {
|
58
|
+
throw new Error("Failed to find value subscription");
|
59
|
+
}
|
60
|
+
if (!this.subscriptions.delete(element[0])) {
|
61
|
+
throw new Error("Failed to delete value subscription");
|
62
|
+
}
|
63
|
+
}
|
64
|
+
});
|
38
65
|
}
|
39
66
|
}
|
40
67
|
|
41
|
-
|
42
|
-
|
43
|
-
|
68
|
+
/**
|
69
|
+
* Adds listeners to the provided values so that the node is notified
|
70
|
+
* when a value changes. This is done in an optimized way so that this
|
71
|
+
* class only needs to listen to the value once and then forwards the
|
72
|
+
* change to the node and its listener. This method is typically called
|
73
|
+
* when the node is mounted and when one or more props on the node changes.
|
74
|
+
* @param node Node to subscribe to value changes for
|
75
|
+
* @param props Node's properties
|
76
|
+
* @param onResolveProp Callback when a property value changes
|
77
|
+
*/
|
78
|
+
subscribeNode<P extends Record<string, unknown>>(
|
79
|
+
node: Node,
|
80
|
+
props: AnimatedProps<P>
|
81
|
+
) {
|
82
|
+
// Get mutators from node's properties
|
83
|
+
const propSubscriptions = initializePropertySubscriptions(node, props);
|
84
|
+
if (propSubscriptions.length === 0) {
|
85
|
+
return;
|
44
86
|
}
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
87
|
+
|
88
|
+
// Install all mutators for the node
|
89
|
+
propSubscriptions.forEach((ps) => {
|
90
|
+
// Do we already have a state for this SkiaValue
|
91
|
+
let subscriptionState = this.subscriptions.get(ps.value);
|
92
|
+
if (!subscriptionState) {
|
93
|
+
// Let's create a new subscription state for the skia value
|
94
|
+
subscriptionState = {
|
95
|
+
nodes: new Map(),
|
96
|
+
unsubscribe: null,
|
97
|
+
};
|
98
|
+
// Add single subscription to the new value
|
99
|
+
subscriptionState.unsubscribe = ps.value.addListener((v) => {
|
100
|
+
subscriptionState!.nodes.forEach((mutators) =>
|
101
|
+
mutators.forEach((m) => m(v))
|
102
|
+
);
|
103
|
+
});
|
104
|
+
this.subscriptions.set(ps.value, subscriptionState);
|
50
105
|
}
|
106
|
+
// subscription mutators
|
107
|
+
subscriptionState.nodes.set(
|
108
|
+
node,
|
109
|
+
propSubscriptions
|
110
|
+
.filter((m) => m.value === ps.value)
|
111
|
+
.map((m) => m.mutator)
|
112
|
+
);
|
51
113
|
});
|
52
114
|
}
|
53
115
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
116
|
+
/**
|
117
|
+
* Called when the hosting container is mounted or updated. This ensures that we have
|
118
|
+
* a ref to the underlying SkiaView so that we can registers redraw listeners
|
119
|
+
* on values used in the current View automatically.
|
120
|
+
*/
|
121
|
+
update() {
|
122
|
+
// Remove any previous registrations
|
123
|
+
if (this.unregisterDependantValues) {
|
124
|
+
this.unregisterDependantValues();
|
125
|
+
}
|
126
|
+
|
127
|
+
// Register redraw requests on the SkiaView for each unique value
|
128
|
+
this.unregisterDependantValues = this.registerValues(
|
129
|
+
Array.from(this.subscriptions.keys())
|
130
|
+
);
|
131
|
+
}
|
132
|
+
|
133
|
+
/**
|
134
|
+
* Called when the hosting container is unmounted or recreated. This ensures that we remove
|
135
|
+
* all subscriptions to Skia values so that we don't have any listeners left after
|
136
|
+
* the component is removed.
|
137
|
+
*/
|
138
|
+
remove() {
|
139
|
+
// 1) Unregister redraw requests
|
140
|
+
if (this.unregisterDependantValues) {
|
141
|
+
this.unregisterDependantValues();
|
142
|
+
this.unregisterDependantValues = null;
|
143
|
+
}
|
144
|
+
|
145
|
+
// 2) Unregister nodes
|
146
|
+
Array.from(this.subscriptions.values()).forEach((si) => {
|
147
|
+
Array.from(si.nodes.keys()).forEach((node) => this.unsubscribeNode(node));
|
59
148
|
});
|
149
|
+
|
150
|
+
// 3) Clear the rest of the subscriptions
|
60
151
|
this.subscriptions.clear();
|
61
152
|
}
|
62
153
|
}
|
154
|
+
|
155
|
+
const initializePropertySubscriptions = <P,>(
|
156
|
+
node: Node<P>,
|
157
|
+
props: AnimatedProps<P>
|
158
|
+
) => {
|
159
|
+
const nodePropSubscriptions: Array<{
|
160
|
+
value: SkiaValue<unknown>;
|
161
|
+
mutator: Mutator;
|
162
|
+
}> = [];
|
163
|
+
|
164
|
+
mapKeys(props).forEach((key) => {
|
165
|
+
const propvalue = props[key];
|
166
|
+
|
167
|
+
if (isValue(propvalue)) {
|
168
|
+
// Subscribe to changes
|
169
|
+
nodePropSubscriptions.push({
|
170
|
+
value: propvalue,
|
171
|
+
mutator: (v) => (node.resolvedProps[key] = v as P[typeof key]),
|
172
|
+
});
|
173
|
+
// Set initial value
|
174
|
+
node.resolvedProps[key] = (propvalue as SkiaValue<P[typeof key]>).current;
|
175
|
+
} else if (isSelector(propvalue)) {
|
176
|
+
// Subscribe to changes
|
177
|
+
nodePropSubscriptions.push({
|
178
|
+
value: propvalue.value,
|
179
|
+
mutator: (v) =>
|
180
|
+
(node.resolvedProps[key] = propvalue.selector(v) as P[typeof key]),
|
181
|
+
});
|
182
|
+
// Set initial value
|
183
|
+
node.resolvedProps[key] = propvalue.selector(
|
184
|
+
propvalue.value.current
|
185
|
+
) as P[typeof key];
|
186
|
+
} else {
|
187
|
+
// Set initial value
|
188
|
+
node.resolvedProps[key] = propvalue as P[typeof key];
|
189
|
+
}
|
190
|
+
});
|
191
|
+
|
192
|
+
return nodePropSubscriptions;
|
193
|
+
};
|
@@ -101,7 +101,7 @@ const removeNode = (parent: Node, child: Node) => {
|
|
101
101
|
bustBranchMemoization(parent);
|
102
102
|
const index = parent.children.indexOf(child);
|
103
103
|
parent.children.splice(index, 1);
|
104
|
-
child.depMgr.
|
104
|
+
child.depMgr.unsubscribeNode(child);
|
105
105
|
// unsubscribe to all children as well
|
106
106
|
for (const c of child.children) {
|
107
107
|
removeNode(child, c);
|
@@ -8,7 +8,7 @@ import { getInput } from "../imageFilters/getInput";
|
|
8
8
|
import type { GroupProps } from "../Group";
|
9
9
|
import { Group } from "../Group";
|
10
10
|
|
11
|
-
const disableFilterMemoization = (children: Node
|
11
|
+
const disableFilterMemoization = (children: Node[]) => {
|
12
12
|
children.forEach((child) => {
|
13
13
|
child.memoizable = false;
|
14
14
|
disableFilterMemoization(child.children);
|
@@ -3,7 +3,7 @@ import { useCallback } from "react";
|
|
3
3
|
|
4
4
|
import type { DrawingContext } from "../DrawingContext";
|
5
5
|
import type { AnimatedProps } from "../processors";
|
6
|
-
import { isAnimated
|
6
|
+
import { isAnimated } from "../processors";
|
7
7
|
import type { DependencyManager } from "../DependencyManager";
|
8
8
|
import type { SkJSIInstance } from "../../skia/types";
|
9
9
|
|
@@ -28,9 +28,8 @@ export const useDeclaration = <P,>(
|
|
28
28
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
29
29
|
useCallback(cb, deps ?? []);
|
30
30
|
|
31
|
-
export const isDeclarationNode = (
|
32
|
-
node
|
33
|
-
): node is DeclarationNode<unknown> => node instanceof DeclarationNode;
|
31
|
+
export const isDeclarationNode = <P,>(node: Node): node is DeclarationNode<P> =>
|
32
|
+
node instanceof DeclarationNode;
|
34
33
|
|
35
34
|
export interface DeclarationProps<P> {
|
36
35
|
onDeclare: DeclarationCallback<P>;
|
@@ -54,14 +53,13 @@ export class DeclarationNode<P> extends Node<P> {
|
|
54
53
|
super.props = props;
|
55
54
|
}
|
56
55
|
|
57
|
-
get props() {
|
58
|
-
return this.
|
56
|
+
get props(): P {
|
57
|
+
return this.resolvedProps;
|
59
58
|
}
|
60
59
|
|
61
60
|
draw(ctx: DrawingContext) {
|
62
61
|
const children = this.visit(ctx);
|
63
|
-
const
|
64
|
-
const obj = this.onDeclare(props, children, ctx);
|
62
|
+
const obj = this.onDeclare(this.props, children, ctx);
|
65
63
|
return obj;
|
66
64
|
}
|
67
65
|
}
|
@@ -3,7 +3,6 @@ import { useCallback } from "react";
|
|
3
3
|
|
4
4
|
import type { DrawingContext } from "../DrawingContext";
|
5
5
|
import type { AnimatedProps } from "../processors/Animations/Animations";
|
6
|
-
import { materialize } from "../processors/Animations/Animations";
|
7
6
|
import { isPaint } from "../../skia/types";
|
8
7
|
import type { DependencyManager } from "../DependencyManager";
|
9
8
|
import { processPaint } from "../processors";
|
@@ -25,8 +24,8 @@ export const useDrawing = <P,>(cb: OnDrawCallback<P>, deps?: DependencyList) =>
|
|
25
24
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
26
25
|
useCallback(cb, deps ?? []);
|
27
26
|
|
28
|
-
export type DrawingProps<
|
29
|
-
onDraw: DrawingCallback<
|
27
|
+
export type DrawingProps<P> = {
|
28
|
+
onDraw: DrawingCallback<P>;
|
30
29
|
skipProcessing?: boolean;
|
31
30
|
children?: ReactNode | ReactNode[];
|
32
31
|
};
|
@@ -47,20 +46,19 @@ export class DrawingNode<P> extends Node<P> {
|
|
47
46
|
}
|
48
47
|
|
49
48
|
draw(ctx: DrawingContext) {
|
50
|
-
const drawingProps = materialize(this.props);
|
51
49
|
if (this.skipProcessing) {
|
52
|
-
this.onDraw(ctx,
|
50
|
+
this.onDraw(ctx, this.props, this);
|
53
51
|
} else {
|
54
52
|
const declarations = this.visit(ctx);
|
55
53
|
const paint = processPaint(
|
56
54
|
ctx.Skia,
|
57
55
|
ctx.paint.copy(),
|
58
56
|
ctx.opacity,
|
59
|
-
|
57
|
+
this.props,
|
60
58
|
declarations
|
61
59
|
);
|
62
60
|
[paint, ...declarations.filter(isPaint)].forEach((currentPaint) => {
|
63
|
-
this.onDraw({ ...ctx, paint: currentPaint },
|
61
|
+
this.onDraw({ ...ctx, paint: currentPaint }, this.props, this);
|
64
62
|
});
|
65
63
|
}
|
66
64
|
}
|
@@ -12,29 +12,31 @@ type DeclarationResult = SkJSIInstance<string> | null;
|
|
12
12
|
|
13
13
|
export abstract class Node<P = unknown> {
|
14
14
|
readonly children: Node[] = [];
|
15
|
-
|
15
|
+
// This cast is ok because we understand that the dependency manager will setup the initial props
|
16
|
+
resolvedProps: P = {} as P;
|
16
17
|
memoizable = false;
|
17
18
|
memoized: DeclarationResult | null = null;
|
18
19
|
parent?: Node;
|
19
20
|
depMgr: DependencyManager;
|
20
21
|
|
21
22
|
constructor(depMgr: DependencyManager, props: AnimatedProps<P>) {
|
22
|
-
this._props = props;
|
23
23
|
this.depMgr = depMgr;
|
24
|
-
this.
|
25
|
-
this.depMgr.subscribeNode(this, props);
|
24
|
+
this.updatePropSubscriptions(props);
|
26
25
|
}
|
27
26
|
|
28
27
|
abstract draw(ctx: DrawingContext): void | DeclarationResult;
|
29
28
|
|
30
|
-
|
31
|
-
this.depMgr.unSubscribeNode(this);
|
29
|
+
updatePropSubscriptions(props: AnimatedProps<P>) {
|
32
30
|
this.depMgr.subscribeNode(this, props);
|
33
|
-
this._props = props;
|
34
31
|
}
|
35
32
|
|
36
|
-
|
37
|
-
|
33
|
+
set props(props: AnimatedProps<P>) {
|
34
|
+
this.depMgr.unsubscribeNode(this);
|
35
|
+
this.updatePropSubscriptions(props);
|
36
|
+
}
|
37
|
+
|
38
|
+
get props(): P {
|
39
|
+
return this.resolvedProps;
|
38
40
|
}
|
39
41
|
|
40
42
|
visit(ctx: DrawingContext, children?: Node[]) {
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import type { SkiaSelector, SkiaValue } from "../../../values";
|
2
|
-
import { mapKeys } from "../../typeddash";
|
3
2
|
|
4
3
|
export const isValue = (value: unknown): value is SkiaValue<unknown> => {
|
5
4
|
if (value === undefined || value === null) {
|
@@ -37,28 +36,16 @@ export const isSelector = <T, R>(
|
|
37
36
|
|
38
37
|
export const isAnimated = <T>(props: AnimatedProps<T>) => {
|
39
38
|
for (const value of Object.values(props)) {
|
40
|
-
if (isValue(value)) {
|
39
|
+
if (isValue(value) || isSelector(value)) {
|
41
40
|
return true;
|
42
41
|
}
|
43
42
|
}
|
44
43
|
return false;
|
45
44
|
};
|
46
45
|
|
47
|
-
export const materialize = <T>(props: AnimatedProps<T>) => {
|
48
|
-
const result = { ...props };
|
49
|
-
mapKeys(props).forEach((key) => {
|
50
|
-
const prop = props[key];
|
51
|
-
if (isValue(prop)) {
|
52
|
-
result[key] = (prop as SkiaValue<T[typeof key]>).current;
|
53
|
-
} else if (isSelector(prop)) {
|
54
|
-
result[key] = prop.selector(prop.value.current) as T[typeof key];
|
55
|
-
}
|
56
|
-
});
|
57
|
-
return result as T;
|
58
|
-
};
|
59
|
-
|
60
46
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
61
47
|
export type AnimatedProp<T, P = any> = T | SkiaValue<T> | SkiaSelector<T, P>;
|
48
|
+
|
62
49
|
export type AnimatedProps<T> = {
|
63
50
|
[K in keyof T]: AnimatedProp<T[K]>;
|
64
51
|
};
|
@@ -34,6 +34,12 @@ export interface SkPaint extends SkJSIInstance<"Paint"> {
|
|
34
34
|
*/
|
35
35
|
copy(): SkPaint;
|
36
36
|
|
37
|
+
/**
|
38
|
+
* Sets all SkPaint contents to their initial values. This is equivalent to replacing
|
39
|
+
SkPaint with the result of SkPaint().
|
40
|
+
*/
|
41
|
+
reset(): void;
|
42
|
+
|
37
43
|
/**
|
38
44
|
* Retrieves the alpha and RGB unpremultiplied. RGB are extended sRGB values
|
39
45
|
* (sRGB gamut, and encoded with the sRGB transfer function).
|
package/src/skia/web/Host.ts
CHANGED
@@ -30,6 +30,10 @@ export class JsiSkPaint extends HostObject<Paint, "Paint"> implements SkPaint {
|
|
30
30
|
return new JsiSkPaint(this.CanvasKit, this.ref.copy());
|
31
31
|
}
|
32
32
|
|
33
|
+
reset() {
|
34
|
+
this.ref = new this.CanvasKit.Paint();
|
35
|
+
}
|
36
|
+
|
33
37
|
getColor() {
|
34
38
|
return this.ref.getColor();
|
35
39
|
}
|