@react-x11/components 0.16.0 → 0.16.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/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 +139 -28
- 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 +4 -0
- package/dist/html/node.js.map +1 -1
- package/package.json +1 -1
- package/src/html/css/ua.ts +12 -8
- package/src/html/layout/boxes.ts +40 -0
- package/src/html/layout/flex.ts +146 -33
- package/src/html/layout/inline.ts +43 -9
- package/src/html/node.ts +4 -0
package/dist/html/layout/flex.js
CHANGED
|
@@ -210,6 +210,13 @@ 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
|
+
// Yoga aligns the lines of a box that wraps, or of a row that aligns by
|
|
214
|
+
// baselines, in one pass of its own, which drops a margin
|
|
215
|
+
// (`lineMarginFix`) — and not those of a column that does not wrap,
|
|
216
|
+
// whatever it aligns by, whose margins Yoga keeps
|
|
217
|
+
let baselines = row &&
|
|
218
|
+
(box.style.alignItems === 'baseline' ||
|
|
219
|
+
items.some(({ box: child }) => child.style.alignSelf === 'baseline'));
|
|
213
220
|
// An `auto` margin across a row that wraps takes the room its line has
|
|
214
221
|
// past the item (CSS Flexbox 8.1, 9.6), where Yoga's pass that sets the
|
|
215
222
|
// items across their lines reads an item's alignment and not its
|
|
@@ -224,6 +231,38 @@ export function layoutFlex(box, ctx, contentWidth) {
|
|
|
224
231
|
node.setAlignSelf(ALIGN[aligned]);
|
|
225
232
|
}
|
|
226
233
|
}
|
|
234
|
+
else if (baselines) {
|
|
235
|
+
// Yoga takes a row that does not wrap through that pass as well, and
|
|
236
|
+
// sets its line there as tall as its items and not the row: an item
|
|
237
|
+
// centred or at the end of a row of a height was centred or ended in
|
|
238
|
+
// the items' height. It has sized that line already, as the most any
|
|
239
|
+
// item reaches down to its bottom edge — a baseline, to Yoga — and the
|
|
240
|
+
// largest bottom margin besides, whichever items those are: a row of
|
|
241
|
+
// no height of its own was as tall as both. And it sets an item with
|
|
242
|
+
// an `auto` margin by its baseline: at the top, where the margin puts
|
|
243
|
+
// it at the bottom, and every item beside it as far down as its height
|
|
244
|
+
// reached. That item takes no part in aligning the line by baselines
|
|
245
|
+
// (9.4 step 8), and Yoga is told the alignment its margins come to.
|
|
246
|
+
// With fewer than two items left that do take part, they come to their
|
|
247
|
+
// line's start (8.3), which Yoga is told as well: then nothing in the
|
|
248
|
+
// row is aligned by its baseline, Yoga takes no such pass, and the line
|
|
249
|
+
// is the row. Two or more are lined up by their baselines once those
|
|
250
|
+
// are known (`baselineLines`), and the row laid out again with none.
|
|
251
|
+
for (const { box: child, node } of items) {
|
|
252
|
+
const aligned = autoAcross(child.style, false);
|
|
253
|
+
if (aligned)
|
|
254
|
+
node.setAlignSelf(ALIGN[aligned]);
|
|
255
|
+
}
|
|
256
|
+
const aligned = items.filter(({ box: child }) => byBaseline(box.style, child.style));
|
|
257
|
+
if (aligned.length < 2) {
|
|
258
|
+
for (const { node } of aligned)
|
|
259
|
+
node.setAlignSelf(Y.ALIGN_FLEX_START);
|
|
260
|
+
if (box.style.alignItems === 'baseline') {
|
|
261
|
+
root.setAlignItems(Y.ALIGN_FLEX_START);
|
|
262
|
+
}
|
|
263
|
+
baselines = false;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
227
266
|
// frozen at its least size on the one line of a box that does not
|
|
228
267
|
// wrap, by a basis where Yoga takes one along the main axis
|
|
229
268
|
// (`applyItem`'s `setBasis`)
|
|
@@ -242,11 +281,12 @@ export function layoutFlex(box, ctx, contentWidth) {
|
|
|
242
281
|
// `align-content` spaces out come out of its layout as tall as their
|
|
243
282
|
// line and the room after it as well (`unspace`): laid out so that each
|
|
244
283
|
// is as tall as its line, where the box has room to space them out in —
|
|
245
|
-
// a height, or a minimum one
|
|
284
|
+
// a height, or a minimum one — and with the lines at its start where it
|
|
285
|
+
// may be too short for them, a height or a maximum one
|
|
246
286
|
const spaced = row &&
|
|
247
287
|
bounded &&
|
|
248
288
|
!hold.frozen &&
|
|
249
|
-
(height !== null || floor > 0) &&
|
|
289
|
+
(height !== null || floor > 0 || ceiling < Infinity) &&
|
|
250
290
|
spacesLines(box.style);
|
|
251
291
|
const ask = restretched.length > 0
|
|
252
292
|
? () => unstretch(items, restretched, sized, layout)
|
|
@@ -357,21 +397,19 @@ export function layoutFlex(box, ctx, contentWidth) {
|
|
|
357
397
|
ctx.flexDepth = depth;
|
|
358
398
|
}
|
|
359
399
|
}
|
|
360
|
-
// Yoga
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
items.some(({ box: child }) => child.style.alignSelf === 'baseline');
|
|
364
|
-
let bottom = placeItems(box, ctx, items, row, own, box.style.flexWrap !== 'nowrap' || baselines, contentWidth, undefined, crossed ? crossLines(box.style, items, contentWidth, columnGap) : undefined);
|
|
400
|
+
// whether Yoga's last layout took its pass for lines (`placeItems`)
|
|
401
|
+
let lined = box.style.flexWrap !== 'nowrap' || baselines;
|
|
402
|
+
let bottom = placeItems(box, ctx, items, row, own, lined, contentWidth, undefined, crossed ? crossLines(box.style, items, contentWidth, columnGap) : undefined);
|
|
365
403
|
// Items aligned by their baselines, which Yoga cannot see, are aligned
|
|
366
404
|
// with their baselines known (`baselineLines`)
|
|
367
405
|
// by the flex layout again, set at their lines' starts with the margins
|
|
368
406
|
// that put their baselines together, which makes each line as tall as
|
|
369
407
|
// that does
|
|
370
|
-
const lines =
|
|
408
|
+
const lines = baselines ? baselineLines(box.style, items) : null;
|
|
409
|
+
const started = new Set();
|
|
371
410
|
if (lines) {
|
|
372
411
|
// every one of them, and the box's own `baseline` too, which is what
|
|
373
412
|
// takes Yoga down that pass
|
|
374
|
-
const started = new Set();
|
|
375
413
|
for (const line of lines) {
|
|
376
414
|
line.forEach(({ box: child, node }, i) => {
|
|
377
415
|
node.setAlignSelf(Y.ALIGN_FLEX_START);
|
|
@@ -382,6 +420,8 @@ export function layoutFlex(box, ctx, contentWidth) {
|
|
|
382
420
|
if (box.style.alignItems === 'baseline') {
|
|
383
421
|
root.setAlignItems(Y.ALIGN_FLEX_START);
|
|
384
422
|
}
|
|
423
|
+
// so it takes it only where the row wraps
|
|
424
|
+
lined = box.style.flexWrap !== 'nowrap';
|
|
385
425
|
ctx.flexDepth = depth + 1;
|
|
386
426
|
try {
|
|
387
427
|
calculate();
|
|
@@ -389,7 +429,7 @@ export function layoutFlex(box, ctx, contentWidth) {
|
|
|
389
429
|
finally {
|
|
390
430
|
ctx.flexDepth = depth;
|
|
391
431
|
}
|
|
392
|
-
bottom = placeItems(box, ctx, items, row, own,
|
|
432
|
+
bottom = placeItems(box, ctx, items, row, own, lined, contentWidth, started);
|
|
393
433
|
}
|
|
394
434
|
// A replaced item with a ratio that is stretched across a line of a
|
|
395
435
|
// definite size takes its flex base size from the stretched one through
|
|
@@ -407,7 +447,7 @@ export function layoutFlex(box, ctx, contentWidth) {
|
|
|
407
447
|
finally {
|
|
408
448
|
ctx.flexDepth = depth;
|
|
409
449
|
}
|
|
410
|
-
bottom = placeItems(box, ctx, items, row, own,
|
|
450
|
+
bottom = placeItems(box, ctx, items, row, own, lined, contentWidth, started);
|
|
411
451
|
}
|
|
412
452
|
const contentHeight = root.getComputedHeight();
|
|
413
453
|
root.freeRecursive();
|
|
@@ -581,7 +621,7 @@ crossed) {
|
|
|
581
621
|
for (const { box: child, node, laid } of items) {
|
|
582
622
|
const placed = crossed?.get(child);
|
|
583
623
|
const across = lined && !placed
|
|
584
|
-
? lineMarginFix(box.style, child, node, row, started?.has(child))
|
|
624
|
+
? lineMarginFix(box.style, child, node, row, own, started?.has(child))
|
|
585
625
|
: 0;
|
|
586
626
|
const itemHeight = row ? heightOf(node, laid) : laid.main;
|
|
587
627
|
const left = box.contentX +
|
|
@@ -771,6 +811,14 @@ weighed) {
|
|
|
771
811
|
node.setFlexShrink(style.flexShrink);
|
|
772
812
|
if (style.alignSelf !== AUTO)
|
|
773
813
|
node.setAlignSelf(ALIGN[style.alignSelf] ?? Y.ALIGN_AUTO);
|
|
814
|
+
// `stretch` sets an item whose height is a percentage of none at its
|
|
815
|
+
// line's start, as tall as its content (`heightOfNone`), where Yoga,
|
|
816
|
+
// which is handed no height for it, stretched it across the line
|
|
817
|
+
if (row && box.parent && heightOfNone(style, own)) {
|
|
818
|
+
const align = style.alignSelf === AUTO ? box.parent.style.alignItems : style.alignSelf;
|
|
819
|
+
if (align === 'stretch')
|
|
820
|
+
node.setAlignSelf(Y.ALIGN_FLEX_START);
|
|
821
|
+
}
|
|
774
822
|
// Yoga's sizes are border boxes, as `box-sizing: border-box` has them;
|
|
775
823
|
// a `content-box` length is the content's, and the item's padding and
|
|
776
824
|
// border go on top of it
|
|
@@ -2462,19 +2510,22 @@ function baselineLines(style, items) {
|
|
|
2462
2510
|
line = [];
|
|
2463
2511
|
}
|
|
2464
2512
|
last = box.x;
|
|
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) {
|
|
2513
|
+
if (byBaseline(style, box.style))
|
|
2471
2514
|
line.push(item);
|
|
2472
|
-
}
|
|
2473
2515
|
}
|
|
2474
2516
|
close();
|
|
2475
2517
|
// one alone on its line is at its start already
|
|
2476
2518
|
return several ? out : null;
|
|
2477
2519
|
}
|
|
2520
|
+
/** Whether an item takes part in aligning its line by baselines (CSS
|
|
2521
|
+
* Flexbox 8.3, 9.4 step 8): aligned by its baseline, with no `auto`
|
|
2522
|
+
* margin across the line, which takes it over its alignment. */
|
|
2523
|
+
function byBaseline(container, item) {
|
|
2524
|
+
const aligned = item.alignSelf === AUTO ? container.alignItems : item.alignSelf;
|
|
2525
|
+
return (aligned === 'baseline' &&
|
|
2526
|
+
item.marginTop !== AUTO &&
|
|
2527
|
+
item.marginBottom !== AUTO);
|
|
2528
|
+
}
|
|
2478
2529
|
/**
|
|
2479
2530
|
* Whether Yoga made a line of a row that wraps the row's height, where its
|
|
2480
2531
|
* items make it another (CSS Flexbox 9.4, steps 7 and 8; `layoutFlex`).
|
|
@@ -2587,9 +2638,12 @@ function autoAcross(item, reverse) {
|
|
|
2587
2638
|
* top one; and one centred, half the difference. A column's, whose cross
|
|
2588
2639
|
* axis runs right to left, or that wraps in reverse, is left as Yoga has
|
|
2589
2640
|
* it, and so is an item an `auto` margin aligns in a row that does not
|
|
2590
|
-
* wrap
|
|
2641
|
+
* wrap: where Yoga still takes that pass for such a row, its items are
|
|
2642
|
+
* laid out again without it, aligned by their baselines (`layoutFlex`).
|
|
2591
2643
|
*/
|
|
2592
|
-
function lineMarginFix(container, item, node, row,
|
|
2644
|
+
function lineMarginFix(container, item, node, row,
|
|
2645
|
+
/** Whether the flex box has a definite height. */
|
|
2646
|
+
own, started = false) {
|
|
2593
2647
|
const reverse = container.flexWrap === 'wrap-reverse';
|
|
2594
2648
|
if (!row && (reverse || container.direction === 'rtl'))
|
|
2595
2649
|
return 0;
|
|
@@ -2609,6 +2663,11 @@ function lineMarginFix(container, item, node, row, started = false) {
|
|
|
2609
2663
|
}
|
|
2610
2664
|
else {
|
|
2611
2665
|
align = style.alignSelf === AUTO ? container.alignItems : style.alignSelf;
|
|
2666
|
+
// which sets one whose height is a percentage of none at its line's
|
|
2667
|
+
// start, as Yoga is told it does (`applyItem`)
|
|
2668
|
+
if (align === 'stretch' && row && heightOfNone(style, own)) {
|
|
2669
|
+
align = 'flex-start';
|
|
2670
|
+
}
|
|
2612
2671
|
}
|
|
2613
2672
|
const leading = node.getComputedMargin(row ? Y.EDGE_TOP : Y.EDGE_LEFT);
|
|
2614
2673
|
const trailing = node.getComputedMargin(row ? Y.EDGE_BOTTOM : Y.EDGE_RIGHT);
|
|
@@ -2625,12 +2684,15 @@ function lineMarginFix(container, item, node, row, started = false) {
|
|
|
2625
2684
|
}
|
|
2626
2685
|
/** An item's first baseline, down from its border edge: its content's
|
|
2627
2686
|
* first line's, or where it has none, or is replaced, one synthesized
|
|
2628
|
-
* from its border box — its bottom edge.
|
|
2687
|
+
* from its border box — its bottom edge. Past that edge where the line
|
|
2688
|
+
* is: only a scroll container's is held to its box (`firstBaselineIn`),
|
|
2689
|
+
* and an item shorter than its text, or whose padding puts the text
|
|
2690
|
+
* under it, sits on its text where it had sat on its bottom. */
|
|
2629
2691
|
function itemBaseline(item) {
|
|
2630
2692
|
if (item.kind !== 'replaced') {
|
|
2631
2693
|
const found = firstBaselineIn(item);
|
|
2632
2694
|
if (found !== null)
|
|
2633
|
-
return
|
|
2695
|
+
return found - item.y;
|
|
2634
2696
|
}
|
|
2635
2697
|
return item.height;
|
|
2636
2698
|
}
|
|
@@ -2765,12 +2827,31 @@ function spacesLines(style) {
|
|
|
2765
2827
|
* makes too, and is kept. Where they do, Yoga is asked again as the row
|
|
2766
2828
|
* is, for where the lines and the items are, and the heights are kept from
|
|
2767
2829
|
* the first layout.
|
|
2830
|
+
*
|
|
2831
|
+
* And where the lines are taller than the row, `space-around` and
|
|
2832
|
+
* `space-evenly` fall back to `safe center`, which sets them at the row's
|
|
2833
|
+
* own start, its top (CSS Box Alignment 3, 4.3 and 5.1; CSS Flexbox 8.4).
|
|
2834
|
+
* Yoga falls back to `flex-start` for both, which is the bottom where the
|
|
2835
|
+
* lines run bottom to top, and ran them out past the row's top. It sets
|
|
2836
|
+
* the lines of a row that wraps in reverse top to bottom and turns them
|
|
2837
|
+
* over once they are set, so it is asked for them at `flex-end` there,
|
|
2838
|
+
* which comes out at the top — where the lines it set at their start, or
|
|
2839
|
+
* spaced, reach past the row's bottom.
|
|
2768
2840
|
*/
|
|
2769
2841
|
function unspace(root, items,
|
|
2770
2842
|
/** Whether the lines run bottom to top. */
|
|
2771
2843
|
reverse, layout) {
|
|
2772
2844
|
for (const { laid } of items)
|
|
2773
2845
|
laid.unstretched = NaN;
|
|
2846
|
+
const lines = root.getAlignContent();
|
|
2847
|
+
// where the lines start at the row's bottom, its start is their end
|
|
2848
|
+
const safe = reverse &&
|
|
2849
|
+
(lines === Y.ALIGN_SPACE_AROUND || lines === Y.ALIGN_SPACE_EVENLY);
|
|
2850
|
+
const atEnd = () => {
|
|
2851
|
+
root.setAlignContent(Y.ALIGN_FLEX_END);
|
|
2852
|
+
layout();
|
|
2853
|
+
root.setAlignContent(lines);
|
|
2854
|
+
};
|
|
2774
2855
|
// each item Yoga stretches: `stretch`, with no height of its own
|
|
2775
2856
|
const align = root.getAlignItems();
|
|
2776
2857
|
const stretched = items.filter(({ node }) => {
|
|
@@ -2782,15 +2863,23 @@ reverse, layout) {
|
|
|
2782
2863
|
});
|
|
2783
2864
|
if (stretched.length === 0) {
|
|
2784
2865
|
layout();
|
|
2866
|
+
// spaced where there is room, and else at their start, past the bottom
|
|
2867
|
+
if (safe &&
|
|
2868
|
+
linesReach(root, items, reverse) - root.getComputedHeight() > NEAR) {
|
|
2869
|
+
atEnd();
|
|
2870
|
+
}
|
|
2785
2871
|
return;
|
|
2786
2872
|
}
|
|
2787
|
-
const lines = root.getAlignContent();
|
|
2788
2873
|
root.setAlignContent(Y.ALIGN_FLEX_START);
|
|
2789
2874
|
layout();
|
|
2790
2875
|
root.setAlignContent(lines);
|
|
2791
|
-
|
|
2876
|
+
const room = root.getComputedHeight() - linesReach(root, items, reverse);
|
|
2877
|
+
if (safe && room < -NEAR) {
|
|
2878
|
+
atEnd();
|
|
2792
2879
|
return;
|
|
2793
2880
|
}
|
|
2881
|
+
if (!(room > NEAR))
|
|
2882
|
+
return;
|
|
2794
2883
|
const heights = stretched.map(({ node }) => node.getComputedHeight());
|
|
2795
2884
|
layout();
|
|
2796
2885
|
stretched.forEach(({ node, laid }, i) => {
|
|
@@ -2835,6 +2924,19 @@ function linesReach(root, items, reverse) {
|
|
|
2835
2924
|
}
|
|
2836
2925
|
return reach;
|
|
2837
2926
|
}
|
|
2927
|
+
/**
|
|
2928
|
+
* Whether a row item's height is a percentage of a height its flex box has
|
|
2929
|
+
* none of. That is `auto` to the item's size (CSS 2.1 10.5), and is not
|
|
2930
|
+
* handed to Yoga (`applyItem`), but it is not `auto` to its alignment:
|
|
2931
|
+
* `stretch` stretches an item whose height computes to `auto` (CSS Flexbox
|
|
2932
|
+
* 8.3), and this one's computes to the percentage. Such an item is as tall
|
|
2933
|
+
* as its content, set at its line's start, which is what Yoga is told.
|
|
2934
|
+
*/
|
|
2935
|
+
function heightOfNone(style,
|
|
2936
|
+
/** Whether the flex box has a definite height. */
|
|
2937
|
+
own) {
|
|
2938
|
+
return !own && isPct(style.height);
|
|
2939
|
+
}
|
|
2838
2940
|
/** Whether an item is stretched across its line: `stretch`, its own or its
|
|
2839
2941
|
* container's, with no height of its own and no `auto` margin across. */
|
|
2840
2942
|
function stretches(box, container,
|
|
@@ -2876,9 +2978,10 @@ function wrapsColumn(style, width) {
|
|
|
2876
2978
|
* where they are short of the box; `center` and `flex-end` whether they are
|
|
2877
2979
|
* or not, so that lines wider than the box run past both its sides, or its
|
|
2878
2980
|
* 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
|
|
2981
|
+
* at their start where there is none, or at the box's (CSS Box Alignment 3,
|
|
2982
|
+
* 4.3: `space-between` falls back to `flex-start`, `space-around` and
|
|
2983
|
+
* `space-evenly` to `safe center`, the box's own start where the lines
|
|
2984
|
+
* overflow, and not theirs where they wrap in reverse). An
|
|
2882
2985
|
* item with an `auto` margin across its line takes the room the line has
|
|
2883
2986
|
* past it on that side (8.1), and none where there is none; a stretched
|
|
2884
2987
|
* item is as wide as its line less its margins, within its limits (9.4,
|
|
@@ -2922,6 +3025,10 @@ gap) {
|
|
|
2922
3025
|
room -= size;
|
|
2923
3026
|
let at = 0;
|
|
2924
3027
|
let between = gap;
|
|
3028
|
+
// Where they are wider than the box, `space-around` and `space-evenly`
|
|
3029
|
+
// set the lines at the box's own start (`safe center`), which is where
|
|
3030
|
+
// their last one ends where they wrap in reverse: they run past its end
|
|
3031
|
+
const reverse = style.flexWrap === 'wrap-reverse';
|
|
2925
3032
|
switch (crossContent(style)) {
|
|
2926
3033
|
case 'flex-end':
|
|
2927
3034
|
at = room;
|
|
@@ -2942,12 +3049,16 @@ gap) {
|
|
|
2942
3049
|
at = room / count / 2;
|
|
2943
3050
|
between += room / count;
|
|
2944
3051
|
}
|
|
3052
|
+
else if (reverse)
|
|
3053
|
+
at = room;
|
|
2945
3054
|
break;
|
|
2946
3055
|
case 'space-evenly':
|
|
2947
3056
|
if (room > 0) {
|
|
2948
3057
|
at = room / (count + 1);
|
|
2949
3058
|
between += room / (count + 1);
|
|
2950
3059
|
}
|
|
3060
|
+
else if (reverse)
|
|
3061
|
+
at = room;
|
|
2951
3062
|
break;
|
|
2952
3063
|
}
|
|
2953
3064
|
const placed = new Map();
|