onejs-react 0.1.5 → 0.1.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": "onejs-react",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "React 19 renderer for OneJS (Unity UI Toolkit)",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -17,7 +17,7 @@
17
17
  ],
18
18
  "repository": {
19
19
  "type": "git",
20
- "url": "https://github.com/Singtaa/onejs-react"
20
+ "url": "git+https://github.com/Singtaa/onejs-react.git"
21
21
  },
22
22
  "author": "Singtaa",
23
23
  "scripts": {
@@ -12,6 +12,13 @@ declare function clearTimeout(id: number): void;
12
12
 
13
13
  declare const console: { log: (...args: unknown[]) => void; error: (...args: unknown[]) => void };
14
14
 
15
+ // Native delegate callback helpers (from QuickJSBootstrap __csHelpers)
16
+ declare const __csHelpers: {
17
+ createDelegateCallback(fn: Function): number;
18
+ freeDelegateCallback(handle: number): void;
19
+ [key: string]: unknown;
20
+ };
21
+
15
22
  // Priority constants from react-reconciler/constants
16
23
  // These match React's internal lane priorities
17
24
  const DiscreteEventPriority = 2;
@@ -149,6 +156,8 @@ export interface Instance {
149
156
  hasMixedContent?: boolean;
150
157
  // For vector drawing: track the current generateVisualContent callback
151
158
  visualContentCallback?: GenerateVisualContentCallback;
159
+ // Native callback handle for the above (used to free slot on replacement)
160
+ visualContentCallbackHandle?: number;
152
161
  }
153
162
 
154
163
  export type TextInstance = Instance; // For Label elements with text content
@@ -435,6 +444,15 @@ function untrackParent(child: CSObject) {
435
444
  }
436
445
  }
437
446
 
447
+ // Free native callback handles tracked on an instance (prevents callback table leak)
448
+ function cleanupCallbackHandles(instance: Instance) {
449
+ if (instance.visualContentCallbackHandle !== undefined) {
450
+ __csHelpers.freeDelegateCallback(instance.visualContentCallbackHandle);
451
+ instance.visualContentCallbackHandle = undefined;
452
+ instance.visualContentCallback = undefined;
453
+ }
454
+ }
455
+
438
456
  // Apply event handlers
