exodeui-react-native 1.0.0 → 1.0.1
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/index.js +1 -0
- package/package.json +10 -7
- package/src/ExodeUIView.tsx +110 -27
- package/src/__tests__/engine.test.ts +299 -0
- package/src/engine.ts +529 -178
- package/src/physics/MatterPhysics.ts +66 -0
- package/src/physics/PhysicsEngine.ts +42 -0
- package/src/physics/index.ts +2 -0
- package/src/types.ts +159 -16
- package/src/useExodeUI.ts +31 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { PhysicsEngine, BodyOptions } from './PhysicsEngine';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stub implementation of MatterPhysics to isolate white screen issues.
|
|
5
|
+
* Original matter-js dependency removed as requested.
|
|
6
|
+
*/
|
|
7
|
+
export class MatterPhysics implements PhysicsEngine {
|
|
8
|
+
private initialized: boolean = false;
|
|
9
|
+
|
|
10
|
+
async init(gravity: { x: number; y: number }): Promise<void> {
|
|
11
|
+
console.log('[MatterPhysics] Stub initialized');
|
|
12
|
+
this.initialized = true;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
destroy(): void {
|
|
16
|
+
this.initialized = false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
createBody(options: BodyOptions): void {
|
|
20
|
+
// No-op
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
removeBody(id: string): void {
|
|
24
|
+
// No-op
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
step(dt: number): void {
|
|
28
|
+
// No-op
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getPosition(id: string): { x: number; y: number } | null {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getRotation(id: string): number | null {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getVelocity(id: string): { x: number; y: number } | null {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
isDynamic(id: string): boolean {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
setPosition(id: string, x: number, y: number): void {
|
|
48
|
+
// No-op
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
setRotation(id: string, angle: number): void {
|
|
52
|
+
// No-op
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
setVelocity(id: string, vx: number, vy: number): void {
|
|
56
|
+
// No-op
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
applyForce(id: string, fx: number, fy: number): void {
|
|
60
|
+
// No-op
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
applyImpulse(id: string, ix: number, iy: number): void {
|
|
64
|
+
// No-op
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface BodyOptions {
|
|
2
|
+
id: string;
|
|
3
|
+
type: 'Rectangle' | 'Ellipse' | 'Triangle' | 'Star' | 'Polygon' | 'Image';
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
rotation?: number;
|
|
9
|
+
isStatic: boolean;
|
|
10
|
+
mass?: number;
|
|
11
|
+
friction?: number;
|
|
12
|
+
restitution?: number;
|
|
13
|
+
frictionAir?: number;
|
|
14
|
+
density?: number;
|
|
15
|
+
isSensor?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface PhysicsEngine {
|
|
19
|
+
// Lifecycle
|
|
20
|
+
init(gravity: { x: number; y: number }): Promise<void>;
|
|
21
|
+
destroy(): void;
|
|
22
|
+
|
|
23
|
+
// Bodies
|
|
24
|
+
createBody(options: BodyOptions): void;
|
|
25
|
+
removeBody(id: string): void;
|
|
26
|
+
|
|
27
|
+
// Simulation
|
|
28
|
+
step(dt: number): void;
|
|
29
|
+
|
|
30
|
+
// Queries
|
|
31
|
+
getPosition(id: string): { x: number; y: number } | null;
|
|
32
|
+
getRotation(id: string): number | null;
|
|
33
|
+
getVelocity(id: string): { x: number; y: number } | null;
|
|
34
|
+
isDynamic(id: string): boolean;
|
|
35
|
+
|
|
36
|
+
// Updates
|
|
37
|
+
setPosition(id: string, x: number, y: number): void;
|
|
38
|
+
setRotation(id: string, angle: number): void;
|
|
39
|
+
setVelocity(id: string, vx: number, vy: number): void;
|
|
40
|
+
applyForce(id: string, fx: number, fy: number): void;
|
|
41
|
+
applyImpulse(id: string, ix: number, iy: number): void;
|
|
42
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -18,12 +18,43 @@ export interface Blur {
|
|
|
18
18
|
amount: number;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
export interface LineDataset {
|
|
22
|
+
id: string;
|
|
23
|
+
label: string;
|
|
24
|
+
data: number[];
|
|
25
|
+
lineColor: string;
|
|
26
|
+
lineWidth: number;
|
|
27
|
+
showArea: boolean;
|
|
28
|
+
areaColor: string;
|
|
29
|
+
smoothing: boolean;
|
|
30
|
+
showPoints: boolean;
|
|
31
|
+
pointSize: number;
|
|
32
|
+
pointFill: string;
|
|
33
|
+
pointStrokeColor: string;
|
|
34
|
+
pointStrokeWidth: number;
|
|
35
|
+
inputId?: string;
|
|
36
|
+
isVarEnabled?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface Fill {
|
|
40
|
+
type: 'Solid' | 'LinearGradient' | 'RadialGradient' | 'AngularGradient' | 'DiamondGradient' | 'Pattern' | 'None';
|
|
41
|
+
color?: string;
|
|
42
|
+
opacity: number;
|
|
43
|
+
stops?: { offset: number; color: string }[];
|
|
44
|
+
start?: [number, number];
|
|
45
|
+
end?: [number, number];
|
|
46
|
+
center?: [number, number];
|
|
47
|
+
radius?: number;
|
|
48
|
+
url?: string;
|
|
49
|
+
scaleX?: number;
|
|
50
|
+
scaleY?: number;
|
|
51
|
+
offsetX?: number;
|
|
52
|
+
offsetY?: number;
|
|
53
|
+
rotation?: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
21
56
|
export interface Style {
|
|
22
|
-
fill?:
|
|
23
|
-
type: 'Solid' | 'LinearGradient' | 'RadialGradient' | 'None';
|
|
24
|
-
color: string;
|
|
25
|
-
opacity: number;
|
|
26
|
-
};
|
|
57
|
+
fill?: Fill;
|
|
27
58
|
stroke?: {
|
|
28
59
|
color: string;
|
|
29
60
|
width: number;
|
|
@@ -35,16 +66,64 @@ export interface Style {
|
|
|
35
66
|
}
|
|
36
67
|
|
|
37
68
|
export type Geometry =
|
|
38
|
-
| { type: 'Rectangle'; width: number; height: number; corner_radius?: number }
|
|
39
|
-
| { type: 'Ellipse'; width: number; height: number }
|
|
40
|
-
| {
|
|
69
|
+
| { type: 'Rectangle'; width: number; height: number; corner_radius?: number | [number, number, number, number]; cornerRadius?: number | [number, number, number, number]; isMask?: boolean }
|
|
70
|
+
| { type: 'Ellipse'; width: number; height: number; isMask?: boolean }
|
|
71
|
+
| {
|
|
72
|
+
type: 'Text';
|
|
73
|
+
text: string;
|
|
74
|
+
fontSize: number;
|
|
75
|
+
fontFamily: string;
|
|
76
|
+
fontWeight?: string | number;
|
|
77
|
+
textAlign?: 'left' | 'center' | 'right' | 'justify';
|
|
78
|
+
textVerticalAlign?: 'top' | 'middle' | 'center' | 'bottom';
|
|
79
|
+
width?: number;
|
|
80
|
+
height?: number;
|
|
81
|
+
lineHeight?: number;
|
|
82
|
+
letterSpacing?: number;
|
|
83
|
+
textCase?: 'none' | 'uppercase' | 'lowercase' | 'capitalize';
|
|
84
|
+
paragraphSpacing?: number;
|
|
85
|
+
textInputId?: string;
|
|
86
|
+
segments?: { text: string; fill: Fill; fontSize?: number; fontFamily?: string; fontWeight?: string | number }[];
|
|
87
|
+
enableSegments?: boolean;
|
|
88
|
+
isMask?: boolean;
|
|
89
|
+
}
|
|
90
|
+
| { type: 'Triangle'; width: number; height: number, isMask?: boolean }
|
|
91
|
+
| { type: 'Polygon'; radius: number; sides: number, isMask?: boolean }
|
|
92
|
+
| { type: 'Star'; inner_radius: number; outer_radius: number; points: number, isMask?: boolean }
|
|
93
|
+
| { type: 'Line'; length: number, isMask?: boolean }
|
|
41
94
|
| { type: 'SVG'; svgContent: string; width: number; height: number; preserveAspectRatio: boolean; colors: string[] }
|
|
42
|
-
| { type: '
|
|
43
|
-
| {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
95
|
+
| { type: 'Image'; src: string; width: number; height: number }
|
|
96
|
+
| {
|
|
97
|
+
type: "LineGraph",
|
|
98
|
+
datasets?: LineDataset[],
|
|
99
|
+
data?: number[],
|
|
100
|
+
width: number,
|
|
101
|
+
height: number,
|
|
102
|
+
lineColor?: string,
|
|
103
|
+
lineWidth?: number,
|
|
104
|
+
showArea?: boolean,
|
|
105
|
+
areaColor?: string,
|
|
106
|
+
smoothing?: boolean,
|
|
107
|
+
showPoints?: boolean,
|
|
108
|
+
pointSize?: number,
|
|
109
|
+
pointFill?: string,
|
|
110
|
+
pointStrokeColor?: string,
|
|
111
|
+
pointStrokeWidth?: number,
|
|
112
|
+
showXAxis?: boolean,
|
|
113
|
+
showYAxis?: boolean,
|
|
114
|
+
xAxisColor?: string,
|
|
115
|
+
yAxisColor?: string,
|
|
116
|
+
showXLabels?: boolean,
|
|
117
|
+
showYLabels?: boolean,
|
|
118
|
+
axisLabelColor?: string,
|
|
119
|
+
axisLabelFontSize?: number,
|
|
120
|
+
showLegend?: boolean,
|
|
121
|
+
legendColor?: string,
|
|
122
|
+
legendFontSize?: number,
|
|
123
|
+
areaOpacity?: number
|
|
124
|
+
}
|
|
125
|
+
| { type: 'Component'; variant: string; width: number; height: number }
|
|
126
|
+
| { type: 'Frame'; width: number; height: number };
|
|
48
127
|
|
|
49
128
|
export interface Trigger {
|
|
50
129
|
id: string;
|
|
@@ -76,16 +155,46 @@ export interface Physics {
|
|
|
76
155
|
}
|
|
77
156
|
|
|
78
157
|
|
|
158
|
+
export interface Constraint {
|
|
159
|
+
id?: string;
|
|
160
|
+
type: 'Translation' | 'Rotation' | 'Scale' | 'Transform' | 'Distance' | 'IK' | 'FollowPath' | 'FollowPointer';
|
|
161
|
+
targetId: string;
|
|
162
|
+
strength: number;
|
|
163
|
+
copyX?: boolean;
|
|
164
|
+
copyY?: boolean;
|
|
165
|
+
limitX?: { enabled: boolean; min: number; max: number };
|
|
166
|
+
limitY?: { enabled: boolean; min: number; max: number };
|
|
167
|
+
distance?: number;
|
|
168
|
+
mode?: 'clamped' | 'exact' | 'minimum' | 'maximum';
|
|
169
|
+
|
|
170
|
+
// Spring Properties
|
|
171
|
+
useSpring?: boolean;
|
|
172
|
+
stiffness?: number; // Hooke's Law: F = -k * x
|
|
173
|
+
damping?: number; // Damping: F = -c * v
|
|
174
|
+
mass?: number; // F = m * a
|
|
175
|
+
}
|
|
176
|
+
|
|
79
177
|
export interface ShapeObject {
|
|
80
|
-
type: 'Shape';
|
|
178
|
+
type: 'Shape' | 'Group' | 'Component' | 'Frame' | 'Button' | 'Bone' | 'Toggle' | 'Slider' | 'Dropdown' | 'ListView';
|
|
81
179
|
id: string;
|
|
82
180
|
name: string;
|
|
83
181
|
transform: Transform;
|
|
84
182
|
geometry: Geometry;
|
|
85
183
|
style: Style;
|
|
184
|
+
parentId?: string;
|
|
185
|
+
children?: string[];
|
|
86
186
|
triggers?: Trigger[];
|
|
87
187
|
interactions?: Interaction[];
|
|
188
|
+
constraints?: Constraint[];
|
|
88
189
|
physics?: Physics;
|
|
190
|
+
renderAsGroup?: boolean;
|
|
191
|
+
opacity?: number;
|
|
192
|
+
visible?: boolean;
|
|
193
|
+
isVisible?: boolean;
|
|
194
|
+
blendMode?: string;
|
|
195
|
+
compositeOperation?: string;
|
|
196
|
+
options?: any;
|
|
197
|
+
inputId?: string;
|
|
89
198
|
}
|
|
90
199
|
|
|
91
200
|
export interface Keyframe {
|
|
@@ -160,7 +269,9 @@ export type InputValue =
|
|
|
160
269
|
| { type: 'Boolean', value: boolean }
|
|
161
270
|
| { type: 'Number', value: number }
|
|
162
271
|
| { type: 'Trigger', value: boolean }
|
|
163
|
-
| { type: 'Text', value: string }
|
|
272
|
+
| { type: 'Text', value: string }
|
|
273
|
+
| { type: 'StringArray', value: string[] }
|
|
274
|
+
| { type: 'NumberArray', value: number[] };
|
|
164
275
|
|
|
165
276
|
export interface InputNodePosition {
|
|
166
277
|
id: string;
|
|
@@ -184,9 +295,31 @@ export interface Layer {
|
|
|
184
295
|
states: State[];
|
|
185
296
|
}
|
|
186
297
|
|
|
298
|
+
export enum LogicOp {
|
|
299
|
+
AND = 'AND',
|
|
300
|
+
OR = 'OR',
|
|
301
|
+
NOT = 'NOT',
|
|
302
|
+
XOR = 'XOR'
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export interface LogicNode {
|
|
306
|
+
id: string;
|
|
307
|
+
name: string;
|
|
308
|
+
op: LogicOp;
|
|
309
|
+
x: number;
|
|
310
|
+
y: number;
|
|
311
|
+
inputs: {
|
|
312
|
+
id: string;
|
|
313
|
+
sourceId?: string;
|
|
314
|
+
sourceHandleId?: string;
|
|
315
|
+
value?: number | boolean;
|
|
316
|
+
}[];
|
|
317
|
+
}
|
|
318
|
+
|
|
187
319
|
export interface StateMachine {
|
|
188
320
|
inputs: Input[];
|
|
189
321
|
layers: Layer[];
|
|
322
|
+
logicNodes?: LogicNode[];
|
|
190
323
|
}
|
|
191
324
|
|
|
192
325
|
export interface Artboard {
|
|
@@ -194,6 +327,8 @@ export interface Artboard {
|
|
|
194
327
|
width: number;
|
|
195
328
|
height: number;
|
|
196
329
|
backgroundColor: string;
|
|
330
|
+
backgroundImage?: string;
|
|
331
|
+
backgroundOpacity?: number;
|
|
197
332
|
objects: ShapeObject[];
|
|
198
333
|
animations: Animation[];
|
|
199
334
|
stateMachine?: StateMachine;
|
|
@@ -211,3 +346,11 @@ export interface Layout {
|
|
|
211
346
|
fit: Fit;
|
|
212
347
|
alignment: Alignment;
|
|
213
348
|
}
|
|
349
|
+
|
|
350
|
+
export interface ComponentEvent {
|
|
351
|
+
objectId: string;
|
|
352
|
+
componentName: string;
|
|
353
|
+
variant: string;
|
|
354
|
+
property: string;
|
|
355
|
+
value: any;
|
|
356
|
+
}
|
package/src/useExodeUI.ts
CHANGED
|
@@ -12,15 +12,45 @@ export function useExodeUI() {
|
|
|
12
12
|
engine?.setInputNumber(name, value);
|
|
13
13
|
}, [engine]);
|
|
14
14
|
|
|
15
|
+
const setInputText = useCallback((name: string, value: string) => {
|
|
16
|
+
engine?.setInputText(name, value);
|
|
17
|
+
}, [engine]);
|
|
18
|
+
|
|
19
|
+
const setInputNumberArray = useCallback((name: string, value: number[]) => {
|
|
20
|
+
engine?.setInputNumberArray(name, value);
|
|
21
|
+
}, [engine]);
|
|
22
|
+
|
|
23
|
+
const setInputStringArray = useCallback((name: string, value: string[]) => {
|
|
24
|
+
engine?.setInputStringArray(name, value);
|
|
25
|
+
}, [engine]);
|
|
26
|
+
|
|
15
27
|
const fireTrigger = useCallback((name: string) => {
|
|
16
28
|
engine?.fireTrigger(name);
|
|
17
29
|
}, [engine]);
|
|
18
30
|
|
|
31
|
+
const updateConstraint = useCallback((objectId: string, index: number, properties: any) => {
|
|
32
|
+
engine?.updateConstraint(objectId, index, properties);
|
|
33
|
+
}, [engine]);
|
|
34
|
+
|
|
35
|
+
const updateGraphData = useCallback((nameOrId: string, data: number[]) => {
|
|
36
|
+
engine?.updateGraphData(nameOrId, data);
|
|
37
|
+
}, [engine]);
|
|
38
|
+
|
|
39
|
+
const updateObjectOptions = useCallback((id: string, newOptions: any) => {
|
|
40
|
+
engine?.updateObjectOptions(id, newOptions);
|
|
41
|
+
}, [engine]);
|
|
42
|
+
|
|
19
43
|
return {
|
|
20
44
|
setEngine,
|
|
21
45
|
engine,
|
|
22
46
|
setInputBool,
|
|
23
47
|
setInputNumber,
|
|
24
|
-
|
|
48
|
+
setInputText,
|
|
49
|
+
setInputNumberArray,
|
|
50
|
+
setInputStringArray,
|
|
51
|
+
fireTrigger,
|
|
52
|
+
updateConstraint,
|
|
53
|
+
updateGraphData,
|
|
54
|
+
updateObjectOptions
|
|
25
55
|
};
|
|
26
56
|
}
|