@pilates/core 1.0.0-rc.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/LICENSE +21 -0
- package/README.md +97 -0
- package/dist/algorithm/axis.d.ts +41 -0
- package/dist/algorithm/axis.d.ts.map +1 -0
- package/dist/algorithm/axis.js +72 -0
- package/dist/algorithm/axis.js.map +1 -0
- package/dist/algorithm/index.d.ts +12 -0
- package/dist/algorithm/index.d.ts.map +1 -0
- package/dist/algorithm/index.js +26 -0
- package/dist/algorithm/index.js.map +1 -0
- package/dist/algorithm/main-axis.d.ts +59 -0
- package/dist/algorithm/main-axis.d.ts.map +1 -0
- package/dist/algorithm/main-axis.js +704 -0
- package/dist/algorithm/main-axis.js.map +1 -0
- package/dist/algorithm/round.d.ts +20 -0
- package/dist/algorithm/round.d.ts.map +1 -0
- package/dist/algorithm/round.js +45 -0
- package/dist/algorithm/round.js.map +1 -0
- package/dist/edge.d.ts +23 -0
- package/dist/edge.d.ts.map +1 -0
- package/dist/edge.js +22 -0
- package/dist/edge.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +15 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +4 -0
- package/dist/layout.js.map +1 -0
- package/dist/measure/ansi.d.ts +15 -0
- package/dist/measure/ansi.d.ts.map +1 -0
- package/dist/measure/ansi.js +118 -0
- package/dist/measure/ansi.js.map +1 -0
- package/dist/measure/grapheme.d.ts +43 -0
- package/dist/measure/grapheme.d.ts.map +1 -0
- package/dist/measure/grapheme.js +169 -0
- package/dist/measure/grapheme.js.map +1 -0
- package/dist/measure/index.d.ts +4 -0
- package/dist/measure/index.d.ts.map +1 -0
- package/dist/measure/index.js +4 -0
- package/dist/measure/index.js.map +1 -0
- package/dist/measure/range-search.d.ts +7 -0
- package/dist/measure/range-search.d.ts.map +1 -0
- package/dist/measure/range-search.js +22 -0
- package/dist/measure/range-search.js.map +1 -0
- package/dist/measure/tables.d.ts +16 -0
- package/dist/measure/tables.d.ts.map +1 -0
- package/dist/measure/tables.js +262 -0
- package/dist/measure/tables.js.map +1 -0
- package/dist/measure/width.d.ts +37 -0
- package/dist/measure/width.d.ts.map +1 -0
- package/dist/measure/width.js +96 -0
- package/dist/measure/width.js.map +1 -0
- package/dist/measure-func.d.ts +24 -0
- package/dist/measure-func.d.ts.map +1 -0
- package/dist/measure-func.js +18 -0
- package/dist/measure-func.js.map +1 -0
- package/dist/node.d.ts +96 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +332 -0
- package/dist/node.js.map +1 -0
- package/dist/style.d.ts +53 -0
- package/dist/style.d.ts.map +1 -0
- package/dist/style.js +40 -0
- package/dist/style.js.map +1 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 pilates contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# @pilates/core
|
|
2
|
+
|
|
3
|
+
> Headless flex layout engine for terminal UIs. Imperative `Node` API, integer cell
|
|
4
|
+
> coordinates, terminal-correct text measurement. **Pure TypeScript, zero runtime
|
|
5
|
+
> dependencies.**
|
|
6
|
+
|
|
7
|
+
`@pilates/core` is what you get when you take Yoga's flex algorithm, rebuild it for
|
|
8
|
+
the terminal (integer cells, CJK / emoji / wide-char awareness, ANSI escape
|
|
9
|
+
passthrough), and *unbundle* it from any UI framework. Use it directly, or wrap it
|
|
10
|
+
in React, Vue, Svelte, or anything else.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @pilates/core
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick start
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { Node, Edge } from '@pilates/core';
|
|
22
|
+
|
|
23
|
+
const root = Node.create();
|
|
24
|
+
root.setFlexDirection('row');
|
|
25
|
+
root.setWidth(80);
|
|
26
|
+
root.setHeight(24);
|
|
27
|
+
root.setPadding(Edge.All, 1);
|
|
28
|
+
|
|
29
|
+
const main = Node.create();
|
|
30
|
+
main.setFlex(1);
|
|
31
|
+
const sidebar = Node.create();
|
|
32
|
+
sidebar.setWidth(20);
|
|
33
|
+
|
|
34
|
+
root.insertChild(main, 0);
|
|
35
|
+
root.insertChild(sidebar, 1);
|
|
36
|
+
|
|
37
|
+
root.calculateLayout();
|
|
38
|
+
|
|
39
|
+
main.getComputedLayout(); // { left:1, top:1, width:57, height:22 }
|
|
40
|
+
sidebar.getComputedLayout(); // { left:58, top:1, width:20, height:22 }
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Style API
|
|
44
|
+
|
|
45
|
+
Setters mirror Yoga / CSS Flexbox semantics. All values are in terminal cells.
|
|
46
|
+
|
|
47
|
+
| Category | Setters |
|
|
48
|
+
|---|---|
|
|
49
|
+
| Direction | `setFlexDirection`, `setFlexWrap` |
|
|
50
|
+
| Sizing | `setWidth`, `setHeight`, `setMinWidth`, `setMinHeight`, `setMaxWidth`, `setMaxHeight` |
|
|
51
|
+
| Flex | `setFlex` (shorthand), `setFlexGrow`, `setFlexShrink`, `setFlexBasis` |
|
|
52
|
+
| Spacing | `setPadding(edge, n)`, `setMargin(edge, n)`, `setGap('row' \| 'column', n)` |
|
|
53
|
+
| Alignment | `setJustifyContent`, `setAlignItems`, `setAlignSelf`, `setAlignContent` |
|
|
54
|
+
| Position | `setPositionType('relative' \| 'absolute')`, `setPosition(edge, n)` |
|
|
55
|
+
| Visibility | `setDisplay('flex' \| 'none')` |
|
|
56
|
+
|
|
57
|
+
`Edge` is `Top` / `Right` / `Bottom` / `Left` / `Horizontal` / `Vertical` / `All`.
|
|
58
|
+
|
|
59
|
+
## Text measurement
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { stringWidth, cellWidth, graphemes, stripAnsi } from '@pilates/core';
|
|
63
|
+
|
|
64
|
+
stringWidth('hello'); // 5
|
|
65
|
+
stringWidth('你好'); // 4 (each CJK char is 2 cells)
|
|
66
|
+
stringWidth('🔥'); // 2
|
|
67
|
+
stringWidth('👨👩👧'); // 2 (ZWJ family is one grapheme)
|
|
68
|
+
stringWidth('🇯🇵'); // 2 (regional indicator pair = flag)
|
|
69
|
+
stringWidth('\x1b[31mred\x1b[0m'); // 3 (ANSI stripped)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Driven by the latest Unicode UCD data: East Asian Width, Emoji Presentation,
|
|
73
|
+
Grapheme Break Property, Default Ignorable. No runtime fetch — tables are
|
|
74
|
+
generated at build time and shipped with the package.
|
|
75
|
+
|
|
76
|
+
## Custom text measurement (measure functions)
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { Node, MeasureMode } from '@pilates/core';
|
|
80
|
+
|
|
81
|
+
const text = Node.create();
|
|
82
|
+
text.setMeasureFunc((width, widthMode, height, heightMode) => {
|
|
83
|
+
// Compute the natural width / height of the leaf's content.
|
|
84
|
+
return { width: stringWidth('Hello'), height: 1 };
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Status
|
|
89
|
+
|
|
90
|
+
Release candidate (`1.0.0-rc.1`). The full v1 surface is implemented and
|
|
91
|
+
verified cell-for-cell against `yoga-layout` (Meta's reference WASM build).
|
|
92
|
+
|
|
93
|
+
**Out of v1:** `aspectRatio`, RTL/LTR direction inheritance, baseline alignment.
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
|
|
97
|
+
MIT
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Axis helpers — translate between flex semantics ("main", "cross", "start",
|
|
3
|
+
* "end") and concrete tuple/property accessors. Keeping this in one place lets
|
|
4
|
+
* the layout pass be written once and work for both row and column directions
|
|
5
|
+
* without endless if-else.
|
|
6
|
+
*
|
|
7
|
+
* Padding and margin tuples are stored as [top, right, bottom, left] in
|
|
8
|
+
* `Style`. Position tuples use the same convention.
|
|
9
|
+
*
|
|
10
|
+
* Gap is split into row-gap and column-gap (per CSS spec):
|
|
11
|
+
* - In `flex-direction: row`, items are laid out horizontally; the gap
|
|
12
|
+
* between them along the main axis is `column-gap`.
|
|
13
|
+
* - In `flex-direction: column`, items are stacked vertically; the gap
|
|
14
|
+
* between them along the main axis is `row-gap`.
|
|
15
|
+
*/
|
|
16
|
+
import type { FlexDirection, Style } from '../style.js';
|
|
17
|
+
export type Axis = 'row' | 'column';
|
|
18
|
+
export declare function mainAxis(d: FlexDirection): Axis;
|
|
19
|
+
export declare function crossAxis(d: FlexDirection): Axis;
|
|
20
|
+
export declare function isReverse(d: FlexDirection): boolean;
|
|
21
|
+
/** Edge index for the start side of a given axis. */
|
|
22
|
+
export declare function startEdge(axis: Axis): number;
|
|
23
|
+
/** Edge index for the end side of a given axis. */
|
|
24
|
+
export declare function endEdge(axis: Axis): number;
|
|
25
|
+
/** Read the start side of a [top, right, bottom, left] tuple. */
|
|
26
|
+
export declare function readStart(box: readonly number[], axis: Axis): number;
|
|
27
|
+
/** Read the end side of a [top, right, bottom, left] tuple. */
|
|
28
|
+
export declare function readEnd(box: readonly number[], axis: Axis): number;
|
|
29
|
+
/**
|
|
30
|
+
* The CSS gap that separates flex items along the given axis.
|
|
31
|
+
* - main axis is row → use column-gap
|
|
32
|
+
* - main axis is column → use row-gap
|
|
33
|
+
*/
|
|
34
|
+
export declare function gapAlong(style: Style, axis: Axis): number;
|
|
35
|
+
/** The style's preferred size along an axis (`width` for row, `height` for column). */
|
|
36
|
+
export declare function preferredSize(style: Style, axis: Axis): number | 'auto';
|
|
37
|
+
export declare function minSize(style: Style, axis: Axis): number;
|
|
38
|
+
export declare function maxSize(style: Style, axis: Axis): number | undefined;
|
|
39
|
+
/** Clamp a candidate size to the [minSize, maxSize] range for the given axis. */
|
|
40
|
+
export declare function clampSize(style: Style, axis: Axis, value: number): number;
|
|
41
|
+
//# sourceMappingURL=axis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"axis.d.ts","sourceRoot":"","sources":["../../src/algorithm/axis.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAExD,MAAM,MAAM,IAAI,GAAG,KAAK,GAAG,QAAQ,CAAC;AAOpC,wBAAgB,QAAQ,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI,CAE/C;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI,CAEhD;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,aAAa,GAAG,OAAO,CAEnD;AAED,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE5C;AAED,mDAAmD;AACnD,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE1C;AAED,iEAAiE;AACjE,wBAAgB,SAAS,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAEpE;AAED,+DAA+D;AAC/D,wBAAgB,OAAO,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAElE;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAEzD;AAED,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAEvE;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAExD;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAEpE;AAED,iFAAiF;AACjF,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMzE"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Axis helpers — translate between flex semantics ("main", "cross", "start",
|
|
3
|
+
* "end") and concrete tuple/property accessors. Keeping this in one place lets
|
|
4
|
+
* the layout pass be written once and work for both row and column directions
|
|
5
|
+
* without endless if-else.
|
|
6
|
+
*
|
|
7
|
+
* Padding and margin tuples are stored as [top, right, bottom, left] in
|
|
8
|
+
* `Style`. Position tuples use the same convention.
|
|
9
|
+
*
|
|
10
|
+
* Gap is split into row-gap and column-gap (per CSS spec):
|
|
11
|
+
* - In `flex-direction: row`, items are laid out horizontally; the gap
|
|
12
|
+
* between them along the main axis is `column-gap`.
|
|
13
|
+
* - In `flex-direction: column`, items are stacked vertically; the gap
|
|
14
|
+
* between them along the main axis is `row-gap`.
|
|
15
|
+
*/
|
|
16
|
+
const TOP = 0;
|
|
17
|
+
const RIGHT = 1;
|
|
18
|
+
const BOTTOM = 2;
|
|
19
|
+
const LEFT = 3;
|
|
20
|
+
export function mainAxis(d) {
|
|
21
|
+
return d === 'row' || d === 'row-reverse' ? 'row' : 'column';
|
|
22
|
+
}
|
|
23
|
+
export function crossAxis(d) {
|
|
24
|
+
return mainAxis(d) === 'row' ? 'column' : 'row';
|
|
25
|
+
}
|
|
26
|
+
export function isReverse(d) {
|
|
27
|
+
return d === 'row-reverse' || d === 'column-reverse';
|
|
28
|
+
}
|
|
29
|
+
/** Edge index for the start side of a given axis. */
|
|
30
|
+
export function startEdge(axis) {
|
|
31
|
+
return axis === 'row' ? LEFT : TOP;
|
|
32
|
+
}
|
|
33
|
+
/** Edge index for the end side of a given axis. */
|
|
34
|
+
export function endEdge(axis) {
|
|
35
|
+
return axis === 'row' ? RIGHT : BOTTOM;
|
|
36
|
+
}
|
|
37
|
+
/** Read the start side of a [top, right, bottom, left] tuple. */
|
|
38
|
+
export function readStart(box, axis) {
|
|
39
|
+
return box[startEdge(axis)] ?? 0;
|
|
40
|
+
}
|
|
41
|
+
/** Read the end side of a [top, right, bottom, left] tuple. */
|
|
42
|
+
export function readEnd(box, axis) {
|
|
43
|
+
return box[endEdge(axis)] ?? 0;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The CSS gap that separates flex items along the given axis.
|
|
47
|
+
* - main axis is row → use column-gap
|
|
48
|
+
* - main axis is column → use row-gap
|
|
49
|
+
*/
|
|
50
|
+
export function gapAlong(style, axis) {
|
|
51
|
+
return axis === 'row' ? style.gapColumn : style.gapRow;
|
|
52
|
+
}
|
|
53
|
+
/** The style's preferred size along an axis (`width` for row, `height` for column). */
|
|
54
|
+
export function preferredSize(style, axis) {
|
|
55
|
+
return axis === 'row' ? style.width : style.height;
|
|
56
|
+
}
|
|
57
|
+
export function minSize(style, axis) {
|
|
58
|
+
return axis === 'row' ? style.minWidth : style.minHeight;
|
|
59
|
+
}
|
|
60
|
+
export function maxSize(style, axis) {
|
|
61
|
+
return axis === 'row' ? style.maxWidth : style.maxHeight;
|
|
62
|
+
}
|
|
63
|
+
/** Clamp a candidate size to the [minSize, maxSize] range for the given axis. */
|
|
64
|
+
export function clampSize(style, axis, value) {
|
|
65
|
+
const min = minSize(style, axis);
|
|
66
|
+
const max = maxSize(style, axis);
|
|
67
|
+
let v = value < min ? min : value;
|
|
68
|
+
if (max !== undefined && v > max)
|
|
69
|
+
v = max;
|
|
70
|
+
return v;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=axis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"axis.js","sourceRoot":"","sources":["../../src/algorithm/axis.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,MAAM,GAAG,GAAG,CAAC,CAAC;AACd,MAAM,KAAK,GAAG,CAAC,CAAC;AAChB,MAAM,MAAM,GAAG,CAAC,CAAC;AACjB,MAAM,IAAI,GAAG,CAAC,CAAC;AAEf,MAAM,UAAU,QAAQ,CAAC,CAAgB;IACvC,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,CAAgB;IACxC,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,CAAgB;IACxC,OAAO,CAAC,KAAK,aAAa,IAAI,CAAC,KAAK,gBAAgB,CAAC;AACvD,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,SAAS,CAAC,IAAU;IAClC,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;AACrC,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,OAAO,CAAC,IAAU;IAChC,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;AACzC,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,SAAS,CAAC,GAAsB,EAAE,IAAU;IAC1D,OAAO,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,OAAO,CAAC,GAAsB,EAAE,IAAU;IACxD,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAY,EAAE,IAAU;IAC/C,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;AACzD,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,aAAa,CAAC,KAAY,EAAE,IAAU;IACpD,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAY,EAAE,IAAU;IAC9C,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAY,EAAE,IAAU;IAC9C,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;AAC3D,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,SAAS,CAAC,KAAY,EAAE,IAAU,EAAE,KAAa;IAC/D,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjC,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;IAClC,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,GAAG,GAAG;QAAE,CAAC,GAAG,GAAG,CAAC;IAC1C,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Top-level entry: turn a tree of styled nodes into a tree of computed
|
|
3
|
+
* layouts. The flow is:
|
|
4
|
+
*
|
|
5
|
+
* 1. Resolve the root's own size from its style + caller availability.
|
|
6
|
+
* 2. Recursively lay out children in floating-point coordinates.
|
|
7
|
+
* 3. Round the whole tree to integer cells.
|
|
8
|
+
* 4. Mark every node clean.
|
|
9
|
+
*/
|
|
10
|
+
import type { Node } from '../node.js';
|
|
11
|
+
export declare function calculateLayout(root: Node, availableWidth: number | undefined, availableHeight: number | undefined): void;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/algorithm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,wBAAgB,eAAe,CAC7B,IAAI,EAAE,IAAI,EACV,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,eAAe,EAAE,MAAM,GAAG,SAAS,GAClC,IAAI,CASN"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Top-level entry: turn a tree of styled nodes into a tree of computed
|
|
3
|
+
* layouts. The flow is:
|
|
4
|
+
*
|
|
5
|
+
* 1. Resolve the root's own size from its style + caller availability.
|
|
6
|
+
* 2. Recursively lay out children in floating-point coordinates.
|
|
7
|
+
* 3. Round the whole tree to integer cells.
|
|
8
|
+
* 4. Mark every node clean.
|
|
9
|
+
*/
|
|
10
|
+
import { layoutChildren, resolveRootAxisSize } from './main-axis.js';
|
|
11
|
+
import { roundLayout } from './round.js';
|
|
12
|
+
export function calculateLayout(root, availableWidth, availableHeight) {
|
|
13
|
+
root.layout.left = 0;
|
|
14
|
+
root.layout.top = 0;
|
|
15
|
+
root.layout.width = resolveRootAxisSize(root, 'row', availableWidth);
|
|
16
|
+
root.layout.height = resolveRootAxisSize(root, 'column', availableHeight);
|
|
17
|
+
layoutChildren(root);
|
|
18
|
+
roundLayout(root);
|
|
19
|
+
markClean(root);
|
|
20
|
+
}
|
|
21
|
+
function markClean(node) {
|
|
22
|
+
node.clearDirty();
|
|
23
|
+
for (let i = 0; i < node.getChildCount(); i++)
|
|
24
|
+
markClean(node.getChild(i));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/algorithm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,UAAU,eAAe,CAC7B,IAAU,EACV,cAAkC,EAClC,eAAmC;IAEnC,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IACrB,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;IACpB,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,mBAAmB,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;IACrE,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;IAE1E,cAAc,CAAC,IAAI,CAAC,CAAC;IACrB,WAAW,CAAC,IAAI,CAAC,CAAC;IAClB,SAAS,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,SAAS,CAAC,IAAU;IAC3B,IAAI,CAAC,UAAU,EAAE,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC,EAAE;QAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC;AAC9E,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The flex layout algorithm — Milestones 4 + 5.
|
|
3
|
+
*
|
|
4
|
+
* Pipeline (one container at a time):
|
|
5
|
+
*
|
|
6
|
+
* 1. Build per-child `FlexItem` records: hypothetical main size (basis or
|
|
7
|
+
* style or measure-func or 0), main and cross margins, "natural" cross
|
|
8
|
+
* size (used when alignment is not stretch).
|
|
9
|
+
* 2. Pack items into `FlexLine`s. With `flex-wrap: nowrap` everything goes
|
|
10
|
+
* on one line; with `wrap` items spill onto a new line whenever the
|
|
11
|
+
* next addition would exceed the container's inner main size.
|
|
12
|
+
* 3. For each line, distribute slack via flex-grow / flex-shrink with the
|
|
13
|
+
* CSS freeze loop (items hitting min/max are frozen, their slack is
|
|
14
|
+
* redistributed among unfrozen siblings). M4 work, unchanged.
|
|
15
|
+
* 4. Compute each line's cross size: max of items' (natural cross +
|
|
16
|
+
* cross-margins). Single-line containers just use the inner cross.
|
|
17
|
+
* 5. Stack lines along the cross axis with `align-content`. Multi-line
|
|
18
|
+
* stacks distribute leftover space; single-line stacks just place the
|
|
19
|
+
* one line at the start.
|
|
20
|
+
* 6. Inside each line, position items along the main axis with
|
|
21
|
+
* `justify-content`. Leftover space is distributed via flex-start /
|
|
22
|
+
* flex-end / center / space-between / space-around / space-evenly.
|
|
23
|
+
* 7. Inside each line, cross-align each item: alignSelf takes precedence,
|
|
24
|
+
* falling back to the container's alignItems for items with
|
|
25
|
+
* alignSelf: 'auto'. Stretch fills the line cross size.
|
|
26
|
+
* 8. Reverse-direction containers flip main positions; wrap-reverse
|
|
27
|
+
* reverses the line stack on the cross axis.
|
|
28
|
+
* 9. Recurse into each visible child.
|
|
29
|
+
*
|
|
30
|
+
* Position rounding lives in `round.ts` and runs once at the very end so
|
|
31
|
+
* sibling boxes butt cleanly on integer cell boundaries.
|
|
32
|
+
*/
|
|
33
|
+
import type { Node } from '../node.js';
|
|
34
|
+
import { type Axis } from './axis.js';
|
|
35
|
+
/**
|
|
36
|
+
* Lay out a node's children. The container's own `layout.width` and
|
|
37
|
+
* `layout.height` must already be set when this is called.
|
|
38
|
+
*
|
|
39
|
+
* Two child populations are handled here:
|
|
40
|
+
* - In-flow flex children (positionType !== 'absolute', display !== 'none'):
|
|
41
|
+
* run through the 8-step flex pipeline.
|
|
42
|
+
* - Out-of-flow absolute children (positionType === 'absolute',
|
|
43
|
+
* display !== 'none'): positioned independently against the parent's
|
|
44
|
+
* content box. They do not contribute to the flex pipeline.
|
|
45
|
+
*
|
|
46
|
+
* After both populations are positioned, the function recurses into every
|
|
47
|
+
* non-hidden child so their own descendants are laid out within the box
|
|
48
|
+
* we just assigned them.
|
|
49
|
+
*/
|
|
50
|
+
export declare function layoutChildren(node: Node): void;
|
|
51
|
+
/**
|
|
52
|
+
* Resolve the root node's own size from style + caller-supplied availability.
|
|
53
|
+
*
|
|
54
|
+
* - explicit number → use it (clamped to min/max).
|
|
55
|
+
* - 'auto' + an `available` value → use available, clamped.
|
|
56
|
+
* - 'auto' with neither → 0.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveRootAxisSize(node: Node, axis: Axis, available: number | undefined): number;
|
|
59
|
+
//# sourceMappingURL=main-axis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main-axis.d.ts","sourceRoot":"","sources":["../../src/algorithm/main-axis.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EACL,KAAK,IAAI,EAWV,MAAM,WAAW,CAAC;AAgCnB;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAyB/C;AAirBD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAcjG"}
|