@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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +97 -0
  3. package/dist/algorithm/axis.d.ts +41 -0
  4. package/dist/algorithm/axis.d.ts.map +1 -0
  5. package/dist/algorithm/axis.js +72 -0
  6. package/dist/algorithm/axis.js.map +1 -0
  7. package/dist/algorithm/index.d.ts +12 -0
  8. package/dist/algorithm/index.d.ts.map +1 -0
  9. package/dist/algorithm/index.js +26 -0
  10. package/dist/algorithm/index.js.map +1 -0
  11. package/dist/algorithm/main-axis.d.ts +59 -0
  12. package/dist/algorithm/main-axis.d.ts.map +1 -0
  13. package/dist/algorithm/main-axis.js +704 -0
  14. package/dist/algorithm/main-axis.js.map +1 -0
  15. package/dist/algorithm/round.d.ts +20 -0
  16. package/dist/algorithm/round.d.ts.map +1 -0
  17. package/dist/algorithm/round.js +45 -0
  18. package/dist/algorithm/round.js.map +1 -0
  19. package/dist/edge.d.ts +23 -0
  20. package/dist/edge.d.ts.map +1 -0
  21. package/dist/edge.js +22 -0
  22. package/dist/edge.js.map +1 -0
  23. package/dist/index.d.ts +9 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +11 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/layout.d.ts +15 -0
  28. package/dist/layout.d.ts.map +1 -0
  29. package/dist/layout.js +4 -0
  30. package/dist/layout.js.map +1 -0
  31. package/dist/measure/ansi.d.ts +15 -0
  32. package/dist/measure/ansi.d.ts.map +1 -0
  33. package/dist/measure/ansi.js +118 -0
  34. package/dist/measure/ansi.js.map +1 -0
  35. package/dist/measure/grapheme.d.ts +43 -0
  36. package/dist/measure/grapheme.d.ts.map +1 -0
  37. package/dist/measure/grapheme.js +169 -0
  38. package/dist/measure/grapheme.js.map +1 -0
  39. package/dist/measure/index.d.ts +4 -0
  40. package/dist/measure/index.d.ts.map +1 -0
  41. package/dist/measure/index.js +4 -0
  42. package/dist/measure/index.js.map +1 -0
  43. package/dist/measure/range-search.d.ts +7 -0
  44. package/dist/measure/range-search.d.ts.map +1 -0
  45. package/dist/measure/range-search.js +22 -0
  46. package/dist/measure/range-search.js.map +1 -0
  47. package/dist/measure/tables.d.ts +16 -0
  48. package/dist/measure/tables.d.ts.map +1 -0
  49. package/dist/measure/tables.js +262 -0
  50. package/dist/measure/tables.js.map +1 -0
  51. package/dist/measure/width.d.ts +37 -0
  52. package/dist/measure/width.d.ts.map +1 -0
  53. package/dist/measure/width.js +96 -0
  54. package/dist/measure/width.js.map +1 -0
  55. package/dist/measure-func.d.ts +24 -0
  56. package/dist/measure-func.d.ts.map +1 -0
  57. package/dist/measure-func.js +18 -0
  58. package/dist/measure-func.js.map +1 -0
  59. package/dist/node.d.ts +96 -0
  60. package/dist/node.d.ts.map +1 -0
  61. package/dist/node.js +332 -0
  62. package/dist/node.js.map +1 -0
  63. package/dist/style.d.ts +53 -0
  64. package/dist/style.d.ts.map +1 -0
  65. package/dist/style.js +40 -0
  66. package/dist/style.js.map +1 -0
  67. 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"}