exodeui-react-native 1.0.6 → 1.0.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "exodeui-react-native",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "React Native runtime for ExodeUI animations",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -11,18 +11,20 @@ export interface ExodeUIViewProps {
11
11
  autoPlay?: boolean;
12
12
  fit?: Fit;
13
13
  alignment?: Alignment;
14
- onReady?: (engine: any) => void; // Changed type to any as per instruction
14
+ onReady?: (engine: any) => void;
15
15
  onTrigger?: (triggerName: string, animationName: string) => void;
16
16
  onInputUpdate?: (nameOrId: string, value: any) => void;
17
- onComponentChange?: (event: ComponentEvent) => void; // Added
18
- onToggle?: (name: string, checked: boolean) => void; // Changed value to checked
19
- onInputChange?: (name: string, text: string) => void; // Changed value to text
17
+ onComponentChange?: (event: ComponentEvent) => void;
18
+ onToggle?: (name: string, checked: boolean) => void;
19
+ onInputChange?: (name: string, text: string) => void;
20
20
  onInputFocus?: (name: string) => void;
21
21
  onInputBlur?: (name: string) => void;
22
+ onButtonClick?: (name: string, objectId: string) => void;
23
+ onGraphPointClick?: (event: { objectId: string; componentName: string; datasetIndex: number; pointIndex: number; value: number; label: string }) => void;
22
24
  }
23
25
 
