taffy-js 0.2.3 → 0.2.5

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,18 @@
1
- # Taffy-JS: WebAssembly Bindings for Taffy Layout Engine
1
+ # Taffy-JS
2
2
 
3
- > **High-performance Flexbox and CSS Grid layout for JavaScript/TypeScript, powered by Rust and WebAssembly.**
3
+ [![npm version](https://badge.fury.io/js/taffy-js.svg)](https://www.npmjs.com/package/taffy-js)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
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
-
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.
6
+ High-performance WebAssembly bindings for the [Taffy](https://github.com/DioxusLabs/taffy) layout engine, bringing CSS Flexbox and Grid layout algorithms to JavaScript with near-native performance.
8
7
 
9
8
  ## ✨ Features
10
9
 
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
10
+ - **🚀 High Performance**: WebAssembly-powered layout calculations
11
+ - **📦 Complete CSS Support**: Full Flexbox and CSS Grid implementation
12
+ - **🔧 Custom Measurement**: Support for custom text/content measurement callbacks
13
+ - **📝 TypeScript Ready**: Complete type definitions included
14
+ - **🌳 Tree-Based API**: Efficient tree structure for complex layouts
15
+ - **💡 Familiar API**: CSS-like property names and values
17
16
 
18
17
  ## 📦 Installation
19
18
 
@@ -21,474 +20,434 @@
21
20
  npm install taffy-js
22
21
  ```
23
22
 
24
- > **Note**: Requires a runtime that supports WebAssembly (all modern browsers and Node.js 12+).
25
-
26
23
  ## 🚀 Quick Start
27
24
 
28
- ```typescript
29
- import init, {
25
+ ```javascript
26
+ import {
27
+ loadTaffy,
30
28
  TaffyTree,
31
29
  Style,
32
30
  Display,
33
31
  FlexDirection,
34
32
  AlignItems,
35
- JustifyContent,
36
33
  } from "taffy-js";
37
34
 
38
35
  async function main() {
39
- // 1. Initialize WASM module
40
- await init();
36
+ // Initialize WebAssembly module
37
+ await loadTaffy();
41
38
 
42
- // 2. Create tree and styles
39
+ // Create a layout tree
43
40
  const tree = new TaffyTree();
44
41
 
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
-
42
+ // Create container style
43
+ const containerStyle = new Style();
44
+ containerStyle.display = Display.Flex;
45
+ containerStyle.flexDirection = FlexDirection.Column;
46
+ containerStyle.alignItems = AlignItems.Center;
47
+ containerStyle.size = { width: { Length: 300 }, height: { Length: 200 } };
48
+ containerStyle.padding = {
49
+ left: { Length: 10 },
50
+ right: { Length: 10 },
51
+ top: { Length: 10 },
52
+ bottom: { Length: 10 },
53
+ };
54
+
55
+ // Create child styles
52
56
  const childStyle = new Style();
53
- childStyle.size = { width: { Length: 100 }, height: { Length: 100 } };
57
+ childStyle.flexGrow = 1;
58
+ childStyle.size = { width: { Percent: 100 }, height: "Auto" };
54
59
 
55
- // 3. Build the tree
60
+ // Create nodes
56
61
  const child1 = tree.newLeaf(childStyle);
57
62
  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 },
63
+ const container = tree.newWithChildren(
64
+ containerStyle,
65
+ BigUint64Array.from([child1, child2]),
66
+ );
67
+
68
+ // Compute layout
69
+ tree.computeLayout(container, {
70
+ width: { Definite: 300 },
71
+ height: { Definite: 200 },
64
72
  });
65
73
 
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));
74
+ // Read computed layouts
75
+ const containerLayout = tree.getLayout(container);
76
+ const child1Layout = tree.getLayout(child1);
77
+ const child2Layout = tree.getLayout(child2);
78
+
79
+ console.log(`Container: ${containerLayout.width}x${containerLayout.height}`);
80
+ console.log(
81
+ `Child 1: ${child1Layout.width}x${child1Layout.height} at (${child1Layout.x}, ${child1Layout.y})`,
82
+ );
83
+ console.log(
84
+ `Child 2: ${child2Layout.width}x${child2Layout.height} at (${child2Layout.x}, ${child2Layout.y})`,
85
+ );
70
86
  }
71
87
 
72
88
  main();
73
89
  ```
74
90
 
75
- ## 📐 Architecture
76
-
77
- The library is organized into four main components:
78
-
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 |
85
-
86
- ### How It Works
87
-
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
132
-
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
91
+ ## 📖 API Reference
162
92
 
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 |
93
+ ### TaffyTree
167
94
 
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.
95
+ The main class for managing layout trees.
193
96
 
194
97
  ```typescript
195
- const style = new Style();
98
+ class TaffyTree {
99
+ // Construction
100
+ constructor();
101
+ static withCapacity(capacity: number): TaffyTree;
102
+
103
+ // Node Creation (throws TaffyError on failure)
104
+ newLeaf(style: Style): bigint;
105
+ newLeafWithContext(style: Style, context: any): bigint;
106
+ newWithChildren(style: Style, children: BigUint64Array): bigint;
107
+
108
+ // Tree Operations
109
+ clear(): void;
110
+ remove(node: bigint): bigint; // throws TaffyError
111
+ totalNodeCount(): number;
112
+
113
+ // Child Management (throws TaffyError on failure)
114
+ addChild(parent: bigint, child: bigint): void;
115
+ removeChild(parent: bigint, child: bigint): bigint;
116
+ setChildren(parent: bigint, children: BigUint64Array): void;
117
+ children(parent: bigint): BigUint64Array;
118
+ childCount(parent: bigint): number;
119
+ parent(child: bigint): bigint | undefined;
120
+
121
+ // Style Management (throws TaffyError on failure)
122
+ setStyle(node: bigint, style: Style): void;
123
+ getStyle(node: bigint): Style;
124
+
125
+ // Layout Computation (throws TaffyError on failure)
126
+ computeLayout(node: bigint, availableSpace: Size<AvailableSpace>): void;
127
+ computeLayoutWithMeasure(
128
+ node: bigint,
129
+ availableSpace: Size<AvailableSpace>,
130
+ measureFunc: MeasureFunction,
131
+ ): void;
132
+
133
+ // Layout Results (throws TaffyError on failure)
134
+ getLayout(node: bigint): Layout;
135
+ unroundedLayout(node: bigint): Layout;
136
+
137
+ // Dirty Tracking (throws TaffyError on failure)
138
+ markDirty(node: bigint): void;
139
+ dirty(node: bigint): boolean;
140
+
141
+ // Configuration
142
+ enableRounding(): void;
143
+ disableRounding(): void;
144
+ }
196
145
  ```
197
146
 
198
- #### Layout Mode
199
-
200
- | Property | Type | Description |
201
- | :--------- | :--------- | :---------------------------------------- |
202
- | `display` | `Display` | Layout algorithm: Block, Flex, Grid, None |
203
- | `position` | `Position` | Positioning: Relative, Absolute |
204
-
205
- #### Flexbox Properties
206
-
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 |
147
+ ### Style
223
148
 
224
- #### Sizing
225
-
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
- | `box_sizing` | `BoxSizing` | Size calculation mode |
233
-
234
- #### Spacing
235
-
236
- | Property | Type | Description |
237
- | :-------- | :----------------------------- | :------------------------------------ |
238
- | `margin` | `{ left, right, top, bottom }` | Outer spacing (supports Auto) |
239
- | `padding` | `{ left, right, top, bottom }` | Inner spacing |
240
- | `border` | `{ left, right, top, bottom }` | Border width |
241
- | `gap` | `{ width, height }` | Gap between children (column/row gap) |
242
- | `inset` | `{ left, right, top, bottom }` | Absolute positioning offsets |
243
-
244
- #### Overflow
245
-
246
- | Property | Type | Description |
247
- | :--------- | :--------- | :------------------------- |
248
- | `overflow` | `{ x, y }` | Overflow behavior per axis |
249
-
250
- ---
251
-
252
- ### Type Definitions
253
-
254
- #### Dimension (JsDimension)
255
-
256
- Values for size properties:
149
+ Configuration object for node layout properties.
257
150
 
258
151
  ```typescript
259
- // Fixed pixel value
260
- {
261
- Length: 100;
152
+ class Style {
153
+ constructor();
154
+
155
+ // Layout Mode
156
+ display: Display; // Block, Flex, Grid, None
157
+ position: Position; // Relative, Absolute
158
+
159
+ // Flexbox
160
+ flexDirection: FlexDirection; // Row, Column, RowReverse, ColumnReverse
161
+ flexWrap: FlexWrap; // NoWrap, Wrap, WrapReverse
162
+ flexGrow: number; // Growth factor (default: 0)
163
+ flexShrink: number; // Shrink factor (default: 1)
164
+ flexBasis: Dimension; // Initial size
165
+
166
+ // Alignment
167
+ alignItems: AlignItems | undefined;
168
+ alignSelf: AlignSelf | undefined;
169
+ alignContent: AlignContent | undefined;
170
+ justifyContent: JustifyContent | undefined;
171
+
172
+ // Sizing
173
+ size: Size<Dimension>; // Width and height
174
+ minSize: Size<Dimension>; // Minimum constraints
175
+ maxSize: Size<Dimension>; // Maximum constraints
176
+ aspectRatio: number | undefined; // Width/height ratio
177
+ boxSizing: BoxSizing; // BorderBox, ContentBox
178
+
179
+ // Spacing
180
+ margin: Rect<LengthPercentageAuto>;
181
+ padding: Rect<LengthPercentage>;
182
+ border: Rect<LengthPercentage>;
183
+ gap: Size<LengthPercentage>; // Row and column gap
184
+ inset: Rect<LengthPercentageAuto>; // For absolute positioning
185
+
186
+ // Overflow
187
+ overflow: Point<Overflow>;
262
188
  }
263
-
264
- // Percentage of parent
265
- {
266
- Percent: 0.5;
267
- } // 50%
268
-
269
- // Automatic sizing
270
- ("Auto");
271
189
  ```
272
190
 
273
- #### LengthPercentage (JsLengthPercentage)
191
+ ### Layout
274
192
 
275
- For properties that don't support Auto (padding, border):
193
+ Read-only computed layout result.
276
194
 
277
195
  ```typescript
278
- {
279
- Length: 10;
280
- }
281
- {
282
- Percent: 0.1;
196
+ class Layout {
197
+ // Position (relative to parent)
198
+ readonly x: number;
199
+ readonly y: number;
200
+
201
+ // Size
202
+ readonly width: number;
203
+ readonly height: number;
204
+
205
+ // Content size (for scrollable content)
206
+ readonly contentWidth: number;
207
+ readonly contentHeight: number;
208
+
209
+ // Spacing
210
+ readonly paddingTop: number;
211
+ readonly paddingRight: number;
212
+ readonly paddingBottom: number;
213
+ readonly paddingLeft: number;
214
+
215
+ readonly borderTop: number;
216
+ readonly borderRight: number;
217
+ readonly borderBottom: number;
218
+ readonly borderLeft: number;
219
+
220
+ readonly marginTop: number;
221
+ readonly marginRight: number;
222
+ readonly marginBottom: number;
223
+ readonly marginLeft: number;
224
+
225
+ // Scrollbars
226
+ readonly scrollbarWidth: number;
227
+ readonly scrollbarHeight: number;
228
+
229
+ // Rendering order
230
+ readonly order: number;
283
231
  }
284
232
  ```
285
233
 
286
- #### LengthPercentageAuto (JsLengthPercentageAuto)
287
-
288
- For properties that support Auto (margin, inset):
234
+ ### Enums
289
235
 
290
236
  ```typescript
291
- {
292
- Length: 10;
237
+ enum Display {
238
+ Block,
239
+ Flex,
240
+ Grid,
241
+ None,
293
242
  }
294
- {
295
- Percent: 0.1;
243
+ enum Position {
244
+ Relative,
245
+ Absolute,
296
246
  }
297
- ("Auto");
298
- ```
299
-
300
- #### AvailableSpace (JsAvailableSize)
301
-
302
- Constraints for layout computation:
303
-
304
- ```typescript
305
- {
306
- width: { Definite: 800 }, // Fixed width
307
- height: { Definite: 600 } // Fixed height
247
+ enum FlexDirection {
248
+ Row,
249
+ Column,
250
+ RowReverse,
251
+ ColumnReverse,
308
252
  }
309
-
310
- {
311
- width: "MaxContent", // Intrinsic max width
312
- height: "MinContent" // Intrinsic min height
253
+ enum FlexWrap {
254
+ NoWrap,
255
+ Wrap,
256
+ WrapReverse,
313
257
  }
314
- ```
315
-
316
- #### Layout Result
317
-
318
- Returned by `getLayout()`:
319
-
320
- ```typescript
321
- {
322
- order: number,
323
- size: { width: number, height: number },
324
- location: { x: number, y: number },
325
- padding: { left, right, top, bottom },
326
- border: { left, right, top, bottom },
327
- scrollbar_size: { width, height },
328
- content_size: { width, height }
258
+ enum AlignItems {
259
+ Start,
260
+ End,
261
+ FlexStart,
262
+ FlexEnd,
263
+ Center,
264
+ Baseline,
265
+ Stretch,
266
+ }
267
+ enum AlignSelf {
268
+ Auto,
269
+ Start,
270
+ End,
271
+ FlexStart,
272
+ FlexEnd,
273
+ Center,
274
+ Baseline,
275
+ Stretch,
276
+ }
277
+ enum AlignContent {
278
+ Start,
279
+ End,
280
+ FlexStart,
281
+ FlexEnd,
282
+ Center,
283
+ Stretch,
284
+ SpaceBetween,
285
+ SpaceAround,
286
+ SpaceEvenly,
287
+ }
288
+ enum JustifyContent {
289
+ Start,
290
+ End,
291
+ FlexStart,
292
+ FlexEnd,
293
+ Center,
294
+ Stretch,
295
+ SpaceBetween,
296
+ SpaceAround,
297
+ SpaceEvenly,
298
+ }
299
+ enum Overflow {
300
+ Visible,
301
+ Hidden,
302
+ Scroll,
303
+ Auto,
304
+ }
305
+ enum BoxSizing {
306
+ BorderBox,
307
+ ContentBox,
329
308
  }
330
309
  ```
331
310
 
332
- ---
333
-
334
- ### Enums
335
-
336
- #### Display
311
+ ### Types
337
312
 
338
313
  ```typescript
339
- Display.Block; // Block layout (default)
340
- Display.Flex; // Flexbox container
341
- Display.Grid; // CSS Grid container
342
- Display.None; // Hidden, takes no space
343
- ```
344
-
345
- #### Position
314
+ // Dimension values
315
+ type Dimension = { Length: number } | { Percent: number } | "Auto";
316
+ type LengthPercentage = { Length: number } | { Percent: number };
317
+ type LengthPercentageAuto = { Length: number } | { Percent: number } | "Auto";
318
+
319
+ // Geometry
320
+ interface Size<T> {
321
+ width: T;
322
+ height: T;
323
+ }
324
+ interface Rect<T> {
325
+ left: T;
326
+ right: T;
327
+ top: T;
328
+ bottom: T;
329
+ }
330
+ interface Point<T> {
331
+ x: T;
332
+ y: T;
333
+ }
346
334
 
347
- ```typescript
348
- Position.Relative; // Normal document flow (default)
349
- Position.Absolute; // Removed from flow, positioned via inset
335
+ // Available space for layout computation
336
+ type AvailableSpace = { Definite: number } | "MinContent" | "MaxContent";
337
+
338
+ // Measure function for custom content measurement
339
+ type MeasureFunction = (
340
+ knownDimensions: Size<number | null>,
341
+ availableSpace: Size<AvailableSpace>,
342
+ node: bigint,
343
+ context: any,
344
+ style: Style,
345
+ ) => Size<number>;
350
346
  ```
351
347
 
352
- #### FlexDirection
348
+ ## 📐 Custom Text Measurement
353
349
 
354
- ```typescript
355
- FlexDirection.Row; // Horizontal, left to right
356
- FlexDirection.Column; // Vertical, top to bottom
357
- FlexDirection.RowReverse; // Horizontal, right to left
358
- FlexDirection.ColumnReverse; // Vertical, bottom to top
359
- ```
350
+ For text nodes or other content that needs dynamic measurement:
360
351
 
361
- #### FlexWrap
352
+ ```javascript
353
+ const textNode = tree.newLeafWithContext(textStyle, { text: "Hello, World!" });
362
354
 
363
- ```typescript
364
- FlexWrap.NoWrap; // Single line (default)
365
- FlexWrap.Wrap; // Wrap to multiple lines
366
- FlexWrap.WrapReverse; // Wrap in reverse order
355
+ tree.computeLayoutWithMeasure(
356
+ rootNode,
357
+ { width: { Definite: 800 }, height: "MaxContent" },
358
+ (known, available, node, context, style) => {
359
+ if (context?.text) {
360
+ // Your text measurement logic here
361
+ const width = measureTextWidth(context.text);
362
+ const height = measureTextHeight(context.text, available.width);
363
+ return { width, height };
364
+ }
365
+ return { width: 0, height: 0 };
366
+ },
367
+ );
367
368
  ```
368
369
 
369
- #### AlignItems / AlignSelf
370
+ ## 🔧 Error Handling
370
371
 
371
- ```typescript
372
- AlignItems.Start; // Align to start
373
- AlignItems.End; // Align to end
374
- AlignItems.FlexStart; // Align to flex start
375
- AlignItems.FlexEnd; // Align to flex end
376
- AlignItems.Center; // Center alignment
377
- AlignItems.Baseline; // Baseline alignment
378
- AlignItems.Stretch; // Stretch to fill
379
-
380
- AlignSelf.Auto; // Inherit from parent (AlignSelf only)
381
- ```
382
-
383
- #### AlignContent
372
+ Methods that can fail throw a `TaffyError` as a JavaScript exception. Use try-catch to handle errors:
384
373
 
385
- ```typescript
386
- AlignContent.Start;
387
- AlignContent.End;
388
- AlignContent.FlexStart;
389
- AlignContent.FlexEnd;
390
- AlignContent.Center;
391
- AlignContent.Stretch;
392
- AlignContent.SpaceBetween;
393
- AlignContent.SpaceAround;
394
- AlignContent.SpaceEvenly;
374
+ ```javascript
375
+ try {
376
+ const nodeId = tree.newLeaf(style);
377
+ console.log("Created node:", nodeId);
378
+ } catch (error) {
379
+ // error is a TaffyError instance
380
+ console.error("Error:", error.message);
381
+ }
395
382
  ```
396
383
 
397
- #### JustifyContent
384
+ ## 🌐 Browser Support
398
385
 
399
- ```typescript
400
- JustifyContent.Start;
401
- JustifyContent.End;
402
- JustifyContent.FlexStart;
403
- JustifyContent.FlexEnd;
404
- JustifyContent.Center;
405
- JustifyContent.Stretch;
406
- JustifyContent.SpaceBetween;
407
- JustifyContent.SpaceAround;
408
- JustifyContent.SpaceEvenly;
409
- ```
386
+ Taffy-JS works in all modern browsers that support WebAssembly:
410
387
 
411
- #### Overflow
388
+ - Chrome 57+
389
+ - Firefox 52+
390
+ - Safari 11+
391
+ - Edge 16+
412
392
 
413
- ```typescript
414
- Overflow.Visible; // Content not clipped
415
- Overflow.Hidden; // Content clipped
416
- Overflow.Scroll; // Always show scrollbars
417
- Overflow.Auto; // Show scrollbars when needed
418
- ```
393
+ ## 📚 Examples
419
394
 
420
- #### BoxSizing
395
+ ### Flexbox Row Layout
421
396
 
422
- ```typescript
423
- BoxSizing.BorderBox; // Include padding/border in size (default)
424
- BoxSizing.ContentBox; // Size is content only
397
+ ```javascript
398
+ const rowStyle = new Style();
399
+ rowStyle.display = Display.Flex;
400
+ rowStyle.flexDirection = FlexDirection.Row;
401
+ rowStyle.justifyContent = JustifyContent.SpaceBetween;
402
+ rowStyle.gap = { width: { Length: 10 }, height: { Length: 0 } };
425
403
  ```
426
404
 
427
- ---
428
-
429
- ## 📏 Custom Measurement
430
-
431
- For nodes with intrinsic sizes (like text), use `computeLayoutWithMeasure`:
432
-
433
- ```typescript
434
- tree.computeLayoutWithMeasure(
435
- root,
436
- { width: { Definite: 800 }, height: { Definite: 600 } },
437
- (knownDimensions, availableSpace, context) => {
438
- // knownDimensions: { width: number | null, height: number | null }
439
- // availableSpace: { width: AvailableSpace, height: AvailableSpace }
440
- // context: The value attached via setNodeContext/newLeafWithContext
441
-
442
- // Return the measured size
443
- return { width: 100, height: 20 };
444
- },
445
- );
405
+ ### Absolute Positioning
406
+
407
+ ```javascript
408
+ const absoluteStyle = new Style();
409
+ absoluteStyle.position = Position.Absolute;
410
+ absoluteStyle.inset = {
411
+ left: { Length: 10 },
412
+ top: { Length: 10 },
413
+ right: "Auto",
414
+ bottom: "Auto",
415
+ };
416
+ absoluteStyle.size = { width: { Length: 100 }, height: { Length: 50 } };
446
417
  ```
447
418
 
448
- **Example with text measurement:**
419
+ ### Percentage Sizing
449
420
 
450
- ```typescript
451
- // Create a text node with context
452
- const textNode = tree.newLeafWithContext(style, { text: "Hello World" });
453
-
454
- // Measure function
455
- tree.computeLayoutWithMeasure(root, availableSpace, (known, available, ctx) => {
456
- if (ctx?.text) {
457
- // Use your text measurement library here
458
- const measured = measureText(ctx.text, available.width);
459
- return { width: measured.width, height: measured.height };
460
- }
461
- return { width: 0, height: 0 };
462
- });
421
+ ```javascript
422
+ const percentStyle = new Style();
423
+ percentStyle.size = {
424
+ width: { Percent: 50 }, // 50% of parent
425
+ height: { Percent: 100 }, // 100% of parent
426
+ };
463
427
  ```
464
428
 
465
- ---
429
+ ## 🏗️ Building from Source
466
430
 
467
- ## 🛠 Building from Source
468
-
469
- 1. **Prerequisites**: Install Rust and `wasm-pack`
470
-
471
- ```bash
472
- curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
473
- ```
474
-
475
- 2. **Build**
476
-
477
- ```bash
478
- npm install
479
- npm run build
480
- ```
431
+ ```bash
432
+ # Clone the repository
433
+ git clone https://github.com/user/taffy-js.git
434
+ cd taffy-js
481
435
 
482
- 3. **Build with debug features**
436
+ # Install dependencies
437
+ npm install
483
438
 
484
- ```bash
485
- wasm-pack build --features console_error_panic_hook
486
- ```
439
+ # Build the WebAssembly module
440
+ npm run build
487
441
 
488
- ---
442
+ # Run tests
443
+ npm test
444
+ ```
489
445
 
490
446
  ## 📄 License
491
447
 
492
- MIT License © 2024 ByteLand Technology
448
+ MIT License - see [LICENSE](LICENSE) for details.
449
+
450
+ ## 🙏 Acknowledgments
493
451
 
494
- This project wraps [Taffy](https://github.com/DioxusLabs/taffy), which is also MIT licensed.
452
+ - [Taffy](https://github.com/DioxusLabs/taffy) - The Rust layout engine this project wraps
453
+ - [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) - Rust/WebAssembly interoperability