439
457
  function applyEvents(instance: Instance, props: BaseProps) {
440
458
  for (const [propName, eventType] of Object.entries(EVENT_PROPS)) {
@@ -468,17 +486,27 @@ function applyVisualContentCallback(instance: Instance, props: BaseProps) {
468
486
  if (callback !== existingCallback) {
469
487
  const element = instance.element as unknown as { generateVisualContent: GenerateVisualContentCallback | null };
470
488
 
471
- // Remove old callback if exists
489
+ // Free old native callback handle to prevent callback table leak
472
490
  if (existingCallback) {
473
- // Clear the delegate via C# interop
474
491
  element.generateVisualContent = null;
492
+ if (instance.visualContentCallbackHandle !== undefined) {
493
+ __csHelpers.freeDelegateCallback(instance.visualContentCallbackHandle);
494
+ }
495
+ instance.visualContentCallbackHandle = undefined;
475
496
  }
476
497
 
477
498
  // Add new callback if provided
478
499
  if (callback) {
479
- // Assign callback to generateVisualContent property
480
- // The C# interop layer handles the delegate conversion
481
- element.generateVisualContent = callback;
500
+ // Register with argument wrapping and track the handle for cleanup
501
+ const handle = __csHelpers.createDelegateCallback(callback);
502
+ if (handle >= 0) {
503
+ instance.visualContentCallbackHandle = handle;
504
+ // Pass pre-resolved handle directly — bypasses __resolveValue's auto-registration
505
+ element.generateVisualContent = { __csCallbackHandle: handle } as any;
506
+ } else {
507
+ // WebGL path: no native callback table
508
+ element.generateVisualContent = callback;
509
+ }
482
510
  instance.visualContentCallback = callback;
483
511
  } else {
484
512
  instance.visualContentCallback = undefined;
@@ -947,6 +975,7 @@ export const hostConfig = {
947
975
  removeMergedTextChild(parentInstance, child);
948
976
  } else {
949
977
  __eventAPI.removeAllEventListeners(child.element);
978
+ cleanupCallbackHandles(child);
950
979
  parentInstance.element.Remove(child.element);
951
980
  }
952
981
  untrackParent(child.element);
@@ -954,6 +983,7 @@ export const hostConfig = {
954
983
 
955
984
  removeChildFromContainer(container: Container, child: Instance) {
956
985
  __eventAPI.removeAllEventListeners(child.element);
986
+ cleanupCallbackHandles(child);
957
987
  container.Remove(child.element);
958
988
  untrackParent(child.element);
959
989
  },
@@ -9,6 +9,7 @@
9
9
  declare const CS: {
10
10
  UnityEngine: {
11
11
  Color: new (r: number, g: number, b: number, a: number) => CSColor;
12
+ FontStyle: Record<string, number>;
12
13
  UIElements: {
13
14
  Length: new (value: number, unit?: number) => CSLength;
14
15
  LengthUnit: { Pixel: number; Percent: number };
@@ -24,6 +25,9 @@ declare const CS: {
24
25
  Visibility: Record<string, number>;
25
26
  WhiteSpace: Record<string, number>;
26
27
  TextAnchor: Record<string, number>;
28
+ TextOverflow: Record<string, number>;
29
+ TextOverflowPosition: Record<string, number>;
30
+ OverflowClipBox: Record<string, number>;
27
31
  };
28
32
  };
29
33
  };
@@ -78,17 +82,20 @@ const LENGTH_PROPERTIES = new Set([
78
82
  "borderWidth", "borderTopWidth", "borderRightWidth", "borderBottomWidth", "borderLeftWidth",
79
83
  "borderRadius", "borderTopLeftRadius", "borderTopRightRadius", "borderBottomLeftRadius", "borderBottomRightRadius",
80
84
  "fontSize",
85
+ "letterSpacing", "wordSpacing", "unityTextOutlineWidth", "unityParagraphSpacing",
81
86
  ])
82
87
 
83
88
  // Style properties that expect color values
84
89
  const COLOR_PROPERTIES = new Set([
85
90
  "color", "backgroundColor",
86
91
  "borderColor", "borderTopColor", "borderRightColor", "borderBottomColor", "borderLeftColor",
92
+ "unityTextOutlineColor", "unityBackgroundImageTintColor",
87
93
  ])
88
94
 
89
95
  // Style properties that are plain numbers (no Length wrapper needed)
90
96
  const NUMBER_PROPERTIES = new Set([
91
97
  "flexGrow", "flexShrink", "opacity",
98
+ "unitySliceTop", "unitySliceRight", "unitySliceBottom", "unitySliceLeft", "unitySliceScale",
92
99
  ])
93
100
 
94
101
  // Enum property mappings: React style value -> Unity enum value
@@ -186,6 +193,37 @@ const ENUM_MAPPINGS: Record<string, { enum: () => Record<string, number>, values
186
193
  "nowrap": "NoWrap",
187
194
  }
188
195
  },
196
+ unityFontStyleAndWeight: {
197
+ enum: () => CS.UnityEngine.FontStyle,
198
+ values: {
199
+ "normal": "Normal",
200
+ "bold": "Bold",
201
+ "italic": "Italic",
202
+ "bold-and-italic": "BoldAndItalic",
203
+ }
204
+ },
205
+ textOverflow: {
206
+ enum: () => CS.UnityEngine.UIElements.TextOverflow,
207
+ values: {
208
+ "clip": "Clip",
209
+ "ellipsis": "Ellipsis",
210
+ }
211
+ },
212
+ unityTextOverflowPosition: {
213
+ enum: () => CS.UnityEngine.UIElements.TextOverflowPosition,
214
+ values: {
215
+ "end": "End",
216
+ "start": "Start",
217
+ "middle": "Middle",
218
+ }
219
+ },
220
+ unityOverflowClipBox: {
221
+ enum: () => CS.UnityEngine.UIElements.OverflowClipBox,
222
+ values: {
223
+ "padding-box": "PaddingBox",
224
+ "content-box": "ContentBox",
225
+ }
226
+ },
189
227
  }
190
228
 
191
229
  /**
package/src/types.ts CHANGED
@@ -127,6 +127,70 @@ export interface ViewStyle {
127
127
  /** Text alignment. Note: Use USS class or stylesheet for -unity-font-style (italic/bold) */
128
128
  unityTextAlign?: 'upper-left' | 'upper-center' | 'upper-right' | 'middle-left' | 'middle-center' | 'middle-right' | 'lower-left' | 'lower-center' | 'lower-right';
129
129
  whiteSpace?: 'normal' | 'nowrap';
130
+
131
+ // Typography
132
+ /** C# Font object */
133
+ unityFont?: any;
134
+ /** C# FontDefinition object */
135
+ unityFontDefinition?: any;
136
+ /** Font style and weight */
137
+ unityFontStyleAndWeight?: 'normal' | 'bold' | 'italic' | 'bold-and-italic';
138
+ /** Spacing between characters */
139
+ letterSpacing?: StyleLength;
140
+ /** Spacing between words */
141
+ wordSpacing?: StyleLength;
142
+ /** Spacing between paragraphs */
143
+ unityParagraphSpacing?: StyleLength;
144
+ /** Text outline color */
145
+ unityTextOutlineColor?: StyleColor;
146
+ /** Text outline width */
147
+ unityTextOutlineWidth?: StyleLength;
148
+ /** How overflowing text is handled */
149
+ textOverflow?: 'clip' | 'ellipsis';
150
+ /** Position of text overflow indicator */
151
+ unityTextOverflowPosition?: 'end' | 'start' | 'middle';
152
+
153
+ // Background (additional)
154
+ /** Tint color applied to the background image */
155
+ unityBackgroundImageTintColor?: StyleColor;
156
+
157
+ // Slicing
158
+ /** 9-slice top inset */
159
+ unitySliceTop?: number;
160
+ /** 9-slice right inset */
161
+ unitySliceRight?: number;
162
+ /** 9-slice bottom inset */
163
+ unitySliceBottom?: number;
164
+ /** 9-slice left inset */
165
+ unitySliceLeft?: number;
166
+ /** Scale applied to 9-slice borders */
167
+ unitySliceScale?: number;
168
+
169
+ // Transform
170
+ /** Rotation transform. Pass a C# Rotate struct. */
171
+ rotate?: any;
172
+ /** Scale transform. Pass a C# Scale struct. */
173
+ scale?: any;
174
+ /** Translation transform. Pass a C# Translate struct. */
175
+ translate?: any;
176
+ /** Transform origin point. Pass a C# TransformOrigin struct. */
177
+ transformOrigin?: any;
178
+
179
+ // Transition
180
+ /** Delay before transitions start. Pass a C# StyleList. */
181
+ transitionDelay?: any;
182
+ /** Duration of transitions. Pass a C# StyleList. */
183
+ transitionDuration?: any;
184
+ /** Properties to transition. Pass a C# StyleList. */
185
+ transitionProperty?: any;
186
+ /** Timing functions for transitions. Pass a C# StyleList. */
187
+ transitionTimingFunction?: any;
188
+
189
+ // Other
190
+ /** Overflow clipping box */
191
+ unityOverflowClipBox?: 'padding-box' | 'content-box';
192
+ /** Cursor style. Pass a C# Cursor struct. */
193
+ cursor?: any;
130
194
  }
131
195
 
132
196
  // Event types