taffy-js 0.1.3 → 0.2.0

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/README.md CHANGED
@@ -1,19 +1,19 @@
1
- # Taffy WebAssembly Bindings
1
+ # Taffy-JS: WebAssembly Bindings for Taffy Layout Engine
2
2
 
3
3
  > **High-performance Flexbox and CSS Grid layout for JavaScript/TypeScript, powered by Rust and WebAssembly.**
4
4
 
5
5
  ![License](https://img.shields.io/npm/l/taffy-js?style=flat-square) ![Version](https://img.shields.io/npm/v/taffy-js?style=flat-square) ![WASM](https://img.shields.io/badge/platform-wasm-blueviolet?style=flat-square)
6
6
 
7
- **Taffy** is a generic, high-performance UI layout library written in Rust. This package (`taffy-js`) provides WebAssembly bindings, allowing you to use Taffy's standards-compliant Flexbox and Grid algorithms directly in your web or Node.js applications with near-native performance.
7
+ **Taffy** is a high-performance UI layout library written in Rust. This package (`taffy-js`) provides WebAssembly bindings, enabling JavaScript/TypeScript applications to use standards-compliant Flexbox, CSS Grid, and Block layout algorithms with near-native performance.
8
8
 
9
9
  ## ✨ Features
10
10
 
11
- - **🚀 High Performance**: Leverages the speed of Rust and WebAssembly for complex layout computations.
12
- - **📦 Tiny Footprint**: Highly optimized WASM binary size.
13
- - **🎨 Modern Layouts**: Full support for **Flexbox** and **CSS Grid** specifications.
14
- - **🛠 Framework Agnostic**: Use it with React, Vue, Svelte, vanilla JS, or even in Node.js for server-side layout calculation.
15
- - **🔒 Type-Safe**: Fully typed API with TypeScript definitions included.
16
- - **🐛 Debug Mode**: Optional verbose logging for debugging layout issues.
11
+ - 🚀 **High Performance** Rust + WebAssembly for complex layout computations
12
+ - 📦 **Tiny Footprint** Optimized WASM binary size
13
+ - 🎨 **Modern Layouts** Full Flexbox, CSS Grid, and Block layout support
14
+ - 🛠 **Framework Agnostic** Works with React, Vue, Svelte, vanilla JS, Node.js
15
+ - 🔒 **Type-Safe** Full TypeScript definitions included
16
+ - 📐 **Custom Measurement** Support for text measurement via callback functions
17
17
 
18
18
  ## 📦 Installation
19
19
 
@@ -21,415 +21,463 @@
21
21
  npm install taffy-js
22
22
  ```
23
23
 
24
- > **Note**: This package relies on WebAssembly. Ensure your runtime (modern browser or Node.js) supports WASM.
24
+ > **Note**: Requires a runtime that supports WebAssembly (all modern browsers and Node.js 12+).
25
25
 
26
26
  ## 🚀 Quick Start
27
27
 
28
- ### Functional API
29
-
30
28
  ```typescript
31
29
  import init, {
32
- new_leaf,
33
- new_with_children,
34
- compute_layout,
35
- get_layout,
30
+ TaffyTree,
31
+ Style,
36
32
  Display,
37
33
  FlexDirection,
38
34
  AlignItems,
39
35
  JustifyContent,
40
36
  } from "taffy-js";
41
37
 
42
- async function run() {
43
- // 1. Initialize the WASM module
38
+ async function main() {
39
+ // 1. Initialize WASM module
44
40
  await init();
45
41
 
46
- // 2. Define Styles
47
- const boxStyle = {
48
- display: Display.Flex,
49
- width: { value: 100, unit: "Pixels" },
50
- height: { value: 100, unit: "Pixels" },
51
- justify_content: JustifyContent.Center,
52
- align_items: AlignItems.Center,
53
- };
54
-
55
- const rootStyle = {
56
- display: Display.Flex,
57
- width: { value: 500, unit: "Pixels" },
58
- height: { value: 500, unit: "Pixels" },
59
- flex_direction: FlexDirection.Row,
60
- justify_content: JustifyContent.SpaceAround,
61
- align_items: AlignItems.Center,
62
- };
63
-
64
- // 3. Create Tree Nodes
65
- const child1 = new_leaf(boxStyle);
66
- const child2 = new_leaf(boxStyle);
67
- const root = new_with_children(rootStyle, [child1, child2]);
68
-
69
- // 4. Compute Layout
70
- compute_layout(root, { width: 500, height: 500 });
71
-
72
- // 5. Retrieve Results
73
- const rootLayout = get_layout(root);
74
- const child1Layout = get_layout(child1);
75
- const child2Layout = get_layout(child2);
76
-
77
- console.log("Root:", rootLayout); // { x: 0, y: 0, width: 500, height: 500 }
78
- console.log("Child 1:", child1Layout); // { x: ..., y: ..., width: 100, height: 100 }
79
- console.log("Child 2:", child2Layout); // { x: ..., y: ..., width: 100, height: 100 }
42
+ // 2. Create tree and styles
43
+ const tree = new TaffyTree();
44
+
45
+ const rootStyle = new Style();
46
+ rootStyle.display = Display.Flex;
47
+ rootStyle.flex_direction = FlexDirection.Row;
48
+ rootStyle.justify_content = JustifyContent.SpaceAround;
49
+ rootStyle.align_items = AlignItems.Center;
50
+ rootStyle.size = { width: { Length: 500 }, height: { Length: 400 } };
51
+
52
+ const childStyle = new Style();
53
+ childStyle.size = { width: { Length: 100 }, height: { Length: 100 } };
54
+
55
+ // 3. Build the tree
56
+ const child1 = tree.newLeaf(childStyle);
57
+ const child2 = tree.newLeaf(childStyle);
58
+ const root = tree.newWithChildren(rootStyle, [child1, child2]);
59
+
60
+ // 4. Compute layout
61
+ tree.computeLayout(root, {
62
+ width: { Definite: 500 },
63
+ height: { Definite: 400 },
64
+ });
65
+
66
+ // 5. Read results
67
+ console.log("Root:", tree.getLayout(root));
68
+ console.log("Child 1:", tree.getLayout(child1));
69
+ console.log("Child 2:", tree.getLayout(child2));
80
70
  }
81
71
 
82
- run();
72
+ main();
83
73
  ```
84
74
 
85
- ### Object-Oriented API (Yoga-like)
75
+ ## 📐 Architecture
86
76
 
87
- The library also provides an OO wrapper for a more intuitive, Yoga-style experience:
77
+ The library is organized into four main components:
88
78
 
89
- ```typescript
90
- import init, {
91
- TaffyNode,
92
- Display,
93
- FlexDirection,
94
- Edge,
95
- Gutter,
96
- } from "taffy-js";
79
+ | Component | Description |
80
+ | :------------ | :------------------------------------------------------------------------------------ |
81
+ | **Enums** | CSS layout enum types (Display, Position, FlexDirection, FlexWrap, AlignItems, etc.) |
82
+ | **DTOs** | Data Transfer Objects for JS ↔ Rust serialization (JsDimension, JsSize, JsRect, etc.) |
83
+ | **Style** | Node style configuration with getter/setter methods for all CSS layout properties |
84
+ | **TaffyTree** | Layout tree manager for node creation, tree manipulation, and layout computation |
97
85
 
98
- async function run() {
99
- await init();
86
+ ### How It Works
100
87
 
101
- // Create nodes using the OO API
102
- const root = new TaffyNode({});
103
- root.setDisplay(Display.Flex);
104
- root.setFlexDirection(FlexDirection.Column);
105
- root.setWidth(400);
106
- root.setHeight(400);
107
- root.setPadding(Edge.All, 10);
108
- root.setGap(Gutter.Row, 8);
109
-
110
- const child1 = new TaffyNode({});
111
- child1.setHeight(100);
112
- child1.setFlexGrow(1);
113
-
114
- const child2 = new TaffyNode({});
115
- child2.setHeight(50);
116
-
117
- // Build the tree
118
- root.addChild(child1);
119
- root.addChild(child2);
120
-
121
- // Compute layout
122
- root.computeLayout({ width: 400, height: 400 });
123
-
124
- // Get results
125
- const layout = root.getLayout();
126
- console.log("Root layout:", layout);
127
- console.log("Child1 layout:", child1.getLayout());
128
- console.log("Child2 layout:", child2.getLayout());
129
-
130
- // Cleanup (optional - nodes are automatically freed when dropped)
131
- root.free();
132
- }
88
+ 1. **Create Tree** Instantiate a `TaffyTree` to manage layout nodes
89
+ 2. **Define Styles** Create `Style` objects and set CSS layout properties
90
+ 3. **Build Nodes** – Use `newLeaf()` or `newWithChildren()` to create nodes
91
+ 4. **Compute Layout** – Call `computeLayout()` on the root node
92
+ 5. **Read Results** – Use `getLayout()` to retrieve computed positions and sizes
93
+
94
+ ---
95
+
96
+ ## 📚 API Reference
97
+
98
+ ### TaffyTree Class
99
+
100
+ The main entry point for layout computation.
101
+
102
+ #### Constructors
103
+
104
+ | Method | Description |
105
+ | :-------------------------- | :------------------------------------------------------- |
106
+ | `new TaffyTree()` | Creates a new empty layout tree |
107
+ | `TaffyTree.withCapacity(n)` | Creates a tree with pre-allocated capacity for `n` nodes |
108
+
109
+ #### Configuration
110
+
111
+ | Method | Description |
112
+ | :------------------ | :------------------------------------------------------- |
113
+ | `enableRounding()` | Enables rounding layout values to whole pixels (default) |
114
+ | `disableRounding()` | Disables rounding for sub-pixel precision |
115
+
116
+ #### Node Creation
117
+
118
+ | Method | Signature | Description |
119
+ | :------------------- | :-------------------------------------------- | :---------------------------------------- |
120
+ | `newLeaf` | `(style: Style) → number` | Creates a leaf node (no children) |
121
+ | `newLeafWithContext` | `(style: Style, context: any) → number` | Creates a leaf with attached context data |
122
+ | `newWithChildren` | `(style: Style, children: number[]) → number` | Creates a container node with children |
123
+
124
+ #### Style Management
125
+
126
+ | Method | Signature | Description |
127
+ | :--------- | :------------------------------------ | :----------------------------------- |
128
+ | `setStyle` | `(node: number, style: Style) → void` | Updates a node's style (marks dirty) |
129
+ | `getStyle` | `(node: number) → Style` | Returns a copy of the node's style |
130
+
131
+ #### Tree Operations
133
132
 
134
- run();
133
+ | Method | Signature | Description |
134
+ | :-------------------- | :-------------------------------- | :----------------------------- |
135
+ | `addChild` | `(parent, child) → void` | Appends a child to a parent |
136
+ | `removeChild` | `(parent, child) → number` | Removes and returns the child |
137
+ | `removeChildAtIndex` | `(parent, index) → number` | Removes child at index |
138
+ | `insertChildAtIndex` | `(parent, index, child) → void` | Inserts child at index |
139
+ | `replaceChildAtIndex` | `(parent, index, child) → number` | Replaces and returns old child |
140
+ | `setChildren` | `(parent, children[]) → void` | Replaces all children |
141
+ | `remove` | `(node) → number` | Removes node from tree |
142
+ | `clear` | `() → void` | Removes all nodes |
143
+
144
+ #### Tree Queries
145
+
146
+ | Method | Signature | Description |
147
+ | :---------------- | :------------------------- | :-------------------------- |
148
+ | `parent` | `(child) → number \| null` | Returns parent node ID |
149
+ | `children` | `(parent) → number[]` | Returns array of child IDs |
150
+ | `childCount` | `(parent) → number` | Returns number of children |
151
+ | `getChildAtIndex` | `(parent, index) → number` | Returns child at index |
152
+ | `totalNodeCount` | `() → number` | Returns total nodes in tree |
153
+
154
+ #### Dirty Tracking
155
+
156
+ | Method | Signature | Description |
157
+ | :---------- | :----------------- | :----------------------------- |
158
+ | `markDirty` | `(node) → void` | Marks node for re-layout |
159
+ | `dirty` | `(node) → boolean` | Checks if node needs re-layout |
160
+
161
+ #### Layout Computation
162
+
163
+ | Method | Signature | Description |
164
+ | :------------------------- | :----------------------------------------- | :------------------------------------ |
165
+ | `computeLayout` | `(node, availableSpace) → void` | Computes layout for subtree |
166
+ | `computeLayoutWithMeasure` | `(node, availableSpace, measureFn) → void` | Computes with custom measure function |
167
+
168
+ #### Layout Results
169
+
170
+ | Method | Signature | Description |
171
+ | :---------------- | :---------------- | :------------------------------------ |
172
+ | `getLayout` | `(node) → Layout` | Returns computed layout (rounded) |
173
+ | `unroundedLayout` | `(node) → Layout` | Returns layout with fractional values |
174
+
175
+ #### Node Context
176
+
177
+ | Method | Signature | Description |
178
+ | :--------------- | :----------------------- | :---------------------- |
179
+ | `setNodeContext` | `(node, context) → void` | Attaches data to node |
180
+ | `getNodeContext` | `(node) → any` | Retrieves attached data |
181
+
182
+ #### Debug
183
+
184
+ | Method | Description |
185
+ | :---------------- | :------------------------------- |
186
+ | `printTree(node)` | Prints tree structure to console |
187
+
188
+ ---
189
+
190
+ ### Style Class
191
+
192
+ Configuration object for CSS layout properties.
193
+
194
+ ```typescript
195
+ const style = new Style();
135
196
  ```
136
197
 
137
- ## 📐 Architecture
198
+ #### Layout Mode
138
199
 
139
- `taffy-js` acts as a thin wrapper around the [Taffy](https://github.com/DioxusLabs/taffy) Rust crate.
200
+ | Property | Type | Description |
201
+ | :--------- | :--------- | :---------------------------------------- |
202
+ | `display` | `Display` | Layout algorithm: Block, Flex, Grid, None |
203
+ | `position` | `Position` | Positioning: Relative, Absolute |
140
204
 
141
- 1. **Node Tree**: You build a flat tree of nodes in the WASM memory space using integer IDs (`u64`).
142
- 2. **Style Transfer**: Styles are serialized from JS objects to Rust structs via `serde-wasm-bindgen`.
143
- 3. **Computation**: Rust runs the layout algorithms (Flexbox/Grid/Block).
144
- 4. **Readout**: You query the final computed geometry (x, y, width, height) back to JS.
205
+ #### Flexbox Properties
145
206
 
146
- ## 📚 API Reference
207
+ | Property | Type | Description |
208
+ | :--------------- | :-------------- | :------------------------------------------------ |
209
+ | `flex_direction` | `FlexDirection` | Main axis: Row, Column, RowReverse, ColumnReverse |
210
+ | `flex_wrap` | `FlexWrap` | Wrap behavior: NoWrap, Wrap, WrapReverse |
211
+ | `flex_grow` | `number` | Grow factor (default: 0) |
212
+ | `flex_shrink` | `number` | Shrink factor (default: 1) |
213
+ | `flex_basis` | `Dimension` | Initial size before grow/shrink |
214
+
215
+ #### Alignment
216
+
217
+ | Property | Type | Description |
218
+ | :---------------- | :---------------- | :--------------------------------- |
219
+ | `align_items` | `AlignItems?` | Cross-axis alignment for children |
220
+ | `align_self` | `AlignSelf?` | Cross-axis alignment for this item |
221
+ | `align_content` | `AlignContent?` | Multi-line cross-axis alignment |
222
+ | `justify_content` | `JustifyContent?` | Main-axis alignment |
223
+
224
+ #### Sizing
147
225
 
148
- ### Lifecycle
149
-
150
- | Function | Description |
151
- | :-------- | :------------------------------------------------------------------------------ |
152
- | `init()` | Initializes the WASM module. Must be awaited before calling any other function. |
153
- | `clear()` | Clears all nodes from the layout tree, resetting to empty state. |
154
-
155
- ### Node Management (Functional API)
156
-
157
- | Function | Signature | Description |
158
- | :------------------ | :--------------------------------------------- | :-------------------------------------- |
159
- | `new_leaf` | `(style: Style) -> number` | Creates a leaf node (no children). |
160
- | `new_with_children` | `(style: Style, children: number[]) -> number` | Creates a node containing child nodes. |
161
- | `add_child` | `(parent: number, child: number) -> void` | Appends a child to a parent. |
162
- | `remove_child` | `(parent: number, child: number) -> void` | Removes a specific child from a parent. |
163
- | `set_children` | `(parent: number, children: number[]) -> void` | Replaces all children of a node. |
164
- | `remove_node` | `(node: number) -> void` | Deletes a node and frees its memory. |
165
- | `get_children` | `(parent: number) -> number[]` | Returns an array of child node IDs. |
166
- | `get_parent` | `(node: number) -> number \| null` | Returns the parent node ID, or null. |
167
-
168
- ### Layout & Style (Functional API)
169
-
170
- | Function | Signature | Description |
171
- | :--------------- | :---------------------------------------------- | :--------------------------------------------------- |
172
- | `set_style` | `(node: number, style: Style) -> void` | Updates the style properties of a node. |
173
- | `compute_layout` | `(root: number, space: AvailableSpace) -> void` | Triggers the layout calculation algorithm. |
174
- | `get_layout` | `(node: number) -> Layout` | Returns `{x, y, width, height}` for a node. |
175
- | `mark_dirty` | `(node: number) -> void` | Manually marks a node as dirty, requiring re-layout. |
176
- | `node_count` | `() -> number` | Returns the total number of nodes in the tree. |
177
-
178
- ### Dimension Helpers
179
-
180
- | Function | Signature | Description |
181
- | :---------- | :-------------------------------------------------- | :-------------------------------------- |
182
- | `px` | `(value: number) -> Dimension` | Creates a pixel dimension. |
183
- | `percent` | `(value: number) -> Dimension` | Creates a percentage dimension. |
184
- | `auto` | `() -> Dimension` | Creates an auto dimension. |
185
- | `dimension` | `(value: number, unit: DimensionUnit) -> Dimension` | Creates a dimension with explicit unit. |
186
-
187
- ### TaffyNode Class (OO API)
188
-
189
- The `TaffyNode` class provides a Yoga-like object-oriented interface:
190
-
191
- #### Constructor & Lifecycle
192
-
193
- | Method | Description |
194
- | :--------------------- | :------------------------------------------------------------ |
195
- | `new TaffyNode(style)` | Creates a new node with the given style. |
196
- | `free()` | Explicitly frees the node. Nodes are also auto-freed on drop. |
197
-
198
- #### Style Methods
199
-
200
- | Method | Description |
201
- | :---------------------------- | :--------------------------------------------- |
202
- | `setStyle(style)` | Updates the full style object. |
203
- | `setDisplay(display)` | Sets display mode (Flex, Grid, Block, None). |
204
- | `setPositionType(position)` | Sets positioning (Relative, Absolute). |
205
- | `setFlexDirection(direction)` | Sets flex direction (Row, Column, etc.). |
206
- | `setFlexWrap(wrap)` | Sets flex wrap behavior. |
207
- | `setAlignItems(align)` | Sets cross-axis alignment for children. |
208
- | `setAlignSelf(align)` | Sets cross-axis alignment for this item. |
209
- | `setJustifyContent(justify)` | Sets main-axis alignment. |
210
- | `setFlexGrow(value)` | Sets the flex grow factor. |
211
- | `setFlexShrink(value)` | Sets the flex shrink factor. |
212
- | `setFlexBasis(value)` | Sets flex basis in pixels. |
213
- | `setFlexBasisPercent(value)` | Sets flex basis as percentage. |
214
- | `setFlexBasisAuto()` | Sets flex basis to auto. |
215
- | `setWidth(value)` | Sets width in pixels. |
216
- | `setWidthPercent(value)` | Sets width as percentage. |
217
- | `setWidthAuto()` | Sets width to auto. |
218
- | `setHeight(value)` | Sets height in pixels. |
219
- | `setHeightPercent(value)` | Sets height as percentage. |
220
- | `setHeightAuto()` | Sets height to auto. |
221
- | `setMinWidth(value)` | Sets minimum width in pixels. |
222
- | `setMinWidthPercent(value)` | Sets minimum width as percentage. |
223
- | `setMinHeight(value)` | Sets minimum height in pixels. |
224
- | `setMinHeightPercent(value)` | Sets minimum height as percentage. |
225
- | `setMargin(edge, value)` | Sets margin for specified edge(s). |
226
- | `setMarginAuto(edge)` | Sets margin to auto for specified edge(s). |
227
- | `setPadding(edge, value)` | Sets padding for specified edge(s). |
228
- | `setBorder(edge, value)` | Sets border for specified edge(s). |
229
- | `setGap(gutter, value)` | Sets gap between children. |
230
- | `setMeasureFunc(fn)` | Sets a custom measure function for leaf nodes. |
231
-
232
- #### Tree Methods
233
-
234
- | Method | Description |
235
- | :-------------------------- | :---------------------------------------- |
236
- | `addChild(child)` | Appends a child node. |
237
- | `insertChild(child, index)` | Inserts a child at the specified index. |
238
- | `removeChild(child)` | Removes a child node. |
239
- | `setChildren(childIds)` | Replaces all children with the given IDs. |
240
-
241
- #### Layout Methods
242
-
243
- | Method | Description |
244
- | :------------------------------ | :------------------------------------ |
245
- | `computeLayout(availableSpace)` | Computes layout for this subtree. |
246
- | `getLayout()` | Returns the computed layout. |
247
- | `markDirty()` | Marks this node as needing re-layout. |
226
+ | Property | Type | Description |
227
+ | :------------- | :------------------ | :----------------------- |
228
+ | `size` | `{ width, height }` | Element dimensions |
229
+ | `min_size` | `{ width, height }` | Minimum size constraints |
230
+ | `max_size` | `{ width, height }` | Maximum size constraints |
231
+ | `aspect_ratio` | `number?` | Width-to-height ratio |
232
+
233
+ #### Spacing
234
+
235
+ | Property | Type | Description |
236
+ | :-------- | :----------------------------- | :------------------------------------ |
237
+ | `margin` | `{ left, right, top, bottom }` | Outer spacing (supports Auto) |
238
+ | `padding` | `{ left, right, top, bottom }` | Inner spacing |
239
+ | `border` | `{ left, right, top, bottom }` | Border width |
240
+ | `gap` | `{ width, height }` | Gap between children (column/row gap) |
241
+ | `inset` | `{ left, right, top, bottom }` | Absolute positioning offsets |
242
+
243
+ #### Overflow
244
+
245
+ | Property | Type | Description |
246
+ | :--------- | :--------- | :------------------------- |
247
+ | `overflow` | `{ x, y }` | Overflow behavior per axis |
248
+
249
+ ---
248
250
 
249
251
  ### Type Definitions
250
252
 
251
- #### `Style`
253
+ #### Dimension (JsDimension)
254
+
255
+ Values for size properties:
256
+
257
+ ```typescript
258
+ // Fixed pixel value
259
+ {
260
+ Length: 100;
261
+ }
262
+
263
+ // Percentage of parent
264
+ {
265
+ Percent: 0.5;
266
+ } // 50%
267
+
268
+ // Automatic sizing
269
+ ("Auto");
270
+ ```
271
+
272
+ #### LengthPercentage (JsLengthPercentage)
252
273
 
253
- A comprehensive object mirroring CSS properties:
274
+ For properties that don't support Auto (padding, border):
254
275
 
255
276
  ```typescript
256
- interface Style {
257
- // Display & Position
258
- display?: Display; // Flex, Grid, Block, None
259
- position?: Position; // Relative, Absolute
260
-
261
- // Dimensions
262
- width?: Dimension;
263
- height?: Dimension;
264
- min_width?: Dimension;
265
- min_height?: Dimension;
266
- max_width?: Dimension;
267
- max_height?: Dimension;
268
-
269
- // Position offsets (for absolute positioning)
270
- left?: Dimension;
271
- right?: Dimension;
272
- top?: Dimension;
273
- bottom?: Dimension;
274
-
275
- // Flexbox
276
- flex_direction?: FlexDirection;
277
- flex_wrap?: FlexWrap;
278
- flex_grow?: number;
279
- flex_shrink?: number;
280
- flex_basis?: Dimension;
281
- justify_content?: JustifyContent;
282
- align_items?: AlignItems;
283
- align_self?: AlignSelf;
284
- align_content?: AlignContent;
285
-
286
- // Spacing
287
- margin_left?: Dimension;
288
- margin_right?: Dimension;
289
- margin_top?: Dimension;
290
- margin_bottom?: Dimension;
291
- padding_left?: Dimension;
292
- padding_right?: Dimension;
293
- padding_top?: Dimension;
294
- padding_bottom?: Dimension;
295
- row_gap?: Dimension;
296
- column_gap?: Dimension;
297
-
298
- // Grid
299
- grid_template_rows?: TrackDefinition[];
300
- grid_template_columns?: TrackDefinition[];
301
- grid_auto_rows?: TrackDefinition[];
302
- grid_auto_columns?: TrackDefinition[];
303
- grid_auto_flow?: GridAutoFlow;
304
- grid_row?: Line;
305
- grid_column?: Line;
277
+ {
278
+ Length: 10;
279
+ }
280
+ {
281
+ Percent: 0.1;
306
282
  }
307
283
  ```
308
284
 
309
- #### `Dimension`
285
+ #### LengthPercentageAuto (JsLengthPercentageAuto)
286
+
287
+ For properties that support Auto (margin, inset):
310
288
 
311
289
  ```typescript
312
- interface Dimension {
313
- value: number;
314
- unit: "Pixels" | "Percent" | "Auto";
290
+ {
291
+ Length: 10;
292
+ }
293
+ {
294
+ Percent: 0.1;
315
295
  }
296
+ ("Auto");
316
297
  ```
317
298
 
318
- #### `AvailableSpace`
299
+ #### AvailableSpace (JsAvailableSize)
319
300
 
320
- Used when triggering layout computation:
301
+ Constraints for layout computation:
321
302
 
322
303
  ```typescript
323
- interface AvailableSpace {
324
- width?: number; // undefined = unlimited/content-based
325
- height?: number; // undefined = unlimited/content-based
304
+ {
305
+ width: { Definite: 800 }, // Fixed width
306
+ height: { Definite: 600 } // Fixed height
307
+ }
308
+
309
+ {
310
+ width: "MaxContent", // Intrinsic max width
311
+ height: "MinContent" // Intrinsic min height
326
312
  }
327
313
  ```
328
314
 
329
- #### `Layout`
315
+ #### Layout Result
330
316
 
331
- The computed layout result:
317
+ Returned by `getLayout()`:
332
318
 
333
319
  ```typescript
334
- interface Layout {
335
- x: number; // X position relative to parent
336
- y: number; // Y position relative to parent
337
- width: number; // Computed width
338
- height: number; // Computed height
320
+ {
321
+ order: number,
322
+ size: { width: number, height: number },
323
+ location: { x: number, y: number },
324
+ padding: { left, right, top, bottom },
325
+ border: { left, right, top, bottom },
326
+ scrollbar_size: { width, height },
327
+ content_size: { width, height }
339
328
  }
340
329
  ```
341
330
 
331
+ ---
332
+
342
333
  ### Enums
343
334
 
344
335
  #### Display
345
336
 
346
- - `Display.None` - Hidden, takes no space
347
- - `Display.Flex` - Flexbox container
348
- - `Display.Grid` - Grid container
349
- - `Display.Block` - Block layout
337
+ ```typescript
338
+ Display.Block; // Block layout (default)
339
+ Display.Flex; // Flexbox container
340
+ Display.Grid; // CSS Grid container
341
+ Display.None; // Hidden, takes no space
342
+ ```
350
343
 
351
344
  #### Position
352
345
 
353
- - `Position.Static` - Normal flow (treated as Relative)
354
- - `Position.Relative` - Normal flow
355
- - `Position.Absolute` - Removed from flow, positioned relative to containing block
346
+ ```typescript
347
+ Position.Relative; // Normal document flow (default)
348
+ Position.Absolute; // Removed from flow, positioned via inset
349
+ ```
356
350
 
357
351
  #### FlexDirection
358
352
 
359
- - `FlexDirection.Row` - Horizontal, left to right
360
- - `FlexDirection.Column` - Vertical, top to bottom
361
- - `FlexDirection.RowReverse` - Horizontal, right to left
362
- - `FlexDirection.ColumnReverse` - Vertical, bottom to top
353
+ ```typescript
354
+ FlexDirection.Row; // Horizontal, left to right
355
+ FlexDirection.Column; // Vertical, top to bottom
356
+ FlexDirection.RowReverse; // Horizontal, right to left
357
+ FlexDirection.ColumnReverse; // Vertical, bottom to top
358
+ ```
363
359
 
364
- #### JustifyContent
360
+ #### FlexWrap
365
361
 
366
- - `JustifyContent.Start`, `FlexStart`
367
- - `JustifyContent.End`, `FlexEnd`
368
- - `JustifyContent.Center`
369
- - `JustifyContent.SpaceBetween`
370
- - `JustifyContent.SpaceAround`
371
- - `JustifyContent.SpaceEvenly`
362
+ ```typescript
363
+ FlexWrap.NoWrap; // Single line (default)
364
+ FlexWrap.Wrap; // Wrap to multiple lines
365
+ FlexWrap.WrapReverse; // Wrap in reverse order
366
+ ```
372
367
 
373
368
  #### AlignItems / AlignSelf
374
369
 
375
- - `Start`, `End`, `FlexStart`, `FlexEnd`
376
- - `Center`, `Baseline`, `Stretch`
377
- - `AlignSelf.Auto` (inherit from parent)
370
+ ```typescript
371
+ AlignItems.Start; // Align to start
372
+ AlignItems.End; // Align to end
373
+ AlignItems.FlexStart; // Align to flex start
374
+ AlignItems.FlexEnd; // Align to flex end
375
+ AlignItems.Center; // Center alignment
376
+ AlignItems.Baseline; // Baseline alignment
377
+ AlignItems.Stretch; // Stretch to fill
378
+
379
+ AlignSelf.Auto; // Inherit from parent (AlignSelf only)
380
+ ```
381
+
382
+ #### AlignContent
383
+
384
+ ```typescript
385
+ AlignContent.Start;
386
+ AlignContent.End;
387
+ AlignContent.FlexStart;
388
+ AlignContent.FlexEnd;
389
+ AlignContent.Center;
390
+ AlignContent.Stretch;
391
+ AlignContent.SpaceBetween;
392
+ AlignContent.SpaceAround;
393
+ AlignContent.SpaceEvenly;
394
+ ```
395
+
396
+ #### JustifyContent
378
397
 
379
- #### Edge
398
+ ```typescript
399
+ JustifyContent.Start;
400
+ JustifyContent.End;
401
+ JustifyContent.FlexStart;
402
+ JustifyContent.FlexEnd;
403
+ JustifyContent.Center;
404
+ JustifyContent.Stretch;
405
+ JustifyContent.SpaceBetween;
406
+ JustifyContent.SpaceAround;
407
+ JustifyContent.SpaceEvenly;
408
+ ```
380
409
 
381
- - `Edge.Left`, `Edge.Right`, `Edge.Top`, `Edge.Bottom`
382
- - `Edge.Start`, `Edge.End` (logical)
383
- - `Edge.Horizontal`, `Edge.Vertical`
384
- - `Edge.All`
410
+ #### Overflow
385
411
 
386
- #### Gutter
412
+ ```typescript
413
+ Overflow.Visible; // Content not clipped
414
+ Overflow.Hidden; // Content clipped
415
+ Overflow.Scroll; // Always show scrollbars
416
+ Overflow.Auto; // Show scrollbars when needed
417
+ ```
387
418
 
388
- - `Gutter.Column` - Gap between columns
389
- - `Gutter.Row` - Gap between rows
390
- - `Gutter.All` - Both directions
419
+ ---
391
420
 
392
- ## 🐛 Debug Logging
421
+ ## 📏 Custom Measurement
393
422
 
394
- For development, you can enable verbose console logging by building with the `debug` feature:
423
+ For nodes with intrinsic sizes (like text), use `computeLayoutWithMeasure`:
395
424
 
396
- ```bash
397
- # When building from source
398
- wasm-pack build --features debug
425
+ ```typescript
426
+ tree.computeLayoutWithMeasure(
427
+ root,
428
+ { width: { Definite: 800 }, height: { Definite: 600 } },
429
+ (knownDimensions, availableSpace, context) => {
430
+ // knownDimensions: { width: number | null, height: number | null }
431
+ // availableSpace: { width: AvailableSpace, height: AvailableSpace }
432
+ // context: The value attached via setNodeContext/newLeafWithContext
433
+
434
+ // Return the measured size
435
+ return { width: 100, height: 20 };
436
+ },
437
+ );
399
438
  ```
400
439
 
401
- When enabled, the library outputs detailed logs to the browser console including:
440
+ **Example with text measurement:**
402
441
 
403
- - Node creation and removal
404
- - Style updates
405
- - Layout computation details
406
- - Error diagnostics
442
+ ```typescript
443
+ // Create a text node with context
444
+ const textNode = tree.newLeafWithContext(style, { text: "Hello World" });
445
+
446
+ // Measure function
447
+ tree.computeLayoutWithMeasure(root, availableSpace, (known, available, ctx) => {
448
+ if (ctx?.text) {
449
+ // Use your text measurement library here
450
+ const measured = measureText(ctx.text, available.width);
451
+ return { width: measured.width, height: measured.height };
452
+ }
453
+ return { width: 0, height: 0 };
454
+ });
455
+ ```
407
456
 
408
- **Note**: Debug logging is disabled by default for optimal performance in production.
457
+ ---
409
458
 
410
459
  ## 🛠 Building from Source
411
460
 
412
- If you want to contribute or build the WASM binary yourself:
461
+ 1. **Prerequisites**: Install Rust and `wasm-pack`
413
462
 
414
- 1. **Prerequisites**: Install Rust and `wasm-pack`.
463
+ ```bash
464
+ curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
465
+ ```
415
466
 
416
- ```bash
417
- curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
418
- ```
467
+ 2. **Build**
419
468
 
420
- 2. **Build** (production):
469
+ ```bash
470
+ npm install
471
+ npm run build
472
+ ```
421
473
 
422
- ```bash
423
- npm install
424
- npm run build
425
- ```
474
+ 3. **Build with debug features**
426
475
 
427
- 3. **Build** (with debug logging):
428
- ```bash
429
- wasm-pack build --features debug
430
- ```
476
+ ```bash
477
+ wasm-pack build --features console_error_panic_hook
478
+ ```
431
479
 
432
- The artifacts will be generated in the `pkg/` directory.
480
+ ---
433
481
 
434
482
  ## 📄 License
435
483