24
26
  export const ExodeUIView = forwardRef<any, ExodeUIViewProps>(
25
- ({ artboard, src, style, autoPlay = true, fit = 'Contain', alignment = 'Center', onReady, onTrigger, onInputUpdate, onInputFocus, onInputBlur, onToggle, onInputChange, onComponentChange }, ref) => {
27
+ ({ artboard, src, style, autoPlay = true, fit = 'Contain', alignment = 'Center', onReady, onTrigger, onInputUpdate, onInputFocus, onInputBlur, onToggle, onInputChange, onComponentChange, onButtonClick, onGraphPointClick }, ref) => {
26
28
 
27
29
  const engineRef = useRef<ExodeUIEngine>(new ExodeUIEngine());
28
30
  const [picture, setPicture] = useState<SkPicture | null>(null);
@@ -72,6 +74,14 @@ export const ExodeUIView = forwardRef<any, ExodeUIViewProps>(
72
74
  if (onComponentChange) engineRef.current.setComponentChangeCallback(onComponentChange);
73
75
  }, [onComponentChange]);
74
76
 
77
+ useEffect(() => {
78
+ if (onButtonClick) engineRef.current.setButtonClickCallback(onButtonClick);
79
+ }, [onButtonClick]);
80
+
81
+ useEffect(() => {
82
+ if (onGraphPointClick) engineRef.current.setGraphPointClickCallback(onGraphPointClick);
83
+ }, [onGraphPointClick]);
84
+
75
85
  // Load Artboard
76
86
  useEffect(() => {
77
87
  const loadArtboard = async () => {
package/src/engine.ts CHANGED
@@ -35,6 +35,8 @@ export class ExodeUIEngine {
35
35
  private onInputChange?: (name: string, text: string) => void;
36
36
  private onInputFocus?: (name: string) => void;
37
37
  private onInputBlur?: (name: string) => void;
38
+ private onButtonClick?: (name: string, objectId: string) => void;
39
+ private onGraphPointClick?: (event: { objectId: string; componentName: string; datasetIndex: number; pointIndex: number; value: number; label: string }) => void;
38
40
 
39
41
  // Track triggers that were just fired in the current frame
40
42
  private justFiredTriggers: Set<string> = new Set();
@@ -78,6 +80,12 @@ export class ExodeUIEngine {
78
80
  setInputBlurCallback(cb: (name: string) => void) {
79
81
  this.onInputBlur = cb;
80
82
  }
83
+ setButtonClickCallback(cb: (name: string, objectId: string) => void) {
84
+ this.onButtonClick = cb;
85
+ }
86
+ setGraphPointClickCallback(cb: (event: { objectId: string; componentName: string; datasetIndex: number; pointIndex: number; value: number; label: string }) => void) {
87
+ this.onGraphPointClick = cb;
88
+ }
81
89
 
82
90
  constructor() {}
83
91
 
@@ -964,6 +972,15 @@ export class ExodeUIEngine {
964
972
  }
965
973
  }
966
974
 
975
+ if (targetObj.type === 'Component' && (targetObj as any).variant === 'button') {
976
+ if (type === 'click' || type === 'PointerDown') {
977
+ if (this.onButtonClick) this.onButtonClick(targetObj.name, targetObj.id);
978
+ if (this.onComponentChange) {
979
+ this.onComponentChange({ objectId: targetObj.id, componentName: targetObj.name, variant: 'button', property: 'click', value: true });
980
+ }
981
+ }
982
+ }
983
+
967
984
  if (targetObj.type === 'Component' && (targetObj as any).variant === 'slider') {
968
985
  if (type === 'PointerDown') {
969
986
  this.draggingSliderId = targetObj.id;
@@ -1021,6 +1038,43 @@ export class ExodeUIEngine {
1021
1038
  }
1022
1039
  }
1023
1040
  }
1041
+
1042
+ if (targetObj.type === 'LineGraph') {
1043
+ if (type === 'click' || type === 'PointerDown') {
1044
+ const geom = targetObj.geometry as any;
1045
+ const datasets = geom?.datasets || [];
1046
+ const state = this.objectStates.get(targetObj.id);
1047
+ const objW = state?.width || geom?.width || 200;
1048
+ const objH = state?.height || geom?.height || 150;
1049
+ const world = this.getWorldTransform(targetObj.id);
1050
+ const axisMarginL = 30;
1051
+ const axisMarginB = 20;
1052
+ const plotW = objW - axisMarginL;
1053
+ const plotH = objH - axisMarginB;
1054
+ let globalMax = 1;
1055
+ datasets.forEach((ds: any) => { const m = Math.max(...(ds.data || [0])); if (m > globalMax) globalMax = m; });
1056
+
1057
+ let closestDist = Infinity;
1058
+ let closestResult: any = null;
1059
+ datasets.forEach((ds: any, dIdx: number) => {
1060
+ const data = ds.data || [];
1061
+ const stepX = plotW / Math.max(data.length - 1, 1);
1062
+ data.forEach((val: number, pIdx: number) => {
1063
+ const px = world.x - objW/2 + axisMarginL + pIdx * stepX;
1064
+ const py = world.y + objH/2 - axisMarginB - (val / globalMax) * plotH;
1065
+ const dist = Math.sqrt((x - px) ** 2 + (y - py) ** 2);
1066
+ if (dist < closestDist) { closestDist = dist; closestResult = { dIdx, pIdx, val, label: ds.label || `Dataset ${dIdx + 1}` }; }
1067
+ });
1068
+ });
1069
+
1070
+ if (closestResult && closestDist < 20 && this.onGraphPointClick) {
1071
+ this.onGraphPointClick({ objectId: targetObj.id, componentName: targetObj.name, datasetIndex: closestResult.dIdx, pointIndex: closestResult.pIdx, value: closestResult.val, label: closestResult.label });
1072
+ }
1073
+ if (this.onComponentChange) {
1074
+ this.onComponentChange({ objectId: targetObj.id, componentName: targetObj.name, variant: 'linegraph', property: 'click', value: closestResult?.val ?? null });
1075
+ }
1076
+ }
1077
+ }
1024
1078
  }
1025
1079
  }
1026
1080
 
package/src/useExodeUI.ts CHANGED
@@ -40,6 +40,14 @@ export function useExodeUI() {
40
40
  engine?.updateObjectOptions(id, newOptions);
41
41
  }, [engine]);
42
42
 
43
+ const onButtonClick = useCallback((cb: (name: string, objectId: string) => void) => {
44
+ engine?.setButtonClickCallback(cb);
45
+ }, [engine]);
46
+
47
+ const onGraphPointClick = useCallback((cb: (event: { objectId: string; componentName: string; datasetIndex: number; pointIndex: number; value: number; label: string }) => void) => {
48
+ engine?.setGraphPointClickCallback(cb);
49
+ }, [engine]);
50
+
43
51
  return {
44
52
  setEngine,
45
53
  engine,
@@ -51,6 +59,8 @@ export function useExodeUI() {
51
59
  fireTrigger,
52
60
  updateConstraint,
53
61
  updateGraphData,
54
- updateObjectOptions
62
+ updateObjectOptions,
63
+ onButtonClick,
64
+ onGraphPointClick,
55
65
  };
56
66
  }