exodeui-react-native 1.0.0 → 1.0.2
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 +127 -32
- package/src/__tests__/engine.test.ts +299 -0
- package/src/engine.ts +1430 -277
- 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 +160 -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,47 @@ 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;
|
|
198
|
+
text?: string;
|
|
89
199
|
}
|
|
90
200
|
|
|
91
201
|
export interface Keyframe {
|
|
@@ -160,7 +270,9 @@ export type InputValue =
|
|
|
160
270
|
| { type: 'Boolean', value: boolean }
|
|
161
271
|
| { type: 'Number', value: number }
|
|
162
272
|
| { type: 'Trigger', value: boolean }
|
|
163
|
-
| { type: 'Text', value: string }
|
|
273
|
+
| { type: 'Text', value: string }
|
|
274
|
+
| { type: 'StringArray', value: string[] }
|
|
275
|
+
| { type: 'NumberArray', value: number[] };
|
|
164
276
|
|
|
165
277
|
export interface InputNodePosition {
|
|
166
278
|
id: string;
|
|
@@ -184,9 +296,31 @@ export interface Layer {
|
|
|
184
296
|
states: State[];
|
|
185
297
|
}
|
|
186
298
|
|
|
299
|
+
export enum LogicOp {
|
|
300
|
+
AND = 'AND',
|
|
301
|
+
OR = 'OR',
|
|
302
|
+
NOT = 'NOT',
|
|
303
|
+
XOR = 'XOR'
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export interface LogicNode {
|
|
307
|
+
id: string;
|
|
308
|
+
name: string;
|
|
309
|
+
op: LogicOp;
|
|
310
|
+
x: number;
|
|
311
|
+
y: number;
|
|
312
|
+
inputs: {
|
|
313
|
+
id: string;
|
|
314
|
+
sourceId?: string;
|
|
315
|
+
sourceHandleId?: string;
|
|
316
|
+
value?: number | boolean;
|
|
317
|
+
}[];
|
|
318
|
+
}
|
|
319
|
+
|
|
187
320
|
export interface StateMachine {
|
|
188
321
|
inputs: Input[];
|
|
189
322
|
layers: Layer[];
|
|
323
|
+
logicNodes?: LogicNode[];
|
|
190
324
|
}
|
|
191
325
|
|
|
192
326
|
export interface Artboard {
|
|
@@ -194,6 +328,8 @@ export interface Artboard {
|
|
|
194
328
|
width: number;
|
|
195
329
|
height: number;
|
|
196
330
|
backgroundColor: string;
|
|
331
|
+
backgroundImage?: string;
|
|
332
|
+
backgroundOpacity?: number;
|
|
197
333
|
objects: ShapeObject[];
|
|
198
334
|
animations: Animation[];
|
|
199
335
|
stateMachine?: StateMachine;
|
|
@@ -211,3 +347,11 @@ export interface Layout {
|
|
|
211
347
|
fit: Fit;
|
|
212
348
|
alignment: Alignment;
|
|
213
349
|
}
|
|
350
|
+
|
|
351
|
+
export interface ComponentEvent {
|
|
352
|
+
objectId: string;
|
|
353
|
+
componentName: string;
|
|
354
|
+
variant: string;
|
|
355
|
+
property: string;
|
|
356
|
+
value: any;
|
|
357
|
+
}
|
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
|
}
|