@simonklee/yoga 0.2.24

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/dist/index.js ADDED
@@ -0,0 +1,1502 @@
1
+ import { dlopen, suffix, JSCallback, FFIType } from "bun:ffi";
2
+ import { join } from "path";
3
+ import { existsSync } from "fs";
4
+ // Import native libraries with { type: "file" } for bun compile support
5
+ // This tells Bun to embed the file and return a real filesystem path
6
+ // Using top-level await import() to load only the current platform's library
7
+ const embeddedLib = await (async () => {
8
+ try {
9
+ if (process.platform === "darwin" && process.arch === "arm64") {
10
+ // @ts-ignore
11
+ return (await import("../dist/darwin-arm64/libyoga.dylib", { with: { type: "file" } })).default;
12
+ }
13
+ else if (process.platform === "darwin" && process.arch === "x64") {
14
+ // @ts-ignore
15
+ return (await import("../dist/darwin-x64/libyoga.dylib", { with: { type: "file" } })).default;
16
+ }
17
+ else if (process.platform === "linux" && process.arch === "x64") {
18
+ // @ts-ignore
19
+ return (await import("../dist/linux-x64/libyoga.so", { with: { type: "file" } })).default;
20
+ }
21
+ else if (process.platform === "linux" && process.arch === "arm64") {
22
+ // @ts-ignore
23
+ return (await import("../dist/linux-arm64/libyoga.so", { with: { type: "file" } })).default;
24
+ }
25
+ else if (process.platform === "win32") {
26
+ // @ts-ignore
27
+ return (await import("../dist/windows-x64/yoga.dll", { with: { type: "file" } })).default;
28
+ }
29
+ }
30
+ catch {
31
+ // Library not found for this platform
32
+ }
33
+ return undefined;
34
+ })();
35
+ function getLibPath() {
36
+ // Check local development path (zig-out) first for development
37
+ if (process.platform === "win32") {
38
+ if (existsSync(join(__dirname, "..", "zig-out", "lib", `yoga.${suffix}`))) {
39
+ return join(__dirname, "..", "zig-out", "lib", `yoga.${suffix}`);
40
+ }
41
+ if (existsSync(join(__dirname, "..", "zig-out", "bin", `yoga.${suffix}`))) {
42
+ return join(__dirname, "..", "zig-out", "bin", `yoga.${suffix}`);
43
+ }
44
+ }
45
+ else {
46
+ if (existsSync(join(__dirname, "..", "zig-out", "lib", `libyoga.${suffix}`))) {
47
+ return join(__dirname, "..", "zig-out", "lib", `libyoga.${suffix}`);
48
+ }
49
+ }
50
+ // Check embedded libraries (for bun compile)
51
+ if (embeddedLib && existsSync(embeddedLib)) {
52
+ return embeddedLib;
53
+ }
54
+ throw new Error(`Could not find native library. ` +
55
+ `Platform: ${process.platform}-${process.arch}\n` +
56
+ `Make sure to run 'zig build' or install the package with binaries.`);
57
+ }
58
+ // Yoga enum definitions
59
+ export const Align = {
60
+ Auto: 0,
61
+ FlexStart: 1,
62
+ Center: 2,
63
+ FlexEnd: 3,
64
+ Stretch: 4,
65
+ Baseline: 5,
66
+ SpaceBetween: 6,
67
+ SpaceAround: 7,
68
+ SpaceEvenly: 8,
69
+ };
70
+ export const BoxSizing = {
71
+ BorderBox: 0,
72
+ ContentBox: 1,
73
+ };
74
+ export const Dimension = {
75
+ Width: 0,
76
+ Height: 1,
77
+ };
78
+ export const Direction = {
79
+ Inherit: 0,
80
+ LTR: 1,
81
+ RTL: 2,
82
+ };
83
+ export const Display = {
84
+ Flex: 0,
85
+ None: 1,
86
+ Contents: 2,
87
+ };
88
+ export const Edge = {
89
+ Left: 0,
90
+ Top: 1,
91
+ Right: 2,
92
+ Bottom: 3,
93
+ Start: 4,
94
+ End: 5,
95
+ Horizontal: 6,
96
+ Vertical: 7,
97
+ All: 8,
98
+ };
99
+ export const Errata = {
100
+ None: 0,
101
+ StretchFlexBasis: 1,
102
+ AbsolutePositionWithoutInsetsExcludesPadding: 2,
103
+ AbsolutePercentAgainstInnerSize: 4,
104
+ All: 2147483647,
105
+ Classic: 2147483646,
106
+ };
107
+ export const ExperimentalFeature = {
108
+ WebFlexBasis: 0,
109
+ };
110
+ export const FlexDirection = {
111
+ Column: 0,
112
+ ColumnReverse: 1,
113
+ Row: 2,
114
+ RowReverse: 3,
115
+ };
116
+ export const Gutter = {
117
+ Column: 0,
118
+ Row: 1,
119
+ All: 2,
120
+ };
121
+ export const Justify = {
122
+ FlexStart: 0,
123
+ Center: 1,
124
+ FlexEnd: 2,
125
+ SpaceBetween: 3,
126
+ SpaceAround: 4,
127
+ SpaceEvenly: 5,
128
+ };
129
+ export const LogLevel = {
130
+ Error: 0,
131
+ Warn: 1,
132
+ Info: 2,
133
+ Debug: 3,
134
+ Verbose: 4,
135
+ Fatal: 5,
136
+ };
137
+ export const MeasureMode = {
138
+ Undefined: 0,
139
+ Exactly: 1,
140
+ AtMost: 2,
141
+ };
142
+ export const NodeType = {
143
+ Default: 0,
144
+ Text: 1,
145
+ };
146
+ export const Overflow = {
147
+ Visible: 0,
148
+ Hidden: 1,
149
+ Scroll: 2,
150
+ };
151
+ export const PositionType = {
152
+ Static: 0,
153
+ Relative: 1,
154
+ Absolute: 2,
155
+ };
156
+ export const Unit = {
157
+ Undefined: 0,
158
+ Point: 1,
159
+ Percent: 2,
160
+ Auto: 3,
161
+ MaxContent: 4,
162
+ FitContent: 5,
163
+ Stretch: 6,
164
+ };
165
+ export const Wrap = {
166
+ NoWrap: 0,
167
+ Wrap: 1,
168
+ WrapReverse: 2,
169
+ };
170
+ // Constants for yoga-layout compatibility
171
+ export const EDGE_LEFT = Edge.Left;
172
+ export const EDGE_TOP = Edge.Top;
173
+ export const EDGE_RIGHT = Edge.Right;
174
+ export const EDGE_BOTTOM = Edge.Bottom;
175
+ export const EDGE_START = Edge.Start;
176
+ export const EDGE_END = Edge.End;
177
+ export const EDGE_HORIZONTAL = Edge.Horizontal;
178
+ export const EDGE_VERTICAL = Edge.Vertical;
179
+ export const EDGE_ALL = Edge.All;
180
+ export const GUTTER_COLUMN = Gutter.Column;
181
+ export const GUTTER_ROW = Gutter.Row;
182
+ export const GUTTER_ALL = Gutter.All;
183
+ export const FLEX_DIRECTION_COLUMN = FlexDirection.Column;
184
+ export const FLEX_DIRECTION_COLUMN_REVERSE = FlexDirection.ColumnReverse;
185
+ export const FLEX_DIRECTION_ROW = FlexDirection.Row;
186
+ export const FLEX_DIRECTION_ROW_REVERSE = FlexDirection.RowReverse;
187
+ export const JUSTIFY_FLEX_START = Justify.FlexStart;
188
+ export const JUSTIFY_CENTER = Justify.Center;
189
+ export const JUSTIFY_FLEX_END = Justify.FlexEnd;
190
+ export const JUSTIFY_SPACE_BETWEEN = Justify.SpaceBetween;
191
+ export const JUSTIFY_SPACE_AROUND = Justify.SpaceAround;
192
+ export const JUSTIFY_SPACE_EVENLY = Justify.SpaceEvenly;
193
+ export const ALIGN_AUTO = Align.Auto;
194
+ export const ALIGN_FLEX_START = Align.FlexStart;
195
+ export const ALIGN_CENTER = Align.Center;
196
+ export const ALIGN_FLEX_END = Align.FlexEnd;
197
+ export const ALIGN_STRETCH = Align.Stretch;
198
+ export const ALIGN_BASELINE = Align.Baseline;
199
+ export const ALIGN_SPACE_BETWEEN = Align.SpaceBetween;
200
+ export const ALIGN_SPACE_AROUND = Align.SpaceAround;
201
+ export const ALIGN_SPACE_EVENLY = Align.SpaceEvenly;
202
+ export const WRAP_NO_WRAP = Wrap.NoWrap;
203
+ export const WRAP_WRAP = Wrap.Wrap;
204
+ export const WRAP_WRAP_REVERSE = Wrap.WrapReverse;
205
+ export const OVERFLOW_VISIBLE = Overflow.Visible;
206
+ export const OVERFLOW_HIDDEN = Overflow.Hidden;
207
+ export const OVERFLOW_SCROLL = Overflow.Scroll;
208
+ export const DISPLAY_FLEX = Display.Flex;
209
+ export const DISPLAY_NONE = Display.None;
210
+ export const DISPLAY_CONTENTS = Display.Contents;
211
+ export const BOX_SIZING_BORDER_BOX = BoxSizing.BorderBox;
212
+ export const BOX_SIZING_CONTENT_BOX = BoxSizing.ContentBox;
213
+ export const DIMENSION_WIDTH = Dimension.Width;
214
+ export const DIMENSION_HEIGHT = Dimension.Height;
215
+ export const POSITION_TYPE_STATIC = PositionType.Static;
216
+ export const POSITION_TYPE_RELATIVE = PositionType.Relative;
217
+ export const POSITION_TYPE_ABSOLUTE = PositionType.Absolute;
218
+ export const DIRECTION_INHERIT = Direction.Inherit;
219
+ export const DIRECTION_LTR = Direction.LTR;
220
+ export const DIRECTION_RTL = Direction.RTL;
221
+ export const UNIT_UNDEFINED = Unit.Undefined;
222
+ export const UNIT_POINT = Unit.Point;
223
+ export const UNIT_PERCENT = Unit.Percent;
224
+ export const UNIT_AUTO = Unit.Auto;
225
+ export const UNIT_MAX_CONTENT = Unit.MaxContent;
226
+ export const UNIT_FIT_CONTENT = Unit.FitContent;
227
+ export const UNIT_STRETCH = Unit.Stretch;
228
+ export const MEASURE_MODE_UNDEFINED = MeasureMode.Undefined;
229
+ export const MEASURE_MODE_EXACTLY = MeasureMode.Exactly;
230
+ export const MEASURE_MODE_AT_MOST = MeasureMode.AtMost;
231
+ export const NODE_TYPE_DEFAULT = NodeType.Default;
232
+ export const NODE_TYPE_TEXT = NodeType.Text;
233
+ export const LOG_LEVEL_ERROR = LogLevel.Error;
234
+ export const LOG_LEVEL_WARN = LogLevel.Warn;
235
+ export const LOG_LEVEL_INFO = LogLevel.Info;
236
+ export const LOG_LEVEL_DEBUG = LogLevel.Debug;
237
+ export const LOG_LEVEL_VERBOSE = LogLevel.Verbose;
238
+ export const LOG_LEVEL_FATAL = LogLevel.Fatal;
239
+ export const EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS = ExperimentalFeature.WebFlexBasis;
240
+ export const ERRATA_NONE = Errata.None;
241
+ export const ERRATA_STRETCH_FLEX_BASIS = Errata.StretchFlexBasis;
242
+ export const ERRATA_ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING = Errata.AbsolutePositionWithoutInsetsExcludesPadding;
243
+ export const ERRATA_ABSOLUTE_PERCENT_AGAINST_INNER_SIZE = Errata.AbsolutePercentAgainstInnerSize;
244
+ export const ERRATA_ALL = Errata.All;
245
+ export const ERRATA_CLASSIC = Errata.Classic;
246
+ function parseValue(value) {
247
+ if (value === undefined) {
248
+ return { unit: Unit.Undefined, asNumber: undefined };
249
+ }
250
+ if (value === "auto") {
251
+ return { unit: Unit.Auto, asNumber: undefined };
252
+ }
253
+ if (typeof value === "string" && value.endsWith("%")) {
254
+ return { unit: Unit.Percent, asNumber: parseFloat(value) };
255
+ }
256
+ return { unit: Unit.Point, asNumber: value };
257
+ }
258
+ // Default value for freed nodes (matches yoga-layout behavior)
259
+ const UNDEFINED_VALUE = { unit: Unit.Undefined, value: NaN };
260
+ // Helper to unpack Value from u64 (lower 32 bits = unit, upper 32 bits = value as f32 bits)
261
+ function unpackValue(packed) {
262
+ const p = BigInt(packed);
263
+ const unit = Number(p & 0xffffffffn);
264
+ const valueBits = Number((p >> 32n) & 0xffffffffn);
265
+ // Convert u32 bits back to f32
266
+ const buffer = new ArrayBuffer(4);
267
+ const view = new DataView(buffer);
268
+ view.setUint32(0, valueBits, true);
269
+ const value = view.getFloat32(0, true);
270
+ return { unit, value };
271
+ }
272
+ // Load the library
273
+ const lib = dlopen(getLibPath(), {
274
+ // Config functions
275
+ ygConfigNew: { args: [], returns: "ptr" },
276
+ ygConfigFree: { args: ["ptr"], returns: "void" },
277
+ ygConfigGetDefault: { args: [], returns: "ptr" },
278
+ ygConfigSetUseWebDefaults: { args: ["ptr", "bool"], returns: "void" },
279
+ ygConfigGetUseWebDefaults: { args: ["ptr"], returns: "bool" },
280
+ ygConfigSetPointScaleFactor: { args: ["ptr", "f32"], returns: "void" },
281
+ ygConfigGetPointScaleFactor: { args: ["ptr"], returns: "f32" },
282
+ ygConfigSetErrata: { args: ["ptr", "i32"], returns: "void" },
283
+ ygConfigGetErrata: { args: ["ptr"], returns: "i32" },
284
+ ygConfigSetExperimentalFeatureEnabled: {
285
+ args: ["ptr", "i32", "bool"],
286
+ returns: "void",
287
+ },
288
+ ygConfigIsExperimentalFeatureEnabled: {
289
+ args: ["ptr", "i32"],
290
+ returns: "bool",
291
+ },
292
+ // Node creation and management
293
+ ygNodeNew: { args: [], returns: "ptr" },
294
+ ygNodeNewWithConfig: { args: ["ptr"], returns: "ptr" },
295
+ ygNodeClone: { args: ["ptr"], returns: "ptr" },
296
+ ygNodeFree: { args: ["ptr"], returns: "void" },
297
+ ygNodeFreeRecursive: { args: ["ptr"], returns: "void" },
298
+ ygNodeReset: { args: ["ptr"], returns: "void" },
299
+ ygNodeCopyStyle: { args: ["ptr", "ptr"], returns: "void" },
300
+ ygNodeSetIsReferenceBaseline: { args: ["ptr", "bool"], returns: "void" },
301
+ ygNodeIsReferenceBaseline: { args: ["ptr"], returns: "bool" },
302
+ ygNodeSetAlwaysFormsContainingBlock: {
303
+ args: ["ptr", "bool"],
304
+ returns: "void",
305
+ },
306
+ // Node hierarchy management
307
+ ygNodeInsertChild: { args: ["ptr", "ptr", "u64"], returns: "void" },
308
+ ygNodeRemoveChild: { args: ["ptr", "ptr"], returns: "void" },
309
+ ygNodeRemoveAllChildren: { args: ["ptr"], returns: "void" },
310
+ ygNodeGetChild: { args: ["ptr", "u64"], returns: "ptr" },
311
+ ygNodeGetChildCount: { args: ["ptr"], returns: "u64" },
312
+ ygNodeGetParent: { args: ["ptr"], returns: "ptr" },
313
+ // Layout calculation
314
+ ygNodeCalculateLayout: { args: ["ptr", "f32", "f32", "i32"], returns: "void" },
315
+ ygNodeGetHasNewLayout: { args: ["ptr"], returns: "bool" },
316
+ ygNodeSetHasNewLayout: { args: ["ptr", "bool"], returns: "void" },
317
+ ygNodeMarkDirty: { args: ["ptr"], returns: "void" },
318
+ ygNodeIsDirty: { args: ["ptr"], returns: "bool" },
319
+ // Layout result access
320
+ ygNodeLayoutGetLeft: { args: ["ptr"], returns: "f32" },
321
+ ygNodeLayoutGetTop: { args: ["ptr"], returns: "f32" },
322
+ ygNodeLayoutGetRight: { args: ["ptr"], returns: "f32" },
323
+ ygNodeLayoutGetBottom: { args: ["ptr"], returns: "f32" },
324
+ ygNodeLayoutGetWidth: { args: ["ptr"], returns: "f32" },
325
+ ygNodeLayoutGetHeight: { args: ["ptr"], returns: "f32" },
326
+ ygNodeLayoutGetBorder: { args: ["ptr", "i32"], returns: "f32" },
327
+ ygNodeLayoutGetMargin: { args: ["ptr", "i32"], returns: "f32" },
328
+ ygNodeLayoutGetPadding: { args: ["ptr", "i32"], returns: "f32" },
329
+ ygNodeLayoutGetRawWidth: { args: ["ptr"], returns: "f32" },
330
+ ygNodeLayoutGetRawHeight: { args: ["ptr"], returns: "f32" },
331
+ // Style properties - Layout
332
+ ygNodeStyleSetDirection: { args: ["ptr", "i32"], returns: "void" },
333
+ ygNodeStyleGetDirection: { args: ["ptr"], returns: "i32" },
334
+ ygNodeStyleSetFlexDirection: { args: ["ptr", "i32"], returns: "void" },
335
+ ygNodeStyleGetFlexDirection: { args: ["ptr"], returns: "i32" },
336
+ ygNodeStyleSetJustifyContent: { args: ["ptr", "i32"], returns: "void" },
337
+ ygNodeStyleGetJustifyContent: { args: ["ptr"], returns: "i32" },
338
+ ygNodeStyleSetAlignContent: { args: ["ptr", "i32"], returns: "void" },
339
+ ygNodeStyleGetAlignContent: { args: ["ptr"], returns: "i32" },
340
+ ygNodeStyleSetAlignItems: { args: ["ptr", "i32"], returns: "void" },
341
+ ygNodeStyleGetAlignItems: { args: ["ptr"], returns: "i32" },
342
+ ygNodeStyleSetAlignSelf: { args: ["ptr", "i32"], returns: "void" },
343
+ ygNodeStyleGetAlignSelf: { args: ["ptr"], returns: "i32" },
344
+ ygNodeStyleSetPositionType: { args: ["ptr", "i32"], returns: "void" },
345
+ ygNodeStyleGetPositionType: { args: ["ptr"], returns: "i32" },
346
+ ygNodeStyleSetFlexWrap: { args: ["ptr", "i32"], returns: "void" },
347
+ ygNodeStyleGetFlexWrap: { args: ["ptr"], returns: "i32" },
348
+ ygNodeStyleSetOverflow: { args: ["ptr", "i32"], returns: "void" },
349
+ ygNodeStyleGetOverflow: { args: ["ptr"], returns: "i32" },
350
+ ygNodeStyleSetDisplay: { args: ["ptr", "i32"], returns: "void" },
351
+ ygNodeStyleGetDisplay: { args: ["ptr"], returns: "i32" },
352
+ ygNodeStyleSetBoxSizing: { args: ["ptr", "i32"], returns: "void" },
353
+ ygNodeStyleGetBoxSizing: { args: ["ptr"], returns: "i32" },
354
+ // Style properties - Flex
355
+ ygNodeStyleSetFlex: { args: ["ptr", "f32"], returns: "void" },
356
+ ygNodeStyleGetFlex: { args: ["ptr"], returns: "f32" },
357
+ ygNodeStyleSetFlexGrow: { args: ["ptr", "f32"], returns: "void" },
358
+ ygNodeStyleGetFlexGrow: { args: ["ptr"], returns: "f32" },
359
+ ygNodeStyleSetFlexShrink: { args: ["ptr", "f32"], returns: "void" },
360
+ ygNodeStyleGetFlexShrink: { args: ["ptr"], returns: "f32" },
361
+ ygNodeStyleSetFlexBasis: { args: ["ptr", "f32"], returns: "void" },
362
+ ygNodeStyleSetFlexBasisPercent: { args: ["ptr", "f32"], returns: "void" },
363
+ ygNodeStyleSetFlexBasisAuto: { args: ["ptr"], returns: "void" },
364
+ ygNodeStyleSetFlexBasisMaxContent: { args: ["ptr"], returns: "void" },
365
+ ygNodeStyleSetFlexBasisFitContent: { args: ["ptr"], returns: "void" },
366
+ ygNodeStyleSetFlexBasisStretch: { args: ["ptr"], returns: "void" },
367
+ // Style properties - Position
368
+ ygNodeStyleSetPosition: { args: ["ptr", "i32", "f32"], returns: "void" },
369
+ ygNodeStyleSetPositionPercent: { args: ["ptr", "i32", "f32"], returns: "void" },
370
+ ygNodeStyleSetPositionAuto: { args: ["ptr", "i32"], returns: "void" },
371
+ // Style properties - Margin
372
+ ygNodeStyleSetMargin: { args: ["ptr", "i32", "f32"], returns: "void" },
373
+ ygNodeStyleSetMarginPercent: { args: ["ptr", "i32", "f32"], returns: "void" },
374
+ ygNodeStyleSetMarginAuto: { args: ["ptr", "i32"], returns: "void" },
375
+ // Style properties - Padding
376
+ ygNodeStyleSetPadding: { args: ["ptr", "i32", "f32"], returns: "void" },
377
+ ygNodeStyleSetPaddingPercent: { args: ["ptr", "i32", "f32"], returns: "void" },
378
+ // Style properties - Border
379
+ ygNodeStyleSetBorder: { args: ["ptr", "i32", "f32"], returns: "void" },
380
+ ygNodeStyleGetBorder: { args: ["ptr", "i32"], returns: "f32" },
381
+ // Style properties - Gap
382
+ ygNodeStyleSetGap: { args: ["ptr", "i32", "f32"], returns: "void" },
383
+ ygNodeStyleSetGapPercent: { args: ["ptr", "i32", "f32"], returns: "void" },
384
+ // Style properties - Size
385
+ ygNodeStyleSetWidth: { args: ["ptr", "f32"], returns: "void" },
386
+ ygNodeStyleSetWidthPercent: { args: ["ptr", "f32"], returns: "void" },
387
+ ygNodeStyleSetWidthAuto: { args: ["ptr"], returns: "void" },
388
+ ygNodeStyleSetWidthMaxContent: { args: ["ptr"], returns: "void" },
389
+ ygNodeStyleSetWidthFitContent: { args: ["ptr"], returns: "void" },
390
+ ygNodeStyleSetWidthStretch: { args: ["ptr"], returns: "void" },
391
+ ygNodeStyleSetHeight: { args: ["ptr", "f32"], returns: "void" },
392
+ ygNodeStyleSetHeightPercent: { args: ["ptr", "f32"], returns: "void" },
393
+ ygNodeStyleSetHeightAuto: { args: ["ptr"], returns: "void" },
394
+ ygNodeStyleSetHeightMaxContent: { args: ["ptr"], returns: "void" },
395
+ ygNodeStyleSetHeightFitContent: { args: ["ptr"], returns: "void" },
396
+ ygNodeStyleSetHeightStretch: { args: ["ptr"], returns: "void" },
397
+ ygNodeStyleSetMinWidth: { args: ["ptr", "f32"], returns: "void" },
398
+ ygNodeStyleSetMinWidthPercent: { args: ["ptr", "f32"], returns: "void" },
399
+ ygNodeStyleSetMinWidthMaxContent: { args: ["ptr"], returns: "void" },
400
+ ygNodeStyleSetMinWidthFitContent: { args: ["ptr"], returns: "void" },
401
+ ygNodeStyleSetMinWidthStretch: { args: ["ptr"], returns: "void" },
402
+ ygNodeStyleSetMinHeight: { args: ["ptr", "f32"], returns: "void" },
403
+ ygNodeStyleSetMinHeightPercent: { args: ["ptr", "f32"], returns: "void" },
404
+ ygNodeStyleSetMinHeightMaxContent: { args: ["ptr"], returns: "void" },
405
+ ygNodeStyleSetMinHeightFitContent: { args: ["ptr"], returns: "void" },
406
+ ygNodeStyleSetMinHeightStretch: { args: ["ptr"], returns: "void" },
407
+ ygNodeStyleSetMaxWidth: { args: ["ptr", "f32"], returns: "void" },
408
+ ygNodeStyleSetMaxWidthPercent: { args: ["ptr", "f32"], returns: "void" },
409
+ ygNodeStyleSetMaxWidthMaxContent: { args: ["ptr"], returns: "void" },
410
+ ygNodeStyleSetMaxWidthFitContent: { args: ["ptr"], returns: "void" },
411
+ ygNodeStyleSetMaxWidthStretch: { args: ["ptr"], returns: "void" },
412
+ ygNodeStyleSetMaxHeight: { args: ["ptr", "f32"], returns: "void" },
413
+ ygNodeStyleSetMaxHeightPercent: { args: ["ptr", "f32"], returns: "void" },
414
+ ygNodeStyleSetMaxHeightMaxContent: { args: ["ptr"], returns: "void" },
415
+ ygNodeStyleSetMaxHeightFitContent: { args: ["ptr"], returns: "void" },
416
+ ygNodeStyleSetMaxHeightStretch: { args: ["ptr"], returns: "void" },
417
+ // Style properties - Aspect Ratio
418
+ ygNodeStyleSetAspectRatio: { args: ["ptr", "f32"], returns: "void" },
419
+ ygNodeStyleGetAspectRatio: { args: ["ptr"], returns: "f32" },
420
+ // Node context
421
+ ygNodeSetContext: { args: ["ptr", "ptr"], returns: "void" },
422
+ ygNodeGetContext: { args: ["ptr"], returns: "ptr" },
423
+ // Callback functions
424
+ ygNodeSetMeasureFunc: { args: ["ptr", "ptr"], returns: "void" },
425
+ ygNodeUnsetMeasureFunc: { args: ["ptr"], returns: "void" },
426
+ ygNodeHasMeasureFunc: { args: ["ptr"], returns: "bool" },
427
+ ygNodeSetBaselineFunc: { args: ["ptr", "ptr"], returns: "void" },
428
+ ygNodeUnsetBaselineFunc: { args: ["ptr"], returns: "void" },
429
+ ygNodeHasBaselineFunc: { args: ["ptr"], returns: "bool" },
430
+ ygNodeSetDirtiedFunc: { args: ["ptr", "ptr"], returns: "void" },
431
+ ygNodeUnsetDirtiedFunc: { args: ["ptr"], returns: "void" },
432
+ ygNodeGetDirtiedFunc: { args: ["ptr"], returns: "ptr" },
433
+ // Callback helper functions
434
+ ygCreateSize: { args: ["f32", "f32"], returns: "u64" },
435
+ ygStoreMeasureResult: { args: ["f32", "f32"], returns: "void" },
436
+ ygStoreBaselineResult: { args: ["f32"], returns: "void" },
437
+ ygNodeSetMeasureFuncTrampoline: { args: ["ptr", "ptr"], returns: "void" },
438
+ ygNodeUnsetMeasureFuncTrampoline: { args: ["ptr"], returns: "void" },
439
+ ygNodeSetBaselineFuncTrampoline: { args: ["ptr", "ptr"], returns: "void" },
440
+ ygNodeUnsetBaselineFuncTrampoline: { args: ["ptr"], returns: "void" },
441
+ ygNodeFreeCallbacks: { args: ["ptr"], returns: "void" },
442
+ // Value getters (packed: lower 32 bits = unit, upper 32 bits = value)
443
+ ygNodeStyleGetWidthPacked: { args: ["ptr"], returns: "u64" },
444
+ ygNodeStyleGetHeightPacked: { args: ["ptr"], returns: "u64" },
445
+ ygNodeStyleGetMinWidthPacked: { args: ["ptr"], returns: "u64" },
446
+ ygNodeStyleGetMinHeightPacked: { args: ["ptr"], returns: "u64" },
447
+ ygNodeStyleGetMaxWidthPacked: { args: ["ptr"], returns: "u64" },
448
+ ygNodeStyleGetMaxHeightPacked: { args: ["ptr"], returns: "u64" },
449
+ ygNodeStyleGetMarginPacked: { args: ["ptr", "i32"], returns: "u64" },
450
+ ygNodeStyleGetPaddingPacked: { args: ["ptr", "i32"], returns: "u64" },
451
+ ygNodeStyleGetPositionPacked: { args: ["ptr", "i32"], returns: "u64" },
452
+ ygNodeStyleGetGapPacked: { args: ["ptr", "i32"], returns: "u64" },
453
+ ygNodeStyleGetFlexBasisPacked: { args: ["ptr"], returns: "u64" },
454
+ });
455
+ const yg = lib.symbols;
456
+ // ============================================================================
457
+ // Node class - yoga-layout compatible API
458
+ // ============================================================================
459
+ export class Node {
460
+ ptr;
461
+ _freed = false;
462
+ measureCallback = null;
463
+ baselineCallback = null;
464
+ dirtiedCallback = null;
465
+ constructor(ptr) {
466
+ this.ptr = ptr;
467
+ }
468
+ /** Check if the node has been freed */
469
+ isFreed() {
470
+ return this._freed;
471
+ }
472
+ static create(config) {
473
+ const ptr = config
474
+ ? yg.ygNodeNewWithConfig(config["ptr"])
475
+ : yg.ygNodeNew();
476
+ if (!ptr)
477
+ throw new Error("Failed to create node");
478
+ return new Node(ptr);
479
+ }
480
+ static createDefault() {
481
+ return Node.create();
482
+ }
483
+ static createWithConfig(config) {
484
+ return Node.create(config);
485
+ }
486
+ static destroy(node) {
487
+ node.free();
488
+ }
489
+ free() {
490
+ if (this._freed)
491
+ return; // Already freed, no-op
492
+ // Clean up callbacks before freeing the node
493
+ this.unsetMeasureFunc();
494
+ this.unsetBaselineFunc();
495
+ this.unsetDirtiedFunc();
496
+ yg.ygNodeFree(this.ptr);
497
+ this._freed = true;
498
+ }
499
+ freeRecursive() {
500
+ if (this._freed)
501
+ return; // Already freed, no-op
502
+ // Clean up this node's callbacks before freeing
503
+ // Note: Child nodes' JSCallback objects are not tracked here - if you have
504
+ // references to child Node objects, their callbacks become invalid after this call
505
+ this.cleanupCallbacks();
506
+ yg.ygNodeFreeRecursive(this.ptr);
507
+ this._freed = true;
508
+ }
509
+ reset() {
510
+ if (this._freed)
511
+ return;
512
+ // Clean up callbacks before reset since reset clears all state
513
+ this.cleanupCallbacks();
514
+ yg.ygNodeReset(this.ptr);
515
+ }
516
+ /** Internal helper to close JSCallback objects without calling native unset functions */
517
+ cleanupCallbacks() {
518
+ if (this.measureCallback) {
519
+ this.measureCallback.close();
520
+ this.measureCallback = null;
521
+ }
522
+ if (this.baselineCallback) {
523
+ this.baselineCallback.close();
524
+ this.baselineCallback = null;
525
+ }
526
+ if (this.dirtiedCallback) {
527
+ this.dirtiedCallback.close();
528
+ this.dirtiedCallback = null;
529
+ }
530
+ }
531
+ clone() {
532
+ if (this._freed)
533
+ throw new Error("Cannot clone freed node");
534
+ const ptr = yg.ygNodeClone(this.ptr);
535
+ if (!ptr)
536
+ throw new Error("Failed to clone node");
537
+ return new Node(ptr);
538
+ }
539
+ copyStyle(node) {
540
+ if (this._freed)
541
+ return;
542
+ yg.ygNodeCopyStyle(this.ptr, node.ptr);
543
+ }
544
+ setIsReferenceBaseline(isReferenceBaseline) {
545
+ if (this._freed)
546
+ return;
547
+ yg.ygNodeSetIsReferenceBaseline(this.ptr, isReferenceBaseline);
548
+ }
549
+ isReferenceBaseline() {
550
+ if (this._freed)
551
+ return false;
552
+ return yg.ygNodeIsReferenceBaseline(this.ptr);
553
+ }
554
+ setAlwaysFormsContainingBlock(alwaysFormsContainingBlock) {
555
+ if (this._freed)
556
+ return;
557
+ yg.ygNodeSetAlwaysFormsContainingBlock(this.ptr, alwaysFormsContainingBlock);
558
+ }
559
+ // Hierarchy
560
+ insertChild(child, index) {
561
+ if (this._freed)
562
+ return;
563
+ yg.ygNodeInsertChild(this.ptr, child.ptr, index);
564
+ }
565
+ removeChild(child) {
566
+ if (this._freed)
567
+ return;
568
+ yg.ygNodeRemoveChild(this.ptr, child.ptr);
569
+ }
570
+ removeAllChildren() {
571
+ if (this._freed)
572
+ return;
573
+ yg.ygNodeRemoveAllChildren(this.ptr);
574
+ }
575
+ getChild(index) {
576
+ if (this._freed)
577
+ return null;
578
+ const ptr = yg.ygNodeGetChild(this.ptr, index);
579
+ return ptr ? new Node(ptr) : null;
580
+ }
581
+ getChildCount() {
582
+ if (this._freed)
583
+ return 0;
584
+ return Number(yg.ygNodeGetChildCount(this.ptr));
585
+ }
586
+ getParent() {
587
+ if (this._freed)
588
+ return null;
589
+ const ptr = yg.ygNodeGetParent(this.ptr);
590
+ return ptr ? new Node(ptr) : null;
591
+ }
592
+ // Layout
593
+ calculateLayout(width, height, direction = Direction.LTR) {
594
+ if (this._freed)
595
+ return;
596
+ const w = width === "auto" || width === undefined ? NaN : width;
597
+ const h = height === "auto" || height === undefined ? NaN : height;
598
+ yg.ygNodeCalculateLayout(this.ptr, w, h, direction);
599
+ }
600
+ hasNewLayout() {
601
+ if (this._freed)
602
+ return false;
603
+ return yg.ygNodeGetHasNewLayout(this.ptr);
604
+ }
605
+ markLayoutSeen() {
606
+ if (this._freed)
607
+ return;
608
+ yg.ygNodeSetHasNewLayout(this.ptr, false);
609
+ }
610
+ markDirty() {
611
+ if (this._freed)
612
+ return;
613
+ yg.ygNodeMarkDirty(this.ptr);
614
+ }
615
+ isDirty() {
616
+ if (this._freed)
617
+ return true; // yoga-layout returns true for freed nodes
618
+ return yg.ygNodeIsDirty(this.ptr);
619
+ }
620
+ // Layout results
621
+ getComputedLayout() {
622
+ if (this._freed)
623
+ return { left: 0, top: 0, right: 0, bottom: 0, width: 0, height: 0 };
624
+ return {
625
+ left: yg.ygNodeLayoutGetLeft(this.ptr),
626
+ top: yg.ygNodeLayoutGetTop(this.ptr),
627
+ right: yg.ygNodeLayoutGetRight(this.ptr),
628
+ bottom: yg.ygNodeLayoutGetBottom(this.ptr),
629
+ width: yg.ygNodeLayoutGetWidth(this.ptr),
630
+ height: yg.ygNodeLayoutGetHeight(this.ptr),
631
+ };
632
+ }
633
+ getComputedLeft() {
634
+ if (this._freed)
635
+ return 0;
636
+ return yg.ygNodeLayoutGetLeft(this.ptr);
637
+ }
638
+ getComputedTop() {
639
+ if (this._freed)
640
+ return 0;
641
+ return yg.ygNodeLayoutGetTop(this.ptr);
642
+ }
643
+ getComputedRight() {
644
+ if (this._freed)
645
+ return 0;
646
+ return yg.ygNodeLayoutGetRight(this.ptr);
647
+ }
648
+ getComputedBottom() {
649
+ if (this._freed)
650
+ return 0;
651
+ return yg.ygNodeLayoutGetBottom(this.ptr);
652
+ }
653
+ getComputedWidth() {
654
+ if (this._freed)
655
+ return 0;
656
+ return yg.ygNodeLayoutGetWidth(this.ptr);
657
+ }
658
+ getComputedHeight() {
659
+ if (this._freed)
660
+ return 0;
661
+ return yg.ygNodeLayoutGetHeight(this.ptr);
662
+ }
663
+ getComputedRawWidth() {
664
+ if (this._freed)
665
+ return 0;
666
+ return yg.ygNodeLayoutGetRawWidth(this.ptr);
667
+ }
668
+ getComputedRawHeight() {
669
+ if (this._freed)
670
+ return 0;
671
+ return yg.ygNodeLayoutGetRawHeight(this.ptr);
672
+ }
673
+ getComputedBorder(edge) {
674
+ if (this._freed)
675
+ return 0;
676
+ return yg.ygNodeLayoutGetBorder(this.ptr, edge);
677
+ }
678
+ getComputedMargin(edge) {
679
+ if (this._freed)
680
+ return 0;
681
+ return yg.ygNodeLayoutGetMargin(this.ptr, edge);
682
+ }
683
+ getComputedPadding(edge) {
684
+ if (this._freed)
685
+ return 0;
686
+ return yg.ygNodeLayoutGetPadding(this.ptr, edge);
687
+ }
688
+ // Style setters
689
+ setDirection(direction) {
690
+ if (this._freed)
691
+ return;
692
+ yg.ygNodeStyleSetDirection(this.ptr, direction);
693
+ }
694
+ getDirection() {
695
+ if (this._freed)
696
+ return Direction.Inherit;
697
+ return yg.ygNodeStyleGetDirection(this.ptr);
698
+ }
699
+ setFlexDirection(flexDirection) {
700
+ if (this._freed)
701
+ return;
702
+ yg.ygNodeStyleSetFlexDirection(this.ptr, flexDirection);
703
+ }
704
+ getFlexDirection() {
705
+ if (this._freed)
706
+ return FlexDirection.Column;
707
+ return yg.ygNodeStyleGetFlexDirection(this.ptr);
708
+ }
709
+ setJustifyContent(justifyContent) {
710
+ if (this._freed)
711
+ return;
712
+ yg.ygNodeStyleSetJustifyContent(this.ptr, justifyContent);
713
+ }
714
+ getJustifyContent() {
715
+ if (this._freed)
716
+ return Justify.FlexStart;
717
+ return yg.ygNodeStyleGetJustifyContent(this.ptr);
718
+ }
719
+ setAlignContent(alignContent) {
720
+ if (this._freed)
721
+ return;
722
+ yg.ygNodeStyleSetAlignContent(this.ptr, alignContent);
723
+ }
724
+ getAlignContent() {
725
+ if (this._freed)
726
+ return Align.Auto;
727
+ return yg.ygNodeStyleGetAlignContent(this.ptr);
728
+ }
729
+ setAlignItems(alignItems) {
730
+ if (this._freed)
731
+ return;
732
+ yg.ygNodeStyleSetAlignItems(this.ptr, alignItems);
733
+ }
734
+ getAlignItems() {
735
+ if (this._freed)
736
+ return Align.Auto;
737
+ return yg.ygNodeStyleGetAlignItems(this.ptr);
738
+ }
739
+ setAlignSelf(alignSelf) {
740
+ if (this._freed)
741
+ return;
742
+ yg.ygNodeStyleSetAlignSelf(this.ptr, alignSelf);
743
+ }
744
+ getAlignSelf() {
745
+ if (this._freed)
746
+ return Align.Auto;
747
+ return yg.ygNodeStyleGetAlignSelf(this.ptr);
748
+ }
749
+ setPositionType(positionType) {
750
+ if (this._freed)
751
+ return;
752
+ yg.ygNodeStyleSetPositionType(this.ptr, positionType);
753
+ }
754
+ getPositionType() {
755
+ if (this._freed)
756
+ return PositionType.Static;
757
+ return yg.ygNodeStyleGetPositionType(this.ptr);
758
+ }
759
+ setFlexWrap(flexWrap) {
760
+ if (this._freed)
761
+ return;
762
+ yg.ygNodeStyleSetFlexWrap(this.ptr, flexWrap);
763
+ }
764
+ getFlexWrap() {
765
+ if (this._freed)
766
+ return Wrap.NoWrap;
767
+ return yg.ygNodeStyleGetFlexWrap(this.ptr);
768
+ }
769
+ setOverflow(overflow) {
770
+ if (this._freed)
771
+ return;
772
+ yg.ygNodeStyleSetOverflow(this.ptr, overflow);
773
+ }
774
+ getOverflow() {
775
+ if (this._freed)
776
+ return Overflow.Visible;
777
+ return yg.ygNodeStyleGetOverflow(this.ptr);
778
+ }
779
+ setDisplay(display) {
780
+ if (this._freed)
781
+ return;
782
+ yg.ygNodeStyleSetDisplay(this.ptr, display);
783
+ }
784
+ getDisplay() {
785
+ if (this._freed)
786
+ return Display.Flex;
787
+ return yg.ygNodeStyleGetDisplay(this.ptr);
788
+ }
789
+ setBoxSizing(boxSizing) {
790
+ if (this._freed)
791
+ return;
792
+ yg.ygNodeStyleSetBoxSizing(this.ptr, boxSizing);
793
+ }
794
+ getBoxSizing() {
795
+ if (this._freed)
796
+ return BoxSizing.BorderBox;
797
+ return yg.ygNodeStyleGetBoxSizing(this.ptr);
798
+ }
799
+ setFlex(flex) {
800
+ if (this._freed)
801
+ return;
802
+ yg.ygNodeStyleSetFlex(this.ptr, flex);
803
+ }
804
+ getFlex() {
805
+ if (this._freed)
806
+ return NaN;
807
+ return yg.ygNodeStyleGetFlex(this.ptr);
808
+ }
809
+ setFlexGrow(flexGrow) {
810
+ if (this._freed)
811
+ return;
812
+ yg.ygNodeStyleSetFlexGrow(this.ptr, flexGrow);
813
+ }
814
+ getFlexGrow() {
815
+ if (this._freed)
816
+ return NaN;
817
+ return yg.ygNodeStyleGetFlexGrow(this.ptr);
818
+ }
819
+ setFlexShrink(flexShrink) {
820
+ if (this._freed)
821
+ return;
822
+ yg.ygNodeStyleSetFlexShrink(this.ptr, flexShrink);
823
+ }
824
+ getFlexShrink() {
825
+ if (this._freed)
826
+ return NaN;
827
+ return yg.ygNodeStyleGetFlexShrink(this.ptr);
828
+ }
829
+ setFlexBasis(flexBasis) {
830
+ if (this._freed)
831
+ return;
832
+ const { unit, asNumber } = parseValue(flexBasis);
833
+ if (unit === Unit.Auto) {
834
+ yg.ygNodeStyleSetFlexBasisAuto(this.ptr);
835
+ }
836
+ else if (unit === Unit.Percent) {
837
+ yg.ygNodeStyleSetFlexBasisPercent(this.ptr, asNumber);
838
+ }
839
+ else if (unit === Unit.Point && asNumber !== undefined) {
840
+ yg.ygNodeStyleSetFlexBasis(this.ptr, asNumber);
841
+ }
842
+ }
843
+ setFlexBasisPercent(flexBasis) {
844
+ if (this._freed)
845
+ return;
846
+ if (flexBasis !== undefined) {
847
+ yg.ygNodeStyleSetFlexBasisPercent(this.ptr, flexBasis);
848
+ }
849
+ }
850
+ setFlexBasisAuto() {
851
+ if (this._freed)
852
+ return;
853
+ yg.ygNodeStyleSetFlexBasisAuto(this.ptr);
854
+ }
855
+ setFlexBasisMaxContent() {
856
+ if (this._freed)
857
+ return;
858
+ yg.ygNodeStyleSetFlexBasisMaxContent(this.ptr);
859
+ }
860
+ setFlexBasisFitContent() {
861
+ if (this._freed)
862
+ return;
863
+ yg.ygNodeStyleSetFlexBasisFitContent(this.ptr);
864
+ }
865
+ setFlexBasisStretch() {
866
+ if (this._freed)
867
+ return;
868
+ yg.ygNodeStyleSetFlexBasisStretch(this.ptr);
869
+ }
870
+ setPosition(edge, position) {
871
+ if (this._freed)
872
+ return;
873
+ const { unit, asNumber } = parseValue(position);
874
+ if (unit === Unit.Percent) {
875
+ yg.ygNodeStyleSetPositionPercent(this.ptr, edge, asNumber);
876
+ }
877
+ else if (unit === Unit.Point && asNumber !== undefined) {
878
+ yg.ygNodeStyleSetPosition(this.ptr, edge, asNumber);
879
+ }
880
+ }
881
+ setPositionPercent(edge, position) {
882
+ if (this._freed)
883
+ return;
884
+ if (position !== undefined) {
885
+ yg.ygNodeStyleSetPositionPercent(this.ptr, edge, position);
886
+ }
887
+ }
888
+ setPositionAuto(edge) {
889
+ if (this._freed)
890
+ return;
891
+ yg.ygNodeStyleSetPositionAuto(this.ptr, edge);
892
+ }
893
+ setMargin(edge, margin) {
894
+ if (this._freed)
895
+ return;
896
+ const { unit, asNumber } = parseValue(margin);
897
+ if (unit === Unit.Auto) {
898
+ yg.ygNodeStyleSetMarginAuto(this.ptr, edge);
899
+ }
900
+ else if (unit === Unit.Percent) {
901
+ yg.ygNodeStyleSetMarginPercent(this.ptr, edge, asNumber);
902
+ }
903
+ else if (unit === Unit.Point && asNumber !== undefined) {
904
+ yg.ygNodeStyleSetMargin(this.ptr, edge, asNumber);
905
+ }
906
+ }
907
+ setMarginPercent(edge, margin) {
908
+ if (this._freed)
909
+ return;
910
+ if (margin !== undefined) {
911
+ yg.ygNodeStyleSetMarginPercent(this.ptr, edge, margin);
912
+ }
913
+ }
914
+ setMarginAuto(edge) {
915
+ if (this._freed)
916
+ return;
917
+ yg.ygNodeStyleSetMarginAuto(this.ptr, edge);
918
+ }
919
+ setPadding(edge, padding) {
920
+ if (this._freed)
921
+ return;
922
+ const { unit, asNumber } = parseValue(padding);
923
+ if (unit === Unit.Percent) {
924
+ yg.ygNodeStyleSetPaddingPercent(this.ptr, edge, asNumber);
925
+ }
926
+ else if (unit === Unit.Point && asNumber !== undefined) {
927
+ yg.ygNodeStyleSetPadding(this.ptr, edge, asNumber);
928
+ }
929
+ }
930
+ setPaddingPercent(edge, padding) {
931
+ if (this._freed)
932
+ return;
933
+ if (padding !== undefined) {
934
+ yg.ygNodeStyleSetPaddingPercent(this.ptr, edge, padding);
935
+ }
936
+ }
937
+ setBorder(edge, border) {
938
+ if (this._freed)
939
+ return;
940
+ if (border !== undefined) {
941
+ yg.ygNodeStyleSetBorder(this.ptr, edge, border);
942
+ }
943
+ }
944
+ getBorder(edge) {
945
+ if (this._freed)
946
+ return NaN;
947
+ return yg.ygNodeStyleGetBorder(this.ptr, edge);
948
+ }
949
+ setGap(gutter, gap) {
950
+ if (this._freed)
951
+ return;
952
+ const { unit, asNumber } = parseValue(gap);
953
+ if (unit === Unit.Percent) {
954
+ yg.ygNodeStyleSetGapPercent(this.ptr, gutter, asNumber);
955
+ }
956
+ else if (unit === Unit.Point && asNumber !== undefined) {
957
+ yg.ygNodeStyleSetGap(this.ptr, gutter, asNumber);
958
+ }
959
+ }
960
+ setGapPercent(gutter, gap) {
961
+ if (this._freed)
962
+ return;
963
+ if (gap !== undefined) {
964
+ yg.ygNodeStyleSetGapPercent(this.ptr, gutter, gap);
965
+ }
966
+ }
967
+ setWidth(width) {
968
+ if (this._freed)
969
+ return;
970
+ const { unit, asNumber } = parseValue(width);
971
+ if (unit === Unit.Auto) {
972
+ yg.ygNodeStyleSetWidthAuto(this.ptr);
973
+ }
974
+ else if (unit === Unit.Percent) {
975
+ yg.ygNodeStyleSetWidthPercent(this.ptr, asNumber);
976
+ }
977
+ else if (unit === Unit.Point && asNumber !== undefined) {
978
+ yg.ygNodeStyleSetWidth(this.ptr, asNumber);
979
+ }
980
+ }
981
+ setWidthPercent(width) {
982
+ if (this._freed)
983
+ return;
984
+ if (width !== undefined) {
985
+ yg.ygNodeStyleSetWidthPercent(this.ptr, width);
986
+ }
987
+ }
988
+ setWidthAuto() {
989
+ if (this._freed)
990
+ return;
991
+ yg.ygNodeStyleSetWidthAuto(this.ptr);
992
+ }
993
+ setWidthMaxContent() {
994
+ if (this._freed)
995
+ return;
996
+ yg.ygNodeStyleSetWidthMaxContent(this.ptr);
997
+ }
998
+ setWidthFitContent() {
999
+ if (this._freed)
1000
+ return;
1001
+ yg.ygNodeStyleSetWidthFitContent(this.ptr);
1002
+ }
1003
+ setWidthStretch() {
1004
+ if (this._freed)
1005
+ return;
1006
+ yg.ygNodeStyleSetWidthStretch(this.ptr);
1007
+ }
1008
+ setHeight(height) {
1009
+ if (this._freed)
1010
+ return;
1011
+ const { unit, asNumber } = parseValue(height);
1012
+ if (unit === Unit.Auto) {
1013
+ yg.ygNodeStyleSetHeightAuto(this.ptr);
1014
+ }
1015
+ else if (unit === Unit.Percent) {
1016
+ yg.ygNodeStyleSetHeightPercent(this.ptr, asNumber);
1017
+ }
1018
+ else if (unit === Unit.Point && asNumber !== undefined) {
1019
+ yg.ygNodeStyleSetHeight(this.ptr, asNumber);
1020
+ }
1021
+ }
1022
+ setHeightPercent(height) {
1023
+ if (this._freed)
1024
+ return;
1025
+ if (height !== undefined) {
1026
+ yg.ygNodeStyleSetHeightPercent(this.ptr, height);
1027
+ }
1028
+ }
1029
+ setHeightAuto() {
1030
+ if (this._freed)
1031
+ return;
1032
+ yg.ygNodeStyleSetHeightAuto(this.ptr);
1033
+ }
1034
+ setHeightMaxContent() {
1035
+ if (this._freed)
1036
+ return;
1037
+ yg.ygNodeStyleSetHeightMaxContent(this.ptr);
1038
+ }
1039
+ setHeightFitContent() {
1040
+ if (this._freed)
1041
+ return;
1042
+ yg.ygNodeStyleSetHeightFitContent(this.ptr);
1043
+ }
1044
+ setHeightStretch() {
1045
+ if (this._freed)
1046
+ return;
1047
+ yg.ygNodeStyleSetHeightStretch(this.ptr);
1048
+ }
1049
+ setMinWidth(minWidth) {
1050
+ if (this._freed)
1051
+ return;
1052
+ const { unit, asNumber } = parseValue(minWidth);
1053
+ if (unit === Unit.Percent) {
1054
+ yg.ygNodeStyleSetMinWidthPercent(this.ptr, asNumber);
1055
+ }
1056
+ else if (unit === Unit.Point && asNumber !== undefined) {
1057
+ yg.ygNodeStyleSetMinWidth(this.ptr, asNumber);
1058
+ }
1059
+ }
1060
+ setMinWidthPercent(minWidth) {
1061
+ if (this._freed)
1062
+ return;
1063
+ if (minWidth !== undefined) {
1064
+ yg.ygNodeStyleSetMinWidthPercent(this.ptr, minWidth);
1065
+ }
1066
+ }
1067
+ setMinWidthMaxContent() {
1068
+ if (this._freed)
1069
+ return;
1070
+ yg.ygNodeStyleSetMinWidthMaxContent(this.ptr);
1071
+ }
1072
+ setMinWidthFitContent() {
1073
+ if (this._freed)
1074
+ return;
1075
+ yg.ygNodeStyleSetMinWidthFitContent(this.ptr);
1076
+ }
1077
+ setMinWidthStretch() {
1078
+ if (this._freed)
1079
+ return;
1080
+ yg.ygNodeStyleSetMinWidthStretch(this.ptr);
1081
+ }
1082
+ setMinHeight(minHeight) {
1083
+ if (this._freed)
1084
+ return;
1085
+ const { unit, asNumber } = parseValue(minHeight);
1086
+ if (unit === Unit.Percent) {
1087
+ yg.ygNodeStyleSetMinHeightPercent(this.ptr, asNumber);
1088
+ }
1089
+ else if (unit === Unit.Point && asNumber !== undefined) {
1090
+ yg.ygNodeStyleSetMinHeight(this.ptr, asNumber);
1091
+ }
1092
+ }
1093
+ setMinHeightPercent(minHeight) {
1094
+ if (this._freed)
1095
+ return;
1096
+ if (minHeight !== undefined) {
1097
+ yg.ygNodeStyleSetMinHeightPercent(this.ptr, minHeight);
1098
+ }
1099
+ }
1100
+ setMinHeightMaxContent() {
1101
+ if (this._freed)
1102
+ return;
1103
+ yg.ygNodeStyleSetMinHeightMaxContent(this.ptr);
1104
+ }
1105
+ setMinHeightFitContent() {
1106
+ if (this._freed)
1107
+ return;
1108
+ yg.ygNodeStyleSetMinHeightFitContent(this.ptr);
1109
+ }
1110
+ setMinHeightStretch() {
1111
+ if (this._freed)
1112
+ return;
1113
+ yg.ygNodeStyleSetMinHeightStretch(this.ptr);
1114
+ }
1115
+ setMaxWidth(maxWidth) {
1116
+ if (this._freed)
1117
+ return;
1118
+ const { unit, asNumber } = parseValue(maxWidth);
1119
+ if (unit === Unit.Percent) {
1120
+ yg.ygNodeStyleSetMaxWidthPercent(this.ptr, asNumber);
1121
+ }
1122
+ else if (unit === Unit.Point && asNumber !== undefined) {
1123
+ yg.ygNodeStyleSetMaxWidth(this.ptr, asNumber);
1124
+ }
1125
+ }
1126
+ setMaxWidthPercent(maxWidth) {
1127
+ if (this._freed)
1128
+ return;
1129
+ if (maxWidth !== undefined) {
1130
+ yg.ygNodeStyleSetMaxWidthPercent(this.ptr, maxWidth);
1131
+ }
1132
+ }
1133
+ setMaxWidthMaxContent() {
1134
+ if (this._freed)
1135
+ return;
1136
+ yg.ygNodeStyleSetMaxWidthMaxContent(this.ptr);
1137
+ }
1138
+ setMaxWidthFitContent() {
1139
+ if (this._freed)
1140
+ return;
1141
+ yg.ygNodeStyleSetMaxWidthFitContent(this.ptr);
1142
+ }
1143
+ setMaxWidthStretch() {
1144
+ if (this._freed)
1145
+ return;
1146
+ yg.ygNodeStyleSetMaxWidthStretch(this.ptr);
1147
+ }
1148
+ setMaxHeight(maxHeight) {
1149
+ if (this._freed)
1150
+ return;
1151
+ const { unit, asNumber } = parseValue(maxHeight);
1152
+ if (unit === Unit.Percent) {
1153
+ yg.ygNodeStyleSetMaxHeightPercent(this.ptr, asNumber);
1154
+ }
1155
+ else if (unit === Unit.Point && asNumber !== undefined) {
1156
+ yg.ygNodeStyleSetMaxHeight(this.ptr, asNumber);
1157
+ }
1158
+ }
1159
+ setMaxHeightPercent(maxHeight) {
1160
+ if (this._freed)
1161
+ return;
1162
+ if (maxHeight !== undefined) {
1163
+ yg.ygNodeStyleSetMaxHeightPercent(this.ptr, maxHeight);
1164
+ }
1165
+ }
1166
+ setMaxHeightMaxContent() {
1167
+ if (this._freed)
1168
+ return;
1169
+ yg.ygNodeStyleSetMaxHeightMaxContent(this.ptr);
1170
+ }
1171
+ setMaxHeightFitContent() {
1172
+ if (this._freed)
1173
+ return;
1174
+ yg.ygNodeStyleSetMaxHeightFitContent(this.ptr);
1175
+ }
1176
+ setMaxHeightStretch() {
1177
+ if (this._freed)
1178
+ return;
1179
+ yg.ygNodeStyleSetMaxHeightStretch(this.ptr);
1180
+ }
1181
+ setAspectRatio(aspectRatio) {
1182
+ if (this._freed)
1183
+ return;
1184
+ if (aspectRatio !== undefined) {
1185
+ yg.ygNodeStyleSetAspectRatio(this.ptr, aspectRatio);
1186
+ }
1187
+ }
1188
+ getAspectRatio() {
1189
+ if (this._freed)
1190
+ return NaN;
1191
+ return yg.ygNodeStyleGetAspectRatio(this.ptr);
1192
+ }
1193
+ // Value getters (return {unit, value} like yoga-layout)
1194
+ getWidth() {
1195
+ if (this._freed)
1196
+ return UNDEFINED_VALUE;
1197
+ return unpackValue(yg.ygNodeStyleGetWidthPacked(this.ptr));
1198
+ }
1199
+ getHeight() {
1200
+ if (this._freed)
1201
+ return UNDEFINED_VALUE;
1202
+ return unpackValue(yg.ygNodeStyleGetHeightPacked(this.ptr));
1203
+ }
1204
+ getMinWidth() {
1205
+ if (this._freed)
1206
+ return UNDEFINED_VALUE;
1207
+ return unpackValue(yg.ygNodeStyleGetMinWidthPacked(this.ptr));
1208
+ }
1209
+ getMinHeight() {
1210
+ if (this._freed)
1211
+ return UNDEFINED_VALUE;
1212
+ return unpackValue(yg.ygNodeStyleGetMinHeightPacked(this.ptr));
1213
+ }
1214
+ getMaxWidth() {
1215
+ if (this._freed)
1216
+ return UNDEFINED_VALUE;
1217
+ return unpackValue(yg.ygNodeStyleGetMaxWidthPacked(this.ptr));
1218
+ }
1219
+ getMaxHeight() {
1220
+ if (this._freed)
1221
+ return UNDEFINED_VALUE;
1222
+ return unpackValue(yg.ygNodeStyleGetMaxHeightPacked(this.ptr));
1223
+ }
1224
+ getMargin(edge) {
1225
+ if (this._freed)
1226
+ return UNDEFINED_VALUE;
1227
+ return unpackValue(yg.ygNodeStyleGetMarginPacked(this.ptr, edge));
1228
+ }
1229
+ getPadding(edge) {
1230
+ if (this._freed)
1231
+ return UNDEFINED_VALUE;
1232
+ return unpackValue(yg.ygNodeStyleGetPaddingPacked(this.ptr, edge));
1233
+ }
1234
+ getPosition(edge) {
1235
+ if (this._freed)
1236
+ return UNDEFINED_VALUE;
1237
+ return unpackValue(yg.ygNodeStyleGetPositionPacked(this.ptr, edge));
1238
+ }
1239
+ getGap(gutter) {
1240
+ if (this._freed)
1241
+ return UNDEFINED_VALUE;
1242
+ return unpackValue(yg.ygNodeStyleGetGapPacked(this.ptr, gutter));
1243
+ }
1244
+ getFlexBasis() {
1245
+ if (this._freed)
1246
+ return UNDEFINED_VALUE;
1247
+ return unpackValue(yg.ygNodeStyleGetFlexBasisPacked(this.ptr));
1248
+ }
1249
+ // Callback functions
1250
+ setMeasureFunc(measureFunc) {
1251
+ if (this._freed)
1252
+ return;
1253
+ this.unsetMeasureFunc(); // Clean up existing callback
1254
+ if (measureFunc) {
1255
+ // Use trampoline approach to work around ARM64 ABI limitations
1256
+ // The trampoline doesn't return the result directly - instead it stores
1257
+ // the result via ygStoreMeasureResult, and our Zig wrapper reads it
1258
+ this.measureCallback = new JSCallback((nodePtr, width, widthMode, height, heightMode) => {
1259
+ const result = measureFunc(width, widthMode, height, heightMode);
1260
+ // Store the result for the Zig wrapper to read
1261
+ yg.ygStoreMeasureResult(result.width, result.height);
1262
+ }, {
1263
+ args: [
1264
+ FFIType.ptr,
1265
+ FFIType.f32,
1266
+ FFIType.u32,
1267
+ FFIType.f32,
1268
+ FFIType.u32,
1269
+ ],
1270
+ returns: FFIType.void,
1271
+ });
1272
+ if (this.measureCallback.ptr) {
1273
+ yg.ygNodeSetMeasureFuncTrampoline(this.ptr, this.measureCallback.ptr);
1274
+ }
1275
+ }
1276
+ }
1277
+ unsetMeasureFunc() {
1278
+ if (this._freed)
1279
+ return; // Skip if already freed
1280
+ if (this.measureCallback) {
1281
+ this.measureCallback.close();
1282
+ this.measureCallback = null;
1283
+ }
1284
+ yg.ygNodeUnsetMeasureFuncTrampoline(this.ptr);
1285
+ }
1286
+ hasMeasureFunc() {
1287
+ if (this._freed)
1288
+ return false;
1289
+ return yg.ygNodeHasMeasureFunc(this.ptr);
1290
+ }
1291
+ setBaselineFunc(baselineFunc) {
1292
+ if (this._freed)
1293
+ return;
1294
+ this.unsetBaselineFunc(); // Clean up existing callback
1295
+ if (baselineFunc) {
1296
+ // Use trampoline approach to work around ARM64 ABI limitations
1297
+ // The trampoline stores the result via ygStoreBaselineResult
1298
+ this.baselineCallback = new JSCallback((nodePtr, width, height) => {
1299
+ const result = baselineFunc(width, height);
1300
+ yg.ygStoreBaselineResult(result);
1301
+ }, {
1302
+ args: [FFIType.ptr, FFIType.f32, FFIType.f32],
1303
+ returns: FFIType.void,
1304
+ });
1305
+ if (this.baselineCallback.ptr) {
1306
+ yg.ygNodeSetBaselineFuncTrampoline(this.ptr, this.baselineCallback.ptr);
1307
+ }
1308
+ }
1309
+ }
1310
+ unsetBaselineFunc() {
1311
+ if (this._freed)
1312
+ return; // Skip if already freed
1313
+ if (this.baselineCallback) {
1314
+ this.baselineCallback.close();
1315
+ this.baselineCallback = null;
1316
+ }
1317
+ yg.ygNodeUnsetBaselineFuncTrampoline(this.ptr);
1318
+ }
1319
+ hasBaselineFunc() {
1320
+ if (this._freed)
1321
+ return false;
1322
+ return yg.ygNodeHasBaselineFunc(this.ptr);
1323
+ }
1324
+ setDirtiedFunc(dirtiedFunc) {
1325
+ if (this._freed)
1326
+ return;
1327
+ this.unsetDirtiedFunc(); // Clean up existing callback
1328
+ if (dirtiedFunc) {
1329
+ // Capture this node instance for the callback
1330
+ const node = this;
1331
+ // Create a JSCallback that matches Yoga's expected dirtied function signature
1332
+ this.dirtiedCallback = new JSCallback((nodePtr) => {
1333
+ dirtiedFunc(node);
1334
+ }, {
1335
+ args: [FFIType.ptr],
1336
+ returns: FFIType.void,
1337
+ });
1338
+ if (this.dirtiedCallback.ptr) {
1339
+ yg.ygNodeSetDirtiedFunc(this.ptr, this.dirtiedCallback.ptr);
1340
+ }
1341
+ }
1342
+ }
1343
+ unsetDirtiedFunc() {
1344
+ if (this._freed)
1345
+ return; // Skip if already freed
1346
+ if (this.dirtiedCallback) {
1347
+ this.dirtiedCallback.close();
1348
+ this.dirtiedCallback = null;
1349
+ }
1350
+ yg.ygNodeUnsetDirtiedFunc(this.ptr);
1351
+ }
1352
+ hasDirtiedFunc() {
1353
+ if (this._freed)
1354
+ return false;
1355
+ return Boolean(yg.ygNodeGetDirtiedFunc(this.ptr));
1356
+ }
1357
+ }
1358
+ // ============================================================================
1359
+ // Config class
1360
+ // ============================================================================
1361
+ export class Config {
1362
+ ptr;
1363
+ constructor(ptr) {
1364
+ this.ptr = ptr;
1365
+ }
1366
+ static create() {
1367
+ const ptr = yg.ygConfigNew();
1368
+ if (!ptr)
1369
+ throw new Error("Failed to create config");
1370
+ return new Config(ptr);
1371
+ }
1372
+ static destroy(config) {
1373
+ config.free();
1374
+ }
1375
+ free() {
1376
+ yg.ygConfigFree(this.ptr);
1377
+ }
1378
+ setUseWebDefaults(useWebDefaults) {
1379
+ yg.ygConfigSetUseWebDefaults(this.ptr, useWebDefaults);
1380
+ }
1381
+ useWebDefaults() {
1382
+ return yg.ygConfigGetUseWebDefaults(this.ptr);
1383
+ }
1384
+ setPointScaleFactor(pointScaleFactor) {
1385
+ yg.ygConfigSetPointScaleFactor(this.ptr, pointScaleFactor);
1386
+ }
1387
+ getPointScaleFactor() {
1388
+ return yg.ygConfigGetPointScaleFactor(this.ptr);
1389
+ }
1390
+ setErrata(errata) {
1391
+ yg.ygConfigSetErrata(this.ptr, errata);
1392
+ }
1393
+ getErrata() {
1394
+ return yg.ygConfigGetErrata(this.ptr);
1395
+ }
1396
+ setExperimentalFeatureEnabled(feature, enabled) {
1397
+ yg.ygConfigSetExperimentalFeatureEnabled(this.ptr, feature, enabled);
1398
+ }
1399
+ isExperimentalFeatureEnabled(feature) {
1400
+ return yg.ygConfigIsExperimentalFeatureEnabled(this.ptr, feature);
1401
+ }
1402
+ }
1403
+ // Default export for yoga-layout compatibility
1404
+ export default {
1405
+ Node,
1406
+ Config,
1407
+ // Enums
1408
+ Align,
1409
+ BoxSizing,
1410
+ Dimension,
1411
+ Direction,
1412
+ Display,
1413
+ Edge,
1414
+ Errata,
1415
+ ExperimentalFeature,
1416
+ FlexDirection,
1417
+ Gutter,
1418
+ Justify,
1419
+ LogLevel,
1420
+ MeasureMode,
1421
+ NodeType,
1422
+ Overflow,
1423
+ PositionType,
1424
+ Unit,
1425
+ Wrap,
1426
+ // Constants
1427
+ EDGE_LEFT,
1428
+ EDGE_TOP,
1429
+ EDGE_RIGHT,
1430
+ EDGE_BOTTOM,
1431
+ EDGE_START,
1432
+ EDGE_END,
1433
+ EDGE_HORIZONTAL,
1434
+ EDGE_VERTICAL,
1435
+ EDGE_ALL,
1436
+ FLEX_DIRECTION_COLUMN,
1437
+ FLEX_DIRECTION_COLUMN_REVERSE,
1438
+ FLEX_DIRECTION_ROW,
1439
+ FLEX_DIRECTION_ROW_REVERSE,
1440
+ JUSTIFY_FLEX_START,
1441
+ JUSTIFY_CENTER,
1442
+ JUSTIFY_FLEX_END,
1443
+ JUSTIFY_SPACE_BETWEEN,
1444
+ JUSTIFY_SPACE_AROUND,
1445
+ JUSTIFY_SPACE_EVENLY,
1446
+ ALIGN_AUTO,
1447
+ ALIGN_FLEX_START,
1448
+ ALIGN_CENTER,
1449
+ ALIGN_FLEX_END,
1450
+ ALIGN_STRETCH,
1451
+ ALIGN_BASELINE,
1452
+ ALIGN_SPACE_BETWEEN,
1453
+ ALIGN_SPACE_AROUND,
1454
+ ALIGN_SPACE_EVENLY,
1455
+ WRAP_NO_WRAP,
1456
+ WRAP_WRAP,
1457
+ WRAP_WRAP_REVERSE,
1458
+ OVERFLOW_VISIBLE,
1459
+ OVERFLOW_HIDDEN,
1460
+ OVERFLOW_SCROLL,
1461
+ DISPLAY_FLEX,
1462
+ DISPLAY_NONE,
1463
+ DISPLAY_CONTENTS,
1464
+ POSITION_TYPE_STATIC,
1465
+ POSITION_TYPE_RELATIVE,
1466
+ POSITION_TYPE_ABSOLUTE,
1467
+ DIRECTION_INHERIT,
1468
+ DIRECTION_LTR,
1469
+ DIRECTION_RTL,
1470
+ BOX_SIZING_BORDER_BOX,
1471
+ BOX_SIZING_CONTENT_BOX,
1472
+ DIMENSION_WIDTH,
1473
+ DIMENSION_HEIGHT,
1474
+ GUTTER_COLUMN,
1475
+ GUTTER_ROW,
1476
+ GUTTER_ALL,
1477
+ UNIT_UNDEFINED,
1478
+ UNIT_POINT,
1479
+ UNIT_PERCENT,
1480
+ UNIT_AUTO,
1481
+ UNIT_MAX_CONTENT,
1482
+ UNIT_FIT_CONTENT,
1483
+ UNIT_STRETCH,
1484
+ MEASURE_MODE_UNDEFINED,
1485
+ MEASURE_MODE_EXACTLY,
1486
+ MEASURE_MODE_AT_MOST,
1487
+ NODE_TYPE_DEFAULT,
1488
+ NODE_TYPE_TEXT,
1489
+ LOG_LEVEL_ERROR,
1490
+ LOG_LEVEL_WARN,
1491
+ LOG_LEVEL_INFO,
1492
+ LOG_LEVEL_DEBUG,
1493
+ LOG_LEVEL_VERBOSE,
1494
+ LOG_LEVEL_FATAL,
1495
+ EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS,
1496
+ ERRATA_NONE,
1497
+ ERRATA_STRETCH_FLEX_BASIS,
1498
+ ERRATA_ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING,
1499
+ ERRATA_ABSOLUTE_PERCENT_AGAINST_INNER_SIZE,
1500
+ ERRATA_ALL,
1501
+ ERRATA_CLASSIC,
1502
+ };