@react-x11/components 0.16.0 → 0.17.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/dist/html/css/animation.d.ts +91 -0
- package/dist/html/css/animation.d.ts.map +1 -0
- package/dist/html/css/animation.js +430 -0
- package/dist/html/css/animation.js.map +1 -0
- package/dist/html/css/cascade.d.ts +27 -4
- package/dist/html/css/cascade.d.ts.map +1 -1
- package/dist/html/css/cascade.js +94 -6
- package/dist/html/css/cascade.js.map +1 -1
- package/dist/html/css/parse.d.ts +35 -0
- package/dist/html/css/parse.d.ts.map +1 -1
- package/dist/html/css/parse.js +115 -2
- package/dist/html/css/parse.js.map +1 -1
- package/dist/html/css/style.d.ts +5 -0
- package/dist/html/css/style.d.ts.map +1 -1
- package/dist/html/css/style.js +57 -7
- package/dist/html/css/style.js.map +1 -1
- package/dist/html/css/ua.js +12 -8
- package/dist/html/css/ua.js.map +1 -1
- package/dist/html/layout/boxes.d.ts +13 -0
- package/dist/html/layout/boxes.d.ts.map +1 -1
- package/dist/html/layout/boxes.js +28 -0
- package/dist/html/layout/boxes.js.map +1 -1
- package/dist/html/layout/flex.d.ts.map +1 -1
- package/dist/html/layout/flex.js +237 -67
- package/dist/html/layout/flex.js.map +1 -1
- package/dist/html/layout/inline.d.ts.map +1 -1
- package/dist/html/layout/inline.js +41 -11
- package/dist/html/layout/inline.js.map +1 -1
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +12 -0
- package/dist/html/node.js.map +1 -1
- package/package.json +1 -1
- package/src/html/css/animation.ts +466 -0
- package/src/html/css/cascade.ts +130 -7
- package/src/html/css/parse.ts +151 -2
- package/src/html/css/style.ts +69 -7
- package/src/html/css/ua.ts +12 -8
- package/src/html/layout/boxes.ts +40 -0
- package/src/html/layout/flex.ts +251 -75
- package/src/html/layout/inline.ts +43 -9
- package/src/html/node.ts +12 -0
package/dist/html/layout/flex.js
CHANGED
|
@@ -210,6 +210,9 @@ export function layoutFlex(box, ctx, contentWidth) {
|
|
|
210
210
|
root.setWidth(contentWidth);
|
|
211
211
|
const direction = box.style.direction === 'rtl' ? Y.DIRECTION_RTL : Y.DIRECTION_LTR;
|
|
212
212
|
const row = box.style.flexDirection.startsWith('row');
|
|
213
|
+
const baselines = row &&
|
|
214
|
+
(box.style.alignItems === 'baseline' ||
|
|
215
|
+
items.some(({ box: child }) => child.style.alignSelf === 'baseline'));
|
|
213
216
|
// An `auto` margin across a row that wraps takes the room its line has
|
|
214
217
|
// past the item (CSS Flexbox 8.1, 9.6), where Yoga's pass that sets the
|
|
215
218
|
// items across their lines reads an item's alignment and not its
|
|
@@ -224,6 +227,46 @@ export function layoutFlex(box, ctx, contentWidth) {
|
|
|
224
227
|
node.setAlignSelf(ALIGN[aligned]);
|
|
225
228
|
}
|
|
226
229
|
}
|
|
230
|
+
else if (baselines) {
|
|
231
|
+
// Yoga takes a row aligned by baselines through that pass whether it
|
|
232
|
+
// wraps or not, and sets an item with an `auto` margin there by its
|
|
233
|
+
// baseline: at the top, where the margin puts it at the bottom, and
|
|
234
|
+
// every item beside it as far down as its height reached. That item
|
|
235
|
+
// takes no part in aligning the line by baselines (9.4 step 8), and
|
|
236
|
+
// Yoga is told the alignment its margins come to.
|
|
237
|
+
for (const { box: child, node } of items) {
|
|
238
|
+
const aligned = autoAcross(child.style, false);
|
|
239
|
+
if (aligned)
|
|
240
|
+
node.setAlignSelf(ALIGN[aligned]);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Items aligned by their baselines, which Yoga cannot see, are told they
|
|
244
|
+
// are at their lines' starts, which is where one is that shares its line
|
|
245
|
+
// with no other (8.3); those that do share one are lined up by their
|
|
246
|
+
// baselines once those are known (`baselineLines`), and the row laid out
|
|
247
|
+
// again. Told an item is aligned by its baseline, Yoga sizes each line
|
|
248
|
+
// of the row as the most any item on it reaches down to its bottom edge
|
|
249
|
+
// — a baseline, to Yoga — and the largest bottom margin besides,
|
|
250
|
+
// whichever items those are, and stretches the items on the line to
|
|
251
|
+
// that: a row of no height of its own was as tall as both, and
|
|
252
|
+
// `align-content` had that much less room to share out. And it takes a
|
|
253
|
+
// row that does not wrap through its pass for lines, which sets the one
|
|
254
|
+
// line there as tall as its items and not the row: an item centred or at
|
|
255
|
+
// the end of a row of a height was centred or ended in the items'
|
|
256
|
+
// height. Told none is, it takes neither. A row whose lines wrap in
|
|
257
|
+
// reverse is left to Yoga.
|
|
258
|
+
const started = new Set();
|
|
259
|
+
if (baselines && box.style.flexWrap !== 'wrap-reverse') {
|
|
260
|
+
for (const { box: child, node } of items) {
|
|
261
|
+
if (!byBaseline(box.style, child.style))
|
|
262
|
+
continue;
|
|
263
|
+
node.setAlignSelf(Y.ALIGN_FLEX_START);
|
|
264
|
+
started.add(child);
|
|
265
|
+
}
|
|
266
|
+
if (box.style.alignItems === 'baseline') {
|
|
267
|
+
root.setAlignItems(Y.ALIGN_FLEX_START);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
227
270
|
// frozen at its least size on the one line of a box that does not
|
|
228
271
|
// wrap, by a basis where Yoga takes one along the main axis
|
|
229
272
|
// (`applyItem`'s `setBasis`)
|
|
@@ -242,11 +285,12 @@ export function layoutFlex(box, ctx, contentWidth) {
|
|
|
242
285
|
// `align-content` spaces out come out of its layout as tall as their
|
|
243
286
|
// line and the room after it as well (`unspace`): laid out so that each
|
|
244
287
|
// is as tall as its line, where the box has room to space them out in —
|
|
245
|
-
// a height, or a minimum one
|
|
288
|
+
// a height, or a minimum one — and with the lines at its start where it
|
|
289
|
+
// may be too short for them, a height or a maximum one
|
|
246
290
|
const spaced = row &&
|
|
247
291
|
bounded &&
|
|
248
292
|
!hold.frozen &&
|
|
249
|
-
(height !== null || floor > 0) &&
|
|
293
|
+
(height !== null || floor > 0 || ceiling < Infinity) &&
|
|
250
294
|
spacesLines(box.style);
|
|
251
295
|
const ask = restretched.length > 0
|
|
252
296
|
? () => unstretch(items, restretched, sized, layout)
|
|
@@ -357,31 +401,23 @@ export function layoutFlex(box, ctx, contentWidth) {
|
|
|
357
401
|
ctx.flexDepth = depth;
|
|
358
402
|
}
|
|
359
403
|
}
|
|
360
|
-
// Yoga aligns the lines of a box that wraps
|
|
361
|
-
//
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
//
|
|
367
|
-
// by the flex layout again, set at their lines' starts with the
|
|
368
|
-
// that put their baselines together, which
|
|
369
|
-
// that does
|
|
370
|
-
const lines =
|
|
404
|
+
// Yoga aligns the lines of a box that wraps in one pass of its own, which
|
|
405
|
+
// drops a margin (`lineMarginFix`), and keeps the margins of one that
|
|
406
|
+
// does not, which it takes through that pass only where it is told an
|
|
407
|
+
// item is aligned by its baseline: here, never
|
|
408
|
+
const lined = box.style.flexWrap !== 'nowrap';
|
|
409
|
+
let bottom = placeItems(box, ctx, items, row, own, lined, contentWidth, started, crossed ? crossLines(box.style, items, contentWidth, columnGap) : undefined);
|
|
410
|
+
// Items that share a line and are aligned by their baselines are laid
|
|
411
|
+
// out by the flex layout again, set at their lines' starts with the
|
|
412
|
+
// margins that put their baselines together (`baselineLines`), which
|
|
413
|
+
// makes each line as tall as that does
|
|
414
|
+
const lines = started.size > 1 ? baselineLines(box.style, items) : null;
|
|
371
415
|
if (lines) {
|
|
372
|
-
// every one of them, and the box's own `baseline` too, which is what
|
|
373
|
-
// takes Yoga down that pass
|
|
374
|
-
const started = new Set();
|
|
375
416
|
for (const line of lines) {
|
|
376
|
-
line.forEach(({
|
|
377
|
-
node.setAlignSelf(Y.ALIGN_FLEX_START);
|
|
417
|
+
line.forEach(({ node }, i) => {
|
|
378
418
|
node.setMargin(Y.EDGE_TOP, line.margins[i]);
|
|
379
|
-
started.add(child);
|
|
380
419
|
});
|
|
381
420
|
}
|
|
382
|
-
if (box.style.alignItems === 'baseline') {
|
|
383
|
-
root.setAlignItems(Y.ALIGN_FLEX_START);
|
|
384
|
-
}
|
|
385
421
|
ctx.flexDepth = depth + 1;
|
|
386
422
|
try {
|
|
387
423
|
calculate();
|
|
@@ -389,7 +425,7 @@ export function layoutFlex(box, ctx, contentWidth) {
|
|
|
389
425
|
finally {
|
|
390
426
|
ctx.flexDepth = depth;
|
|
391
427
|
}
|
|
392
|
-
bottom = placeItems(box, ctx, items, row, own,
|
|
428
|
+
bottom = placeItems(box, ctx, items, row, own, lined, contentWidth, started);
|
|
393
429
|
}
|
|
394
430
|
// A replaced item with a ratio that is stretched across a line of a
|
|
395
431
|
// definite size takes its flex base size from the stretched one through
|
|
@@ -407,7 +443,7 @@ export function layoutFlex(box, ctx, contentWidth) {
|
|
|
407
443
|
finally {
|
|
408
444
|
ctx.flexDepth = depth;
|
|
409
445
|
}
|
|
410
|
-
bottom = placeItems(box, ctx, items, row, own,
|
|
446
|
+
bottom = placeItems(box, ctx, items, row, own, lined, contentWidth, started);
|
|
411
447
|
}
|
|
412
448
|
const contentHeight = root.getComputedHeight();
|
|
413
449
|
root.freeRecursive();
|
|
@@ -578,14 +614,23 @@ crossed) {
|
|
|
578
614
|
let bottom = 0;
|
|
579
615
|
// the lines of a row that wraps in reverse are turned round to run up it
|
|
580
616
|
const reverse = row && box.style.flexWrap === 'wrap-reverse';
|
|
617
|
+
// the left edge a column's items aligned by baselines share, where it
|
|
618
|
+
// does not wrap (`baselineEdge`); a column that wraps is `crossed`
|
|
619
|
+
const edge = row || box.style.flexWrap !== 'nowrap'
|
|
620
|
+
? NaN
|
|
621
|
+
: baselineEdge(box.style, items);
|
|
581
622
|
for (const { box: child, node, laid } of items) {
|
|
582
623
|
const placed = crossed?.get(child);
|
|
583
624
|
const across = lined && !placed
|
|
584
|
-
? lineMarginFix(box.style, child, node, row, started?.has(child))
|
|
625
|
+
? lineMarginFix(box.style, child, node, row, own, started?.has(child))
|
|
585
626
|
: 0;
|
|
586
627
|
const itemHeight = row ? heightOf(node, laid) : laid.main;
|
|
587
628
|
const left = box.contentX +
|
|
588
|
-
(placed
|
|
629
|
+
(placed
|
|
630
|
+
? placed.x
|
|
631
|
+
: !Number.isNaN(edge) && byBaseline(box.style, child.style, false)
|
|
632
|
+
? edge
|
|
633
|
+
: node.getComputedLeft() + (row ? 0 : across));
|
|
589
634
|
// which Yoga turns an item round in by the height it laid it out at, and
|
|
590
635
|
// not the one it is (`unspace`)
|
|
591
636
|
const top = box.contentY +
|
|
@@ -771,6 +816,14 @@ weighed) {
|
|
|
771
816
|
node.setFlexShrink(style.flexShrink);
|
|
772
817
|
if (style.alignSelf !== AUTO)
|
|
773
818
|
node.setAlignSelf(ALIGN[style.alignSelf] ?? Y.ALIGN_AUTO);
|
|
819
|
+
// `stretch` sets an item whose height is a percentage of none at its
|
|
820
|
+
// line's start, as tall as its content (`heightOfNone`), where Yoga,
|
|
821
|
+
// which is handed no height for it, stretched it across the line
|
|
822
|
+
if (row && box.parent && heightOfNone(style, own)) {
|
|
823
|
+
const align = style.alignSelf === AUTO ? box.parent.style.alignItems : style.alignSelf;
|
|
824
|
+
if (align === 'stretch')
|
|
825
|
+
node.setAlignSelf(Y.ALIGN_FLEX_START);
|
|
826
|
+
}
|
|
774
827
|
// Yoga's sizes are border boxes, as `box-sizing: border-box` has them;
|
|
775
828
|
// a `content-box` length is the content's, and the item's padding and
|
|
776
829
|
// border go on top of it
|
|
@@ -2427,15 +2480,15 @@ function contentBottom(box) {
|
|
|
2427
2480
|
* its bottom edge, so it lined them up by their bottoms. With the items laid
|
|
2428
2481
|
* out, each line's, and for each the top margin that sets it at the line's
|
|
2429
2482
|
* start with its first baseline where the lowest-reaching one's is — or
|
|
2430
|
-
* null where no line has two to align.
|
|
2483
|
+
* null where no line has two to align. Not for a row whose lines wrap in
|
|
2484
|
+
* reverse, which grow from their ends and are left to Yoga (`layoutFlex`).
|
|
2431
2485
|
*/
|
|
2432
2486
|
function baselineLines(style, items) {
|
|
2433
|
-
// a line that grows from its end is aligned from there, and left to Yoga
|
|
2434
|
-
if (style.flexWrap === 'wrap-reverse')
|
|
2435
|
-
return null;
|
|
2436
2487
|
const wraps = style.flexWrap !== 'nowrap';
|
|
2437
|
-
// along a line the items go the way the main axis does,
|
|
2438
|
-
// line starts
|
|
2488
|
+
// along a line the items go the way the main axis does, each margin box
|
|
2489
|
+
// after the last one's end, and the next line starts before it (9.3): at
|
|
2490
|
+
// the line's start, where an item with a margin before it was further
|
|
2491
|
+
// along than one alone on the line before
|
|
2439
2492
|
const back = (style.flexDirection === 'row-reverse') !== (style.direction === 'rtl');
|
|
2440
2493
|
const out = [];
|
|
2441
2494
|
let line = [];
|
|
@@ -2456,25 +2509,64 @@ function baselineLines(style, items) {
|
|
|
2456
2509
|
out.push(Object.assign(line, { margins }));
|
|
2457
2510
|
};
|
|
2458
2511
|
for (const item of items) {
|
|
2459
|
-
const box = item
|
|
2460
|
-
|
|
2512
|
+
const { box, node } = item;
|
|
2513
|
+
const left = node.getComputedLeft() - node.getComputedMargin(Y.EDGE_LEFT);
|
|
2514
|
+
const right = node.getComputedLeft() +
|
|
2515
|
+
node.getComputedWidth() +
|
|
2516
|
+
node.getComputedMargin(Y.EDGE_RIGHT);
|
|
2517
|
+
if (wraps &&
|
|
2518
|
+
line.length &&
|
|
2519
|
+
(back ? right > last + 0.01 : left < last - 0.01)) {
|
|
2461
2520
|
close();
|
|
2462
2521
|
line = [];
|
|
2463
2522
|
}
|
|
2464
|
-
last =
|
|
2465
|
-
|
|
2466
|
-
const aligned = own.alignSelf === AUTO ? style.alignItems : own.alignSelf;
|
|
2467
|
-
// an `auto` margin across the line takes it over alignment
|
|
2468
|
-
if (aligned === 'baseline' &&
|
|
2469
|
-
own.marginTop !== AUTO &&
|
|
2470
|
-
own.marginBottom !== AUTO) {
|
|
2523
|
+
last = back ? left : right;
|
|
2524
|
+
if (byBaseline(style, box.style))
|
|
2471
2525
|
line.push(item);
|
|
2472
|
-
}
|
|
2473
2526
|
}
|
|
2474
2527
|
close();
|
|
2475
2528
|
// one alone on its line is at its start already
|
|
2476
2529
|
return several ? out : null;
|
|
2477
2530
|
}
|
|
2531
|
+
/** Whether an item takes part in aligning its line by baselines (CSS
|
|
2532
|
+
* Flexbox 8.3, 9.4 step 8): aligned by its baseline, with no `auto`
|
|
2533
|
+
* margin across the line, which takes it over its alignment. */
|
|
2534
|
+
function byBaseline(container, item,
|
|
2535
|
+
/** Whether the line is a row's, across which its margins are its top
|
|
2536
|
+
* and bottom ones; a column's are its left and right ones. */
|
|
2537
|
+
row = true) {
|
|
2538
|
+
const aligned = item.alignSelf === AUTO ? container.alignItems : item.alignSelf;
|
|
2539
|
+
return (aligned === 'baseline' &&
|
|
2540
|
+
(row ? item.marginTop : item.marginLeft) !== AUTO &&
|
|
2541
|
+
(row ? item.marginBottom : item.marginRight) !== AUTO);
|
|
2542
|
+
}
|
|
2543
|
+
/**
|
|
2544
|
+
* Where the items a column that does not wrap aligns by baselines have
|
|
2545
|
+
* their left edges, from its content box's: NaN where it has none.
|
|
2546
|
+
*
|
|
2547
|
+
* A horizontal item has no baseline across a column, and one is made from
|
|
2548
|
+
* its border box — the line-under edge of the vertical writing mode it is
|
|
2549
|
+
* taken to have, its left, whichever way its text runs (CSS Box Alignment
|
|
2550
|
+
* 3, 9.1). So the items share their left edges, and are set together at
|
|
2551
|
+
* the line's cross start, the column's left or, where it runs right to
|
|
2552
|
+
* left, its right (9.3; CSS Flexbox 8.3), as Chrome sets them: as far from
|
|
2553
|
+
* there as the most any of them reaches past its edge on that side. Yoga
|
|
2554
|
+
* never aligns a column by baselines, and sets each at its line's start
|
|
2555
|
+
* with its margin there, so that is the furthest any of them is from the
|
|
2556
|
+
* start: the rightmost left edge, or from the right the leftmost.
|
|
2557
|
+
*/
|
|
2558
|
+
function baselineEdge(container, items) {
|
|
2559
|
+
const rtl = container.direction === 'rtl';
|
|
2560
|
+
let edge = NaN;
|
|
2561
|
+
for (const { box, node } of items) {
|
|
2562
|
+
if (!byBaseline(container, box.style, false))
|
|
2563
|
+
continue;
|
|
2564
|
+
const left = node.getComputedLeft();
|
|
2565
|
+
if (!(rtl ? left >= edge : left <= edge))
|
|
2566
|
+
edge = left;
|
|
2567
|
+
}
|
|
2568
|
+
return edge;
|
|
2569
|
+
}
|
|
2478
2570
|
/**
|
|
2479
2571
|
* Whether Yoga made a line of a row that wraps the row's height, where its
|
|
2480
2572
|
* items make it another (CSS Flexbox 9.4, steps 7 and 8; `layoutFlex`).
|
|
@@ -2571,13 +2663,13 @@ function autoAcross(item, reverse) {
|
|
|
2571
2663
|
}
|
|
2572
2664
|
/**
|
|
2573
2665
|
* How far an item is from where it belongs across its line, where Yoga
|
|
2574
|
-
* (3.2.1) aligned the lines in the pass it takes for a box that wraps
|
|
2575
|
-
*
|
|
2576
|
-
*
|
|
2577
|
-
*
|
|
2578
|
-
*
|
|
2579
|
-
*
|
|
2580
|
-
*
|
|
2666
|
+
* (3.2.1) aligned the lines in the pass it takes for a box that wraps: it
|
|
2667
|
+
* sets an item aligned to its line's start there as though it had no
|
|
2668
|
+
* margin at that side, and one centred as though it had none at either —
|
|
2669
|
+
* `items-start` in a wrapping row put every card's top margin under it. By
|
|
2670
|
+
* the margin at the start of the line's cross axis, and by half what it
|
|
2671
|
+
* exceeds the one at the end by, as Yoga holds them: for an item set at
|
|
2672
|
+
* its line's start (`started`), its baseline's.
|
|
2581
2673
|
*
|
|
2582
2674
|
* A row whose lines wrap in reverse Yoga lays out as though they wrapped
|
|
2583
2675
|
* forward, and then turns each item over across the box, its margins with
|
|
@@ -2586,10 +2678,11 @@ function autoAcross(item, reverse) {
|
|
|
2586
2678
|
* stretched, is its bottom margin down from its line's top where it is its
|
|
2587
2679
|
* top one; and one centred, half the difference. A column's, whose cross
|
|
2588
2680
|
* axis runs right to left, or that wraps in reverse, is left as Yoga has
|
|
2589
|
-
* it, and so is an item an `auto` margin aligns
|
|
2590
|
-
* wrap.
|
|
2681
|
+
* it, and so is an item an `auto` margin aligns across a column.
|
|
2591
2682
|
*/
|
|
2592
|
-
function lineMarginFix(container, item, node, row,
|
|
2683
|
+
function lineMarginFix(container, item, node, row,
|
|
2684
|
+
/** Whether the flex box has a definite height. */
|
|
2685
|
+
own, started = false) {
|
|
2593
2686
|
const reverse = container.flexWrap === 'wrap-reverse';
|
|
2594
2687
|
if (!row && (reverse || container.direction === 'rtl'))
|
|
2595
2688
|
return 0;
|
|
@@ -2602,13 +2695,15 @@ function lineMarginFix(container, item, node, row, started = false) {
|
|
|
2602
2695
|
if (started)
|
|
2603
2696
|
align = 'flex-start';
|
|
2604
2697
|
else if (lead === AUTO || trail === AUTO) {
|
|
2605
|
-
align =
|
|
2606
|
-
row && container.flexWrap !== 'nowrap'
|
|
2607
|
-
? autoAcross(style, reverse)
|
|
2608
|
-
: null;
|
|
2698
|
+
align = row ? autoAcross(style, reverse) : null;
|
|
2609
2699
|
}
|
|
2610
2700
|
else {
|
|
2611
2701
|
align = style.alignSelf === AUTO ? container.alignItems : style.alignSelf;
|
|
2702
|
+
// which sets one whose height is a percentage of none at its line's
|
|
2703
|
+
// start, as Yoga is told it does (`applyItem`)
|
|
2704
|
+
if (align === 'stretch' && row && heightOfNone(style, own)) {
|
|
2705
|
+
align = 'flex-start';
|
|
2706
|
+
}
|
|
2612
2707
|
}
|
|
2613
2708
|
const leading = node.getComputedMargin(row ? Y.EDGE_TOP : Y.EDGE_LEFT);
|
|
2614
2709
|
const trailing = node.getComputedMargin(row ? Y.EDGE_BOTTOM : Y.EDGE_RIGHT);
|
|
@@ -2625,12 +2720,15 @@ function lineMarginFix(container, item, node, row, started = false) {
|
|
|
2625
2720
|
}
|
|
2626
2721
|
/** An item's first baseline, down from its border edge: its content's
|
|
2627
2722
|
* first line's, or where it has none, or is replaced, one synthesized
|
|
2628
|
-
* from its border box — its bottom edge.
|
|
2723
|
+
* from its border box — its bottom edge. Past that edge where the line
|
|
2724
|
+
* is: only a scroll container's is held to its box (`firstBaselineIn`),
|
|
2725
|
+
* and an item shorter than its text, or whose padding puts the text
|
|
2726
|
+
* under it, sits on its text where it had sat on its bottom. */
|
|
2629
2727
|
function itemBaseline(item) {
|
|
2630
2728
|
if (item.kind !== 'replaced') {
|
|
2631
2729
|
const found = firstBaselineIn(item);
|
|
2632
2730
|
if (found !== null)
|
|
2633
|
-
return
|
|
2731
|
+
return found - item.y;
|
|
2634
2732
|
}
|
|
2635
2733
|
return item.height;
|
|
2636
2734
|
}
|
|
@@ -2765,12 +2863,31 @@ function spacesLines(style) {
|
|
|
2765
2863
|
* makes too, and is kept. Where they do, Yoga is asked again as the row
|
|
2766
2864
|
* is, for where the lines and the items are, and the heights are kept from
|
|
2767
2865
|
* the first layout.
|
|
2866
|
+
*
|
|
2867
|
+
* And where the lines are taller than the row, `space-around` and
|
|
2868
|
+
* `space-evenly` fall back to `safe center`, which sets them at the row's
|
|
2869
|
+
* own start, its top (CSS Box Alignment 3, 4.3 and 5.1; CSS Flexbox 8.4).
|
|
2870
|
+
* Yoga falls back to `flex-start` for both, which is the bottom where the
|
|
2871
|
+
* lines run bottom to top, and ran them out past the row's top. It sets
|
|
2872
|
+
* the lines of a row that wraps in reverse top to bottom and turns them
|
|
2873
|
+
* over once they are set, so it is asked for them at `flex-end` there,
|
|
2874
|
+
* which comes out at the top — where the lines it set at their start, or
|
|
2875
|
+
* spaced, reach past the row's bottom.
|
|
2768
2876
|
*/
|
|
2769
2877
|
function unspace(root, items,
|
|
2770
2878
|
/** Whether the lines run bottom to top. */
|
|
2771
2879
|
reverse, layout) {
|
|
2772
2880
|
for (const { laid } of items)
|
|
2773
2881
|
laid.unstretched = NaN;
|
|
2882
|
+
const lines = root.getAlignContent();
|
|
2883
|
+
// where the lines start at the row's bottom, its start is their end
|
|
2884
|
+
const safe = reverse &&
|
|
2885
|
+
(lines === Y.ALIGN_SPACE_AROUND || lines === Y.ALIGN_SPACE_EVENLY);
|
|
2886
|
+
const atEnd = () => {
|
|
2887
|
+
root.setAlignContent(Y.ALIGN_FLEX_END);
|
|
2888
|
+
layout();
|
|
2889
|
+
root.setAlignContent(lines);
|
|
2890
|
+
};
|
|
2774
2891
|
// each item Yoga stretches: `stretch`, with no height of its own
|
|
2775
2892
|
const align = root.getAlignItems();
|
|
2776
2893
|
const stretched = items.filter(({ node }) => {
|
|
@@ -2782,15 +2899,23 @@ reverse, layout) {
|
|
|
2782
2899
|
});
|
|
2783
2900
|
if (stretched.length === 0) {
|
|
2784
2901
|
layout();
|
|
2902
|
+
// spaced where there is room, and else at their start, past the bottom
|
|
2903
|
+
if (safe &&
|
|
2904
|
+
linesReach(root, items, reverse) - root.getComputedHeight() > NEAR) {
|
|
2905
|
+
atEnd();
|
|
2906
|
+
}
|
|
2785
2907
|
return;
|
|
2786
2908
|
}
|
|
2787
|
-
const lines = root.getAlignContent();
|
|
2788
2909
|
root.setAlignContent(Y.ALIGN_FLEX_START);
|
|
2789
2910
|
layout();
|
|
2790
2911
|
root.setAlignContent(lines);
|
|
2791
|
-
|
|
2912
|
+
const room = root.getComputedHeight() - linesReach(root, items, reverse);
|
|
2913
|
+
if (safe && room < -NEAR) {
|
|
2914
|
+
atEnd();
|
|
2792
2915
|
return;
|
|
2793
2916
|
}
|
|
2917
|
+
if (!(room > NEAR))
|
|
2918
|
+
return;
|
|
2794
2919
|
const heights = stretched.map(({ node }) => node.getComputedHeight());
|
|
2795
2920
|
layout();
|
|
2796
2921
|
stretched.forEach(({ node, laid }, i) => {
|
|
@@ -2835,6 +2960,19 @@ function linesReach(root, items, reverse) {
|
|
|
2835
2960
|
}
|
|
2836
2961
|
return reach;
|
|
2837
2962
|
}
|
|
2963
|
+
/**
|
|
2964
|
+
* Whether a row item's height is a percentage of a height its flex box has
|
|
2965
|
+
* none of. That is `auto` to the item's size (CSS 2.1 10.5), and is not
|
|
2966
|
+
* handed to Yoga (`applyItem`), but it is not `auto` to its alignment:
|
|
2967
|
+
* `stretch` stretches an item whose height computes to `auto` (CSS Flexbox
|
|
2968
|
+
* 8.3), and this one's computes to the percentage. Such an item is as tall
|
|
2969
|
+
* as its content, set at its line's start, which is what Yoga is told.
|
|
2970
|
+
*/
|
|
2971
|
+
function heightOfNone(style,
|
|
2972
|
+
/** Whether the flex box has a definite height. */
|
|
2973
|
+
own) {
|
|
2974
|
+
return !own && isPct(style.height);
|
|
2975
|
+
}
|
|
2838
2976
|
/** Whether an item is stretched across its line: `stretch`, its own or its
|
|
2839
2977
|
* container's, with no height of its own and no `auto` margin across. */
|
|
2840
2978
|
function stretches(box, container,
|
|
@@ -2876,15 +3014,17 @@ function wrapsColumn(style, width) {
|
|
|
2876
3014
|
* where they are short of the box; `center` and `flex-end` whether they are
|
|
2877
3015
|
* or not, so that lines wider than the box run past both its sides, or its
|
|
2878
3016
|
* start; and the spacing values only where there is room, setting the lines
|
|
2879
|
-
* at
|
|
2880
|
-
* `space-between` falls back to `flex-start`, `space-around` and
|
|
2881
|
-
* `space-evenly` to `safe center`, the start where the lines
|
|
3017
|
+
* at their start where there is none, or at the box's (CSS Box Alignment 3,
|
|
3018
|
+
* 4.3: `space-between` falls back to `flex-start`, `space-around` and
|
|
3019
|
+
* `space-evenly` to `safe center`, the box's own start where the lines
|
|
3020
|
+
* overflow, and not theirs where they wrap in reverse). An
|
|
2882
3021
|
* item with an `auto` margin across its line takes the room the line has
|
|
2883
3022
|
* past it on that side (8.1), and none where there is none; a stretched
|
|
2884
3023
|
* item is as wide as its line less its margins, within its limits (9.4,
|
|
2885
|
-
* step 11), and as tall as the column made it;
|
|
2886
|
-
*
|
|
2887
|
-
*
|
|
3024
|
+
* step 11), and as tall as the column made it; those aligned by baselines
|
|
3025
|
+
* share their left edges, set together at the line's start, where a column
|
|
3026
|
+
* that does not wrap sets them (`baselineEdge`); and the rest are where
|
|
3027
|
+
* `align-self` says.
|
|
2888
3028
|
*/
|
|
2889
3029
|
function crossLines(style, items,
|
|
2890
3030
|
/** The flex box's content width. */
|
|
@@ -2915,13 +3055,36 @@ gap) {
|
|
|
2915
3055
|
lead.push(fromRight ? r : l);
|
|
2916
3056
|
trail.push(fromRight ? l : r);
|
|
2917
3057
|
});
|
|
2918
|
-
|
|
3058
|
+
// A line is as wide as its widest item, margins and all, and as the
|
|
3059
|
+
// items it aligns by baselines come to, sharing their left edges: the
|
|
3060
|
+
// most any reaches from the line's start to that edge, and the most any
|
|
3061
|
+
// reaches past it (`baselineEdge`; 9.4 step 8). `reach` is each line's
|
|
3062
|
+
// first, where those items' left edges are from its start.
|
|
3063
|
+
const reach = [];
|
|
3064
|
+
const across = lines.map((line) => {
|
|
3065
|
+
let most = 0;
|
|
3066
|
+
let before = -Infinity;
|
|
3067
|
+
let after = -Infinity;
|
|
3068
|
+
for (const i of line) {
|
|
3069
|
+
most = Math.max(most, sizes[i] + lead[i] + trail[i]);
|
|
3070
|
+
if (!byBaseline(style, items[i].box.style, false))
|
|
3071
|
+
continue;
|
|
3072
|
+
before = Math.max(before, lead[i] + (fromRight ? sizes[i] : 0));
|
|
3073
|
+
after = Math.max(after, trail[i] + (fromRight ? 0 : sizes[i]));
|
|
3074
|
+
}
|
|
3075
|
+
reach.push(before);
|
|
3076
|
+
return Math.max(most, before + after);
|
|
3077
|
+
});
|
|
2919
3078
|
const count = lines.length;
|
|
2920
3079
|
let room = width - gap * (count - 1);
|
|
2921
3080
|
for (const size of across)
|
|
2922
3081
|
room -= size;
|
|
2923
3082
|
let at = 0;
|
|
2924
3083
|
let between = gap;
|
|
3084
|
+
// Where they are wider than the box, `space-around` and `space-evenly`
|
|
3085
|
+
// set the lines at the box's own start (`safe center`), which is where
|
|
3086
|
+
// their last one ends where they wrap in reverse: they run past its end
|
|
3087
|
+
const reverse = style.flexWrap === 'wrap-reverse';
|
|
2925
3088
|
switch (crossContent(style)) {
|
|
2926
3089
|
case 'flex-end':
|
|
2927
3090
|
at = room;
|
|
@@ -2942,12 +3105,16 @@ gap) {
|
|
|
2942
3105
|
at = room / count / 2;
|
|
2943
3106
|
between += room / count;
|
|
2944
3107
|
}
|
|
3108
|
+
else if (reverse)
|
|
3109
|
+
at = room;
|
|
2945
3110
|
break;
|
|
2946
3111
|
case 'space-evenly':
|
|
2947
3112
|
if (room > 0) {
|
|
2948
3113
|
at = room / (count + 1);
|
|
2949
3114
|
between += room / (count + 1);
|
|
2950
3115
|
}
|
|
3116
|
+
else if (reverse)
|
|
3117
|
+
at = room;
|
|
2951
3118
|
break;
|
|
2952
3119
|
}
|
|
2953
3120
|
const placed = new Map();
|
|
@@ -2976,6 +3143,9 @@ gap) {
|
|
|
2976
3143
|
itemWidth = least;
|
|
2977
3144
|
itemWidth = Math.max(itemWidth, box.horizontalExtra);
|
|
2978
3145
|
}
|
|
3146
|
+
else if (byBaseline(style, own, false)) {
|
|
3147
|
+
offset = reach[k] - (fromRight ? itemWidth : 0);
|
|
3148
|
+
}
|
|
2979
3149
|
else {
|
|
2980
3150
|
const align = own.alignSelf === AUTO ? style.alignItems : own.alignSelf;
|
|
2981
3151
|
if (align === 'center')
|