@react-x11/components 0.12.0 → 0.14.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/controls.d.ts +41 -5
- package/dist/html/controls.d.ts.map +1 -1
- package/dist/html/controls.js +85 -57
- package/dist/html/controls.js.map +1 -1
- package/dist/html/css/cascade.d.ts +134 -20
- package/dist/html/css/cascade.d.ts.map +1 -1
- package/dist/html/css/cascade.js +545 -126
- package/dist/html/css/cascade.js.map +1 -1
- package/dist/html/css/color.d.ts +18 -0
- package/dist/html/css/color.d.ts.map +1 -1
- package/dist/html/css/color.js +27 -0
- package/dist/html/css/color.js.map +1 -1
- package/dist/html/css/parse.d.ts +47 -6
- package/dist/html/css/parse.d.ts.map +1 -1
- package/dist/html/css/parse.js +336 -30
- package/dist/html/css/parse.js.map +1 -1
- package/dist/html/css/style.d.ts +142 -15
- package/dist/html/css/style.d.ts.map +1 -1
- package/dist/html/css/style.js +563 -147
- package/dist/html/css/style.js.map +1 -1
- package/dist/html/css/transform.d.ts +85 -0
- package/dist/html/css/transform.d.ts.map +1 -0
- package/dist/html/css/transform.js +425 -0
- package/dist/html/css/transform.js.map +1 -0
- package/dist/html/css/ua.d.ts +11 -1
- package/dist/html/css/ua.d.ts.map +1 -1
- package/dist/html/css/ua.js +73 -9
- package/dist/html/css/ua.js.map +1 -1
- package/dist/html/css/values.d.ts +4 -0
- package/dist/html/css/values.d.ts.map +1 -1
- package/dist/html/css/values.js.map +1 -1
- package/dist/html/dom.d.ts.map +1 -1
- package/dist/html/dom.js +3 -1
- package/dist/html/dom.js.map +1 -1
- package/dist/html/fonts.d.ts +78 -4
- package/dist/html/fonts.d.ts.map +1 -1
- package/dist/html/fonts.js +373 -19
- package/dist/html/fonts.js.map +1 -1
- package/dist/html/form.d.ts +200 -0
- package/dist/html/form.d.ts.map +1 -0
- package/dist/html/form.js +801 -0
- package/dist/html/form.js.map +1 -0
- package/dist/html/index.d.ts +12 -0
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +30 -301
- package/dist/html/index.js.map +1 -1
- package/dist/html/layout/axes.d.ts +14 -0
- package/dist/html/layout/axes.d.ts.map +1 -0
- package/dist/html/layout/axes.js +28 -0
- package/dist/html/layout/axes.js.map +1 -0
- package/dist/html/layout/block.d.ts +93 -12
- package/dist/html/layout/block.d.ts.map +1 -1
- package/dist/html/layout/block.js +393 -39
- package/dist/html/layout/block.js.map +1 -1
- package/dist/html/layout/boxes.d.ts +90 -2
- package/dist/html/layout/boxes.d.ts.map +1 -1
- package/dist/html/layout/boxes.js +74 -10
- package/dist/html/layout/boxes.js.map +1 -1
- package/dist/html/layout/cache.d.ts +1 -1
- package/dist/html/layout/cache.d.ts.map +1 -1
- package/dist/html/layout/cache.js +6 -0
- package/dist/html/layout/cache.js.map +1 -1
- package/dist/html/layout/css-grid.d.ts.map +1 -1
- package/dist/html/layout/css-grid.js +90 -18
- package/dist/html/layout/css-grid.js.map +1 -1
- package/dist/html/layout/flex.d.ts.map +1 -1
- package/dist/html/layout/flex.js +574 -84
- package/dist/html/layout/flex.js.map +1 -1
- package/dist/html/layout/inline.d.ts +3 -0
- package/dist/html/layout/inline.d.ts.map +1 -1
- package/dist/html/layout/inline.js +154 -54
- package/dist/html/layout/inline.js.map +1 -1
- package/dist/html/layout/multicol.d.ts +42 -0
- package/dist/html/layout/multicol.d.ts.map +1 -0
- package/dist/html/layout/multicol.js +897 -0
- package/dist/html/layout/multicol.js.map +1 -0
- package/dist/html/layout/shaping.d.ts +7 -0
- package/dist/html/layout/shaping.d.ts.map +1 -1
- package/dist/html/layout/shaping.js +25 -20
- package/dist/html/layout/shaping.js.map +1 -1
- package/dist/html/layout/table.d.ts.map +1 -1
- package/dist/html/layout/table.js +62 -18
- package/dist/html/layout/table.js.map +1 -1
- package/dist/html/node.d.ts +90 -15
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +771 -186
- package/dist/html/node.js.map +1 -1
- package/dist/html/paint.d.ts +101 -5
- package/dist/html/paint.d.ts.map +1 -1
- package/dist/html/paint.js +1502 -160
- package/dist/html/paint.js.map +1 -1
- package/dist/html/svg.d.ts +15 -2
- package/dist/html/svg.d.ts.map +1 -1
- package/dist/html/svg.js +249 -17
- package/dist/html/svg.js.map +1 -1
- package/dist/html/widgets.d.ts +29 -0
- package/dist/html/widgets.d.ts.map +1 -0
- package/dist/html/widgets.js +700 -0
- package/dist/html/widgets.js.map +1 -0
- package/dist/html/woff2.d.ts +14 -0
- package/dist/html/woff2.d.ts.map +1 -0
- package/dist/html/woff2.js +608 -0
- package/dist/html/woff2.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/maps/controller.d.ts +17 -1
- package/dist/maps/controller.d.ts.map +1 -1
- package/dist/maps/controller.js +27 -7
- package/dist/maps/controller.js.map +1 -1
- package/dist/richtext/node.d.ts +8 -1
- package/dist/richtext/node.d.ts.map +1 -1
- package/dist/richtext/node.js +5 -1
- package/dist/richtext/node.js.map +1 -1
- package/dist/richtext/runs.d.ts +25 -6
- package/dist/richtext/runs.d.ts.map +1 -1
- package/dist/richtext/runs.js +240 -24
- package/dist/richtext/runs.js.map +1 -1
- package/package.json +2 -2
- package/src/html/controls.ts +114 -51
- package/src/html/css/cascade.ts +614 -140
- package/src/html/css/color.ts +29 -0
- package/src/html/css/parse.ts +388 -33
- package/src/html/css/style.ts +688 -150
- package/src/html/css/transform.ts +459 -0
- package/src/html/css/ua.ts +77 -10
- package/src/html/css/values.ts +4 -0
- package/src/html/dom.ts +3 -1
- package/src/html/fonts.ts +417 -24
- package/src/html/form.ts +962 -0
- package/src/html/index.ts +49 -338
- package/src/html/layout/axes.ts +62 -0
- package/src/html/layout/block.ts +447 -37
- package/src/html/layout/boxes.ts +143 -14
- package/src/html/layout/cache.ts +6 -0
- package/src/html/layout/css-grid.ts +95 -22
- package/src/html/layout/flex.ts +675 -78
- package/src/html/layout/inline.ts +159 -55
- package/src/html/layout/multicol.ts +977 -0
- package/src/html/layout/shaping.ts +27 -18
- package/src/html/layout/table.ts +62 -19
- package/src/html/node.ts +798 -172
- package/src/html/paint.ts +1742 -241
- package/src/html/svg.ts +277 -19
- package/src/html/widgets.ts +821 -0
- package/src/html/woff2.ts +612 -0
- package/src/index.ts +1 -0
- package/src/maps/controller.ts +28 -7
- package/src/richtext/node.ts +13 -2
- package/src/richtext/runs.ts +313 -35
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
// formatting context it is inside.
|
|
13
13
|
import { AUTO, gapOf, isPct, isTransparent, resolve, resolveOrNull, } from '../css/values.js';
|
|
14
14
|
import { CONTAIN_INLINE_SIZE, CONTAIN_LAYOUT, CONTAIN_PAINT, CONTAIN_SIZE, scrolls, } from '../css/style.js';
|
|
15
|
+
import { about, linearOf, matrixOf, transformed } from '../css/transform.js';
|
|
15
16
|
import { lineOf, spanToName } from './grid-lines.js';
|
|
16
|
-
import {
|
|
17
|
+
import { columnsOf, forgetColumns, layoutColumns, spansColumns, } from './multicol.js';
|
|
18
|
+
import { BOX_RAISES, Box, CLAMPED, CLEARED_FROM, COLUMN_PIECES, CUT_BLOCKS, GRID_TRACKS, FIRST_LINE, INLINE_OFFSETS, MOVED_OFF_LINES, LINE_BOX_RAISES, SHIFTED_LINES, TEXT_SHIFTS, columned, isBlank, } from './boxes.js';
|
|
17
19
|
import { FloatContext } from './floats.js';
|
|
18
|
-
import { faceExtentOf, joinsBefore, layoutInline, lineHeightMultiplier, spaceBreaksOnly, strutOf, widestWord, } from './inline.js';
|
|
20
|
+
import { faceExtentOf, isButton, joinsBefore, layoutInline, lineHeightMultiplier, spaceBreaksOnly, strutOf, widestWord, } from './inline.js';
|
|
19
21
|
import { layoutFlex } from './flex.js';
|
|
20
22
|
import { finishCaptions, layoutTable } from './table.js';
|
|
21
23
|
import { collapseEdges } from './collapse.js';
|
|
@@ -27,7 +29,7 @@ export function layoutDocument(tree, fonts, viewportWidth, viewportHeight) {
|
|
|
27
29
|
viewportWidth,
|
|
28
30
|
viewportHeight,
|
|
29
31
|
positioned: [],
|
|
30
|
-
layoutSubtree: (box, width) => layoutSubtree(box, ctx, width),
|
|
32
|
+
layoutSubtree: (box, width, containing) => layoutSubtree(box, ctx, width, containing),
|
|
31
33
|
firstLine: tree.firstLine,
|
|
32
34
|
firstLineStyler: tree.firstLineStyler,
|
|
33
35
|
nestedOutOfLine: tree.nestedOutOfLine,
|
|
@@ -710,6 +712,10 @@ function layoutChildren(box, ctx, floats, contentTop, contentWidth, leading = 0)
|
|
|
710
712
|
}
|
|
711
713
|
first = false;
|
|
712
714
|
const moved = childY !== at;
|
|
715
|
+
if (moved)
|
|
716
|
+
CLEARED_FROM.set(child, at);
|
|
717
|
+
else
|
|
718
|
+
CLEARED_FROM.delete(child);
|
|
713
719
|
if (!moved && collapsesThrough(child)) {
|
|
714
720
|
// nothing in it parts its margins: they and the ones either side of
|
|
715
721
|
// it are one (CSS 2.1 8.3.1), still hanging for what comes next —
|
|
@@ -1334,16 +1340,24 @@ export function measureIntrinsicWidth(box, ctx, available, content = false) {
|
|
|
1334
1340
|
* the shrink-to-fit probe uses. A replaced box is sized rather than laid out,
|
|
1335
1341
|
* because there is nothing inside it to lay out.
|
|
1336
1342
|
*/
|
|
1337
|
-
function layoutSubtree(box, ctx, width
|
|
1338
|
-
|
|
1343
|
+
function layoutSubtree(box, ctx, width,
|
|
1344
|
+
/** Its containing block's width, where `width` is the box's own. */
|
|
1345
|
+
containing = width) {
|
|
1346
|
+
resolveEdges(box, Number.isFinite(containing) ? containing : 0);
|
|
1339
1347
|
if (box.kind === 'replaced') {
|
|
1340
1348
|
sizeReplaced(box, width);
|
|
1341
1349
|
box.x = 0;
|
|
1342
1350
|
box.y = 0;
|
|
1343
1351
|
return;
|
|
1344
1352
|
}
|
|
1353
|
+
// within its limits, a percentage among them of its containing block's
|
|
1354
|
+
// width and not of its own: a flex item `max-width: 50%` that the flex
|
|
1355
|
+
// layout made half its row was laid out at a quarter of it. A table
|
|
1356
|
+
// cell's is of nothing, and ignored: what a percentage limit does to a
|
|
1357
|
+
// cell it does where its column is sized (CSS Tables 3, 3.8.2), and a
|
|
1358
|
+
// cell is laid out in the width its columns came to.
|
|
1345
1359
|
const borderBox = Number.isFinite(width)
|
|
1346
|
-
? clampWidth(box, width,
|
|
1360
|
+
? clampWidth(box, width, box.kind === 'table-cell' ? NaN : containing)
|
|
1347
1361
|
: Infinity;
|
|
1348
1362
|
layoutInternals(box, ctx, borderBox, 0, 0);
|
|
1349
1363
|
}
|
|
@@ -1430,9 +1444,13 @@ function layoutBox(box, ctx, borderBoxWidth, x, y, outerFloats) {
|
|
|
1430
1444
|
finishCaptions(box);
|
|
1431
1445
|
return;
|
|
1432
1446
|
}
|
|
1447
|
+
// A multicol container's content is laid out as one column, all of it,
|
|
1448
|
+
// and then set in the columns there are (`layoutColumns`)
|
|
1449
|
+
const columns = columnsOf(box, contentWidth);
|
|
1450
|
+
const flowWidth = columns ? columns.width : contentWidth;
|
|
1433
1451
|
const ownFloats = establishesBFC(box) || !outerFloats;
|
|
1434
1452
|
const floats = ownFloats
|
|
1435
|
-
? new FloatContext(box.contentX, box.contentX +
|
|
1453
|
+
? new FloatContext(box.contentX, box.contentX + flowWidth)
|
|
1436
1454
|
: outerFloats;
|
|
1437
1455
|
// the line a pass before gave a marker, which this one may not
|
|
1438
1456
|
if (box.marker)
|
|
@@ -1448,7 +1466,18 @@ function layoutBox(box, ctx, borderBoxWidth, x, y, outerFloats) {
|
|
|
1448
1466
|
else
|
|
1449
1467
|
MARKER_ASCENT.set(box, markerAscent(box, box.marker, ctx.fonts));
|
|
1450
1468
|
}
|
|
1451
|
-
|
|
1469
|
+
// a column wide while its content is laid out, for what reads the box
|
|
1470
|
+
// it is in rather than the width it is handed
|
|
1471
|
+
// and about a box that spans them, in rows of columns (`layoutRows`)
|
|
1472
|
+
const rows = columns && columns.count > 1 && box.children.some(spansColumns)
|
|
1473
|
+
? layoutRows(box, ctx, columns, contentWidth, borderBoxWidth)
|
|
1474
|
+
: null;
|
|
1475
|
+
if (columns)
|
|
1476
|
+
box.width = columns.width + box.horizontalExtra;
|
|
1477
|
+
const flow = rows === null
|
|
1478
|
+
? layoutChildren(box, ctx, floats, box.contentY, flowWidth)
|
|
1479
|
+
: { height: rows, hanging: NO_MARGIN };
|
|
1480
|
+
box.width = borderBoxWidth;
|
|
1452
1481
|
// A list item with a marker and no line holds one, the marker's, a line
|
|
1453
1482
|
// of its own face tall: an empty `<li>` is a line tall in a browser, and
|
|
1454
1483
|
// an inline-block around one sits on its marker's baseline.
|
|
@@ -1488,7 +1517,16 @@ function layoutBox(box, ctx, borderBoxWidth, x, y, outerFloats) {
|
|
|
1488
1517
|
const withFloats = ownFloats && !clamped
|
|
1489
1518
|
? Math.max(height, floats.bottom === -Infinity ? 0 : floats.bottom - box.contentY)
|
|
1490
1519
|
: height;
|
|
1491
|
-
|
|
1520
|
+
if (rows !== null)
|
|
1521
|
+
finishHeight(box, rows);
|
|
1522
|
+
else if (columns) {
|
|
1523
|
+
finishHeight(box, layoutColumns(box, columns, withFloats, columnLimit(box)));
|
|
1524
|
+
}
|
|
1525
|
+
else {
|
|
1526
|
+
if (box.style.columns)
|
|
1527
|
+
forgetColumns(box);
|
|
1528
|
+
finishHeight(box, withFloats);
|
|
1529
|
+
}
|
|
1492
1530
|
// The margin that escaped through this box's bottom edge becomes part of
|
|
1493
1531
|
// its own: the parent's flow loop reads `child.marginBottom` for the next
|
|
1494
1532
|
// sibling's collapse, which is exactly where an escaped margin goes.
|
|
@@ -1503,6 +1541,76 @@ function layoutBox(box, ctx, borderBoxWidth, x, y, outerFloats) {
|
|
|
1503
1541
|
box.bottomStrut = null;
|
|
1504
1542
|
if (box.marker)
|
|
1505
1543
|
layoutMarker(box, box.marker, ctx);
|
|
1544
|
+
if (isButtonBlock(box)) {
|
|
1545
|
+
BUTTON_CONTENT.set(box, { height: withFloats, down: 0 });
|
|
1546
|
+
centreButton(box);
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
/**
|
|
1550
|
+
* A multicol container's content about the boxes that span its columns
|
|
1551
|
+
* (`column-span: all`, CSS Multi-column 1, 6): what comes before one is set
|
|
1552
|
+
* in columns of its own, balanced, the spanner under them across the whole
|
|
1553
|
+
* container, and what comes after in columns under that. A spanner is a
|
|
1554
|
+
* formatting context of its own and its margins collapse with no column
|
|
1555
|
+
* content's, only with the spanner's next to it. Answers the content's
|
|
1556
|
+
* height.
|
|
1557
|
+
*/
|
|
1558
|
+
function layoutRows(box, ctx, columns, contentWidth, borderBoxWidth) {
|
|
1559
|
+
const all = box.children;
|
|
1560
|
+
const limit = columnLimit(box);
|
|
1561
|
+
const top = box.contentY;
|
|
1562
|
+
let y = top;
|
|
1563
|
+
/** The bottom margin of the spanner just before, which the next thing
|
|
1564
|
+
* comes under: all of it, or what the next spanner's does not cover. */
|
|
1565
|
+
let margin = null;
|
|
1566
|
+
let from = 0;
|
|
1567
|
+
try {
|
|
1568
|
+
for (let i = 0; i <= all.length; i += 1) {
|
|
1569
|
+
const child = all[i];
|
|
1570
|
+
if (child && !spansColumns(child))
|
|
1571
|
+
continue;
|
|
1572
|
+
const row = all.slice(from, i);
|
|
1573
|
+
from = i + 1;
|
|
1574
|
+
if (row.length) {
|
|
1575
|
+
const set = row.some((in_) => in_.kind !== 'text' && in_.kind !== 'break' && !in_.outOfFlow);
|
|
1576
|
+
if (set && margin !== null) {
|
|
1577
|
+
y += margin;
|
|
1578
|
+
margin = null;
|
|
1579
|
+
}
|
|
1580
|
+
// the row's content as a strip a column wide, and then in columns,
|
|
1581
|
+
// no taller than the container has left
|
|
1582
|
+
box.children = row;
|
|
1583
|
+
box.width = columns.width + box.horizontalExtra;
|
|
1584
|
+
const floats = new FloatContext(box.contentX, box.contentX + columns.width);
|
|
1585
|
+
const flow = layoutChildren(box, ctx, floats, y, columns.width);
|
|
1586
|
+
box.width = borderBoxWidth;
|
|
1587
|
+
const strip = Math.max(flow.height, floats.bottom === -Infinity ? 0 : floats.bottom - y);
|
|
1588
|
+
y += layoutColumns(box, columns, strip, Math.max(0, limit - (y - top)), y);
|
|
1589
|
+
}
|
|
1590
|
+
if (!child)
|
|
1591
|
+
break;
|
|
1592
|
+
resolveEdges(child, contentWidth);
|
|
1593
|
+
y +=
|
|
1594
|
+
margin === null ? child.marginTop : Math.max(margin, child.marginTop);
|
|
1595
|
+
layoutBlockLevel(child, ctx, new FloatContext(box.contentX, box.contentX + contentWidth), box.contentX, y, contentWidth);
|
|
1596
|
+
y = child.y + child.height;
|
|
1597
|
+
margin = child.marginBottom;
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
finally {
|
|
1601
|
+
box.children = all;
|
|
1602
|
+
box.width = borderBoxWidth;
|
|
1603
|
+
}
|
|
1604
|
+
return y + (margin ?? 0) - top;
|
|
1605
|
+
}
|
|
1606
|
+
/** The tallest a multicol container's columns may be: its own height where
|
|
1607
|
+
* it has one, and its `max-height`; no limit where it has neither. */
|
|
1608
|
+
function columnLimit(box) {
|
|
1609
|
+
const height = box.height;
|
|
1610
|
+
finishHeight(box, specifiedHeight(box) === null ? Infinity : 0);
|
|
1611
|
+
const limit = box.height - box.verticalExtra;
|
|
1612
|
+
box.height = height;
|
|
1613
|
+
return Math.max(0, limit);
|
|
1506
1614
|
}
|
|
1507
1615
|
/**
|
|
1508
1616
|
* The room a list item's marker takes about its first line's baseline,
|
|
@@ -1791,12 +1899,23 @@ function stretchHeight(box) {
|
|
|
1791
1899
|
return Math.max(box.verticalExtra, base - top - bottom);
|
|
1792
1900
|
}
|
|
1793
1901
|
/**
|
|
1794
|
-
* The content height a flex layout made definite for an item — a
|
|
1795
|
-
* item's, a flexed one's in a container of a definite height (CSS
|
|
1796
|
-
* 9.8)
|
|
1797
|
-
*
|
|
1902
|
+
* The content height a flex or grid layout made definite for an item — a
|
|
1903
|
+
* stretched item's, a flexed one's in a container of a definite height (CSS
|
|
1904
|
+
* Flexbox 9.8), a grid item's stretched down its area (CSS Grid 1, 11.1) —
|
|
1905
|
+
* which what is in it takes its percentages of, and which an item that is
|
|
1906
|
+
* a flex or grid container itself lays its own items out in. Set by
|
|
1907
|
+
* `flex.ts` and `css-grid.ts` for the item's own layout alone.
|
|
1798
1908
|
*/
|
|
1799
1909
|
export const FLEXED_HEIGHT = new WeakMap();
|
|
1910
|
+
/**
|
|
1911
|
+
* The content height a flex layout gave an item without making it definite:
|
|
1912
|
+
* flexed along a column that has no height of its own, which 9.8 leaves
|
|
1913
|
+
* indefinite. An item that is a flex or grid container lays its own items
|
|
1914
|
+
* out in it all the same — it is its used size (9.7) — and nothing in it
|
|
1915
|
+
* takes a percentage of it. Set by `flex.ts` for the item's own layout
|
|
1916
|
+
* alone.
|
|
1917
|
+
*/
|
|
1918
|
+
export const USED_HEIGHT = new WeakMap();
|
|
1800
1919
|
/**
|
|
1801
1920
|
* Hand a box's children the height their percentages resolve against —
|
|
1802
1921
|
* through inline boxes, which are no containing block, to the inline-block
|
|
@@ -2067,7 +2186,7 @@ function placeBlock(box, contentLeft, y, containingWidth) {
|
|
|
2067
2186
|
function blockWidth(box, containingWidth, percentBase = containingWidth, ctx) {
|
|
2068
2187
|
const style = box.style;
|
|
2069
2188
|
const available = containingWidth - box.marginLeft - box.marginRight;
|
|
2070
|
-
if (style.width === AUTO) {
|
|
2189
|
+
if (style.width === AUTO || cyclicWidth(style, percentBase)) {
|
|
2071
2190
|
// a width its height gives it through its ratio
|
|
2072
2191
|
const fromRatio = ratioWidth(box);
|
|
2073
2192
|
if (fromRatio !== null) {
|
|
@@ -2075,8 +2194,9 @@ function blockWidth(box, containingWidth, percentBase = containingWidth, ctx) {
|
|
|
2075
2194
|
return ratioMinimum(box, clamped, percentBase, ctx);
|
|
2076
2195
|
}
|
|
2077
2196
|
const room = Math.max(0, available);
|
|
2078
|
-
const
|
|
2079
|
-
|
|
2197
|
+
const keyword = style.widthKeyword ?? (fitsContent(box) ? 'fit-content' : null);
|
|
2198
|
+
const width = keyword && ctx
|
|
2199
|
+
? contentSizedWidth(box, ctx, keyword, room, percentBase)
|
|
2080
2200
|
: room;
|
|
2081
2201
|
return clampWidth(box, transferredWidth(box, width), percentBase, ctx, containingWidth);
|
|
2082
2202
|
}
|
|
@@ -2087,6 +2207,41 @@ function blockWidth(box, containingWidth, percentBase = containingWidth, ctx) {
|
|
|
2087
2207
|
: specified + box.horizontalExtra;
|
|
2088
2208
|
return clampWidth(box, borderBox, percentBase, ctx, containingWidth);
|
|
2089
2209
|
}
|
|
2210
|
+
/**
|
|
2211
|
+
* Whether a block-level box's `width: auto` is `fit-content` and not the
|
|
2212
|
+
* room its margins leave: a `<button>`'s, of which HTML's rendering section
|
|
2213
|
+
* says "If the computed value of 'inline-size' is 'auto', then the used
|
|
2214
|
+
* value is the fit-content inline size" (button layout, 15.5.3) — whatever
|
|
2215
|
+
* it is laid out as inside, a block, a flex box or a grid, as Blink leaves
|
|
2216
|
+
* it out of the boxes whose `auto` stretches
|
|
2217
|
+
* (`ShouldBlockContainerChildStretchAutoInlineSize`). Set `display: block`
|
|
2218
|
+
* to stand on a line of its own, a button was as wide as the line, where it
|
|
2219
|
+
* is as wide as its label. Not one a flex box, a grid or a pair of offsets
|
|
2220
|
+
* sizes, which stretch it still.
|
|
2221
|
+
*
|
|
2222
|
+
* Asked of every block: most are told from a button by the length of their
|
|
2223
|
+
* name.
|
|
2224
|
+
*/
|
|
2225
|
+
function fitsContent(box) {
|
|
2226
|
+
return box.el !== null && box.el.name.length === 6 && isButton(box);
|
|
2227
|
+
}
|
|
2228
|
+
/**
|
|
2229
|
+
* Whether a box's `width` is a percentage of a width that is not there to
|
|
2230
|
+
* take it of: its containing block's, while that is being found from what
|
|
2231
|
+
* it holds — a float's, an inline-block's, a flex item's or a table cell's
|
|
2232
|
+
* content measured at its widest. The percentage is cyclic, and the box is
|
|
2233
|
+
* measured as though its width were `auto` (CSS Sizing 3, 5.2.1); it is a
|
|
2234
|
+
* share of the width that comes to once there is one.
|
|
2235
|
+
*
|
|
2236
|
+
* Taken as a share of nothing, the box was no width at all, and its content
|
|
2237
|
+
* wrapped at every word in it: a float around a `width: 100%` block was as
|
|
2238
|
+
* wide as the block's longest word, and one around a `width: 100%` flex box
|
|
2239
|
+
* of a label that clips — the branch button of a GitHub repository — as
|
|
2240
|
+
* wide as nothing, its label gone.
|
|
2241
|
+
*/
|
|
2242
|
+
export function cyclicWidth(style, base) {
|
|
2243
|
+
return isPct(style.width) && !Number.isFinite(base);
|
|
2244
|
+
}
|
|
2090
2245
|
/**
|
|
2091
2246
|
* A width a box with a ratio and no height of its own works out for itself
|
|
2092
2247
|
* within the least and greatest widths its least and greatest heights make
|
|
@@ -2247,7 +2402,7 @@ function shrinkToFitWidth(box, ctx, available,
|
|
|
2247
2402
|
* absolute box's offset, or its static position. */
|
|
2248
2403
|
offset = 0) {
|
|
2249
2404
|
const style = box.style;
|
|
2250
|
-
if (style.width !== AUTO) {
|
|
2405
|
+
if (style.width !== AUTO && !cyclicWidth(style, available)) {
|
|
2251
2406
|
const specified = Math.max(0, resolve(style.width, available, 0));
|
|
2252
2407
|
const borderBox = style.boxSizing === 'border-box'
|
|
2253
2408
|
? Math.max(specified, box.horizontalExtra)
|
|
@@ -2473,8 +2628,12 @@ function wordBound(box, fonts, measured) {
|
|
|
2473
2628
|
* was `Infinity`), so its own width says nothing and only what it drew does.
|
|
2474
2629
|
* Skipping the non-finite ones is what stops the probe from answering
|
|
2475
2630
|
* `Infinity` for every box that contains a paragraph.
|
|
2631
|
+
*
|
|
2632
|
+
* `seen.cut` is set where a line it measured was cut short by
|
|
2633
|
+
* `text-overflow`, in a box with a width to cut it at: the line is wider
|
|
2634
|
+
* than it was drawn, and the answer is of what was drawn.
|
|
2476
2635
|
*/
|
|
2477
|
-
export function intrinsicWidth(box) {
|
|
2636
|
+
export function intrinsicWidth(box, seen) {
|
|
2478
2637
|
// under size containment, as though it held nothing: the size
|
|
2479
2638
|
// `contain-intrinsic-size` gives it, or none (CSS Containment 2, 3.2)
|
|
2480
2639
|
if (contained(box, CONTAIN_WIDTH)) {
|
|
@@ -2511,6 +2670,10 @@ export function intrinsicWidth(box) {
|
|
|
2511
2670
|
widest = Math.max(widest, line.width + (line.floats ?? 0));
|
|
2512
2671
|
}
|
|
2513
2672
|
widest = Math.max(widest, box.floatRow);
|
|
2673
|
+
// a line `text-overflow` cut short is wider than this finds it
|
|
2674
|
+
if (seen && !seen.cut && box.style.textOverflow === 'ellipsis') {
|
|
2675
|
+
seen.cut = lines.some((line) => line.texts.some((text) => text.layout.truncated));
|
|
2676
|
+
}
|
|
2514
2677
|
}
|
|
2515
2678
|
// Floats among blocks stand side by side too, as many as come together,
|
|
2516
2679
|
// where each block in flow is a line of its own; one with a formatting
|
|
@@ -2521,6 +2684,9 @@ export function intrinsicWidth(box) {
|
|
|
2521
2684
|
const sideBySide = !Number.isFinite(box.width);
|
|
2522
2685
|
let left = 0;
|
|
2523
2686
|
let right = 0;
|
|
2687
|
+
/** In a multicol container, the widest box that spans its columns. */
|
|
2688
|
+
const spanning = box.style.columns !== 0 && box.kind === 'block';
|
|
2689
|
+
let across = 0;
|
|
2524
2690
|
for (const child of box.children) {
|
|
2525
2691
|
if (child.kind === 'text' || child.kind === 'break')
|
|
2526
2692
|
continue;
|
|
@@ -2544,9 +2710,25 @@ export function intrinsicWidth(box) {
|
|
|
2544
2710
|
// counts as `auto`, so its content decides.
|
|
2545
2711
|
if (typeof style.width === 'number') {
|
|
2546
2712
|
contribution = Math.max(own, min + margins);
|
|
2713
|
+
// And it is that width where the box was laid out at less. In a row
|
|
2714
|
+
// of flex items it was shrunk to fit the width this is measured at,
|
|
2715
|
+
// and what an item gives its flex box's own size is its width (CSS
|
|
2716
|
+
// Flexbox 9.9.3); under a percentage `max-width` it was cut short,
|
|
2717
|
+
// by a percentage of the size being worked out, which is none to
|
|
2718
|
+
// what a box contributes (5.2.1). But a replaced box's is of nothing
|
|
2719
|
+
// at its least and none at its most: as it was laid out.
|
|
2720
|
+
const cyclic = typeof style.maxWidth === 'object';
|
|
2721
|
+
if (cyclic ? child.kind !== 'replaced' : row) {
|
|
2722
|
+
let stated = style.width + contentExtra(child);
|
|
2723
|
+
if (typeof style.maxWidth === 'number') {
|
|
2724
|
+
stated = Math.min(stated, style.maxWidth + contentExtra(child));
|
|
2725
|
+
}
|
|
2726
|
+
stated = Math.max(stated, child.horizontalExtra, min);
|
|
2727
|
+
contribution = Math.max(contribution, stated + margins);
|
|
2728
|
+
}
|
|
2547
2729
|
}
|
|
2548
2730
|
else {
|
|
2549
|
-
let inner = intrinsicWidth(child) + child.horizontalExtra;
|
|
2731
|
+
let inner = intrinsicWidth(child, seen) + child.horizontalExtra;
|
|
2550
2732
|
if (typeof style.maxWidth === 'number') {
|
|
2551
2733
|
inner = Math.min(inner, style.maxWidth + contentExtra(child));
|
|
2552
2734
|
}
|
|
@@ -2554,6 +2736,11 @@ export function intrinsicWidth(box) {
|
|
|
2554
2736
|
inner = min;
|
|
2555
2737
|
contribution = Math.max(inner + margins, own);
|
|
2556
2738
|
}
|
|
2739
|
+
if (spanning && spansColumns(child)) {
|
|
2740
|
+
// across the columns, and no part of what a column is as wide as
|
|
2741
|
+
across = Math.max(across, contribution);
|
|
2742
|
+
continue;
|
|
2743
|
+
}
|
|
2557
2744
|
if (row) {
|
|
2558
2745
|
total += contribution;
|
|
2559
2746
|
items += 1;
|
|
@@ -2586,6 +2773,19 @@ export function intrinsicWidth(box) {
|
|
|
2586
2773
|
const gap = gapOf(box.style.columnGap, NaN);
|
|
2587
2774
|
widest = Math.max(widest, total + gap * (items - 1));
|
|
2588
2775
|
}
|
|
2776
|
+
// A multicol container is as wide as its columns side by side, each as
|
|
2777
|
+
// wide as its content or as `column-width` where that is wider, and the
|
|
2778
|
+
// gaps between them (as Blink measures one,
|
|
2779
|
+
// `NGColumnLayoutAlgorithm::ComputeMinMaxSizes`)
|
|
2780
|
+
if (box.style.columns && box.kind === 'block') {
|
|
2781
|
+
const count = box.style.columnCount ?? 1;
|
|
2782
|
+
const gap = box.style.columnGapNormal
|
|
2783
|
+
? box.style.fontSize
|
|
2784
|
+
: gapOf(box.style.columnGap, NaN);
|
|
2785
|
+
widest = Math.max(widest, box.style.columnWidth ?? 0);
|
|
2786
|
+
// and no narrower than a box that spans them
|
|
2787
|
+
widest = Math.max(widest * count + gap * (count - 1), across);
|
|
2788
|
+
}
|
|
2589
2789
|
return widest;
|
|
2590
2790
|
}
|
|
2591
2791
|
/** What a box's own width leaves out of its border box: its padding and
|
|
@@ -2806,6 +3006,21 @@ function placeFloat(box, floats, y, containingLeft, containingWidth) {
|
|
|
2806
3006
|
side: box.style.float === 'right' ? 'right' : 'left',
|
|
2807
3007
|
});
|
|
2808
3008
|
}
|
|
3009
|
+
/** Whether a box is a form control's: a replaced box for what draws it,
|
|
3010
|
+
* a widget, and an inline block for how it is sized. */
|
|
3011
|
+
function isControl(box) {
|
|
3012
|
+
switch (box.replaced) {
|
|
3013
|
+
case 'input':
|
|
3014
|
+
case 'textarea':
|
|
3015
|
+
case 'select':
|
|
3016
|
+
case 'button':
|
|
3017
|
+
case 'checkbox':
|
|
3018
|
+
case 'radio':
|
|
3019
|
+
return true;
|
|
3020
|
+
default:
|
|
3021
|
+
return false;
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
2809
3024
|
/**
|
|
2810
3025
|
* An absolutely positioned box, against its containing block: a box's
|
|
2811
3026
|
* padding box, or an inline box's fragments (`inlineContainingBlock`). An
|
|
@@ -2901,9 +3116,23 @@ function layoutPositioned(box, containing, ctx) {
|
|
|
2901
3116
|
style.minHeightKeyword === 'stretch') {
|
|
2902
3117
|
STRETCH_TOP.set(box, top ?? (bottom === null && at ? at.from.y + at.y - cbY : 0));
|
|
2903
3118
|
}
|
|
3119
|
+
// A form control is an inline block to CSS and no replaced element,
|
|
3120
|
+
// whatever draws it (HTML's rendering section): with both offsets and no
|
|
3121
|
+
// size of its own it fills what they leave, as any box does, where an
|
|
3122
|
+
// image keeps its own (10.3.8, 10.6.5). A page lays an invisible
|
|
3123
|
+
// `<select>` over a picker it draws, `position: absolute; inset: 0`, to
|
|
3124
|
+
// take the press, and it has to cover it.
|
|
3125
|
+
const control = isControl(box);
|
|
2904
3126
|
if (box.kind === 'replaced') {
|
|
2905
3127
|
sizeReplaced(box, cbWidth);
|
|
2906
|
-
stretchReplaced(box, style.widthKeyword === 'stretch'
|
|
3128
|
+
stretchReplaced(box, style.widthKeyword === 'stretch' ||
|
|
3129
|
+
(control &&
|
|
3130
|
+
style.width === AUTO &&
|
|
3131
|
+
style.widthKeyword === null &&
|
|
3132
|
+
left !== null &&
|
|
3133
|
+
right !== null)
|
|
3134
|
+
? width
|
|
3135
|
+
: null, cbWidth);
|
|
2907
3136
|
}
|
|
2908
3137
|
else
|
|
2909
3138
|
layoutOwn(box, ctx, width);
|
|
@@ -2964,13 +3193,17 @@ function layoutPositioned(box, containing, ctx) {
|
|
|
2964
3193
|
if (top !== null && bottom !== null) {
|
|
2965
3194
|
const fill = Math.max(0, cbHeight - top - bottom - box.marginTop - box.marginBottom);
|
|
2966
3195
|
// — a box with a ratio has its height from its width
|
|
2967
|
-
const stretches = style.height === AUTO &&
|
|
3196
|
+
const stretches = style.height === AUTO &&
|
|
3197
|
+
(box.kind !== 'replaced' || control) &&
|
|
3198
|
+
!boxRatio(box);
|
|
2968
3199
|
// both offsets and no height: the box fills what they leave, its
|
|
2969
3200
|
// `auto` margins nothing (10.6.4, rule 5) — unless `min-height` or
|
|
2970
3201
|
// `max-height` moves that, which makes it a height like one set, and
|
|
2971
3202
|
// the rules run again with it (10.7)
|
|
2972
|
-
if (stretches)
|
|
3203
|
+
if (stretches) {
|
|
2973
3204
|
box.height = clampHeight(box, fill);
|
|
3205
|
+
centreButton(box);
|
|
3206
|
+
}
|
|
2974
3207
|
if (!stretches || box.height !== fill) {
|
|
2975
3208
|
// and a height: the `auto` margins share the rest, and where none
|
|
2976
3209
|
// is `auto`, `bottom` gives way (10.6.4, 10.6.5)
|
|
@@ -3363,11 +3596,87 @@ export function moveTo(box, x, y) {
|
|
|
3363
3596
|
return;
|
|
3364
3597
|
translate(box, x - box.x, y - box.y);
|
|
3365
3598
|
}
|
|
3366
|
-
/**
|
|
3367
|
-
*
|
|
3599
|
+
/**
|
|
3600
|
+
* Move what a box holds down, and not the box: a table cell's content
|
|
3601
|
+
* sits where its `vertical-align` puts it, in a box that fills the row, and
|
|
3602
|
+
* a button's in the middle of its own (`centreButton`).
|
|
3603
|
+
*
|
|
3604
|
+
* The static positions the box gave the absolutely positioned boxes in its
|
|
3605
|
+
* flow go down with the content: each is where its box "would have been in
|
|
3606
|
+
* the normal flow" (CSS 2.1 10.6.4), and the flow is what moved. They are
|
|
3607
|
+
* kept from the box's own corner, which stays, so that moving the boxes
|
|
3608
|
+
* alone left them behind: a badge with no offsets in a `vertical-align:
|
|
3609
|
+
* middle` cell stood at the cell's top, over an icon 22px further down.
|
|
3610
|
+
*
|
|
3611
|
+
* It adds to where the content stands, so it is asked for once for each
|
|
3612
|
+
* layout of the box, which puts the content and the static positions back
|
|
3613
|
+
* at the top. A table lays a cell out and moves its content in one pass
|
|
3614
|
+
* over its cells, however many times a pass lays the table out, and one
|
|
3615
|
+
* whose layout is kept (`kept`) is moved whole, the cell with it; a button
|
|
3616
|
+
* counts how far down its content stands (`centreButton`).
|
|
3617
|
+
*/
|
|
3368
3618
|
export function moveContent(box, dy) {
|
|
3619
|
+
if (!dy)
|
|
3620
|
+
return;
|
|
3369
3621
|
translate(box, 0, dy);
|
|
3370
3622
|
box.y -= dy;
|
|
3623
|
+
moveStatics(box, box, dy);
|
|
3624
|
+
}
|
|
3625
|
+
/** Whether a box is a `<button>`'s own, laid out as a block container: the
|
|
3626
|
+
* one HTML's button layout sets an anonymous button content box in. Not
|
|
3627
|
+
* the text in it, whose element is the button too; not a button that is a
|
|
3628
|
+
* flex box or a grid, which has no such box; nor an `<input type=button>`,
|
|
3629
|
+
* which is a widget of its label's size. */
|
|
3630
|
+
function isButtonBlock(box) {
|
|
3631
|
+
return box.kind === 'block' && box.el !== null && box.el.name === 'button';
|
|
3632
|
+
}
|
|
3633
|
+
/** How tall a `<button>`'s content came to, and how far down its content
|
|
3634
|
+
* box it stands for being centred in it (`centreButton`). */
|
|
3635
|
+
const BUTTON_CONTENT = new WeakMap();
|
|
3636
|
+
/**
|
|
3637
|
+
* Centre a `<button>`'s content down its content box, where the box is the
|
|
3638
|
+
* taller: a button's content is in an anonymous box of its own that is
|
|
3639
|
+
* "centered vertically" where it "does not overflow in the vertical axis"
|
|
3640
|
+
* (HTML 15.5.5, button layout), and is at the top where it does. Blink
|
|
3641
|
+
* moves a button's children down by half the room left, clamped at none
|
|
3642
|
+
* (`AlignBlockContent`); set at the top as any block's is, the two lines of
|
|
3643
|
+
* a 60px sidebar picker on nextjs.org sat 4px high in it.
|
|
3644
|
+
*
|
|
3645
|
+
* Asked for when the button is laid out, and again wherever its height is
|
|
3646
|
+
* given to it afterwards — a flex or a grid item stretched to its line, or
|
|
3647
|
+
* put back to the height it was measured at, and an absolute box between
|
|
3648
|
+
* two offsets: the content moves by the difference from where it was last
|
|
3649
|
+
* put. A button that is a flex box or a grid has no such box, and its
|
|
3650
|
+
* content is where its own alignment puts it.
|
|
3651
|
+
*/
|
|
3652
|
+
export function centreButton(box) {
|
|
3653
|
+
if (!isButtonBlock(box))
|
|
3654
|
+
return;
|
|
3655
|
+
const content = BUTTON_CONTENT.get(box);
|
|
3656
|
+
if (content === undefined)
|
|
3657
|
+
return;
|
|
3658
|
+
const down = Math.max(0, (box.contentHeight - content.height) / 2);
|
|
3659
|
+
const by = down - content.down;
|
|
3660
|
+
if (by === 0 || !Number.isFinite(by))
|
|
3661
|
+
return;
|
|
3662
|
+
content.down = down;
|
|
3663
|
+
// and the static positions kept from its corner with it: a menu under a
|
|
3664
|
+
// button's label opens under the label, where the label went
|
|
3665
|
+
moveContent(box, by);
|
|
3666
|
+
}
|
|
3667
|
+
/** Move the static positions a block gave the absolutely positioned boxes
|
|
3668
|
+
* in its flow, at any depth of inline box, which are kept from its own
|
|
3669
|
+
* corner and not from its content's (`moveContent`). One from a box
|
|
3670
|
+
* inside it is kept from that box's corner, which moved with the rest. */
|
|
3671
|
+
function moveStatics(parent, block, dy) {
|
|
3672
|
+
for (const child of parent.children) {
|
|
3673
|
+
if (child.outOfFlow) {
|
|
3674
|
+
if (child.staticPosition?.from === block)
|
|
3675
|
+
child.staticPosition.y += dy;
|
|
3676
|
+
}
|
|
3677
|
+
else if (child.kind === 'inline')
|
|
3678
|
+
moveStatics(child, block, dy);
|
|
3679
|
+
}
|
|
3371
3680
|
}
|
|
3372
3681
|
function translate(box, dx, dy) {
|
|
3373
3682
|
if (!dx && !dy)
|
|
@@ -3379,6 +3688,17 @@ function translate(box, dx, dy) {
|
|
|
3379
3688
|
box.marker.x += dx;
|
|
3380
3689
|
box.marker.y += dy;
|
|
3381
3690
|
}
|
|
3691
|
+
// the pieces columns broke it in, which are kept beside it
|
|
3692
|
+
if (columned.any) {
|
|
3693
|
+
const pieces = COLUMN_PIECES.get(box);
|
|
3694
|
+
if (pieces) {
|
|
3695
|
+
for (const piece of pieces) {
|
|
3696
|
+
piece.x += dx;
|
|
3697
|
+
piece.y += dy;
|
|
3698
|
+
piece.wholeY += dy;
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3382
3702
|
if (box.lines) {
|
|
3383
3703
|
for (const line of box.lines) {
|
|
3384
3704
|
line.x += dx;
|
|
@@ -3508,6 +3828,12 @@ export function establishesBFC(box) {
|
|
|
3508
3828
|
return true;
|
|
3509
3829
|
if (style.position === 'absolute' || style.position === 'fixed')
|
|
3510
3830
|
return true;
|
|
3831
|
+
// a multicol container (CSS Multi-column 1, 2), and a box that spans
|
|
3832
|
+
// one's columns (6)
|
|
3833
|
+
if (style.columns && box.kind === 'block')
|
|
3834
|
+
return true;
|
|
3835
|
+
if (style.columnSpan && box.parent?.style.columns)
|
|
3836
|
+
return true;
|
|
3511
3837
|
if (style.display === 'inline-block' ||
|
|
3512
3838
|
style.display === 'flex' ||
|
|
3513
3839
|
style.display === 'inline-flex') {
|
|
@@ -3518,11 +3844,20 @@ export function establishesBFC(box) {
|
|
|
3518
3844
|
box.kind === 'table') {
|
|
3519
3845
|
return true;
|
|
3520
3846
|
}
|
|
3847
|
+
// a flex item, and a grid's: each an independent formatting context, which
|
|
3848
|
+
// the margins of what it holds stay inside (CSS Flexbox 1, 4; CSS Grid 1,
|
|
3849
|
+
// 6.1)
|
|
3850
|
+
if (box.parent?.kind === 'flex' && !box.outOfFlow)
|
|
3851
|
+
return true;
|
|
3521
3852
|
// The root element establishes the document's formatting context. Here it
|
|
3522
3853
|
// is a box below the synthetic initial containing block, so it is named:
|
|
3523
3854
|
// without it, <html>'s own margin collapsed with <body>'s first block's.
|
|
3524
3855
|
if (box.el?.name === 'html')
|
|
3525
3856
|
return true;
|
|
3857
|
+
// a button's content is in a formatting context of its own, the
|
|
3858
|
+
// anonymous button content box's (HTML 15.5.5), whatever its `display`
|
|
3859
|
+
if (isButtonBlock(box))
|
|
3860
|
+
return true;
|
|
3526
3861
|
return box.parent === null;
|
|
3527
3862
|
}
|
|
3528
3863
|
/** What a box's `position: relative` offset moves it by, applied after
|
|
@@ -3560,23 +3895,42 @@ export function applyRelativeOffsets(box, viewportWidth, viewportHeight) {
|
|
|
3560
3895
|
for (const block of blocks)
|
|
3561
3896
|
translate(block, dx, dy);
|
|
3562
3897
|
}
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
export
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
*
|
|
3898
|
+
// what makes a box a containing block and a layer, as a positioned box is,
|
|
3899
|
+
// is asked here by the layouts beside this one
|
|
3900
|
+
export { transformed };
|
|
3901
|
+
/** How far a box's transform moves it — `translate`, and the translation
|
|
3902
|
+
* its `transform` comes to with its turns and scales: a percentage is of
|
|
3903
|
+
* its own border box (CSS Transforms 1, 7). The rest of the transform is
|
|
3904
|
+
* paint's (`placedMatrix`). */
|
|
3570
3905
|
function translationOf(box, style = box.style) {
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3906
|
+
if (!transformed(style))
|
|
3907
|
+
return [0, 0];
|
|
3908
|
+
const m = matrixOf(style, box.width, box.height);
|
|
3909
|
+
return [m[4], m[5]];
|
|
3910
|
+
}
|
|
3911
|
+
/**
|
|
3912
|
+
* The matrix a box is painted through, in the document's coordinates: what
|
|
3913
|
+
* its transform does besides move it — a turn, a scale, a skew — about its
|
|
3914
|
+
* `transform-origin`, where layout has put it (`applyRelativeOffsets`). Null
|
|
3915
|
+
* for a box that only moves, which is every box but a few, and for an
|
|
3916
|
+
* inline box, which no transform applies to (CSS Transforms 1, 2: a
|
|
3917
|
+
* transformable element is no inline box).
|
|
3918
|
+
*/
|
|
3919
|
+
export function placedMatrix(box) {
|
|
3920
|
+
const style = box.style;
|
|
3921
|
+
if (style.transform === null &&
|
|
3922
|
+
style.rotate === null &&
|
|
3923
|
+
style.scale === null) {
|
|
3924
|
+
return null;
|
|
3578
3925
|
}
|
|
3579
|
-
|
|
3926
|
+
if (box.kind === 'inline' || box.kind === 'text' || box.kind === 'break') {
|
|
3927
|
+
return null;
|
|
3928
|
+
}
|
|
3929
|
+
const linear = linearOf(style);
|
|
3930
|
+
if (!linear)
|
|
3931
|
+
return null;
|
|
3932
|
+
const origin = style.transformOrigin;
|
|
3933
|
+
return about(linear, box.x + resolve(origin[0], box.width, 0), box.y + resolve(origin[1], box.height, 0));
|
|
3580
3934
|
}
|
|
3581
3935
|
/**
|
|
3582
3936
|
* Move a laid-out box, and everything in it, by how far its translation
|