@react-x11/components 0.13.0 → 0.14.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/controls.d.ts +29 -2
- package/dist/html/controls.d.ts.map +1 -1
- package/dist/html/controls.js +70 -2
- package/dist/html/controls.js.map +1 -1
- package/dist/html/css/cascade.d.ts +42 -1
- package/dist/html/css/cascade.d.ts.map +1 -1
- package/dist/html/css/cascade.js +336 -16
- 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 +18 -4
- package/dist/html/css/parse.d.ts.map +1 -1
- package/dist/html/css/parse.js +66 -28
- package/dist/html/css/parse.js.map +1 -1
- package/dist/html/css/shapes.d.ts +44 -0
- package/dist/html/css/shapes.d.ts.map +1 -0
- package/dist/html/css/shapes.js +194 -0
- package/dist/html/css/shapes.js.map +1 -0
- package/dist/html/css/style.d.ts +128 -15
- package/dist/html/css/style.d.ts.map +1 -1
- package/dist/html/css/style.js +547 -144
- 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.map +1 -1
- package/dist/html/css/ua.js +14 -2
- 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/fonts.d.ts +55 -5
- package/dist/html/fonts.d.ts.map +1 -1
- package/dist/html/fonts.js +284 -23
- package/dist/html/fonts.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 +104 -12
- package/dist/html/layout/block.d.ts.map +1 -1
- package/dist/html/layout/block.js +410 -39
- package/dist/html/layout/block.js.map +1 -1
- package/dist/html/layout/boxes.d.ts +72 -1
- package/dist/html/layout/boxes.d.ts.map +1 -1
- package/dist/html/layout/boxes.js +40 -2
- 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 +144 -24
- 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 +585 -85
- 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 +144 -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 +97 -31
- package/dist/html/layout/table.js.map +1 -1
- package/dist/html/node.d.ts +4 -0
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +319 -47
- package/dist/html/node.js.map +1 -1
- package/dist/html/paint.d.ts +83 -5
- package/dist/html/paint.d.ts.map +1 -1
- package/dist/html/paint.js +1474 -217
- package/dist/html/paint.js.map +1 -1
- package/dist/html/svg.d.ts +39 -9
- package/dist/html/svg.d.ts.map +1 -1
- package/dist/html/svg.js +482 -37
- package/dist/html/svg.js.map +1 -1
- package/dist/html/widgets.js +87 -7
- package/dist/html/widgets.js.map +1 -1
- 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/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 +1 -1
- package/src/html/controls.ts +85 -2
- package/src/html/css/cascade.ts +366 -8
- package/src/html/css/color.ts +29 -0
- package/src/html/css/parse.ts +71 -31
- package/src/html/css/shapes.ts +239 -0
- package/src/html/css/style.ts +652 -147
- package/src/html/css/transform.ts +459 -0
- package/src/html/css/ua.ts +15 -2
- package/src/html/css/values.ts +4 -0
- package/src/html/fonts.ts +312 -29
- package/src/html/layout/axes.ts +62 -0
- package/src/html/layout/block.ts +466 -37
- package/src/html/layout/boxes.ts +95 -3
- package/src/html/layout/cache.ts +6 -0
- package/src/html/layout/css-grid.ts +169 -32
- package/src/html/layout/flex.ts +686 -79
- package/src/html/layout/inline.ts +149 -55
- package/src/html/layout/multicol.ts +977 -0
- package/src/html/layout/shaping.ts +27 -18
- package/src/html/layout/table.ts +105 -35
- package/src/html/node.ts +354 -48
- package/src/html/paint.ts +1804 -315
- package/src/html/svg.ts +573 -36
- package/src/html/widgets.ts +95 -9
- package/src/html/woff2.ts +612 -0
- package/src/maps/controller.ts +28 -7
- package/src/richtext/node.ts +13 -2
- package/src/richtext/runs.ts +313 -35
package/src/html/layout/boxes.ts
CHANGED
|
@@ -38,6 +38,7 @@ import type { CollapsedTable } from './collapse.js';
|
|
|
38
38
|
import { quoteAt } from '../css/content.js';
|
|
39
39
|
import type { CounterStyles } from '../css/counter-styles.js';
|
|
40
40
|
import type { ContentItem } from '../css/content.js';
|
|
41
|
+
import type { ShapeStyles } from '../css/shapes.js';
|
|
41
42
|
import {
|
|
42
43
|
CONTAIN_STYLE,
|
|
43
44
|
FIRST_LINE_INHERITED,
|
|
@@ -202,6 +203,17 @@ export interface LineText {
|
|
|
202
203
|
* the ones before a forced break that fit take room on the line.
|
|
203
204
|
*/
|
|
204
205
|
hung?: { at: number; x: number; width: number }[];
|
|
206
|
+
/**
|
|
207
|
+
* How far the line goes on past this text for the collapsible spaces it
|
|
208
|
+
* ends on, which its engine, laying out a piece of a line as a line,
|
|
209
|
+
* stripped: the room they take where more follows them on the line, and
|
|
210
|
+
* none where the line ends on them, since CSS removes them there (CSS
|
|
211
|
+
* Text 3, 4.1.2). They are the text's, in the elements they are in, and
|
|
212
|
+
* `trailRun` is the run they are the end of: whose underline, line
|
|
213
|
+
* through and highlight go on under them.
|
|
214
|
+
*/
|
|
215
|
+
trail?: number;
|
|
216
|
+
trailRun?: TextRun;
|
|
205
217
|
/** Any offset in the layout's own text as a document index — how a run
|
|
206
218
|
* under the pointer finds the element whose text it is. Per pass: the
|
|
207
219
|
* layout may be one an earlier pass made (`TextLayoutCache`), and the
|
|
@@ -630,12 +642,16 @@ export const CLAMPED = new WeakSet<Box>();
|
|
|
630
642
|
/** A grid's tracks as its layout left them, each column's and each row's
|
|
631
643
|
* start and end from the content box's corner, with the lines of each
|
|
632
644
|
* axis by number and by name: what an absolutely positioned box's grid
|
|
633
|
-
* area is found in (CSS Grid 1, 9.1).
|
|
645
|
+
* area is found in (CSS Grid 1, 9.1). And the first of its items in
|
|
646
|
+
* row-major order, where they were placed and not where they were
|
|
647
|
+
* written, which the grid's own baseline is taken from (10.6): null for a
|
|
648
|
+
* grid with no item. */
|
|
634
649
|
export interface GridTracks {
|
|
635
650
|
cols: [number, number][];
|
|
636
651
|
rows: [number, number][];
|
|
637
652
|
colLines: GridLines;
|
|
638
653
|
rowLines: GridLines;
|
|
654
|
+
first: Box | null;
|
|
639
655
|
}
|
|
640
656
|
export const GRID_TRACKS = new WeakMap<Box, GridTracks>();
|
|
641
657
|
|
|
@@ -656,6 +672,57 @@ export const CUT_BLOCKS = new WeakMap<Box, Box[]>();
|
|
|
656
672
|
* the clearance in (`elementRect`). Only the blocks that had clearance. */
|
|
657
673
|
export const CLEARED_FROM = new WeakMap<Box, number>();
|
|
658
674
|
|
|
675
|
+
/**
|
|
676
|
+
* One piece of a block that a column break falls inside (CSS Multi-column
|
|
677
|
+
* 1): its border box in one column, as far as the box goes in it, and where
|
|
678
|
+
* the whole box would stand there — the box its background and its borders
|
|
679
|
+
* are drawn as, cut to the piece (`box-decoration-break: slice`).
|
|
680
|
+
*/
|
|
681
|
+
export interface ColumnPiece {
|
|
682
|
+
x: number;
|
|
683
|
+
y: number;
|
|
684
|
+
width: number;
|
|
685
|
+
height: number;
|
|
686
|
+
/** The top of the whole box, in this column, and its height. */
|
|
687
|
+
wholeY: number;
|
|
688
|
+
wholeHeight: number;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/** The pieces of each block a column break falls inside, in the order of
|
|
692
|
+
* the columns. The block's own rect is what takes them all in, as a
|
|
693
|
+
* browser's bounding rect of it is. */
|
|
694
|
+
export const COLUMN_PIECES = new WeakMap<Box, ColumnPiece[]>();
|
|
695
|
+
|
|
696
|
+
/** The lines of a box that columns took apart: they are not one under
|
|
697
|
+
* another, and a search that counts on their tops rising reads them all
|
|
698
|
+
* instead. */
|
|
699
|
+
export const COLUMN_LINES = new WeakSet<LineBox[]>();
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* The rows of a text's layout that are in the text's own column, from the
|
|
703
|
+
* layout's origin, where the layout's lines went to more than one: a layout
|
|
704
|
+
* is drawn whole, so it is drawn once for each column, there, and clipped
|
|
705
|
+
* to the rows that are that column's. One object for all the texts of a
|
|
706
|
+
* layout in a column, which is what tells a draw of it from another.
|
|
707
|
+
*/
|
|
708
|
+
export const COLUMN_ROWS = new WeakMap<
|
|
709
|
+
LineText,
|
|
710
|
+
{ top: number; bottom: number }
|
|
711
|
+
>();
|
|
712
|
+
|
|
713
|
+
/** Whether any layout has broken a box between columns: what the walks
|
|
714
|
+
* that would ask the three maps above of every box ask first. */
|
|
715
|
+
export const columned = { any: false };
|
|
716
|
+
|
|
717
|
+
/** What the document's rules give the elements inside an inline `<svg>`
|
|
718
|
+
* (`Cascade.shapeStyles`), null where they give none. */
|
|
719
|
+
export type ShapeStyler = (box: Box) => ShapeStyles | null;
|
|
720
|
+
|
|
721
|
+
/** What `BoxTree.shapeStyler` answered for each drawing's box it has been
|
|
722
|
+
* asked of, which are the ones painted: a box restyled where it is has
|
|
723
|
+
* its answer put here again (`HtmlViewNode._hoverInPlace`). */
|
|
724
|
+
export const SHAPE_STYLES = new WeakMap<Box, ShapeStyles | null>();
|
|
725
|
+
|
|
659
726
|
/** The element a pseudo-element's box is generated from, which has no
|
|
660
727
|
* element of its own (`Box.pseudo`): whose the images its styles name are,
|
|
661
728
|
* when the host is asked for them. */
|
|
@@ -717,6 +784,11 @@ export interface BoxTree {
|
|
|
717
784
|
* one: worked out as a selection is first painted over it, not as the
|
|
718
785
|
* tree is built, since most builds are never selected in. */
|
|
719
786
|
selectionStyler: SelectionStyler | null;
|
|
787
|
+
/** What the rules give the elements in each inline `<svg>`
|
|
788
|
+
* (`ShapeStyler`), which have no boxes and no styles, where any rule
|
|
789
|
+
* could reach one: worked out as a drawing is first painted, since a
|
|
790
|
+
* page of icons shows few of them at once. */
|
|
791
|
+
shapeStyler: ShapeStyler | null;
|
|
720
792
|
/** Whether a float or an out-of-flow box sits in an inline box: where
|
|
721
793
|
* none does, layout looks for them among a block's own children and
|
|
722
794
|
* goes through no inline box to find them. */
|
|
@@ -733,6 +805,10 @@ export interface BoxTree {
|
|
|
733
805
|
* (`Cascade.rootStyle`), whose background is the canvas's; null where
|
|
734
806
|
* the document has either. */
|
|
735
807
|
impliedHtml: ComputedStyle | null;
|
|
808
|
+
/** The scheme the palette is, which the element the document is drawn
|
|
809
|
+
* in is of: where the root element's is the other, the canvas is that
|
|
810
|
+
* scheme's and opaque (`paintDocument`). */
|
|
811
|
+
paletteScheme: 'light' | 'dark';
|
|
736
812
|
}
|
|
737
813
|
|
|
738
814
|
export interface BuildOptions {
|
|
@@ -878,10 +954,12 @@ class Builder {
|
|
|
878
954
|
firstLine: this._firstLine,
|
|
879
955
|
firstLineStyler: this._firstLine ? this._firstLineStyler() : null,
|
|
880
956
|
selectionStyler: cascade.hasSelection ? this._selectionStyler() : null,
|
|
957
|
+
shapeStyler: cascade.stylesShapes ? this._shapeStyler() : null,
|
|
881
958
|
nestedOutOfLine: this._nestedOutOfLine,
|
|
882
959
|
movedInline: this._movedInline,
|
|
883
960
|
clipText: this._clipText,
|
|
884
961
|
impliedHtml,
|
|
962
|
+
paletteScheme: cascade.initial.colorScheme,
|
|
885
963
|
};
|
|
886
964
|
}
|
|
887
965
|
|
|
@@ -909,6 +987,20 @@ class Builder {
|
|
|
909
987
|
};
|
|
910
988
|
}
|
|
911
989
|
|
|
990
|
+
/** `BoxTree.shapeStyler`, over this build's cascade: each drawing's
|
|
991
|
+
* once, from its box's style as it is when first asked. */
|
|
992
|
+
private _shapeStyler(): ShapeStyler {
|
|
993
|
+
const cascade = this._options.cascade;
|
|
994
|
+
return (box) => {
|
|
995
|
+
let shapes = SHAPE_STYLES.get(box);
|
|
996
|
+
if (shapes === undefined) {
|
|
997
|
+
shapes = box.el ? cascade.shapeStyles(box.el, box.style) : null;
|
|
998
|
+
SHAPE_STYLES.set(box, shapes);
|
|
999
|
+
}
|
|
1000
|
+
return shapes;
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
|
|
912
1004
|
/** `BoxTree.firstLineStyler`, over this build's cascade. */
|
|
913
1005
|
private _firstLineStyler(): FirstLineStyler {
|
|
914
1006
|
const cascade = this._options.cascade;
|
|
@@ -1043,7 +1135,7 @@ class Builder {
|
|
|
1043
1135
|
}
|
|
1044
1136
|
}
|
|
1045
1137
|
// a translation is moved by the same pass
|
|
1046
|
-
if (style.translate || style.
|
|
1138
|
+
if (style.translate || style.transform) this._relative = true;
|
|
1047
1139
|
if (style.backgroundClipText) this._clipText = true;
|
|
1048
1140
|
if (style.verticalAlign !== 'baseline' && style.display === 'inline') {
|
|
1049
1141
|
this._movedInline = true;
|
|
@@ -1348,7 +1440,7 @@ class Builder {
|
|
|
1348
1440
|
}
|
|
1349
1441
|
}
|
|
1350
1442
|
// a translation is moved by the same pass
|
|
1351
|
-
if (style.translate || style.
|
|
1443
|
+
if (style.translate || style.transform) this._relative = true;
|
|
1352
1444
|
if (style.backgroundClipText) this._clipText = true;
|
|
1353
1445
|
if (style.verticalAlign !== 'baseline' && style.display === 'inline') {
|
|
1354
1446
|
this._movedInline = true;
|
package/src/html/layout/cache.ts
CHANGED
|
@@ -186,6 +186,8 @@ export const RUN_FIELDS = [
|
|
|
186
186
|
'underlineOffset',
|
|
187
187
|
'underlineThickness',
|
|
188
188
|
'strike',
|
|
189
|
+
'strikeStyle',
|
|
190
|
+
'strikeThickness',
|
|
189
191
|
'href',
|
|
190
192
|
'features',
|
|
191
193
|
'nowrap',
|
|
@@ -221,6 +223,8 @@ function sameRun(a: TextRun, b: TextRun): boolean {
|
|
|
221
223
|
a.underlineOffset === b.underlineOffset &&
|
|
222
224
|
a.underlineThickness === b.underlineThickness &&
|
|
223
225
|
a.strike === b.strike &&
|
|
226
|
+
a.strikeStyle === b.strikeStyle &&
|
|
227
|
+
a.strikeThickness === b.strikeThickness &&
|
|
224
228
|
a.href === b.href &&
|
|
225
229
|
a.features === b.features &&
|
|
226
230
|
a.nowrap === b.nowrap &&
|
|
@@ -249,6 +253,8 @@ function sameStyle(
|
|
|
249
253
|
a.underlineOffset === b.underlineOffset &&
|
|
250
254
|
a.underlineThickness === b.underlineThickness &&
|
|
251
255
|
a.strike === b.strike &&
|
|
256
|
+
a.strikeStyle === b.strikeStyle &&
|
|
257
|
+
a.strikeThickness === b.strikeThickness &&
|
|
252
258
|
a.href === b.href &&
|
|
253
259
|
a.features === b.features &&
|
|
254
260
|
a.nowrap === b.nowrap &&
|
|
@@ -31,6 +31,9 @@ import { Box, GRID_TRACKS, isBlank } from './boxes.js';
|
|
|
31
31
|
import {
|
|
32
32
|
FLEXED_HEIGHT,
|
|
33
33
|
MIN_CONTENT_PROBE,
|
|
34
|
+
STRETCHED_ACROSS,
|
|
35
|
+
USED_HEIGHT,
|
|
36
|
+
centreButton,
|
|
34
37
|
clampHeight,
|
|
35
38
|
clampWidth,
|
|
36
39
|
exactMinContent,
|
|
@@ -58,6 +61,28 @@ interface Item {
|
|
|
58
61
|
/** Min-content and max-content widths, margin box, taken when asked. */
|
|
59
62
|
min: number;
|
|
60
63
|
max: number;
|
|
64
|
+
/** Whether it is a table stretched across its area (`STRETCHED_ACROSS`),
|
|
65
|
+
* which `layoutItem` decides. */
|
|
66
|
+
across: boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The first of a grid's items in row-major order: the one furthest to the
|
|
71
|
+
* start of the first row that holds an item, which the grid's baseline is
|
|
72
|
+
* taken from (CSS Grid 1, 10.6).
|
|
73
|
+
*/
|
|
74
|
+
function firstItem(items: Item[]): Box | null {
|
|
75
|
+
let first: Item | null = null;
|
|
76
|
+
for (const item of items) {
|
|
77
|
+
if (
|
|
78
|
+
first === null ||
|
|
79
|
+
item.row < first.row ||
|
|
80
|
+
(item.row === first.row && item.col < first.col)
|
|
81
|
+
) {
|
|
82
|
+
first = item;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return first?.box ?? null;
|
|
61
86
|
}
|
|
62
87
|
|
|
63
88
|
/**
|
|
@@ -78,7 +103,13 @@ export function layoutGrid(
|
|
|
78
103
|
positionOutOfFlow(child, box, ctx, false);
|
|
79
104
|
continue;
|
|
80
105
|
}
|
|
81
|
-
|
|
106
|
+
// While the columns are sized, the area an item is in has no width for
|
|
107
|
+
// the percentages in its margins and its padding to be of, and they
|
|
108
|
+
// are of nothing (CSS Sizing 3, 5.2.1): a column is as wide as what
|
|
109
|
+
// is in the item. They are of the area once it has a width
|
|
110
|
+
// (`layoutItem`). Taken of the grid's width, an item `margin: 0 25%`
|
|
111
|
+
// made its `min-content` column half the grid wide.
|
|
112
|
+
resolveEdges(child, 0);
|
|
82
113
|
boxes.push(child);
|
|
83
114
|
}
|
|
84
115
|
// the gaps: a percentage of the grid's content size along them, and of
|
|
@@ -176,6 +207,11 @@ export function layoutGrid(
|
|
|
176
207
|
const extra = style.boxSizing === 'border-box' ? 0 : box.horizontalExtra;
|
|
177
208
|
widest = narrowest = Math.max(style.width + extra, box.horizontalExtra);
|
|
178
209
|
} else {
|
|
210
|
+
// A percentage is of an area the columns are still being sized for,
|
|
211
|
+
// and what it comes to depends on what the item makes them: it is
|
|
212
|
+
// `auto` for that (CSS Sizing 3, 5.2.1), and the item's content says
|
|
213
|
+
// how wide it is. Measured at the width a percentage made of the
|
|
214
|
+
// probe's, an item `width: 100%` made its `auto` column nothing.
|
|
179
215
|
const fresh = box.intrinsicMaxContent < 0;
|
|
180
216
|
widest = maxContentOf(box, ctx);
|
|
181
217
|
if (box.intrinsicMinContent < 0) {
|
|
@@ -183,8 +219,7 @@ export function layoutGrid(
|
|
|
183
219
|
// which is the max-content one only if it was made just now
|
|
184
220
|
const exact =
|
|
185
221
|
fresh && ctx.fonts ? exactMinContent(box, ctx.fonts) : null;
|
|
186
|
-
box.intrinsicMinContent =
|
|
187
|
-
exact ?? measureIntrinsicWidth(box, ctx, MIN_CONTENT_PROBE);
|
|
222
|
+
box.intrinsicMinContent = exact ?? minContentOf(box, ctx);
|
|
188
223
|
}
|
|
189
224
|
narrowest = box.intrinsicMinContent;
|
|
190
225
|
}
|
|
@@ -240,14 +275,15 @@ export function layoutGrid(
|
|
|
240
275
|
item,
|
|
241
276
|
extent(widths, lefts, item.col, item.cols),
|
|
242
277
|
ctx,
|
|
243
|
-
|
|
278
|
+
spanBefore(item),
|
|
244
279
|
);
|
|
245
280
|
}
|
|
246
281
|
|
|
247
282
|
// a height of the grid's own, or else the least it may be, which the
|
|
248
|
-
// `fr` rows and the `auto` ones fill
|
|
283
|
+
// `fr` rows and the `auto` ones fill: its `min-height`, or the height a
|
|
284
|
+
// column it is an item of flexed it to (`USED_HEIGHT`)
|
|
249
285
|
const own = Number.isFinite(definite);
|
|
250
|
-
const least = own ? 0 : leastHeight(box);
|
|
286
|
+
const least = own ? 0 : Math.max(leastHeight(box), USED_HEIGHT.get(box) ?? 0);
|
|
251
287
|
// the rows against a height: percentages of it, or `auto` without one
|
|
252
288
|
const sizeRows = (base: number, available: number, atLeast: number) => {
|
|
253
289
|
const rowTracks: SizingTrack[] = [];
|
|
@@ -301,18 +337,14 @@ export function layoutGrid(
|
|
|
301
337
|
if (Object.is(child.percentHeightBase, tall) || !percentOwn(child))
|
|
302
338
|
continue;
|
|
303
339
|
child.percentHeightBase = tall;
|
|
304
|
-
layoutItem(
|
|
305
|
-
item,
|
|
306
|
-
extent(widths, lefts, item.col, item.cols),
|
|
307
|
-
ctx,
|
|
308
|
-
heightBeforeRows(child, tall),
|
|
309
|
-
);
|
|
340
|
+
layoutItem(item, extent(widths, lefts, item.col, item.cols), ctx, tall);
|
|
310
341
|
}
|
|
311
342
|
GRID_TRACKS.set(box, {
|
|
312
343
|
cols: tracksOf(widths, lefts, keepCols),
|
|
313
344
|
rows: tracksOf(heights, tops, keepRows),
|
|
314
345
|
colLines,
|
|
315
346
|
rowLines,
|
|
347
|
+
first: firstItem(items),
|
|
316
348
|
});
|
|
317
349
|
|
|
318
350
|
for (const item of items) {
|
|
@@ -371,20 +403,34 @@ export function layoutGrid(
|
|
|
371
403
|
const width =
|
|
372
404
|
wide === null ? child.width : clampWidth(child, wide, area, ctx);
|
|
373
405
|
// what is in it takes its percentages of that height, which a
|
|
374
|
-
// stretch makes definite, as it does a flex item's
|
|
406
|
+
// stretch makes definite, as it does a flex item's — and an item that
|
|
407
|
+
// is a flex or grid container lays its own items out in it (11.1:
|
|
408
|
+
// "the grid area's width and height are considered definite for this
|
|
409
|
+
// purpose"): a card's `margin-top: auto` takes what its row is taller
|
|
410
|
+
// than the card by, its `flex: 1` grows into it (CSS Flexbox 8.1,
|
|
411
|
+
// 9.7). Its content's own height is the same layout, and kept.
|
|
412
|
+
// A table shares out among its rows what the area is taller than
|
|
413
|
+
// they are (`layoutTable`), and is no shorter than they are however
|
|
414
|
+
// short its area: its rows are the least it can be, as they are
|
|
415
|
+
// where it has a height of its own (CSS 2.1 17.5.3).
|
|
375
416
|
if (
|
|
376
417
|
child.kind !== 'replaced' &&
|
|
377
|
-
(wide !== null ||
|
|
418
|
+
(wide !== null ||
|
|
419
|
+
percentHeightsIn(child) ||
|
|
420
|
+
(child.kind === 'flex' && height !== child.height) ||
|
|
421
|
+
(child.kind === 'table' && height > child.height + 0.01))
|
|
378
422
|
) {
|
|
379
423
|
FLEXED_HEIGHT.set(child, Math.max(0, height - child.verticalExtra));
|
|
380
424
|
try {
|
|
381
|
-
|
|
425
|
+
layoutAcross(item, width, area, ctx);
|
|
382
426
|
} finally {
|
|
383
427
|
FLEXED_HEIGHT.delete(child);
|
|
384
428
|
}
|
|
385
429
|
}
|
|
386
430
|
child.width = width;
|
|
387
|
-
child.height =
|
|
431
|
+
child.height =
|
|
432
|
+
child.kind === 'table' ? Math.max(height, child.height) : height;
|
|
433
|
+
centreButton(child);
|
|
388
434
|
}
|
|
389
435
|
moveTo(
|
|
390
436
|
child,
|
|
@@ -564,6 +610,7 @@ function place(
|
|
|
564
610
|
cols: p.bs,
|
|
565
611
|
min: -1,
|
|
566
612
|
max: -1,
|
|
613
|
+
across: false,
|
|
567
614
|
}
|
|
568
615
|
: {
|
|
569
616
|
box: p.box,
|
|
@@ -573,6 +620,7 @@ function place(
|
|
|
573
620
|
cols: p.as,
|
|
574
621
|
min: -1,
|
|
575
622
|
max: -1,
|
|
623
|
+
across: false,
|
|
576
624
|
},
|
|
577
625
|
);
|
|
578
626
|
}
|
|
@@ -609,23 +657,56 @@ function extent(
|
|
|
609
657
|
}
|
|
610
658
|
|
|
611
659
|
/** An item's max-content width, its border box's: measured once in the
|
|
612
|
-
* box's life, as a table cell's is (`Box.intrinsicMaxContent`).
|
|
660
|
+
* box's life, as a table cell's is (`Box.intrinsicMaxContent`). Its
|
|
661
|
+
* content's, whatever width it has of its own (`minContentOf`). */
|
|
613
662
|
function maxContentOf(box: Box, ctx: LayoutContext): number {
|
|
614
663
|
if (box.intrinsicMaxContent < 0) {
|
|
615
|
-
box.intrinsicMaxContent = measureIntrinsicWidth(
|
|
664
|
+
box.intrinsicMaxContent = measureIntrinsicWidth(
|
|
665
|
+
box,
|
|
666
|
+
ctx,
|
|
667
|
+
Infinity,
|
|
668
|
+
box.kind !== 'replaced',
|
|
669
|
+
);
|
|
616
670
|
}
|
|
617
671
|
return box.intrinsicMaxContent;
|
|
618
672
|
}
|
|
619
673
|
|
|
620
|
-
/**
|
|
621
|
-
*
|
|
622
|
-
*
|
|
674
|
+
/**
|
|
675
|
+
* An item's min-content width, its border box's. What it is measured for is
|
|
676
|
+
* what it contributes to its columns, and the width a percentage makes of
|
|
677
|
+
* them is not known then: a box that is not replaced is as wide as its
|
|
678
|
+
* content for that, whatever its own `width` says, and a replaced element
|
|
679
|
+
* takes its percentage of nothing (CSS Sizing 3, 5.2.1). A width that is a
|
|
680
|
+
* length is weighed apart (`measure` in `layoutGrid`).
|
|
681
|
+
*/
|
|
682
|
+
function minContentOf(box: Box, ctx: LayoutContext): number {
|
|
683
|
+
return measureIntrinsicWidth(
|
|
684
|
+
box,
|
|
685
|
+
ctx,
|
|
686
|
+
MIN_CONTENT_PROBE,
|
|
687
|
+
box.kind !== 'replaced',
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Lay an item out in its area: stretched across it where its width is
|
|
693
|
+
* `auto` and it is stretched, or at its content's width, no wider than
|
|
694
|
+
* the area, where it is aligned instead.
|
|
695
|
+
*
|
|
696
|
+
* The area is the item's containing block (CSS Grid 1, 3.3), so it is its
|
|
697
|
+
* width that a percentage in the item's margins, its padding, its
|
|
698
|
+
* `min-width` and its `max-width` is of (6.4, and CSS 2.1 8.3, 8.4 and
|
|
699
|
+
* 10.4), whatever width the item comes to in it. With its own width
|
|
700
|
+
* standing for its area's, an item `width: 50%; max-width: 80%` was four
|
|
701
|
+
* tenths of its column, and one `min-width: 50%` aligned to the start was
|
|
702
|
+
* as wide as its text.
|
|
703
|
+
*/
|
|
623
704
|
function layoutItem(
|
|
624
705
|
item: Item,
|
|
625
706
|
area: number,
|
|
626
707
|
ctx: LayoutContext,
|
|
627
|
-
/**
|
|
628
|
-
|
|
708
|
+
/** The height of the rows it spans, where they have one yet. */
|
|
709
|
+
rows: number,
|
|
629
710
|
): void {
|
|
630
711
|
const child = item.box;
|
|
631
712
|
const style = child.style;
|
|
@@ -634,19 +715,31 @@ function layoutItem(
|
|
|
634
715
|
style.justifySelf === 'auto'
|
|
635
716
|
? (parent?.justifyItems ?? 'normal')
|
|
636
717
|
: style.justifySelf;
|
|
718
|
+
resolveEdges(child, area);
|
|
719
|
+
// its border box's height before the rows are sized, where it has one
|
|
720
|
+
const tall = heightBeforeRows(child, rows);
|
|
637
721
|
const margins = child.marginLeft + child.marginRight;
|
|
638
722
|
const room = Math.max(0, area - margins);
|
|
639
|
-
//
|
|
723
|
+
// Its content's widths, border box: measured once in its life, with the
|
|
724
|
+
// percentages in its padding of nothing, as they are while the columns
|
|
725
|
+
// are sized, and here with what those come to of its area. Measuring
|
|
726
|
+
// resolves its edges against nothing, and they are put back.
|
|
727
|
+
const padded = percentPadding(child);
|
|
640
728
|
const content = (): [number, number] => {
|
|
641
|
-
|
|
729
|
+
let probed = false;
|
|
730
|
+
if (child.intrinsicMaxContent < 0) {
|
|
731
|
+
maxContentOf(child, ctx);
|
|
732
|
+
probed = true;
|
|
733
|
+
}
|
|
642
734
|
if (child.intrinsicMinContent < 0) {
|
|
643
|
-
child.intrinsicMinContent =
|
|
644
|
-
|
|
645
|
-
ctx,
|
|
646
|
-
MIN_CONTENT_PROBE,
|
|
647
|
-
);
|
|
735
|
+
child.intrinsicMinContent = minContentOf(child, ctx);
|
|
736
|
+
probed = true;
|
|
648
737
|
}
|
|
649
|
-
|
|
738
|
+
if (probed) resolveEdges(child, area);
|
|
739
|
+
return [
|
|
740
|
+
child.intrinsicMinContent + padded,
|
|
741
|
+
child.intrinsicMaxContent + padded,
|
|
742
|
+
];
|
|
650
743
|
};
|
|
651
744
|
const keyword = style.widthKeyword;
|
|
652
745
|
// `stretch` fills its area, and so does `normal` but for a replaced
|
|
@@ -699,7 +792,15 @@ function layoutItem(
|
|
|
699
792
|
width = Math.min(widest, Math.max(narrowest, room));
|
|
700
793
|
}
|
|
701
794
|
if (child.kind !== 'replaced') {
|
|
702
|
-
|
|
795
|
+
// a table stretched across is as wide as its area, which in a block's
|
|
796
|
+
// flow it would shrink from to its columns (`STRETCHED_ACROSS`)
|
|
797
|
+
item.across =
|
|
798
|
+
across &&
|
|
799
|
+
child.kind === 'table' &&
|
|
800
|
+
style.width === AUTO &&
|
|
801
|
+
!keyword &&
|
|
802
|
+
through === null;
|
|
803
|
+
layoutAcross(item, width, area, ctx);
|
|
703
804
|
return;
|
|
704
805
|
}
|
|
705
806
|
// a replaced element sizes itself from its style: then it is given the
|
|
@@ -718,6 +819,42 @@ function layoutItem(
|
|
|
718
819
|
}
|
|
719
820
|
}
|
|
720
821
|
|
|
822
|
+
/** Lay an item out at a width: a table stretched across its area at that
|
|
823
|
+
* width as its own (`STRETCHED_ACROSS`), for this layout alone. */
|
|
824
|
+
function layoutAcross(
|
|
825
|
+
item: Item,
|
|
826
|
+
width: number,
|
|
827
|
+
area: number,
|
|
828
|
+
ctx: LayoutContext,
|
|
829
|
+
): void {
|
|
830
|
+
const child = item.box;
|
|
831
|
+
if (!item.across) {
|
|
832
|
+
ctx.layoutSubtree(child, width, area);
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
STRETCHED_ACROSS.add(child);
|
|
836
|
+
try {
|
|
837
|
+
ctx.layoutSubtree(child, width, area);
|
|
838
|
+
} finally {
|
|
839
|
+
STRETCHED_ACROSS.delete(child);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
/** What the percentages in a box's padding come to across it, its edges
|
|
844
|
+
* resolved: what a width of its content's, measured with them of nothing,
|
|
845
|
+
* is short of its border box by. */
|
|
846
|
+
function percentPadding(box: Box): number {
|
|
847
|
+
const { paddingLeft, paddingRight } = box.style;
|
|
848
|
+
let out = 0;
|
|
849
|
+
if (isPct(paddingLeft)) {
|
|
850
|
+
out += box.padLeft - Math.max(0, resolve(paddingLeft, 0));
|
|
851
|
+
}
|
|
852
|
+
if (isPct(paddingRight)) {
|
|
853
|
+
out += box.padRight - Math.max(0, resolve(paddingRight, 0));
|
|
854
|
+
}
|
|
855
|
+
return out;
|
|
856
|
+
}
|
|
857
|
+
|
|
721
858
|
/** Whether a box's content is its least size through a ratio, which it is
|
|
722
859
|
* where the box shows what overflows it and its least width is `auto`
|
|
723
860
|
* (CSS Sizing 4, 5.2). */
|