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 +356 -397
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +66 -0
- package/dist/index.js.map +1 -0
- package/package.json +70 -15
- package/taffy_js.d.ts +0 -958
- package/taffy_js.js +0 -2031
- 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,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
|
-
```
|
|
29
|
-
import
|
|
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
|
-
//
|
|
40
|
-
await
|
|
36
|
+
// Initialize WebAssembly module
|
|
37
|
+
await loadTaffy();
|
|
41
38
|
|
|
42
|
-
//
|
|
39
|
+
// Create a layout tree
|
|
43
40
|
const tree = new TaffyTree();
|
|
44
41
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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.
|
|
57
|
+
childStyle.flexGrow = 1;
|
|
58
|
+
childStyle.size = { width: { Percent: 100 }, height: "Auto" };
|
|
54
59
|
|
|
55
|
-
//
|
|
60
|
+
// Create nodes
|
|
56
61
|
const child1 = tree.newLeaf(childStyle);
|
|
57
62
|
const child2 = tree.newLeaf(childStyle);
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
191
|
+
### Layout
|
|
274
192
|
|
|
275
|
-
|
|
193
|
+
Read-only computed layout result.
|
|
276
194
|
|
|
277
195
|
```typescript
|
|
278
|
-
{
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
-
|
|
287
|
-
|
|
288
|
-
For properties that support Auto (margin, inset):
|
|
234
|
+
### Enums
|
|
289
235
|
|
|
290
236
|
```typescript
|
|
291
|
-
{
|
|
292
|
-
|
|
237
|
+
enum Display {
|
|
238
|
+
Block,
|
|
239
|
+
Flex,
|
|
240
|
+
Grid,
|
|
241
|
+
None,
|
|
293
242
|
}
|
|
294
|
-
{
|
|
295
|
-
|
|
243
|
+
enum Position {
|
|
244
|
+
Relative,
|
|
245
|
+
Absolute,
|
|
296
246
|
}
|
|
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
|
|
247
|
+
enum FlexDirection {
|
|
248
|
+
Row,
|
|
249
|
+
Column,
|
|
250
|
+
RowReverse,
|
|
251
|
+
ColumnReverse,
|
|
308
252
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
253
|
+
enum FlexWrap {
|
|
254
|
+
NoWrap,
|
|
255
|
+
Wrap,
|
|
256
|
+
WrapReverse,
|
|
313
257
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
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
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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
|
-
|
|
348
|
+
## 📐 Custom Text Measurement
|
|
353
349
|
|
|
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
|
-
```
|
|
350
|
+
For text nodes or other content that needs dynamic measurement:
|
|
360
351
|
|
|
361
|
-
|
|
352
|
+
```javascript
|
|
353
|
+
const textNode = tree.newLeafWithContext(textStyle, { text: "Hello, World!" });
|
|
362
354
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
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
|
-
|
|
370
|
+
## 🔧 Error Handling
|
|
370
371
|
|
|
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
|
|
372
|
+
Methods that can fail throw a `TaffyError` as a JavaScript exception. Use try-catch to handle errors:
|
|
384
373
|
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
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
|
-
|
|
384
|
+
## 🌐 Browser Support
|
|
398
385
|
|
|
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
|
-
```
|
|
386
|
+
Taffy-JS works in all modern browsers that support WebAssembly:
|
|
410
387
|
|
|
411
|
-
|
|
388
|
+
- Chrome 57+
|
|
389
|
+
- Firefox 52+
|
|
390
|
+
- Safari 11+
|
|
391
|
+
- Edge 16+
|
|
412
392
|
|
|
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
|
-
```
|
|
393
|
+
## 📚 Examples
|
|
419
394
|
|
|
420
|
-
|
|
395
|
+
### Flexbox Row Layout
|
|
421
396
|
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
|
|
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
|
-
|
|
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
|
-
);
|
|
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
|
-
|
|
419
|
+
### Percentage Sizing
|
|
449
420
|
|
|
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
|
-
});
|
|
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
|
-
|
|
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
|
-
```
|
|
431
|
+
```bash
|
|
432
|
+
# Clone the repository
|
|
433
|
+
git clone https://github.com/user/taffy-js.git
|
|
434
|
+
cd taffy-js
|
|
481
435
|
|
|
482
|
-
|
|
436
|
+
# Install dependencies
|
|
437
|
+
npm install
|
|
483
438
|
|
|
484
|
-
|
|
485
|
-
|
|
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
|
|
448
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
449
|
+
|
|
450
|
+
## 🙏 Acknowledgments
|
|
493
451
|
|
|
494
|
-
|
|
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
|