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 +353 -395
- package/package.json +2 -2
- package/taffy_js.d.ts +1688 -572
- package/taffy_js.js +2804 -1820
- package/taffy_js_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
# Taffy-JS
|
|
1
|
+
# Taffy-JS
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/taffy-js)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
5
|
|
|
5
|
-
|
|
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
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
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
|
-
```
|
|
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
|
-
//
|
|
35
|
+
// Initialize WebAssembly module
|
|
40
36
|
await init();
|
|
41
37
|
|
|
42
|
-
//
|
|
38
|
+
// Create a layout tree
|
|
43
39
|
const tree = new TaffyTree();
|
|
44
40
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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.
|
|
56
|
+
childStyle.flexGrow = 1;
|
|
57
|
+
childStyle.size = { width: { Percent: 100 }, height: "Auto" };
|
|
54
58
|
|
|
55
|
-
//
|
|
59
|
+
// Create nodes
|
|
56
60
|
const child1 = tree.newLeaf(childStyle);
|
|
57
61
|
const child2 = tree.newLeaf(childStyle);
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
190
|
+
### Layout
|
|
274
191
|
|
|
275
|
-
|
|
192
|
+
Read-only computed layout result.
|
|
276
193
|
|
|
277
194
|
```typescript
|
|
278
|
-
{
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
-
|
|
287
|
-
|
|
288
|
-
For properties that support Auto (margin, inset):
|
|
233
|
+
### Enums
|
|
289
234
|
|
|
290
235
|
```typescript
|
|
291
|
-
{
|
|
292
|
-
|
|
236
|
+
enum Display {
|
|
237
|
+
Block,
|
|
238
|
+
Flex,
|
|
239
|
+
Grid,
|
|
240
|
+
None,
|
|
293
241
|
}
|
|
294
|
-
{
|
|
295
|
-
|
|
242
|
+
enum Position {
|
|
243
|
+
Relative,
|
|
244
|
+
Absolute,
|
|
296
245
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
-
|
|
312
|
-
|
|
252
|
+
enum FlexWrap {
|
|
253
|
+
NoWrap,
|
|
254
|
+
Wrap,
|
|
255
|
+
WrapReverse,
|
|
313
256
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
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
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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
|
-
|
|
347
|
+
## 📐 Custom Text Measurement
|
|
353
348
|
|
|
354
|
-
|
|
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
|
-
|
|
351
|
+
```javascript
|
|
352
|
+
const textNode = tree.newLeafWithContext(textStyle, { text: "Hello, World!" });
|
|
362
353
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
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
|
-
|
|
369
|
+
## 🔧 Error Handling
|
|
370
370
|
|
|
371
|
-
|
|
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
|
-
```
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
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
|
-
|
|
383
|
+
## 🌐 Browser Support
|
|
398
384
|
|
|
399
|
-
|
|
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
|
-
|
|
387
|
+
- Chrome 57+
|
|
388
|
+
- Firefox 52+
|
|
389
|
+
- Safari 11+
|
|
390
|
+
- Edge 16+
|
|
412
391
|
|
|
413
|
-
|
|
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
|
-
|
|
394
|
+
### Flexbox Row Layout
|
|
421
395
|
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
|
|
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
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
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
|
-
|
|
418
|
+
### Percentage Sizing
|
|
449
419
|
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
//
|
|
455
|
-
|
|
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
|
-
|
|
468
|
-
|
|
469
|
-
|
|
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
|
-
|
|
435
|
+
# Install dependencies
|
|
436
|
+
npm install
|
|
483
437
|
|
|
484
|
-
|
|
485
|
-
|
|
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
|
|
447
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
448
|
+
|
|
449
|
+
## 🙏 Acknowledgments
|
|
493
450
|
|
|
494
|
-
|
|
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
|