@react-x11/components 0.14.0 → 0.16.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/code-editor/node.d.ts +13 -0
- package/dist/code-editor/node.d.ts.map +1 -1
- package/dist/code-editor/node.js +23 -5
- package/dist/code-editor/node.js.map +1 -1
- package/dist/html/css/cascade.d.ts +209 -23
- package/dist/html/css/cascade.d.ts.map +1 -1
- package/dist/html/css/cascade.js +873 -175
- package/dist/html/css/cascade.js.map +1 -1
- package/dist/html/css/color.d.ts +25 -0
- package/dist/html/css/color.d.ts.map +1 -1
- package/dist/html/css/color.js +307 -19
- package/dist/html/css/color.js.map +1 -1
- package/dist/html/css/content.d.ts +11 -6
- package/dist/html/css/content.d.ts.map +1 -1
- package/dist/html/css/content.js +171 -12
- package/dist/html/css/content.js.map +1 -1
- package/dist/html/css/parse.d.ts.map +1 -1
- package/dist/html/css/parse.js +62 -9
- package/dist/html/css/parse.js.map +1 -1
- package/dist/html/css/shapes.d.ts +62 -0
- package/dist/html/css/shapes.d.ts.map +1 -0
- package/dist/html/css/shapes.js +214 -0
- package/dist/html/css/shapes.js.map +1 -0
- package/dist/html/css/style.d.ts +42 -5
- package/dist/html/css/style.d.ts.map +1 -1
- package/dist/html/css/style.js +75 -27
- package/dist/html/css/style.js.map +1 -1
- package/dist/html/css/ua.js +15 -0
- package/dist/html/css/ua.js.map +1 -1
- package/dist/html/css/values.d.ts +5 -0
- package/dist/html/css/values.d.ts.map +1 -1
- package/dist/html/css/values.js +18 -9
- package/dist/html/css/values.js.map +1 -1
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +7 -0
- package/dist/html/index.js.map +1 -1
- package/dist/html/layout/block.d.ts +38 -7
- package/dist/html/layout/block.d.ts.map +1 -1
- package/dist/html/layout/block.js +160 -50
- package/dist/html/layout/block.js.map +1 -1
- package/dist/html/layout/boxes.d.ts +29 -2
- package/dist/html/layout/boxes.d.ts.map +1 -1
- package/dist/html/layout/boxes.js +159 -20
- package/dist/html/layout/boxes.js.map +1 -1
- package/dist/html/layout/css-grid.d.ts.map +1 -1
- package/dist/html/layout/css-grid.js +69 -19
- 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 +1648 -225
- package/dist/html/layout/flex.js.map +1 -1
- package/dist/html/layout/inline.d.ts +15 -3
- package/dist/html/layout/inline.d.ts.map +1 -1
- package/dist/html/layout/inline.js +23 -8
- package/dist/html/layout/inline.js.map +1 -1
- package/dist/html/layout/table.d.ts +27 -1
- package/dist/html/layout/table.d.ts.map +1 -1
- package/dist/html/layout/table.js +907 -323
- package/dist/html/layout/table.js.map +1 -1
- package/dist/html/node.d.ts +36 -4
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +174 -37
- package/dist/html/node.js.map +1 -1
- package/dist/html/paint.d.ts +4 -1
- package/dist/html/paint.d.ts.map +1 -1
- package/dist/html/paint.js +769 -204
- package/dist/html/paint.js.map +1 -1
- package/dist/html/resources.js +14 -1
- package/dist/html/resources.js.map +1 -1
- package/dist/html/svg.d.ts +50 -17
- package/dist/html/svg.d.ts.map +1 -1
- package/dist/html/svg.js +501 -83
- package/dist/html/svg.js.map +1 -1
- package/dist/html/widgets.d.ts.map +1 -1
- package/dist/html/widgets.js +57 -4
- package/dist/html/widgets.js.map +1 -1
- package/package.json +3 -3
- package/src/code-editor/node.ts +24 -5
- package/src/html/css/cascade.ts +987 -176
- package/src/html/css/color.ts +345 -18
- package/src/html/css/content.ts +173 -15
- package/src/html/css/parse.ts +60 -8
- package/src/html/css/shapes.ts +273 -0
- package/src/html/css/style.ts +123 -30
- package/src/html/css/ua.ts +15 -0
- package/src/html/css/values.ts +23 -9
- package/src/html/index.ts +7 -0
- package/src/html/layout/block.ts +169 -56
- package/src/html/layout/boxes.ts +198 -24
- package/src/html/layout/css-grid.ts +89 -22
- package/src/html/layout/flex.ts +1863 -219
- package/src/html/layout/inline.ts +27 -7
- package/src/html/layout/table.ts +989 -333
- package/src/html/node.ts +204 -37
- package/src/html/paint.ts +999 -252
- package/src/html/resources.ts +13 -1
- package/src/html/svg.ts +600 -78
- package/src/html/widgets.ts +61 -4
|
@@ -11,15 +11,15 @@
|
|
|
11
11
|
// inline pass ask "how wide is the line at this y" without knowing whose
|
|
12
12
|
// formatting context it is inside.
|
|
13
13
|
import { AUTO, gapOf, isPct, isTransparent, resolve, resolveOrNull, } from '../css/values.js';
|
|
14
|
-
import { CONTAIN_INLINE_SIZE, CONTAIN_LAYOUT, CONTAIN_PAINT, CONTAIN_SIZE, scrolls, } from '../css/style.js';
|
|
14
|
+
import { CONTAIN_INLINE_SIZE, CONTAIN_LAYOUT, CONTAIN_PAINT, CONTAIN_SIZE, INLINE_BEFORE_ABSOLUTE, scrolls, } from '../css/style.js';
|
|
15
15
|
import { about, linearOf, matrixOf, transformed } from '../css/transform.js';
|
|
16
16
|
import { lineOf, spanToName } from './grid-lines.js';
|
|
17
17
|
import { columnsOf, forgetColumns, layoutColumns, spansColumns, } from './multicol.js';
|
|
18
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';
|
|
19
19
|
import { FloatContext } from './floats.js';
|
|
20
|
-
import { faceExtentOf, isButton, joinsBefore, layoutInline, lineHeightMultiplier, spaceBreaksOnly, strutOf, widestWord, } from './inline.js';
|
|
20
|
+
import { emptyLinePoint, faceExtentOf, isButton, joinsBefore, layoutInline, lineHeightMultiplier, spaceBreaksOnly, strutOf, widestWord, } from './inline.js';
|
|
21
21
|
import { layoutFlex } from './flex.js';
|
|
22
|
-
import { finishCaptions, layoutTable } from './table.js';
|
|
22
|
+
import { finishCaptions, givenHeight, layoutTable } from './table.js';
|
|
23
23
|
import { collapseEdges } from './collapse.js';
|
|
24
24
|
import { clipsFor, computePaintBounds, FIXED_BOXES, fixedToViewport, hoistNegative, OUT_OF_FLOW_REACH, stackLayers, } from '../paint.js';
|
|
25
25
|
/** Lay the whole document out at a width. */
|
|
@@ -622,7 +622,16 @@ function layoutChildren(box, ctx, floats, contentTop, contentWidth, leading = 0)
|
|
|
622
622
|
marked = null;
|
|
623
623
|
}
|
|
624
624
|
if (child.outOfFlow) {
|
|
625
|
-
|
|
625
|
+
const top = y + marginOf(pendingMargin);
|
|
626
|
+
if (INLINE_BEFORE_ABSOLUTE.has(child.style)) {
|
|
627
|
+
// one that was inline-level is on a line of its own, beside the
|
|
628
|
+
// floats there, where the line's alignment puts what it holds
|
|
629
|
+
const band = floats.bandAt(top, 1, contentLeft, contentLeft + contentWidth);
|
|
630
|
+
const at = emptyLinePoint(box.style, band.left, band.right);
|
|
631
|
+
placeStatic(child, box, at, 0, top);
|
|
632
|
+
}
|
|
633
|
+
else
|
|
634
|
+
placeStatic(child, box, contentLeft, contentWidth, top);
|
|
626
635
|
ctx.positioned.push({
|
|
627
636
|
box: child,
|
|
628
637
|
containing: containingBlockFor(child) ?? box,
|
|
@@ -1327,38 +1336,61 @@ export const MIN_CONTENT_PROBE = 0;
|
|
|
1327
1336
|
* a cell set to 10% measured no wider than its padding.
|
|
1328
1337
|
*/
|
|
1329
1338
|
export function measureIntrinsicWidth(box, ctx, available, content = false) {
|
|
1330
|
-
ctx.layoutSubtree
|
|
1339
|
+
// not through `ctx.layoutSubtree`, which is this and one frame more on
|
|
1340
|
+
// the stack for every level of a document that measures what it holds
|
|
1341
|
+
// (`layoutTable`)
|
|
1342
|
+
layoutSubtree(box, ctx, available, undefined, true);
|
|
1331
1343
|
const specified = box.style.width;
|
|
1332
1344
|
if (!content && specified !== AUTO && Number.isFinite(box.width)) {
|
|
1333
1345
|
return box.width;
|
|
1334
1346
|
}
|
|
1335
|
-
return intrinsicWidth(box) +
|
|
1347
|
+
return (intrinsicWidth(box, undefined, available === MIN_CONTENT_PROBE) +
|
|
1348
|
+
box.horizontalExtra);
|
|
1336
1349
|
}
|
|
1337
1350
|
/**
|
|
1338
1351
|
* Lay a box and everything under it out at a width, at the origin — what
|
|
1339
|
-
* `LayoutContext.layoutSubtree` hands to `flex.ts` and `
|
|
1340
|
-
* the shrink-to-fit probe
|
|
1341
|
-
* because there is nothing inside it to lay out.
|
|
1352
|
+
* `LayoutContext.layoutSubtree` hands to `flex.ts` and `css-grid.ts`, and
|
|
1353
|
+
* what the shrink-to-fit probe and a table's cells use. A replaced box is
|
|
1354
|
+
* sized rather than laid out, because there is nothing inside it to lay out.
|
|
1342
1355
|
*/
|
|
1343
|
-
function layoutSubtree(box, ctx, width,
|
|
1356
|
+
export function layoutSubtree(box, ctx, width,
|
|
1344
1357
|
/** Its containing block's width, where `width` is the box's own. */
|
|
1345
|
-
containing
|
|
1346
|
-
|
|
1358
|
+
containing,
|
|
1359
|
+
/** Whether this lays it out to measure it (`measureIntrinsicWidth`). */
|
|
1360
|
+
measuring = false) {
|
|
1361
|
+
const base = containing ?? width;
|
|
1362
|
+
resolveEdges(box, Number.isFinite(base) ? base : 0);
|
|
1347
1363
|
if (box.kind === 'replaced') {
|
|
1348
1364
|
sizeReplaced(box, width);
|
|
1349
1365
|
box.x = 0;
|
|
1350
1366
|
box.y = 0;
|
|
1351
1367
|
return;
|
|
1352
1368
|
}
|
|
1353
|
-
//
|
|
1369
|
+
// Within its limits, a percentage among them of its containing block's
|
|
1354
1370
|
// 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.
|
|
1356
|
-
//
|
|
1357
|
-
//
|
|
1358
|
-
//
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1371
|
+
// layout made half its row was laid out at a quarter of it. An
|
|
1372
|
+
// intrinsic limit is among them, as it is in a block's flow: without it,
|
|
1373
|
+
// a flex or grid item `min-width: max-content` that its layout made as
|
|
1374
|
+
// wide as its content was laid out at a smaller `max-width`, where the
|
|
1375
|
+
// minimum wins (CSS Sizing 3, 3.1). Not where the box is laid out to be
|
|
1376
|
+
// measured, since that is what an intrinsic limit is measured from.
|
|
1377
|
+
//
|
|
1378
|
+
// A table cell laid out in its columns, which hand it its row's width,
|
|
1379
|
+
// is as wide as they are (CSS Tables 3, 3.10.2): its limits are theirs
|
|
1380
|
+
// to weigh (3.8.2), and have been. Clamped again, `td { max-width:
|
|
1381
|
+
// 50px }` in a column 200 wide set its text in 50 of it. Probed for
|
|
1382
|
+
// what it asks of them, at none, it keeps within its length limits as
|
|
1383
|
+
// any box does; a percentage one is of nothing and does not hold it.
|
|
1384
|
+
let borderBox = Infinity;
|
|
1385
|
+
if (Number.isFinite(width)) {
|
|
1386
|
+
if (box.kind !== 'table-cell') {
|
|
1387
|
+
borderBox = clampWidth(box, width, base, measuring ? undefined : ctx);
|
|
1388
|
+
}
|
|
1389
|
+
else if (containing !== undefined)
|
|
1390
|
+
borderBox = width;
|
|
1391
|
+
else
|
|
1392
|
+
borderBox = clampWidth(box, width, NaN);
|
|
1393
|
+
}
|
|
1362
1394
|
layoutInternals(box, ctx, borderBox, 0, 0);
|
|
1363
1395
|
}
|
|
1364
1396
|
/**
|
|
@@ -1704,12 +1736,12 @@ function layoutMarker(box, marker, ctx) {
|
|
|
1704
1736
|
const style = box.style;
|
|
1705
1737
|
if (marker.image) {
|
|
1706
1738
|
// an image: its bottom on the first line's baseline, as an inline
|
|
1707
|
-
// image's is, and
|
|
1739
|
+
// image's is, and its own gap before the content (`MARKER_IMAGE_GAP`)
|
|
1708
1740
|
const first = firstLineIn(box);
|
|
1709
1741
|
marker.y = first
|
|
1710
1742
|
? first.y + first.baseline - marker.image.height
|
|
1711
1743
|
: box.contentY;
|
|
1712
|
-
const gap =
|
|
1744
|
+
const { gap } = marker.image;
|
|
1713
1745
|
// at the start of the line, which is its right in a right-to-left item
|
|
1714
1746
|
marker.x =
|
|
1715
1747
|
style.direction === 'rtl'
|
|
@@ -1743,8 +1775,13 @@ function layoutMarker(box, marker, ctx) {
|
|
|
1743
1775
|
});
|
|
1744
1776
|
marker.layout = layout;
|
|
1745
1777
|
// a space between it and the content — the one its style's suffix ends
|
|
1746
|
-
// in, or its own text's — in its own face: a line measures without
|
|
1747
|
-
|
|
1778
|
+
// in, or its own text's — in its own face: a line measures without the
|
|
1779
|
+
// spaces it ends in, and with a no-break space, which `content: "1.\a0"`
|
|
1780
|
+
// writes and which was a second gap on top of its own
|
|
1781
|
+
const trailing = marker.flush
|
|
1782
|
+
? (/[ \t\n\r\f]*$/.exec(marker.text)?.[0].length ?? 0)
|
|
1783
|
+
: 1;
|
|
1784
|
+
const gap = trailing ? trailing * markerGap(fonts, face) : 0;
|
|
1748
1785
|
// The marker sits on the first line of the item's *content*, which is not
|
|
1749
1786
|
// always the item's own: an `<li>` holding a paragraph, or one holding text
|
|
1750
1787
|
// and a nested list, has its inline content in an anonymous block. Looking
|
|
@@ -1903,19 +1940,33 @@ function stretchHeight(box) {
|
|
|
1903
1940
|
* stretched item's, a flexed one's in a container of a definite height (CSS
|
|
1904
1941
|
* Flexbox 9.8), a grid item's stretched down its area (CSS Grid 1, 11.1) —
|
|
1905
1942
|
* 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
|
|
1907
|
-
* `flex.ts` and `css-grid.ts` for the
|
|
1943
|
+
* a flex or grid container itself lays its own items out in, and a table
|
|
1944
|
+
* shares out among its rows. Set by `flex.ts` and `css-grid.ts` for the
|
|
1945
|
+
* item's own layout alone.
|
|
1908
1946
|
*/
|
|
1909
1947
|
export const FLEXED_HEIGHT = new WeakMap();
|
|
1910
1948
|
/**
|
|
1911
1949
|
* The content height a flex layout gave an item without making it definite:
|
|
1912
1950
|
* flexed along a column that has no height of its own, which 9.8 leaves
|
|
1913
1951
|
* 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) —
|
|
1915
|
-
* takes a percentage of it. Set by
|
|
1916
|
-
* alone.
|
|
1952
|
+
* out in it all the same — it is its used size (9.7) — as a table shares
|
|
1953
|
+
* it among its rows, and nothing in it takes a percentage of it. Set by
|
|
1954
|
+
* `flex.ts` for the item's own layout alone.
|
|
1917
1955
|
*/
|
|
1918
1956
|
export const USED_HEIGHT = new WeakMap();
|
|
1957
|
+
/**
|
|
1958
|
+
* A table a grid or a flex layout gives its width, whose `auto` width is
|
|
1959
|
+
* then the one it is laid out at. `normal` stretches any grid item but a
|
|
1960
|
+
* replaced one across its area (CSS Grid 1, 6.2), and a flex item across a
|
|
1961
|
+
* column's line (CSS Flexbox 9.4, step 11), a table among them; and a flex
|
|
1962
|
+
* item along a row is the size the line flexed it to (9.7) — where in a
|
|
1963
|
+
* block's flow a table's `auto` width is its columns' (CSS 2.1 17.5.2;
|
|
1964
|
+
* Blink leaves tables out of the boxes a block stretches, `space_utils.cc`,
|
|
1965
|
+
* and stretches them in a grid, `grid_item.cc`, and a flex box). Set by
|
|
1966
|
+
* `css-grid.ts` and `flex.ts` for the item's own layout alone, and never
|
|
1967
|
+
* while its widths are measured.
|
|
1968
|
+
*/
|
|
1969
|
+
export const STRETCHED_ACROSS = new WeakSet();
|
|
1919
1970
|
/**
|
|
1920
1971
|
* Hand a box's children the height their percentages resolve against —
|
|
1921
1972
|
* through inline boxes, which are no containing block, to the inline-block
|
|
@@ -2081,6 +2132,14 @@ function finishHeight(box, contentHeight) {
|
|
|
2081
2132
|
if (box.kind === 'table-cell') {
|
|
2082
2133
|
CELL_CONTENT.set(box, contentHeight + box.verticalExtra);
|
|
2083
2134
|
}
|
|
2135
|
+
// A table a flex or grid layout gave a height is as tall as that, or as
|
|
2136
|
+
// its rows where they need more, which `layoutTable` has shared it out
|
|
2137
|
+
// among — whatever height it has of its own, which the flex layout
|
|
2138
|
+
// started from (`layoutTable`)
|
|
2139
|
+
if (box.kind === 'table' && Number.isFinite(givenHeight(box))) {
|
|
2140
|
+
box.height = contentHeight + box.verticalExtra;
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
2084
2143
|
const set = specifiedHeight(box);
|
|
2085
2144
|
// at least zero: a `calc()` may come to less
|
|
2086
2145
|
const specified = set === null ? null : Math.max(0, set);
|
|
@@ -2135,7 +2194,9 @@ export function clampHeight(box, height) {
|
|
|
2135
2194
|
out = Math.min(out, max + (box.style.boxSizing === 'border-box' ? 0 : box.verticalExtra));
|
|
2136
2195
|
if (min !== null)
|
|
2137
2196
|
out = Math.max(out, min + (box.style.boxSizing === 'border-box' ? 0 : box.verticalExtra));
|
|
2138
|
-
|
|
2197
|
+
// no shorter than its padding and borders, as `clampWidth` is no
|
|
2198
|
+
// narrower
|
|
2199
|
+
return Math.max(box.verticalExtra, out);
|
|
2139
2200
|
}
|
|
2140
2201
|
/** Place a block-level box horizontally, honouring `margin: auto`. */
|
|
2141
2202
|
function placeBlock(box, contentLeft, y, containingWidth) {
|
|
@@ -2324,7 +2385,10 @@ room = containingWidth) {
|
|
|
2324
2385
|
if (style.minWidthKeyword && ctx) {
|
|
2325
2386
|
out = Math.max(out, keywordWidth(box, ctx, style.minWidthKeyword, containingWidth, room));
|
|
2326
2387
|
}
|
|
2327
|
-
|
|
2388
|
+
// and no narrower than its padding and borders: a `border-box` length
|
|
2389
|
+
// less than them leaves its content box none wide, and not less (CSS
|
|
2390
|
+
// Sizing 3, 3.3)
|
|
2391
|
+
return Math.max(box.horizontalExtra, out);
|
|
2328
2392
|
}
|
|
2329
2393
|
/** An intrinsic `min-width` or `max-width` in the room a box's margins
|
|
2330
2394
|
* leave it. Apart from `clampWidth`, which every block is sized through,
|
|
@@ -2354,21 +2418,25 @@ export function contentSizedWidth(box, ctx, size, available, percentBase) {
|
|
|
2354
2418
|
// the content's sizes, whatever width the box has of its own: a
|
|
2355
2419
|
// `min-width: max-content` beside a `width` is its content's widest,
|
|
2356
2420
|
// and a probe of the box at no width answered the probe's width
|
|
2357
|
-
let probed = false;
|
|
2358
2421
|
if (box.intrinsicMaxContent < 0) {
|
|
2359
2422
|
box.intrinsicMaxContent = measureIntrinsicWidth(box, ctx, Infinity, true);
|
|
2360
|
-
probed = true;
|
|
2361
2423
|
}
|
|
2362
2424
|
if (size !== 'max-content' && box.intrinsicMinContent < 0) {
|
|
2363
2425
|
box.intrinsicMinContent = measureIntrinsicWidth(box, ctx, MIN_CONTENT_PROBE, true);
|
|
2364
|
-
probed = true;
|
|
2365
2426
|
}
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2427
|
+
// The probes resolved a percentage of the box's padding or border
|
|
2428
|
+
// against nothing, which is how the sizes are kept, whatever the width
|
|
2429
|
+
// around the box: what one comes to against `percentBase` goes on top.
|
|
2430
|
+
// Left out, `width: max-content; padding-left: 10%` was as wide as its
|
|
2431
|
+
// content, the padding inside it.
|
|
2432
|
+
resolveEdges(box, 0);
|
|
2433
|
+
const bare = box.horizontalExtra;
|
|
2434
|
+
resolveEdges(box, Number.isFinite(percentBase) ? percentBase : 0);
|
|
2435
|
+
const extra = box.horizontalExtra - bare;
|
|
2436
|
+
const max = box.intrinsicMaxContent + extra;
|
|
2369
2437
|
if (size === 'max-content')
|
|
2370
2438
|
return max;
|
|
2371
|
-
const min = box.intrinsicMinContent;
|
|
2439
|
+
const min = box.intrinsicMinContent + extra;
|
|
2372
2440
|
if (size === 'min-content')
|
|
2373
2441
|
return min;
|
|
2374
2442
|
return Math.min(max, Math.max(min, fitRoom(box, size, available, percentBase)));
|
|
@@ -2495,6 +2563,11 @@ const PREFERRED = new WeakMap();
|
|
|
2495
2563
|
* or is indented, a block with widths of its own.
|
|
2496
2564
|
*/
|
|
2497
2565
|
export function exactMinContent(box, fonts) {
|
|
2566
|
+
// a flex row's is its items' side by side, a grid's its columns', and a
|
|
2567
|
+
// replaced element has no words: read as its widest word, a row of two
|
|
2568
|
+
// in a flex column's item was as narrow as the wider of them
|
|
2569
|
+
if (box.kind !== 'block' && box.kind !== 'table-cell')
|
|
2570
|
+
return null;
|
|
2498
2571
|
if (hasWidths(box.style) || contained(box, CONTAIN_WIDTH))
|
|
2499
2572
|
return null;
|
|
2500
2573
|
const inner = exactWords(box, fonts);
|
|
@@ -2632,13 +2705,28 @@ function wordBound(box, fonts, measured) {
|
|
|
2632
2705
|
* `seen.cut` is set where a line it measured was cut short by
|
|
2633
2706
|
* `text-overflow`, in a box with a width to cut it at: the line is wider
|
|
2634
2707
|
* than it was drawn, and the answer is of what was drawn.
|
|
2708
|
+
*
|
|
2709
|
+
* `narrowest` says the box was laid out by the min-content probe
|
|
2710
|
+
* (`MIN_CONTENT_PROBE`), and the answer is its min-content width: the
|
|
2711
|
+
* probe lays a box out at no width, but one with a least width of its own
|
|
2712
|
+
* at that, and nothing in the layout tells the two apart.
|
|
2635
2713
|
*/
|
|
2636
|
-
export function intrinsicWidth(box, seen) {
|
|
2714
|
+
export function intrinsicWidth(box, seen, narrowest = false) {
|
|
2637
2715
|
// under size containment, as though it held nothing: the size
|
|
2638
2716
|
// `contain-intrinsic-size` gives it, or none (CSS Containment 2, 3.2)
|
|
2639
2717
|
if (contained(box, CONTAIN_WIDTH)) {
|
|
2640
2718
|
return box.style.containIntrinsicWidth ?? 0;
|
|
2641
2719
|
}
|
|
2720
|
+
// a table is as wide as its layout made it: its columns, the spacing
|
|
2721
|
+
// either side of them and between, and its captions' least (`layoutTable`)
|
|
2722
|
+
// — at no width limit its widest, and at none its narrowest. What it
|
|
2723
|
+
// holds says less: its rows run from the first column to the last, the
|
|
2724
|
+
// spacing either side outside them, and measured by them a table in a
|
|
2725
|
+
// flex row, a grid, a float or an `inline-table` came to that much too
|
|
2726
|
+
// narrow, and its columns gave it up
|
|
2727
|
+
if (box.kind === 'table' && Number.isFinite(box.width)) {
|
|
2728
|
+
return Math.max(0, box.width - box.horizontalExtra);
|
|
2729
|
+
}
|
|
2642
2730
|
// a grid laid out at no width limit has its columns at their widest, and
|
|
2643
2731
|
// is as wide as they are — an item that runs past its column makes it no
|
|
2644
2732
|
// wider — or, where it has none, as where its items end
|
|
@@ -2656,10 +2744,16 @@ export function intrinsicWidth(box, seen) {
|
|
|
2656
2744
|
}
|
|
2657
2745
|
let widest = 0;
|
|
2658
2746
|
// A row of flex items is as wide as all of them side by side, and gaps
|
|
2659
|
-
// between them; any other box is as wide as the widest thing in it
|
|
2747
|
+
// between them; any other box is as wide as the widest thing in it. So
|
|
2748
|
+
// is a row that wraps, at its narrowest: each of its items may be a line
|
|
2749
|
+
// of its own, and it is as wide as the widest of them (CSS Flexbox
|
|
2750
|
+
// 9.9.1). Summed, a wrapping row of three 30px items made a
|
|
2751
|
+
// `width: min-content` box around it 90 wide, the items side by side,
|
|
2752
|
+
// where Chrome has 30, one under another
|
|
2660
2753
|
const display = box.style.display;
|
|
2661
2754
|
const row = (display === 'flex' || display === 'inline-flex') &&
|
|
2662
2755
|
box.style.flexDirection.startsWith('row');
|
|
2756
|
+
const wraps = row && narrowest && box.style.flexWrap !== 'nowrap';
|
|
2663
2757
|
let total = 0;
|
|
2664
2758
|
let items = 0;
|
|
2665
2759
|
const lines = box.lines;
|
|
@@ -2728,7 +2822,7 @@ export function intrinsicWidth(box, seen) {
|
|
|
2728
2822
|
}
|
|
2729
2823
|
}
|
|
2730
2824
|
else {
|
|
2731
|
-
let inner = intrinsicWidth(child, seen) + child.horizontalExtra;
|
|
2825
|
+
let inner = intrinsicWidth(child, seen, narrowest) + child.horizontalExtra;
|
|
2732
2826
|
if (typeof style.maxWidth === 'number') {
|
|
2733
2827
|
inner = Math.min(inner, style.maxWidth + contentExtra(child));
|
|
2734
2828
|
}
|
|
@@ -2741,11 +2835,11 @@ export function intrinsicWidth(box, seen) {
|
|
|
2741
2835
|
across = Math.max(across, contribution);
|
|
2742
2836
|
continue;
|
|
2743
2837
|
}
|
|
2744
|
-
if (row) {
|
|
2838
|
+
if (row && !wraps) {
|
|
2745
2839
|
total += contribution;
|
|
2746
2840
|
items += 1;
|
|
2747
2841
|
}
|
|
2748
|
-
else if (!sideBySide)
|
|
2842
|
+
else if (wraps || !sideBySide)
|
|
2749
2843
|
widest = Math.max(widest, contribution);
|
|
2750
2844
|
else if (child.isFloat) {
|
|
2751
2845
|
const clear = style.clear;
|
|
@@ -2865,7 +2959,17 @@ stretchRoom = containingWidth) {
|
|
|
2865
2959
|
const ih = own.missing & 2 ? null : own.height;
|
|
2866
2960
|
// `aspect-ratio` over its own, unless written `auto` and it has one
|
|
2867
2961
|
const aspect = style.aspectRatio;
|
|
2868
|
-
const
|
|
2962
|
+
const pages = aspect !== null && !(aspect.auto && own.ratio > 0);
|
|
2963
|
+
const ratio = pages ? aspect.ratio : own.ratio;
|
|
2964
|
+
// A ratio of the page's is of the box `box-sizing` names (CSS Sizing 4,
|
|
2965
|
+
// 5.1): one axis's content size to the other's goes through the border
|
|
2966
|
+
// box there. Written with `auto`, it is of the content box, as the
|
|
2967
|
+
// replaced element's own is, whichever it is.
|
|
2968
|
+
const outer = pages && !aspect.auto && style.boxSizing === 'border-box';
|
|
2969
|
+
const ox = outer ? box.horizontalExtra : 0;
|
|
2970
|
+
const oy = outer ? box.verticalExtra : 0;
|
|
2971
|
+
const widthOf = (h) => Math.max(0, (h + oy) * ratio - ox);
|
|
2972
|
+
const heightOf = (w) => Math.max(0, (w + ox) / ratio - oy);
|
|
2869
2973
|
// the width a block would have here: what a ratio with no size fills, and
|
|
2870
2974
|
// an `hr`, whose whole appearance is its border across the line
|
|
2871
2975
|
const room = () => {
|
|
@@ -2879,18 +2983,18 @@ stretchRoom = containingWidth) {
|
|
|
2879
2983
|
// which moves both axes together
|
|
2880
2984
|
if (iw !== null) {
|
|
2881
2985
|
w = iw;
|
|
2882
|
-
h = ih ?? iw
|
|
2986
|
+
h = ih ?? heightOf(iw);
|
|
2883
2987
|
}
|
|
2884
2988
|
else if (ih !== null) {
|
|
2885
2989
|
h = ih;
|
|
2886
|
-
w = ih
|
|
2990
|
+
w = widthOf(ih);
|
|
2887
2991
|
}
|
|
2888
2992
|
else {
|
|
2889
2993
|
// a ratio and no size: CSS 2.1 leaves it undefined and suggests the
|
|
2890
2994
|
// width a block would have, which is what browsers do — or, where the
|
|
2891
2995
|
// containing block waits on this box, the default object size
|
|
2892
2996
|
w = Number.isFinite(containingWidth) ? room() : own.width;
|
|
2893
|
-
h = w
|
|
2997
|
+
h = heightOf(w);
|
|
2894
2998
|
}
|
|
2895
2999
|
[w, h] = constrained(w, h, minW, maxW, minH, maxH);
|
|
2896
3000
|
}
|
|
@@ -2902,7 +3006,7 @@ stretchRoom = containingWidth) {
|
|
|
2902
3006
|
if (width !== null)
|
|
2903
3007
|
w = width;
|
|
2904
3008
|
else if (usedHeight !== null && ratio > 0)
|
|
2905
|
-
w = usedHeight
|
|
3009
|
+
w = widthOf(usedHeight);
|
|
2906
3010
|
else if (box.replaced === 'hr')
|
|
2907
3011
|
w = room();
|
|
2908
3012
|
else
|
|
@@ -2911,7 +3015,7 @@ stretchRoom = containingWidth) {
|
|
|
2911
3015
|
if (usedHeight !== null)
|
|
2912
3016
|
h = usedHeight;
|
|
2913
3017
|
else if (ratio > 0)
|
|
2914
|
-
h = clamp(w
|
|
3018
|
+
h = clamp(heightOf(w), minH, maxH);
|
|
2915
3019
|
else
|
|
2916
3020
|
h = clamp(own.height, minH, maxH);
|
|
2917
3021
|
}
|
|
@@ -3192,9 +3296,15 @@ function layoutPositioned(box, containing, ctx) {
|
|
|
3192
3296
|
let y;
|
|
3193
3297
|
if (top !== null && bottom !== null) {
|
|
3194
3298
|
const fill = Math.max(0, cbHeight - top - bottom - box.marginTop - box.marginBottom);
|
|
3195
|
-
// — a box with a ratio has its height from its width
|
|
3299
|
+
// — a box with a ratio has its height from its width, and a table is
|
|
3300
|
+
// as tall as its rows, as it is as wide as its columns between two
|
|
3301
|
+
// offsets: `normal` stretches neither (Blink: "Replaced/tables don't
|
|
3302
|
+
// stretch in abspos", `out_of_flow_layout_part.cc`), and a table taken
|
|
3303
|
+
// to the height its offsets leave was that tall around rows that were
|
|
3304
|
+
// not
|
|
3196
3305
|
const stretches = style.height === AUTO &&
|
|
3197
3306
|
(box.kind !== 'replaced' || control) &&
|
|
3307
|
+
box.kind !== 'table' &&
|
|
3198
3308
|
!boxRatio(box);
|
|
3199
3309
|
// both offsets and no height: the box fills what they leave, its
|
|
3200
3310
|
// `auto` margins nothing (10.6.4, rule 5) — unless `min-height` or
|