taffy-js 0.2.3 → 0.2.4

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