taffy-layout 0.1.0

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 ADDED
@@ -0,0 +1,262 @@
1
+ # Taffy Layout
2
+
3
+ [![npm version](https://badge.fury.io/js/taffy-layout.svg)](https://www.npmjs.com/package/taffy-layout)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
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.
7
+
8
+ ## ✨ Features
9
+
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
16
+
17
+ ## 📦 Installation
18
+
19
+ ```bash
20
+ npm install taffy-layout
21
+ ```
22
+
23
+ ## 🚀 Quick Start
24
+
25
+ ```typescript
26
+ import {
27
+ loadTaffy,
28
+ TaffyTree,
29
+ Style,
30
+ Display,
31
+ FlexDirection,
32
+ AlignItems,
33
+ } from "taffy-layout";
34
+
35
+ // Initialize WebAssembly module
36
+ await loadTaffy();
37
+
38
+ // Create a layout tree
39
+ const tree = new TaffyTree();
40
+
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: 300, height: 200 };
47
+ containerStyle.padding = { left: 10, right: 10, top: 10, bottom: 10 };
48
+
49
+ // Create child styles
50
+ const childStyle = new Style();
51
+ childStyle.flexGrow = 1;
52
+ childStyle.size = { width: "100%", height: "auto" };
53
+
54
+ // Create nodes
55
+ const child1 = tree.newLeaf(childStyle);
56
+ const child2 = tree.newLeaf(childStyle);
57
+ const container = tree.newWithChildren(
58
+ containerStyle,
59
+ BigUint64Array.from([child1, child2]),
60
+ );
61
+
62
+ // Compute layout
63
+ tree.computeLayout(container, { width: 300, height: 200 });
64
+
65
+ // Read computed layouts
66
+ const containerLayout = tree.getLayout(container);
67
+ const child1Layout = tree.getLayout(child1);
68
+ const child2Layout = tree.getLayout(child2);
69
+
70
+ console.log(`Container: ${containerLayout.width}x${containerLayout.height}`);
71
+ console.log(
72
+ `Child 1: ${child1Layout.width}x${child1Layout.height} at (${child1Layout.x}, ${child1Layout.y})`,
73
+ );
74
+ console.log(
75
+ `Child 2: ${child2Layout.width}x${child2Layout.height} at (${child2Layout.x}, ${child2Layout.y})`,
76
+ );
77
+ ```
78
+
79
+ ## 📖 API Reference
80
+
81
+ ### TaffyTree
82
+
83
+ The main class for managing layout trees.
84
+
85
+ [View Documentation](./docs/classes/TaffyTree.md)
86
+
87
+ ### Style
88
+
89
+ Configuration object for node layout properties.
90
+
91
+ [View Documentation](./docs/classes/Style.md)
92
+
93
+ ### Layout
94
+
95
+ Read-only computed layout result.
96
+
97
+ [View Documentation](./docs/classes/Layout.md)
98
+
99
+ ### Enums
100
+
101
+ [View Documentation](./docs/index.md#enumerations)
102
+
103
+ ### Types
104
+
105
+ [View Documentation](./docs/index.md#type-aliases)
106
+
107
+ ## 📐 Custom Text Measurement
108
+
109
+ For text nodes or other content that needs dynamic measurement:
110
+
111
+ ```typescript
112
+ const tree = new TaffyTree();
113
+ const textStyle = new Style();
114
+ const rootNode = tree.newLeaf(new Style());
115
+ const measureTextWidth = (text: string) => text.length * 8;
116
+ const measureTextHeight = (text: string, width: number) => 20;
117
+
118
+ const textNode = tree.newLeafWithContext(textStyle, { text: "Hello, World!" });
119
+
120
+ tree.computeLayoutWithMeasure(
121
+ rootNode,
122
+ { width: 800, height: "max-content" },
123
+ (known, available, node, context, style) => {
124
+ if (context?.text) {
125
+ // Your text measurement logic here
126
+ const width = measureTextWidth(context.text);
127
+ const height = measureTextHeight(context.text, available.width as number);
128
+ return { width, height };
129
+ }
130
+ return { width: 0, height: 0 };
131
+ },
132
+ );
133
+ ```
134
+
135
+ ## 🔧 Error Handling
136
+
137
+ Methods that can fail throw a `TaffyError` as a JavaScript exception. Use try-catch to handle errors:
138
+
139
+ ```typescript
140
+ try {
141
+ const tree = new TaffyTree();
142
+ const style = new Style();
143
+ const nodeId = tree.newLeaf(style);
144
+ console.log("Created node:", nodeId);
145
+ } catch (e) {
146
+ if (e instanceof TaffyError) {
147
+ console.error("Error:", e.message);
148
+ }
149
+ }
150
+ ```
151
+
152
+ ## 🌐 Browser Support
153
+
154
+ Taffy Layout works in all modern browsers that support WebAssembly:
155
+
156
+ - Chrome 57+
157
+ - Firefox 52+
158
+ - Safari 11+
159
+ - Edge 16+
160
+
161
+ ## 📚 Examples
162
+
163
+ ### Flexbox Row Layout
164
+
165
+ ```typescript
166
+ const rowStyle = new Style();
167
+ rowStyle.display = Display.Flex;
168
+ rowStyle.flexDirection = FlexDirection.Row;
169
+ rowStyle.justifyContent = JustifyContent.SpaceBetween;
170
+ rowStyle.gap = { width: 10, height: 0 };
171
+ ```
172
+
173
+ ### CSS Grid Layout
174
+
175
+ ```typescript
176
+ import { Style, Display, GridAutoFlow } from "taffy-layout";
177
+
178
+ const gridStyle = new Style();
179
+ gridStyle.display = Display.Grid;
180
+ gridStyle.gridAutoFlow = GridAutoFlow.Row;
181
+ gridStyle.gap = { width: 10, height: 10 };
182
+
183
+ // Grid item placement
184
+ const itemStyle = new Style();
185
+ itemStyle.gridRow = { start: 1, end: 3 }; // Spans 2 rows
186
+ itemStyle.gridColumn = { start: 1, end: { span: 2 } }; // Spans 2 columns
187
+ ```
188
+
189
+ ### Grid Template Areas
190
+
191
+ ```typescript
192
+ const gridStyle = new Style();
193
+ gridStyle.display = Display.Grid;
194
+ gridStyle.gridTemplateAreas = [
195
+ { name: "header", rowStart: 1, rowEnd: 2, columnStart: 1, columnEnd: 4 },
196
+ { name: "sidebar", rowStart: 2, rowEnd: 4, columnStart: 1, columnEnd: 2 },
197
+ { name: "main", rowStart: 2, rowEnd: 4, columnStart: 2, columnEnd: 4 },
198
+ { name: "footer", rowStart: 4, rowEnd: 5, columnStart: 1, columnEnd: 4 },
199
+ ];
200
+
201
+ // Named grid lines
202
+ gridStyle.gridTemplateRowNames = [
203
+ ["header-start"],
204
+ ["header-end", "content-start"],
205
+ ["content-end", "footer-start"],
206
+ ["footer-end"],
207
+ ];
208
+ ```
209
+
210
+ ### Absolute Positioning
211
+
212
+ ```typescript
213
+ const absoluteStyle = new Style();
214
+ absoluteStyle.position = Position.Absolute;
215
+ absoluteStyle.inset = { left: 10, top: 10, right: "auto", bottom: "auto" };
216
+ absoluteStyle.size = { width: 100, height: 50 };
217
+ ```
218
+
219
+ ### Percentage Sizing
220
+
221
+ ```typescript
222
+ const percentStyle = new Style();
223
+ percentStyle.size = {
224
+ width: "50%", // 50% of parent
225
+ height: "100%", // 100% of parent
226
+ };
227
+ ```
228
+
229
+ ### Block Layout with Replaced Elements
230
+
231
+ ```typescript
232
+ const imgStyle = new Style();
233
+ imgStyle.itemIsReplaced = true;
234
+ imgStyle.aspectRatio = 16 / 9; // 16:9 aspect ratio
235
+ imgStyle.size = { width: "100%", height: "auto" };
236
+ ```
237
+
238
+ ## 🏗️ Building from Source
239
+
240
+ ```bash
241
+ # Clone the repository
242
+ git clone https://github.com/ByteLandTechnology/taffy-layout.git
243
+ cd taffy-layout
244
+
245
+ # Install dependencies
246
+ npm install
247
+
248
+ # Build the WebAssembly module
249
+ npm run build
250
+
251
+ # Run tests
252
+ npm test
253
+ ```
254
+
255
+ ## 📄 License
256
+
257
+ MIT License - see [LICENSE](LICENSE) for details.
258
+
259
+ ## 🙏 Acknowledgments
260
+
261
+ - [Taffy](https://github.com/DioxusLabs/taffy) - The Rust layout engine this project wraps
262
+ - [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) - Rust/WebAssembly interoperability
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Taffy Layout: TypeScript wrapper for Taffy WASM bindings
3
+ *
4
+ * This module provides the `loadTaffy` function for initializing the WASM module
5
+ * and re-exports all types and functions from the underlying WASM bindings.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { loadTaffy, TaffyTree, Style, Display } from 'taffy-layout';
10
+ *
11
+ * await loadTaffy();
12
+ *
13
+ * const tree = new TaffyTree();
14
+ * const style = new Style();
15
+ * style.display = Display.Flex;
16
+ * const node = tree.newLeaf(style);
17
+ * ```
18
+ */
19
+ export * from "../pkg/taffy_wasm.js";
20
+ export type { InitOutput } from "../pkg/taffy_wasm.js";
21
+ import type { InitOutput } from "../pkg/taffy_wasm.js";
22
+ /**
23
+ * Universal initialization function for Taffy WASM module.
24
+ *
25
+ * Automatically detects the environment (Web or Node.js) and loads the WASM accordingly.
26
+ * - In a **Web environment**, it uses `fetch` to load the WASM file.
27
+ * - In a **Node.js environment**, it uses `fs` to read the WASM file.
28
+ *
29
+ * @returns - A promise that resolves to the WASM module exports.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * import { loadTaffy } from 'taffy-layout';
34
+ * await loadTaffy();
35
+ * ```
36
+ */
37
+ export declare function loadTaffy(): Promise<InitOutput>;
38
+ export default loadTaffy;
39
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,cAAc,sBAAsB,CAAC;AACrC,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAavD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC,CAkBrD;AAGD,eAAe,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Taffy Layout: TypeScript wrapper for Taffy WASM bindings
3
+ *
4
+ * This module provides the `loadTaffy` function for initializing the WASM module
5
+ * and re-exports all types and functions from the underlying WASM bindings.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { loadTaffy, TaffyTree, Style, Display } from 'taffy-layout';
10
+ *
11
+ * await loadTaffy();
12
+ *
13
+ * const tree = new TaffyTree();
14
+ * const style = new Style();
15
+ * style.display = Display.Flex;
16
+ * const node = tree.newLeaf(style);
17
+ * ```
18
+ */
19
+ // Re-export everything from the WASM module
20
+ export * from "../pkg/taffy_wasm.js";
21
+ // Import the init functions for the loader
22
+ import init, { initSync } from "../pkg/taffy_wasm.js";
23
+ /**
24
+ * Detects if running in a Node.js environment
25
+ */
26
+ function isNode() {
27
+ return (typeof process !== "undefined" &&
28
+ process.versions != null &&
29
+ process.versions.node != null);
30
+ }
31
+ /**
32
+ * Universal initialization function for Taffy WASM module.
33
+ *
34
+ * Automatically detects the environment (Web or Node.js) and loads the WASM accordingly.
35
+ * - In a **Web environment**, it uses `fetch` to load the WASM file.
36
+ * - In a **Node.js environment**, it uses `fs` to read the WASM file.
37
+ *
38
+ * @returns - A promise that resolves to the WASM module exports.
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * import { loadTaffy } from 'taffy-layout';
43
+ * await loadTaffy();
44
+ * ```
45
+ */
46
+ export async function loadTaffy() {
47
+ if (isNode()) {
48
+ // Node.js environment - use fs to read the WASM file
49
+ const fs = await import("fs");
50
+ const url = await import("url");
51
+ const path = await import("path");
52
+ // Resolve WASM path relative to this module
53
+ const __filename = url.fileURLToPath(import.meta.url);
54
+ const __dirname = path.dirname(__filename);
55
+ const wasmPath = path.join(__dirname, "..", "pkg", "taffy_wasm_bg.wasm");
56
+ const wasmBuffer = fs.readFileSync(wasmPath);
57
+ return initSync({ module: wasmBuffer });
58
+ }
59
+ else {
60
+ // Web environment - use fetch via the default init function
61
+ return await init();
62
+ }
63
+ }
64
+ // Default export for convenience
65
+ export default loadTaffy;
66
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,4CAA4C;AAC5C,cAAc,sBAAsB,CAAC;AAGrC,2CAA2C;AAC3C,OAAO,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGtD;;GAEG;AACH,SAAS,MAAM;IACb,OAAO,CACL,OAAO,OAAO,KAAK,WAAW;QAC9B,OAAO,CAAC,QAAQ,IAAI,IAAI;QACxB,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,CAC9B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,MAAM,EAAE,EAAE,CAAC;QACb,qDAAqD;QACrD,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAElC,4CAA4C;QAC5C,MAAM,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC;QAEzE,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC7C,OAAO,QAAQ,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,4DAA4D;QAC5D,OAAO,MAAM,IAAI,EAAE,CAAC;IACtB,CAAC;AACH,CAAC;AAED,iCAAiC;AACjC,eAAe,SAAS,CAAC"}
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "taffy-layout",
3
+ "version": "0.1.0",
4
+ "description": "WebAssembly bindings for Taffy layout library",
5
+ "keywords": [
6
+ "layout",
7
+ "flexbox",
8
+ "css-grid",
9
+ "grid",
10
+ "ui",
11
+ "wasm",
12
+ "webassembly"
13
+ ],
14
+ "homepage": "https://github.com/ByteLandTechnology/taffy-layout#readme",
15
+ "bugs": {
16
+ "url": "https://github.com/ByteLandTechnology/taffy-layout/issues"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/ByteLandTechnology/taffy-layout.git"
21
+ },
22
+ "license": "MIT",
23
+ "author": "ByteLandTechnology <github@byteland.app>",
24
+ "type": "module",
25
+ "main": "dist/index.js",
26
+ "types": "dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "import": "./dist/index.js"
31
+ },
32
+ "./wasm": {
33
+ "types": "./pkg/taffy_wasm.d.ts",
34
+ "import": "./pkg/taffy_wasm.js"
35
+ }
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "pkg"
40
+ ],
41
+ "scripts": {
42
+ "build": "npm run build:wasm && npm run build:ts && npm run docs",
43
+ "build:wasm": "wasm-pack build --release --target web && rm -f pkg/.gitignore && npm run patch-dts",
44
+ "build:ts": "tsc && npm run generate:examples",
45
+ "build:dev": "wasm-pack build --dev --target web && npm run patch-dts && npm run build:ts",
46
+ "docs": "typedoc && prettier --write docs",
47
+ "patch-dts": "npx tsx scripts/patch-dts.ts",
48
+ "generate:examples": "npx tsx scripts/generate-example-tests.ts",
49
+ "test": "vitest run",
50
+ "prepare": "husky"
51
+ },
52
+ "devDependencies": {
53
+ "@commitlint/cli": "^20.3.0",
54
+ "@commitlint/config-conventional": "^20.3.0",
55
+ "@types/node": "^22.0.0",
56
+ "husky": "^9.1.7",
57
+ "lint-staged": "^16.2.7",
58
+ "prettier": "^3.7.4",
59
+ "tsx": "^4.0.0",
60
+ "typedoc": "^0.28.15",
61
+ "typedoc-plugin-markdown": "^4.9.0",
62
+ "typescript": "^5.7.0",
63
+ "vitest": "^4.0.16",
64
+ "wasm-pack": "^0.13.1"
65
+ },
66
+ "engines": {
67
+ "node": ">=12"
68
+ },
69
+ "overrides": {
70
+ "axios": "^1.7.9"
71
+ },
72
+ "commitlint": {
73
+ "extends": [
74
+ "@commitlint/config-conventional"
75
+ ]
76
+ },
77
+ "lint-staged": {
78
+ "*.{js,ts,jsx,tsx,json,md,yaml,yml}": "prettier --write",
79
+ "*.rs": "cargo fmt --"
80
+ }
81
+ }