@alchemy.run/sigil 0.0.0-alpha.1 → 0.0.0-alpha.2
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 +299 -299
- package/dist/ansi.d.ts +223 -0
- package/dist/ansi.js +2 -0
- package/dist/{devtools-QpCMm9JH.mjs → devtools-BhYGjb7h.js} +1 -1
- package/dist/index-DDVME65c.d.ts +919 -0
- package/dist/index.d.ts +1657 -0
- package/dist/index.js +4643 -0
- package/dist/sgr-CMfEpjSk.d.ts +91 -0
- package/dist/truncate-CBiyyZzw.js +2156 -0
- package/dist/yoga-5jKhYCJC.js +3465 -0
- package/dist/yoga.d.ts +2 -0
- package/dist/yoga.js +2 -0
- package/package.json +37 -17
- package/src/ansi/chalk.ts +179 -0
- package/src/ansi/cursor.ts +48 -0
- package/src/ansi/east-asian-width.ts +215 -0
- package/src/ansi/escapes.ts +128 -0
- package/src/ansi/index.ts +27 -0
- package/src/ansi/sgr.ts +237 -0
- package/src/ansi/slice.ts +43 -0
- package/src/ansi/string-width.ts +236 -0
- package/src/ansi/strip.ts +33 -0
- package/src/ansi/supports-color.ts +213 -0
- package/src/ansi/tokenize.ts +453 -0
- package/src/ansi/truncate.ts +194 -0
- package/src/ansi/widest-line.ts +12 -0
- package/src/ansi/wrap.ts +766 -0
- package/src/ansi-tokenizer.ts +510 -0
- package/src/auto-bind.ts +41 -0
- package/src/boxes.ts +100 -0
- package/src/code-excerpt.ts +39 -0
- package/src/colorize.ts +60 -0
- package/src/components/AccessibilityContext.ts +5 -0
- package/src/components/AnimationContext.ts +24 -0
- package/src/components/App.tsx +781 -0
- package/src/components/AppContext.ts +111 -0
- package/src/components/BackgroundContext.ts +8 -0
- package/src/components/Box.tsx +116 -0
- package/src/components/CursorContext.ts +19 -0
- package/src/components/ErrorBoundary.tsx +38 -0
- package/src/components/ErrorOverview.tsx +133 -0
- package/src/components/FocusContext.ts +30 -0
- package/src/components/Newline.tsx +15 -0
- package/src/components/Spacer.tsx +10 -0
- package/src/components/Static.tsx +59 -0
- package/src/components/StderrContext.ts +26 -0
- package/src/components/StdinContext.ts +49 -0
- package/src/components/StdoutContext.ts +28 -0
- package/src/components/Text.tsx +144 -0
- package/src/components/Transform.tsx +37 -0
- package/src/cursor-position.ts +103 -0
- package/src/devtools-window-polyfill.ts +73 -0
- package/src/devtools.ts +43 -0
- package/src/dom.ts +292 -0
- package/src/get-max-width.ts +11 -0
- package/src/global.d.ts +36 -0
- package/src/hooks/use-animation.ts +142 -0
- package/src/hooks/use-app.ts +8 -0
- package/src/hooks/use-box-metrics.ts +134 -0
- package/src/hooks/use-cursor.ts +33 -0
- package/src/hooks/use-focus-manager.ts +62 -0
- package/src/hooks/use-focus.ts +83 -0
- package/src/hooks/use-input.ts +267 -0
- package/src/hooks/use-is-screen-reader-enabled.ts +12 -0
- package/src/hooks/use-paste.ts +78 -0
- package/src/hooks/use-stderr.ts +8 -0
- package/src/hooks/use-stdin.ts +10 -0
- package/src/hooks/use-stdout.ts +8 -0
- package/src/hooks/use-window-size.ts +41 -0
- package/src/indent-string.ts +16 -0
- package/src/index.ts +44 -0
- package/src/ink.tsx +1506 -0
- package/src/input-parser.ts +283 -0
- package/src/instances.ts +9 -0
- package/src/is-in-ci.ts +7 -0
- package/src/kitty-keyboard.ts +57 -0
- package/src/log-update.ts +370 -0
- package/src/measure-element.ts +62 -0
- package/src/measure-text.ts +31 -0
- package/src/output.ts +308 -0
- package/src/parse-keypress.ts +516 -0
- package/src/parse-stack-line.ts +139 -0
- package/src/patch-console.ts +62 -0
- package/src/quick-lru.ts +85 -0
- package/src/reconciler.ts +451 -0
- package/src/render-background.ts +38 -0
- package/src/render-border.ts +134 -0
- package/src/render-node-to-output.ts +191 -0
- package/src/render-to-string.ts +131 -0
- package/src/render.ts +276 -0
- package/src/renderer.ts +73 -0
- package/src/sanitize-ansi.ts +33 -0
- package/src/signal-exit.ts +107 -0
- package/src/squash-text-nodes.ts +40 -0
- package/src/stream.ts +30 -0
- package/src/styles.ts +748 -0
- package/src/terminal-size.ts +57 -0
- package/src/throttle.ts +73 -0
- package/src/types.ts +15 -0
- package/src/utils.ts +40 -0
- package/src/wrap-text.ts +50 -0
- package/src/write-synchronized.ts +9 -0
- package/src/yoga/config.ts +57 -0
- package/src/yoga/core/absoluteLayout.ts +626 -0
- package/src/yoga/core/baseline.ts +66 -0
- package/src/yoga/core/cache.ts +136 -0
- package/src/yoga/core/calculateLayout.ts +2920 -0
- package/src/yoga/core/config.ts +104 -0
- package/src/yoga/core/flexLine.ts +177 -0
- package/src/yoga/core/helpers.ts +293 -0
- package/src/yoga/core/layoutResults.ts +167 -0
- package/src/yoga/core/node.ts +611 -0
- package/src/yoga/core/numeric.ts +44 -0
- package/src/yoga/core/pixelGrid.ts +151 -0
- package/src/yoga/core/style.ts +887 -0
- package/src/yoga/core/types.ts +224 -0
- package/src/yoga/generated/YGEnums.ts +263 -0
- package/src/yoga/index.ts +19 -0
- package/src/yoga/node.ts +1140 -0
- package/dist/index.d.mts +0 -2379
- package/dist/index.mjs +0 -10072
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Derived from Yoga. See THIRD_PARTY_NOTICES.md.
|
|
3
|
+
|
|
4
|
+
// Port of yoga/algorithm/AbsoluteLayout.cpp. Grid-specific branches are kept
|
|
5
|
+
// where they read from style, but Display.Grid is not otherwise supported.
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
Align,
|
|
9
|
+
Dimension,
|
|
10
|
+
Direction,
|
|
11
|
+
Display,
|
|
12
|
+
Errata,
|
|
13
|
+
FlexDirection,
|
|
14
|
+
Justify,
|
|
15
|
+
PositionType,
|
|
16
|
+
Wrap,
|
|
17
|
+
} from "../generated/YGEnums.ts";
|
|
18
|
+
import {
|
|
19
|
+
type LayoutData,
|
|
20
|
+
LayoutPassReason,
|
|
21
|
+
calculateLayoutInternal,
|
|
22
|
+
cleanupContentsNodesRecursively,
|
|
23
|
+
} from "./calculateLayout.ts";
|
|
24
|
+
import {
|
|
25
|
+
PhysicalEdge,
|
|
26
|
+
SizingMode,
|
|
27
|
+
boundAxis,
|
|
28
|
+
dimension,
|
|
29
|
+
flexEndEdge,
|
|
30
|
+
flexStartEdge,
|
|
31
|
+
getPositionOfOppositeEdge,
|
|
32
|
+
inlineStartEdge,
|
|
33
|
+
isRow,
|
|
34
|
+
needsTrailingPosition,
|
|
35
|
+
resolveChildAlignment,
|
|
36
|
+
resolveChildJustification,
|
|
37
|
+
resolveCrossDirection,
|
|
38
|
+
resolveDirection,
|
|
39
|
+
setChildTrailingPosition,
|
|
40
|
+
} from "./helpers.ts";
|
|
41
|
+
import type { Node } from "./node.ts";
|
|
42
|
+
import { isDefined, isUndefined } from "./numeric.ts";
|
|
43
|
+
|
|
44
|
+
function setFlexStartLayoutPosition(
|
|
45
|
+
parent: Node,
|
|
46
|
+
child: Node,
|
|
47
|
+
direction: Direction,
|
|
48
|
+
axis: FlexDirection,
|
|
49
|
+
containingBlockWidth: number,
|
|
50
|
+
): void {
|
|
51
|
+
let position =
|
|
52
|
+
child.style.computeFlexStartMargin(axis, direction, containingBlockWidth) +
|
|
53
|
+
parent.layout.border(flexStartEdge(axis));
|
|
54
|
+
|
|
55
|
+
// https://www.w3.org/TR/css-grid-1/#abspos
|
|
56
|
+
// absolute positioned grid items are positioned relative to the padding edge
|
|
57
|
+
// of the grid container
|
|
58
|
+
if (
|
|
59
|
+
!child.hasErrata(Errata.AbsolutePositionWithoutInsetsExcludesPadding) &&
|
|
60
|
+
parent.style.display() !== Display.Grid
|
|
61
|
+
) {
|
|
62
|
+
position += parent.layout.padding(flexStartEdge(axis));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
child.setLayoutPosition(position, flexStartEdge(axis));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function setFlexEndLayoutPosition(
|
|
69
|
+
parent: Node,
|
|
70
|
+
child: Node,
|
|
71
|
+
direction: Direction,
|
|
72
|
+
axis: FlexDirection,
|
|
73
|
+
containingBlockWidth: number,
|
|
74
|
+
): void {
|
|
75
|
+
let flexEndPosition =
|
|
76
|
+
parent.layout.border(flexEndEdge(axis)) +
|
|
77
|
+
child.style.computeFlexEndMargin(axis, direction, containingBlockWidth);
|
|
78
|
+
|
|
79
|
+
// https://www.w3.org/TR/css-grid-1/#abspos
|
|
80
|
+
// absolute positioned grid items are positioned relative to the padding edge
|
|
81
|
+
// of the grid container
|
|
82
|
+
if (
|
|
83
|
+
!child.hasErrata(Errata.AbsolutePositionWithoutInsetsExcludesPadding) &&
|
|
84
|
+
parent.style.display() !== Display.Grid
|
|
85
|
+
) {
|
|
86
|
+
flexEndPosition += parent.layout.padding(flexEndEdge(axis));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
child.setLayoutPosition(
|
|
90
|
+
getPositionOfOppositeEdge(flexEndPosition, axis, parent, child),
|
|
91
|
+
flexStartEdge(axis),
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function setCenterLayoutPosition(
|
|
96
|
+
parent: Node,
|
|
97
|
+
child: Node,
|
|
98
|
+
direction: Direction,
|
|
99
|
+
axis: FlexDirection,
|
|
100
|
+
containingBlockWidth: number,
|
|
101
|
+
): void {
|
|
102
|
+
let parentContentBoxSize =
|
|
103
|
+
parent.layout.measuredDimension(dimension(axis)) -
|
|
104
|
+
parent.layout.border(flexStartEdge(axis)) -
|
|
105
|
+
parent.layout.border(flexEndEdge(axis));
|
|
106
|
+
|
|
107
|
+
// https://www.w3.org/TR/css-grid-1/#abspos
|
|
108
|
+
// absolute positioned grid items are positioned relative to the padding edge
|
|
109
|
+
// of the grid container
|
|
110
|
+
if (
|
|
111
|
+
!child.hasErrata(Errata.AbsolutePositionWithoutInsetsExcludesPadding) &&
|
|
112
|
+
parent.style.display() !== Display.Grid
|
|
113
|
+
) {
|
|
114
|
+
parentContentBoxSize -= parent.layout.padding(flexStartEdge(axis));
|
|
115
|
+
parentContentBoxSize -= parent.layout.padding(flexEndEdge(axis));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const childOuterSize =
|
|
119
|
+
child.layout.measuredDimension(dimension(axis)) +
|
|
120
|
+
child.style.computeMarginForAxis(axis, containingBlockWidth);
|
|
121
|
+
|
|
122
|
+
let position =
|
|
123
|
+
(parentContentBoxSize - childOuterSize) / 2.0 +
|
|
124
|
+
parent.layout.border(flexStartEdge(axis)) +
|
|
125
|
+
child.style.computeFlexStartMargin(axis, direction, containingBlockWidth);
|
|
126
|
+
|
|
127
|
+
// https://www.w3.org/TR/css-grid-1/#abspos
|
|
128
|
+
// absolute positioned grid items are positioned relative to the padding edge
|
|
129
|
+
// of the grid container
|
|
130
|
+
if (
|
|
131
|
+
!child.hasErrata(Errata.AbsolutePositionWithoutInsetsExcludesPadding) &&
|
|
132
|
+
parent.style.display() !== Display.Grid
|
|
133
|
+
) {
|
|
134
|
+
position += parent.layout.padding(flexStartEdge(axis));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
child.setLayoutPosition(position, flexStartEdge(axis));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function justifyAbsoluteChild(
|
|
141
|
+
parent: Node,
|
|
142
|
+
child: Node,
|
|
143
|
+
direction: Direction,
|
|
144
|
+
mainAxis: FlexDirection,
|
|
145
|
+
containingBlockWidth: number,
|
|
146
|
+
): void {
|
|
147
|
+
const justify =
|
|
148
|
+
parent.style.display() === Display.Grid
|
|
149
|
+
? resolveChildJustification(parent, child)
|
|
150
|
+
: parent.style.justifyContent();
|
|
151
|
+
switch (justify) {
|
|
152
|
+
case Justify.Start:
|
|
153
|
+
case Justify.Auto:
|
|
154
|
+
case Justify.Stretch:
|
|
155
|
+
case Justify.FlexStart:
|
|
156
|
+
case Justify.SpaceBetween:
|
|
157
|
+
setFlexStartLayoutPosition(parent, child, direction, mainAxis, containingBlockWidth);
|
|
158
|
+
break;
|
|
159
|
+
case Justify.End:
|
|
160
|
+
case Justify.FlexEnd:
|
|
161
|
+
setFlexEndLayoutPosition(parent, child, direction, mainAxis, containingBlockWidth);
|
|
162
|
+
break;
|
|
163
|
+
case Justify.Center:
|
|
164
|
+
case Justify.SpaceAround:
|
|
165
|
+
case Justify.SpaceEvenly:
|
|
166
|
+
setCenterLayoutPosition(parent, child, direction, mainAxis, containingBlockWidth);
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function alignAbsoluteChild(
|
|
172
|
+
parent: Node,
|
|
173
|
+
child: Node,
|
|
174
|
+
direction: Direction,
|
|
175
|
+
crossAxis: FlexDirection,
|
|
176
|
+
containingBlockWidth: number,
|
|
177
|
+
): void {
|
|
178
|
+
let itemAlign = resolveChildAlignment(parent, child);
|
|
179
|
+
const parentWrap = parent.style.flexWrap();
|
|
180
|
+
if (parentWrap === Wrap.WrapReverse) {
|
|
181
|
+
if (itemAlign === Align.FlexEnd) {
|
|
182
|
+
itemAlign = Align.FlexStart;
|
|
183
|
+
} else if (itemAlign !== Align.Center) {
|
|
184
|
+
itemAlign = Align.FlexEnd;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
switch (itemAlign) {
|
|
189
|
+
case Align.Start:
|
|
190
|
+
case Align.Auto:
|
|
191
|
+
case Align.FlexStart:
|
|
192
|
+
case Align.Baseline:
|
|
193
|
+
case Align.SpaceAround:
|
|
194
|
+
case Align.SpaceBetween:
|
|
195
|
+
case Align.Stretch:
|
|
196
|
+
case Align.SpaceEvenly:
|
|
197
|
+
setFlexStartLayoutPosition(parent, child, direction, crossAxis, containingBlockWidth);
|
|
198
|
+
break;
|
|
199
|
+
case Align.End:
|
|
200
|
+
case Align.FlexEnd:
|
|
201
|
+
setFlexEndLayoutPosition(parent, child, direction, crossAxis, containingBlockWidth);
|
|
202
|
+
break;
|
|
203
|
+
case Align.Center:
|
|
204
|
+
setCenterLayoutPosition(parent, child, direction, crossAxis, containingBlockWidth);
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/*
|
|
210
|
+
* Absolutely positioned nodes do not participate in flex layout and thus their
|
|
211
|
+
* positions can be determined independently from the rest of their siblings.
|
|
212
|
+
* For each axis there are essentially two cases:
|
|
213
|
+
*
|
|
214
|
+
* 1) The node has insets defined. In this case we can just use these to
|
|
215
|
+
* determine the position of the node.
|
|
216
|
+
* 2) The node does not have insets defined. In this case we look at the style
|
|
217
|
+
* of the parent to position the node. Things like justify content and
|
|
218
|
+
* align content will move absolute children around. If none of these
|
|
219
|
+
* special properties are defined, the child is positioned at the start
|
|
220
|
+
* (defined by flex direction) of the leading flex line.
|
|
221
|
+
*
|
|
222
|
+
* This function does that positioning for the given axis. The spec has more
|
|
223
|
+
* information on this topic: https://www.w3.org/TR/css-flexbox-1/#abspos-items
|
|
224
|
+
*/
|
|
225
|
+
function positionAbsoluteChild(
|
|
226
|
+
containingNode: Node,
|
|
227
|
+
parent: Node,
|
|
228
|
+
child: Node,
|
|
229
|
+
direction: Direction,
|
|
230
|
+
axis: FlexDirection,
|
|
231
|
+
isMainAxis: boolean,
|
|
232
|
+
containingBlockWidth: number,
|
|
233
|
+
containingBlockHeight: number,
|
|
234
|
+
): void {
|
|
235
|
+
const isAxisRow = isRow(axis);
|
|
236
|
+
const containingBlockSize = isAxisRow ? containingBlockWidth : containingBlockHeight;
|
|
237
|
+
|
|
238
|
+
// The inline-start position takes priority over the end position in the case
|
|
239
|
+
// that they are both set and the node has a fixed width. Thus we only have 2
|
|
240
|
+
// cases here: if inline-start is defined and if inline-end is defined.
|
|
241
|
+
//
|
|
242
|
+
// Despite checking inline-start to honor prioritization of insets, we write
|
|
243
|
+
// to the flex-start edge because this algorithm works by positioning on the
|
|
244
|
+
// flex-start edge and then filling in the flex-end direction at the end if
|
|
245
|
+
// necessary.
|
|
246
|
+
if (
|
|
247
|
+
child.style.isInlineStartPositionDefined(axis, direction) &&
|
|
248
|
+
!child.style.isInlineStartPositionAuto(axis, direction)
|
|
249
|
+
) {
|
|
250
|
+
const positionRelativeToInlineStart =
|
|
251
|
+
child.style.computeInlineStartPosition(axis, direction, containingBlockSize) +
|
|
252
|
+
containingNode.style.computeInlineStartBorder(axis, direction) +
|
|
253
|
+
child.style.computeInlineStartMargin(axis, direction, containingBlockSize);
|
|
254
|
+
const positionRelativeToFlexStart =
|
|
255
|
+
inlineStartEdge(axis, direction) !== flexStartEdge(axis)
|
|
256
|
+
? getPositionOfOppositeEdge(positionRelativeToInlineStart, axis, containingNode, child)
|
|
257
|
+
: positionRelativeToInlineStart;
|
|
258
|
+
|
|
259
|
+
child.setLayoutPosition(positionRelativeToFlexStart, flexStartEdge(axis));
|
|
260
|
+
} else if (
|
|
261
|
+
child.style.isInlineEndPositionDefined(axis, direction) &&
|
|
262
|
+
!child.style.isInlineEndPositionAuto(axis, direction)
|
|
263
|
+
) {
|
|
264
|
+
const positionRelativeToInlineStart =
|
|
265
|
+
containingNode.layout.measuredDimension(dimension(axis)) -
|
|
266
|
+
child.layout.measuredDimension(dimension(axis)) -
|
|
267
|
+
containingNode.style.computeInlineEndBorder(axis, direction) -
|
|
268
|
+
child.style.computeInlineEndMargin(axis, direction, containingBlockSize) -
|
|
269
|
+
child.style.computeInlineEndPosition(axis, direction, containingBlockSize);
|
|
270
|
+
const positionRelativeToFlexStart =
|
|
271
|
+
inlineStartEdge(axis, direction) !== flexStartEdge(axis)
|
|
272
|
+
? getPositionOfOppositeEdge(positionRelativeToInlineStart, axis, containingNode, child)
|
|
273
|
+
: positionRelativeToInlineStart;
|
|
274
|
+
|
|
275
|
+
child.setLayoutPosition(positionRelativeToFlexStart, flexStartEdge(axis));
|
|
276
|
+
} else if (isMainAxis) {
|
|
277
|
+
justifyAbsoluteChild(parent, child, direction, axis, containingBlockWidth);
|
|
278
|
+
} else {
|
|
279
|
+
alignAbsoluteChild(parent, child, direction, axis, containingBlockWidth);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export function layoutAbsoluteChild(
|
|
284
|
+
containingNode: Node,
|
|
285
|
+
node: Node,
|
|
286
|
+
child: Node,
|
|
287
|
+
containingBlockWidth: number,
|
|
288
|
+
containingBlockHeight: number,
|
|
289
|
+
widthMode: SizingMode,
|
|
290
|
+
direction: Direction,
|
|
291
|
+
layoutMarkerData: LayoutData,
|
|
292
|
+
depth: number,
|
|
293
|
+
generationCount: number,
|
|
294
|
+
): void {
|
|
295
|
+
// For grid containers, use inline (Row) and block (Column) axes for
|
|
296
|
+
// positioning, since grid alignment properties (justify-self, align-self)
|
|
297
|
+
// operate on inline/block axes, not main/cross axes based on flex-direction.
|
|
298
|
+
const mainAxis =
|
|
299
|
+
node.style.display() === Display.Grid
|
|
300
|
+
? resolveDirection(FlexDirection.Row, direction)
|
|
301
|
+
: resolveDirection(node.style.flexDirection(), direction);
|
|
302
|
+
const crossAxis =
|
|
303
|
+
node.style.display() === Display.Grid
|
|
304
|
+
? FlexDirection.Column
|
|
305
|
+
: resolveCrossDirection(mainAxis, direction);
|
|
306
|
+
const isMainAxisRow = isRow(mainAxis);
|
|
307
|
+
|
|
308
|
+
let childWidth = NaN;
|
|
309
|
+
let childHeight = NaN;
|
|
310
|
+
let childWidthSizingMode: SizingMode = SizingMode.MaxContent;
|
|
311
|
+
let childHeightSizingMode: SizingMode = SizingMode.MaxContent;
|
|
312
|
+
|
|
313
|
+
const marginRow = child.style.computeMarginForAxis(FlexDirection.Row, containingBlockWidth);
|
|
314
|
+
const marginColumn = child.style.computeMarginForAxis(FlexDirection.Column, containingBlockWidth);
|
|
315
|
+
|
|
316
|
+
if (child.hasDefiniteLength(Dimension.Width, containingBlockWidth)) {
|
|
317
|
+
childWidth =
|
|
318
|
+
child.getResolvedDimension(
|
|
319
|
+
direction,
|
|
320
|
+
Dimension.Width,
|
|
321
|
+
containingBlockWidth,
|
|
322
|
+
containingBlockWidth,
|
|
323
|
+
) + marginRow;
|
|
324
|
+
} else {
|
|
325
|
+
// If the child doesn't have a specified width, compute the width based on
|
|
326
|
+
// the left/right offsets if they're defined.
|
|
327
|
+
if (
|
|
328
|
+
child.style.isFlexStartPositionDefined(FlexDirection.Row, direction) &&
|
|
329
|
+
child.style.isFlexEndPositionDefined(FlexDirection.Row, direction) &&
|
|
330
|
+
!child.style.isFlexStartPositionAuto(FlexDirection.Row, direction) &&
|
|
331
|
+
!child.style.isFlexEndPositionAuto(FlexDirection.Row, direction)
|
|
332
|
+
) {
|
|
333
|
+
childWidth =
|
|
334
|
+
containingNode.layout.measuredDimension(Dimension.Width) -
|
|
335
|
+
(containingNode.style.computeFlexStartBorder(FlexDirection.Row, direction) +
|
|
336
|
+
containingNode.style.computeFlexEndBorder(FlexDirection.Row, direction)) -
|
|
337
|
+
(child.style.computeFlexStartPosition(FlexDirection.Row, direction, containingBlockWidth) +
|
|
338
|
+
child.style.computeFlexEndPosition(FlexDirection.Row, direction, containingBlockWidth));
|
|
339
|
+
childWidth = boundAxis(
|
|
340
|
+
child,
|
|
341
|
+
FlexDirection.Row,
|
|
342
|
+
direction,
|
|
343
|
+
childWidth,
|
|
344
|
+
containingBlockWidth,
|
|
345
|
+
containingBlockWidth,
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (child.hasDefiniteLength(Dimension.Height, containingBlockHeight)) {
|
|
351
|
+
childHeight =
|
|
352
|
+
child.getResolvedDimension(
|
|
353
|
+
direction,
|
|
354
|
+
Dimension.Height,
|
|
355
|
+
containingBlockHeight,
|
|
356
|
+
containingBlockWidth,
|
|
357
|
+
) + marginColumn;
|
|
358
|
+
} else {
|
|
359
|
+
// If the child doesn't have a specified height, compute the height based
|
|
360
|
+
// on the top/bottom offsets if they're defined.
|
|
361
|
+
if (
|
|
362
|
+
child.style.isFlexStartPositionDefined(FlexDirection.Column, direction) &&
|
|
363
|
+
child.style.isFlexEndPositionDefined(FlexDirection.Column, direction) &&
|
|
364
|
+
!child.style.isFlexStartPositionAuto(FlexDirection.Column, direction) &&
|
|
365
|
+
!child.style.isFlexEndPositionAuto(FlexDirection.Column, direction)
|
|
366
|
+
) {
|
|
367
|
+
childHeight =
|
|
368
|
+
containingNode.layout.measuredDimension(Dimension.Height) -
|
|
369
|
+
(containingNode.style.computeFlexStartBorder(FlexDirection.Column, direction) +
|
|
370
|
+
containingNode.style.computeFlexEndBorder(FlexDirection.Column, direction)) -
|
|
371
|
+
(child.style.computeFlexStartPosition(
|
|
372
|
+
FlexDirection.Column,
|
|
373
|
+
direction,
|
|
374
|
+
containingBlockHeight,
|
|
375
|
+
) +
|
|
376
|
+
child.style.computeFlexEndPosition(
|
|
377
|
+
FlexDirection.Column,
|
|
378
|
+
direction,
|
|
379
|
+
containingBlockHeight,
|
|
380
|
+
));
|
|
381
|
+
childHeight = boundAxis(
|
|
382
|
+
child,
|
|
383
|
+
FlexDirection.Column,
|
|
384
|
+
direction,
|
|
385
|
+
childHeight,
|
|
386
|
+
containingBlockHeight,
|
|
387
|
+
containingBlockWidth,
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Exactly one dimension needs to be defined for us to be able to do aspect
|
|
393
|
+
// ratio calculation. One dimension being the anchor and the other being
|
|
394
|
+
// flexible.
|
|
395
|
+
const childStyle = child.style;
|
|
396
|
+
if (isUndefined(childWidth) !== isUndefined(childHeight)) {
|
|
397
|
+
if (isDefined(childStyle.aspectRatio())) {
|
|
398
|
+
if (isUndefined(childWidth)) {
|
|
399
|
+
childWidth = marginRow + (childHeight - marginColumn) * childStyle.aspectRatio();
|
|
400
|
+
} else if (isUndefined(childHeight)) {
|
|
401
|
+
childHeight = marginColumn + (childWidth - marginRow) / childStyle.aspectRatio();
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// If we're still missing one or the other dimension, measure the content.
|
|
407
|
+
if (isUndefined(childWidth) || isUndefined(childHeight)) {
|
|
408
|
+
childWidthSizingMode = isUndefined(childWidth) ? SizingMode.MaxContent : SizingMode.StretchFit;
|
|
409
|
+
childHeightSizingMode = isUndefined(childHeight)
|
|
410
|
+
? SizingMode.MaxContent
|
|
411
|
+
: SizingMode.StretchFit;
|
|
412
|
+
|
|
413
|
+
// If the size of the owner is defined then try to constrain the absolute
|
|
414
|
+
// child to that size as well. This allows text within the absolute child
|
|
415
|
+
// to wrap to the size of its owner. This is the same behavior as many
|
|
416
|
+
// browsers implement.
|
|
417
|
+
if (
|
|
418
|
+
!isMainAxisRow &&
|
|
419
|
+
isUndefined(childWidth) &&
|
|
420
|
+
widthMode !== SizingMode.MaxContent &&
|
|
421
|
+
isDefined(containingBlockWidth) &&
|
|
422
|
+
containingBlockWidth > 0
|
|
423
|
+
) {
|
|
424
|
+
childWidth = containingBlockWidth;
|
|
425
|
+
childWidthSizingMode = SizingMode.FitContent;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
calculateLayoutInternal(
|
|
429
|
+
child,
|
|
430
|
+
childWidth,
|
|
431
|
+
childHeight,
|
|
432
|
+
direction,
|
|
433
|
+
childWidthSizingMode,
|
|
434
|
+
childHeightSizingMode,
|
|
435
|
+
containingBlockWidth,
|
|
436
|
+
containingBlockHeight,
|
|
437
|
+
false,
|
|
438
|
+
LayoutPassReason.AbsMeasureChild,
|
|
439
|
+
layoutMarkerData,
|
|
440
|
+
depth,
|
|
441
|
+
generationCount,
|
|
442
|
+
);
|
|
443
|
+
childWidth =
|
|
444
|
+
child.layout.measuredDimension(Dimension.Width) +
|
|
445
|
+
child.style.computeMarginForAxis(FlexDirection.Row, containingBlockWidth);
|
|
446
|
+
childHeight =
|
|
447
|
+
child.layout.measuredDimension(Dimension.Height) +
|
|
448
|
+
child.style.computeMarginForAxis(FlexDirection.Column, containingBlockWidth);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
calculateLayoutInternal(
|
|
452
|
+
child,
|
|
453
|
+
childWidth,
|
|
454
|
+
childHeight,
|
|
455
|
+
direction,
|
|
456
|
+
SizingMode.StretchFit,
|
|
457
|
+
SizingMode.StretchFit,
|
|
458
|
+
containingBlockWidth,
|
|
459
|
+
containingBlockHeight,
|
|
460
|
+
true,
|
|
461
|
+
LayoutPassReason.AbsLayout,
|
|
462
|
+
layoutMarkerData,
|
|
463
|
+
depth,
|
|
464
|
+
generationCount,
|
|
465
|
+
);
|
|
466
|
+
|
|
467
|
+
positionAbsoluteChild(
|
|
468
|
+
containingNode,
|
|
469
|
+
node,
|
|
470
|
+
child,
|
|
471
|
+
direction,
|
|
472
|
+
mainAxis,
|
|
473
|
+
true /*isMainAxis*/,
|
|
474
|
+
containingBlockWidth,
|
|
475
|
+
containingBlockHeight,
|
|
476
|
+
);
|
|
477
|
+
positionAbsoluteChild(
|
|
478
|
+
containingNode,
|
|
479
|
+
node,
|
|
480
|
+
child,
|
|
481
|
+
direction,
|
|
482
|
+
crossAxis,
|
|
483
|
+
false /*isMainAxis*/,
|
|
484
|
+
containingBlockWidth,
|
|
485
|
+
containingBlockHeight,
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
export function layoutAbsoluteDescendants(
|
|
490
|
+
containingNode: Node,
|
|
491
|
+
currentNode: Node,
|
|
492
|
+
widthSizingMode: SizingMode,
|
|
493
|
+
currentNodeDirection: Direction,
|
|
494
|
+
layoutMarkerData: LayoutData,
|
|
495
|
+
currentDepth: number,
|
|
496
|
+
generationCount: number,
|
|
497
|
+
currentNodeLeftOffsetFromContainingBlock: number,
|
|
498
|
+
currentNodeTopOffsetFromContainingBlock: number,
|
|
499
|
+
containingNodeAvailableInnerWidth: number,
|
|
500
|
+
containingNodeAvailableInnerHeight: number,
|
|
501
|
+
): boolean {
|
|
502
|
+
let hasNewLayout = false;
|
|
503
|
+
for (const child of currentNode.getLayoutChildren()) {
|
|
504
|
+
if (child.style.display() === Display.None) {
|
|
505
|
+
continue;
|
|
506
|
+
} else if (child.style.positionType() === PositionType.Absolute) {
|
|
507
|
+
const absoluteErrata = currentNode.hasErrata(Errata.AbsolutePercentAgainstInnerSize);
|
|
508
|
+
const containingBlockWidth = absoluteErrata
|
|
509
|
+
? containingNodeAvailableInnerWidth
|
|
510
|
+
: containingNode.layout.measuredDimension(Dimension.Width) -
|
|
511
|
+
containingNode.style.computeBorderForAxis(FlexDirection.Row);
|
|
512
|
+
const containingBlockHeight = absoluteErrata
|
|
513
|
+
? containingNodeAvailableInnerHeight
|
|
514
|
+
: containingNode.layout.measuredDimension(Dimension.Height) -
|
|
515
|
+
containingNode.style.computeBorderForAxis(FlexDirection.Column);
|
|
516
|
+
|
|
517
|
+
layoutAbsoluteChild(
|
|
518
|
+
containingNode,
|
|
519
|
+
currentNode,
|
|
520
|
+
child,
|
|
521
|
+
containingBlockWidth,
|
|
522
|
+
containingBlockHeight,
|
|
523
|
+
widthSizingMode,
|
|
524
|
+
currentNodeDirection,
|
|
525
|
+
layoutMarkerData,
|
|
526
|
+
currentDepth,
|
|
527
|
+
generationCount,
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
hasNewLayout = hasNewLayout || child.hasNewLayout_;
|
|
531
|
+
|
|
532
|
+
/*
|
|
533
|
+
* At this point the child has its position set but only on its the
|
|
534
|
+
* parent's flexStart edge. Additionally, this position should be
|
|
535
|
+
* interpreted relative to the containing block of the child if it had
|
|
536
|
+
* insets defined. So we need to adjust the position by subtracting the
|
|
537
|
+
* the parents offset from the containing block. However, getting that
|
|
538
|
+
* offset is complicated since the two nodes can have different main/cross
|
|
539
|
+
* axes.
|
|
540
|
+
*/
|
|
541
|
+
const parentMainAxis = resolveDirection(
|
|
542
|
+
currentNode.style.flexDirection(),
|
|
543
|
+
currentNodeDirection,
|
|
544
|
+
);
|
|
545
|
+
const parentCrossAxis = resolveCrossDirection(parentMainAxis, currentNodeDirection);
|
|
546
|
+
|
|
547
|
+
if (needsTrailingPosition(parentMainAxis)) {
|
|
548
|
+
const mainInsetsDefined = isRow(parentMainAxis)
|
|
549
|
+
? child.style.horizontalInsetsDefined()
|
|
550
|
+
: child.style.verticalInsetsDefined();
|
|
551
|
+
setChildTrailingPosition(
|
|
552
|
+
mainInsetsDefined ? containingNode : currentNode,
|
|
553
|
+
child,
|
|
554
|
+
parentMainAxis,
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
if (needsTrailingPosition(parentCrossAxis)) {
|
|
558
|
+
const crossInsetsDefined = isRow(parentCrossAxis)
|
|
559
|
+
? child.style.horizontalInsetsDefined()
|
|
560
|
+
: child.style.verticalInsetsDefined();
|
|
561
|
+
setChildTrailingPosition(
|
|
562
|
+
crossInsetsDefined ? containingNode : currentNode,
|
|
563
|
+
child,
|
|
564
|
+
parentCrossAxis,
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/*
|
|
569
|
+
* At this point we know the left and top physical edges of the child are
|
|
570
|
+
* set with positions that are relative to the containing block if insets
|
|
571
|
+
* are defined
|
|
572
|
+
*/
|
|
573
|
+
const childLeftPosition = child.layout.position(PhysicalEdge.Left);
|
|
574
|
+
const childTopPosition = child.layout.position(PhysicalEdge.Top);
|
|
575
|
+
|
|
576
|
+
const childLeftOffsetFromParent = child.style.horizontalInsetsDefined()
|
|
577
|
+
? childLeftPosition - currentNodeLeftOffsetFromContainingBlock
|
|
578
|
+
: childLeftPosition;
|
|
579
|
+
const childTopOffsetFromParent = child.style.verticalInsetsDefined()
|
|
580
|
+
? childTopPosition - currentNodeTopOffsetFromContainingBlock
|
|
581
|
+
: childTopPosition;
|
|
582
|
+
|
|
583
|
+
child.setLayoutPosition(childLeftOffsetFromParent, PhysicalEdge.Left);
|
|
584
|
+
child.setLayoutPosition(childTopOffsetFromParent, PhysicalEdge.Top);
|
|
585
|
+
} else if (
|
|
586
|
+
child.style.positionType() === PositionType.Static &&
|
|
587
|
+
!child.alwaysFormsContainingBlock
|
|
588
|
+
) {
|
|
589
|
+
// We may write new layout results for absolute descendants of "child"
|
|
590
|
+
// which are positioned relative to the current containing block instead
|
|
591
|
+
// of their parent. "child" may not be dirty, or have new constraints, so
|
|
592
|
+
// absolute positioning may be the first time during this layout pass
|
|
593
|
+
// that we need to mutate these descendents. Make sure the path of nodes
|
|
594
|
+
// to them is mutable before positioning.
|
|
595
|
+
child.cloneChildrenIfNeeded();
|
|
596
|
+
const childDirection = child.resolveDirection(currentNodeDirection);
|
|
597
|
+
// By now all descendants of the containing block that are not absolute
|
|
598
|
+
// will have their positions set for left and top.
|
|
599
|
+
const childLeftOffsetFromContainingBlock =
|
|
600
|
+
currentNodeLeftOffsetFromContainingBlock + child.layout.position(PhysicalEdge.Left);
|
|
601
|
+
const childTopOffsetFromContainingBlock =
|
|
602
|
+
currentNodeTopOffsetFromContainingBlock + child.layout.position(PhysicalEdge.Top);
|
|
603
|
+
|
|
604
|
+
hasNewLayout =
|
|
605
|
+
layoutAbsoluteDescendants(
|
|
606
|
+
containingNode,
|
|
607
|
+
child,
|
|
608
|
+
widthSizingMode,
|
|
609
|
+
childDirection,
|
|
610
|
+
layoutMarkerData,
|
|
611
|
+
currentDepth + 1,
|
|
612
|
+
generationCount,
|
|
613
|
+
childLeftOffsetFromContainingBlock,
|
|
614
|
+
childTopOffsetFromContainingBlock,
|
|
615
|
+
containingNodeAvailableInnerWidth,
|
|
616
|
+
containingNodeAvailableInnerHeight,
|
|
617
|
+
) || hasNewLayout;
|
|
618
|
+
|
|
619
|
+
cleanupContentsNodesRecursively(child, /* didPerformLayout */ hasNewLayout);
|
|
620
|
+
if (hasNewLayout) {
|
|
621
|
+
child.hasNewLayout_ = hasNewLayout;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return hasNewLayout;
|
|
626
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Derived from Yoga. See THIRD_PARTY_NOTICES.md.
|
|
3
|
+
|
|
4
|
+
// Port of yoga/algorithm/Baseline.cpp.
|
|
5
|
+
|
|
6
|
+
import { Align, Dimension, PositionType } from "../generated/YGEnums.ts";
|
|
7
|
+
import { PhysicalEdge, isColumn, resolveChildAlignment } from "./helpers.ts";
|
|
8
|
+
import type { Node } from "./node.ts";
|
|
9
|
+
|
|
10
|
+
export function calculateBaseline(node: Node): number {
|
|
11
|
+
if (node.hasBaselineFunc()) {
|
|
12
|
+
const baseline = node.baseline(
|
|
13
|
+
node.layout.measuredDimension(Dimension.Width),
|
|
14
|
+
node.layout.measuredDimension(Dimension.Height),
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
if (Number.isNaN(baseline)) {
|
|
18
|
+
throw new Error("Expect custom baseline function to not return NaN");
|
|
19
|
+
}
|
|
20
|
+
return baseline;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let baselineChild: Node | null = null;
|
|
24
|
+
for (const child of node.getLayoutChildren()) {
|
|
25
|
+
if (child.lineIndex > 0) {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
if (child.style.positionType() === PositionType.Absolute) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (resolveChildAlignment(node, child) === Align.Baseline || child.isReferenceBaseline_) {
|
|
32
|
+
baselineChild = child;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (baselineChild === null) {
|
|
37
|
+
baselineChild = child;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (baselineChild === null) {
|
|
42
|
+
return node.layout.measuredDimension(Dimension.Height);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const baseline = calculateBaseline(baselineChild);
|
|
46
|
+
return baseline + baselineChild.layout.position(PhysicalEdge.Top);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function isBaselineLayout(node: Node): boolean {
|
|
50
|
+
if (isColumn(node.style.flexDirection())) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
if (node.style.alignItems() === Align.Baseline) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
for (const child of node.getLayoutChildren()) {
|
|
57
|
+
if (
|
|
58
|
+
child.style.positionType() !== PositionType.Absolute &&
|
|
59
|
+
child.style.alignSelf() === Align.Baseline
|
|
60
|
+
) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return false;
|
|
66
|
+
}
|