taffy-js 0.1.3 → 0.2.1
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 +376 -328
- package/package.json +1 -1
- package/taffy_js.d.ts +647 -1058
- package/taffy_js.js +960 -1902
- package/taffy_js_bg.wasm +0 -0
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
|
  
|
|
6
6
|
|
|
7
|
-
**Taffy** is a
|
|
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
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
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**:
|
|
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
|
-
|
|
33
|
-
|
|
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
|
|
43
|
-
// 1. Initialize
|
|
38
|
+
async function main() {
|
|
39
|
+
// 1. Initialize WASM module
|
|
44
40
|
await init();
|
|
45
41
|
|
|
46
|
-
// 2.
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
72
|
+
main();
|
|
83
73
|
```
|
|
84
74
|
|
|
85
|
-
|
|
75
|
+
## 📐 Architecture
|
|
86
76
|
|
|
87
|
-
The library
|
|
77
|
+
The library is organized into four main components:
|
|
88
78
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
99
|
-
await init();
|
|
86
|
+
### How It Works
|
|
100
87
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
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
|
-
|
|
198
|
+
#### Layout Mode
|
|
138
199
|
|
|
139
|
-
|
|
200
|
+
| Property | Type | Description |
|
|
201
|
+
| :--------- | :--------- | :---------------------------------------- |
|
|
202
|
+
| `display` | `Display` | Layout algorithm: Block, Flex, Grid, None |
|
|
203
|
+
| `position` | `Position` | Positioning: Relative, Absolute |
|
|
140
204
|
|
|
141
|
-
|
|
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
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
|
151
|
-
|
|
|
152
|
-
| `
|
|
153
|
-
| `
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
|
158
|
-
|
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
-
####
|
|
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
|
-
|
|
274
|
+
For properties that don't support Auto (padding, border):
|
|
254
275
|
|
|
255
276
|
```typescript
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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
|
-
####
|
|
285
|
+
#### LengthPercentageAuto (JsLengthPercentageAuto)
|
|
286
|
+
|
|
287
|
+
For properties that support Auto (margin, inset):
|
|
310
288
|
|
|
311
289
|
```typescript
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
290
|
+
{
|
|
291
|
+
Length: 10;
|
|
292
|
+
}
|
|
293
|
+
{
|
|
294
|
+
Percent: 0.1;
|
|
315
295
|
}
|
|
296
|
+
("Auto");
|
|
316
297
|
```
|
|
317
298
|
|
|
318
|
-
####
|
|
299
|
+
#### AvailableSpace (JsAvailableSize)
|
|
319
300
|
|
|
320
|
-
|
|
301
|
+
Constraints for layout computation:
|
|
321
302
|
|
|
322
303
|
```typescript
|
|
323
|
-
|
|
324
|
-
width
|
|
325
|
-
height
|
|
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
|
-
####
|
|
315
|
+
#### Layout Result
|
|
330
316
|
|
|
331
|
-
|
|
317
|
+
Returned by `getLayout()`:
|
|
332
318
|
|
|
333
319
|
```typescript
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
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
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
-
####
|
|
360
|
+
#### FlexWrap
|
|
365
361
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
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
|
-
|
|
376
|
-
|
|
377
|
-
|
|
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
|
-
|
|
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
|
-
|
|
382
|
-
- `Edge.Start`, `Edge.End` (logical)
|
|
383
|
-
- `Edge.Horizontal`, `Edge.Vertical`
|
|
384
|
-
- `Edge.All`
|
|
410
|
+
#### Overflow
|
|
385
411
|
|
|
386
|
-
|
|
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
|
-
|
|
389
|
-
- `Gutter.Row` - Gap between rows
|
|
390
|
-
- `Gutter.All` - Both directions
|
|
419
|
+
---
|
|
391
420
|
|
|
392
|
-
##
|
|
421
|
+
## 📏 Custom Measurement
|
|
393
422
|
|
|
394
|
-
For
|
|
423
|
+
For nodes with intrinsic sizes (like text), use `computeLayoutWithMeasure`:
|
|
395
424
|
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
|
|
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
|
-
|
|
440
|
+
**Example with text measurement:**
|
|
402
441
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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
|
-
|
|
457
|
+
---
|
|
409
458
|
|
|
410
459
|
## 🛠 Building from Source
|
|
411
460
|
|
|
412
|
-
|
|
461
|
+
1. **Prerequisites**: Install Rust and `wasm-pack`
|
|
413
462
|
|
|
414
|
-
|
|
463
|
+
```bash
|
|
464
|
+
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
|
465
|
+
```
|
|
415
466
|
|
|
416
|
-
|
|
417
|
-
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
|
418
|
-
```
|
|
467
|
+
2. **Build**
|
|
419
468
|
|
|
420
|
-
|
|
469
|
+
```bash
|
|
470
|
+
npm install
|
|
471
|
+
npm run build
|
|
472
|
+
```
|
|
421
473
|
|
|
422
|
-
|
|
423
|
-
npm install
|
|
424
|
-
npm run build
|
|
425
|
-
```
|
|
474
|
+
3. **Build with debug features**
|
|
426
475
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
```
|
|
476
|
+
```bash
|
|
477
|
+
wasm-pack build --features console_error_panic_hook
|
|
478
|
+
```
|
|
431
479
|
|
|
432
|
-
|
|
480
|
+
---
|
|
433
481
|
|
|
434
482
|
## 📄 License
|
|
435
483
|
|