gesso-core 0.6.21 → 0.6.23
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/CHANGELOG.md +15 -0
- package/dist/{CanvasSurface-BAhcLj2K.js → CanvasSurface-D5QaKaWH.js} +277 -31
- package/dist/CanvasSurface-D5QaKaWH.js.map +1 -0
- package/dist/{index-DR8HAfh3.d.ts → index-Cgzq72eC.d.ts} +75 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +119 -40
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/package.json +1 -1
- package/dist/CanvasSurface-BAhcLj2K.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# gesso-core
|
|
2
2
|
|
|
3
|
+
## 0.6.23
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ae5a84e: A flex or grid container placed in the box its measurement already used no longer lays its children out a second time: placement takes the lines (or the tracks and placements) that measurement worked out. A full layout pass of five thousand nodes is about 7% faster.
|
|
8
|
+
- 62e3bd4: A lazy list's scroll no longer slows down as more rows are measured. Row offsets are kept in a Fenwick tree, so finding a row and recording a row's height cost the logarithm of the list's length rather than the number of rows measured so far: 2,000 scroll frames over 100,000 measured rows went from 7 seconds to 38 ms.
|
|
9
|
+
- 2aecc54: A modifier writing a property it already holds no longer sorts the property's overrides or allocates, which an animated modifier did on every frame.
|
|
10
|
+
- 72f7b90, 4b92a02: Typing into a long text field no longer pushes every label's laid-out paragraph out of the cache: paragraphs of 16K characters or more are remembered apart, in a small budget of their own (eight paragraphs, half a million characters). The memo of a paragraph's hard lines is bounded by the length of the text it holds (a million characters) as well as by count, so a long line edited many times keeps about ten versions rather than twenty thousand: 300 edits of a 100 KB field keep 15 MB.
|
|
11
|
+
|
|
12
|
+
## 0.6.22
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 02f186e: A scroll layer repaints a sticky node where a scroll carried it and where it sticks, so a spreadsheet's sticky header row and gutter no longer leave copies of themselves over the rows after scrolling down and back up. `LayoutEngine` gains `allStickyNodes()`, which `LayoutReader` may offer as well; a reader without it repaints a scroll layer whole every frame.
|
|
17
|
+
|
|
3
18
|
## 0.6.21
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
@@ -710,17 +710,30 @@ function removeDeclaredProperty(graph, node, property, flags) {
|
|
|
710
710
|
*/
|
|
711
711
|
function writeOverrideProperty(graph, node, property, override, flags) {
|
|
712
712
|
const overrides = overridesFor(node, property);
|
|
713
|
-
const
|
|
713
|
+
const entries = overrides.entries;
|
|
714
|
+
const existing = entries.find((entry) => entry.source === override.source);
|
|
714
715
|
if (existing !== void 0) {
|
|
715
716
|
existing.value = override.value;
|
|
716
|
-
existing.order
|
|
717
|
+
if (existing.order !== override.order) {
|
|
718
|
+
existing.order = override.order;
|
|
719
|
+
entries.sort((a, b) => a.order - b.order);
|
|
720
|
+
}
|
|
717
721
|
} else {
|
|
718
|
-
warnOnConflict(node, property,
|
|
719
|
-
|
|
722
|
+
warnOnConflict(node, property, entries, override);
|
|
723
|
+
entries.splice(insertionIndex(entries, override.order), 0, { ...override });
|
|
720
724
|
}
|
|
721
|
-
overrides.entries.sort((a, b) => a.order - b.order);
|
|
722
725
|
return applyEffective(graph, node, property, overrides, flags);
|
|
723
726
|
}
|
|
727
|
+
/**
|
|
728
|
+
* Where a new entry goes in the sorted list: after every entry whose
|
|
729
|
+
* order is at most its own, which is where a push followed by a stable
|
|
730
|
+
* sort would have put it.
|
|
731
|
+
*/
|
|
732
|
+
function insertionIndex(entries, order) {
|
|
733
|
+
let index = entries.length;
|
|
734
|
+
while (index > 0 && entries[index - 1].order > order) index--;
|
|
735
|
+
return index;
|
|
736
|
+
}
|
|
724
737
|
/** Removes one modifier's write, restoring whatever was under it. */
|
|
725
738
|
function clearOverrideProperty(graph, node, property, source, flags) {
|
|
726
739
|
const overrides = node.overrides?.get(property);
|
|
@@ -6967,8 +6980,23 @@ function layoutParagraph(request, runs) {
|
|
|
6967
6980
|
maxContentWidth
|
|
6968
6981
|
};
|
|
6969
6982
|
}
|
|
6970
|
-
/**
|
|
6983
|
+
/**
|
|
6984
|
+
* How much a measurer's hard-line memo holds before the least recently
|
|
6985
|
+
* used line is forgotten: a number of lines, and their text counted in
|
|
6986
|
+
* UTF-16 code units, whichever runs out first; the same two bounds as
|
|
6987
|
+
* the paragraph cache (`PARAGRAPH_CACHE_ENTRIES`), for the same reason.
|
|
6988
|
+
*
|
|
6989
|
+
* A count alone let one long hard line, edited over and over, keep a
|
|
6990
|
+
* copy of every version of itself (twice: in its key and in `ownCopy`)
|
|
6991
|
+
* up to the count, 20,000 copies of a line however long. The text
|
|
6992
|
+
* budget is a million code units, so every line of a document that
|
|
6993
|
+
* long is still here for the next edit to find; a longer one is broken
|
|
6994
|
+
* again whole. A line held costs far more than its text, since its
|
|
6995
|
+
* breaking at each width is kept with it: 300 edits of one 100 KB line
|
|
6996
|
+
* held 32 MB at twice this budget and hold 15 MB at it.
|
|
6997
|
+
*/
|
|
6971
6998
|
const HARD_LINE_ENTRIES = 2e4;
|
|
6999
|
+
const HARD_LINE_TEXT = 1 << 20;
|
|
6972
7000
|
/** Widths a hard line keeps its breaking for: a resize sweeps through many, an edit asks for one. */
|
|
6973
7001
|
const WIDTHS_PER_LINE = 4;
|
|
6974
7002
|
/**
|
|
@@ -6977,6 +7005,39 @@ const WIDTHS_PER_LINE = 4;
|
|
|
6977
7005
|
* so a measurer that is dropped takes its lines with it.
|
|
6978
7006
|
*/
|
|
6979
7007
|
const hardLineMemos = /* @__PURE__ */ new WeakMap();
|
|
7008
|
+
/** A least-recently-used map of hard lines, bounded by count and by text; see `HARD_LINE_ENTRIES`. */
|
|
7009
|
+
var HardLineMemo = class {
|
|
7010
|
+
entries = /* @__PURE__ */ new Map();
|
|
7011
|
+
text = 0;
|
|
7012
|
+
get size() {
|
|
7013
|
+
return this.entries.size;
|
|
7014
|
+
}
|
|
7015
|
+
/** The code units of text remembered, for specs. */
|
|
7016
|
+
get textLength() {
|
|
7017
|
+
return this.text;
|
|
7018
|
+
}
|
|
7019
|
+
get(key) {
|
|
7020
|
+
const entry = this.entries.get(key);
|
|
7021
|
+
if (entry === void 0) return;
|
|
7022
|
+
this.entries.delete(key);
|
|
7023
|
+
this.entries.set(key, entry);
|
|
7024
|
+
return entry;
|
|
7025
|
+
}
|
|
7026
|
+
set(key, line) {
|
|
7027
|
+
const previous = this.entries.get(key);
|
|
7028
|
+
if (previous !== void 0) {
|
|
7029
|
+
this.entries.delete(key);
|
|
7030
|
+
this.text -= previous.text.length;
|
|
7031
|
+
}
|
|
7032
|
+
while (this.entries.size > 0 && (this.entries.size >= HARD_LINE_ENTRIES || this.text + line.text.length > HARD_LINE_TEXT)) {
|
|
7033
|
+
const [oldest, entry] = this.entries.entries().next().value;
|
|
7034
|
+
this.entries.delete(oldest);
|
|
7035
|
+
this.text -= entry.text.length;
|
|
7036
|
+
}
|
|
7037
|
+
this.entries.set(key, line);
|
|
7038
|
+
this.text += line.text.length;
|
|
7039
|
+
}
|
|
7040
|
+
};
|
|
6980
7041
|
/** Forgets a measurer's hard lines: what its widths mean has changed, as when a font face arrives. */
|
|
6981
7042
|
function forgetHardLines(runs) {
|
|
6982
7043
|
hardLineMemos.delete(runs);
|
|
@@ -6984,7 +7045,7 @@ function forgetHardLines(runs) {
|
|
|
6984
7045
|
function hardLinesFor(runs) {
|
|
6985
7046
|
let memo = hardLineMemos.get(runs);
|
|
6986
7047
|
if (memo === void 0) {
|
|
6987
|
-
memo =
|
|
7048
|
+
memo = new HardLineMemo();
|
|
6988
7049
|
hardLineMemos.set(runs, memo);
|
|
6989
7050
|
}
|
|
6990
7051
|
return memo;
|
|
@@ -6996,11 +7057,7 @@ function styleKey(request) {
|
|
|
6996
7057
|
function hardLine(memo, style, text, wrap, measure) {
|
|
6997
7058
|
const key = `${style}\0${wrap}\0${text}`;
|
|
6998
7059
|
const cached = memo.get(key);
|
|
6999
|
-
if (cached !== void 0)
|
|
7000
|
-
memo.delete(key);
|
|
7001
|
-
memo.set(key, cached);
|
|
7002
|
-
return cached;
|
|
7003
|
-
}
|
|
7060
|
+
if (cached !== void 0) return cached;
|
|
7004
7061
|
const own = ownCopy(text);
|
|
7005
7062
|
const segments = segmentParagraph(own, wrap);
|
|
7006
7063
|
let minContentWidth = 0;
|
|
@@ -7012,10 +7069,6 @@ function hardLine(memo, style, text, wrap, measure) {
|
|
|
7012
7069
|
minContentWidth,
|
|
7013
7070
|
lines: /* @__PURE__ */ new Map()
|
|
7014
7071
|
};
|
|
7015
|
-
if (memo.size >= HARD_LINE_ENTRIES) {
|
|
7016
|
-
const oldest = memo.keys().next().value;
|
|
7017
|
-
if (oldest !== void 0) memo.delete(oldest);
|
|
7018
|
-
}
|
|
7019
7072
|
memo.set(key, entry);
|
|
7020
7073
|
return entry;
|
|
7021
7074
|
}
|
|
@@ -7352,10 +7405,74 @@ function spannedRunsFor(request, runs) {
|
|
|
7352
7405
|
*/
|
|
7353
7406
|
const PARAGRAPH_CACHE_ENTRIES = 16384;
|
|
7354
7407
|
const PARAGRAPH_CACHE_TEXT = 1 << 20;
|
|
7355
|
-
/**
|
|
7408
|
+
/**
|
|
7409
|
+
* The key length, in UTF-16 code units, from which a paragraph is
|
|
7410
|
+
* remembered apart from the rest; see `ParagraphCache`.
|
|
7411
|
+
*/
|
|
7412
|
+
const LARGE_PARAGRAPH = 16384;
|
|
7413
|
+
/**
|
|
7414
|
+
* The large map's budget, far below the labels': what it mostly holds
|
|
7415
|
+
* is the versions of a field being edited, and only the newest is asked
|
|
7416
|
+
* for again. A version costs much more than its text, since its lines
|
|
7417
|
+
* are kept with it: 300 edits of a 100 KB field held 33 MB in a map
|
|
7418
|
+
* with the labels' budget. Half a million code units still holds every
|
|
7419
|
+
* request for two documents of 250K drawn side by side, so neither
|
|
7420
|
+
* pushes the other out on each frame.
|
|
7421
|
+
*/
|
|
7422
|
+
const LARGE_PARAGRAPH_ENTRIES = 8;
|
|
7423
|
+
const LARGE_PARAGRAPH_TEXT = 1 << 19;
|
|
7424
|
+
/**
|
|
7425
|
+
* The paragraph cache: two least-recently-used maps, one for large
|
|
7426
|
+
* paragraphs (a key of `LARGE_PARAGRAPH` code units or more), with a
|
|
7427
|
+
* budget of its own (`LARGE_PARAGRAPH_ENTRIES`), and one for the rest,
|
|
7428
|
+
* with the whole budget of `PARAGRAPH_CACHE_ENTRIES`.
|
|
7429
|
+
*
|
|
7430
|
+
* A keystroke in a long field is a new request keyed by its whole
|
|
7431
|
+
* text, and both the layout engine and paint ask for it. In one map a
|
|
7432
|
+
* 100 KB field spent the text budget in about ten keystrokes, and
|
|
7433
|
+
* every label on screen was laid out again on the next frame. Apart,
|
|
7434
|
+
* the field's versions only push out each other's and those of other
|
|
7435
|
+
* long texts, which is what they did among themselves before, and the
|
|
7436
|
+
* labels are not touched. A paragraph's map is chosen by its key, so a
|
|
7437
|
+
* request finds it again without being told which it is.
|
|
7438
|
+
*
|
|
7439
|
+
* Editable text is not singled out instead: the layout engine's
|
|
7440
|
+
* request does not say whether it is for an editable, and paint (the
|
|
7441
|
+
* caret, the selection) asks for the field's paragraph again on every
|
|
7442
|
+
* frame it is drawn, so it does need remembering somewhere. A short
|
|
7443
|
+
* field still shares the map with labels, but one keystroke there
|
|
7444
|
+
* costs at most `LARGE_PARAGRAPH` of a million code units.
|
|
7445
|
+
*/
|
|
7356
7446
|
var ParagraphCache = class {
|
|
7447
|
+
small = new ParagraphLru(PARAGRAPH_CACHE_ENTRIES, PARAGRAPH_CACHE_TEXT);
|
|
7448
|
+
large = new ParagraphLru(LARGE_PARAGRAPH_ENTRIES, LARGE_PARAGRAPH_TEXT);
|
|
7449
|
+
get size() {
|
|
7450
|
+
return this.small.size + this.large.size;
|
|
7451
|
+
}
|
|
7452
|
+
get(key) {
|
|
7453
|
+
return this.mapFor(key).get(key);
|
|
7454
|
+
}
|
|
7455
|
+
set(key, paragraph, text) {
|
|
7456
|
+
this.mapFor(key).set(key, paragraph, text);
|
|
7457
|
+
}
|
|
7458
|
+
clear() {
|
|
7459
|
+
this.small.clear();
|
|
7460
|
+
this.large.clear();
|
|
7461
|
+
}
|
|
7462
|
+
mapFor(key) {
|
|
7463
|
+
return key.length >= LARGE_PARAGRAPH ? this.large : this.small;
|
|
7464
|
+
}
|
|
7465
|
+
};
|
|
7466
|
+
/** A least-recently-used map of paragraphs, bounded by count and by text; see `PARAGRAPH_CACHE_ENTRIES`. */
|
|
7467
|
+
var ParagraphLru = class {
|
|
7468
|
+
maxEntries;
|
|
7469
|
+
maxText;
|
|
7357
7470
|
entries = /* @__PURE__ */ new Map();
|
|
7358
7471
|
text = 0;
|
|
7472
|
+
constructor(maxEntries, maxText) {
|
|
7473
|
+
this.maxEntries = maxEntries;
|
|
7474
|
+
this.maxText = maxText;
|
|
7475
|
+
}
|
|
7359
7476
|
get size() {
|
|
7360
7477
|
return this.entries.size;
|
|
7361
7478
|
}
|
|
@@ -7372,7 +7489,7 @@ var ParagraphCache = class {
|
|
|
7372
7489
|
this.entries.delete(key);
|
|
7373
7490
|
this.text -= previous.text;
|
|
7374
7491
|
}
|
|
7375
|
-
while (this.entries.size > 0 && (this.entries.size >=
|
|
7492
|
+
while (this.entries.size > 0 && (this.entries.size >= this.maxEntries || this.text + text > this.maxText)) {
|
|
7376
7493
|
const [oldest, entry] = this.entries.entries().next().value;
|
|
7377
7494
|
this.entries.delete(oldest);
|
|
7378
7495
|
this.text -= entry.text;
|
|
@@ -14330,6 +14447,24 @@ var LayoutRecord = class {
|
|
|
14330
14447
|
/** Constraints this record was last measured under. */
|
|
14331
14448
|
lastConstraints = NEVER_MEASURED;
|
|
14332
14449
|
/**
|
|
14450
|
+
* What a flex or grid container's last measurement worked out about
|
|
14451
|
+
* its children — the flexed items and their lines, or the sized
|
|
14452
|
+
* tracks — kept for its placement to take over. Placement used to
|
|
14453
|
+
* work it all out again, a FlexItem and a set of constraints per
|
|
14454
|
+
* child, even when the box it was placing in was the very one the
|
|
14455
|
+
* measurement had been given; a container's last measurement is
|
|
14456
|
+
* usually its final one, so that was most of them.
|
|
14457
|
+
*
|
|
14458
|
+
* Only the last measurement that actually ran is kept, because it is
|
|
14459
|
+
* the one its children's records still describe: a measurement
|
|
14460
|
+
* recalled from an alternate leaves the children as the last run
|
|
14461
|
+
* left them. Null when that run's content box was not definite on
|
|
14462
|
+
* both axes, since placement's always is. Placement takes it and
|
|
14463
|
+
* clears it whatever it decides, so nothing uses one twice; see
|
|
14464
|
+
* `LayoutEngine.takeArrangement`.
|
|
14465
|
+
*/
|
|
14466
|
+
arrangement = null;
|
|
14467
|
+
/**
|
|
14333
14468
|
* The paragraphs a text leaf was last measured as, one asked with a
|
|
14334
14469
|
* width and one without; see `LayoutEngine.measureLeaf`. Flex asks
|
|
14335
14470
|
* an item both questions every pass (its max-content basis, then its
|
|
@@ -14542,6 +14677,7 @@ var LayoutRecord = class {
|
|
|
14542
14677
|
this.contentWidth = 0;
|
|
14543
14678
|
this.contentHeight = 0;
|
|
14544
14679
|
this.lastConstraints = NEVER_MEASURED;
|
|
14680
|
+
this.arrangement = null;
|
|
14545
14681
|
this.lastBaseWidth = void 0;
|
|
14546
14682
|
this.lastBaseHeight = void 0;
|
|
14547
14683
|
this.alternates = null;
|
|
@@ -15499,6 +15635,14 @@ var LayoutEngine = class {
|
|
|
15499
15635
|
return this.records.get(node);
|
|
15500
15636
|
}
|
|
15501
15637
|
/**
|
|
15638
|
+
* Every `position: 'sticky'` node in the tree. A sticky node moves
|
|
15639
|
+
* with a scroll without its box moving, so a renderer keeping a
|
|
15640
|
+
* scroll container's pixels has to be told where they are.
|
|
15641
|
+
*/
|
|
15642
|
+
allStickyNodes() {
|
|
15643
|
+
return this.stickyNodes;
|
|
15644
|
+
}
|
|
15645
|
+
/**
|
|
15502
15646
|
* A box around everything in a node's subtree that could take a
|
|
15503
15647
|
* point, so a hit test can pass the subtree over instead of
|
|
15504
15648
|
* descending into it. Undefined for a node with no record, and
|
|
@@ -16392,7 +16536,19 @@ var LayoutEngine = class {
|
|
|
16392
16536
|
measureGrid(node, rec, content) {
|
|
16393
16537
|
const paddingH = rec.paddingLeft + rec.paddingRight;
|
|
16394
16538
|
const paddingV = rec.paddingTop + rec.paddingBottom;
|
|
16395
|
-
const
|
|
16539
|
+
const availableWidth = this.definiteAxis(content, "width");
|
|
16540
|
+
const availableHeight = this.definiteAxis(content, "height");
|
|
16541
|
+
const grid = this.layoutGrid(node, content, availableWidth, availableHeight);
|
|
16542
|
+
let arrangement = null;
|
|
16543
|
+
if (availableWidth !== void 0 && availableHeight !== void 0) arrangement = {
|
|
16544
|
+
kind: "grid",
|
|
16545
|
+
pass: this.layoutPass,
|
|
16546
|
+
content,
|
|
16547
|
+
contentMatters: rec.contentMatters,
|
|
16548
|
+
subgridColumns: rec.subgridColumns,
|
|
16549
|
+
grid
|
|
16550
|
+
};
|
|
16551
|
+
rec.arrangement = arrangement;
|
|
16396
16552
|
rec.minContentWidth = paddingH + grid.columns.minTotal;
|
|
16397
16553
|
const first = grid.placements[0];
|
|
16398
16554
|
if (first !== void 0) {
|
|
@@ -16411,7 +16567,8 @@ var LayoutEngine = class {
|
|
|
16411
16567
|
const contentWidth = Math.max(0, rec.width - rec.paddingLeft - rec.paddingRight);
|
|
16412
16568
|
const contentHeight = Math.max(0, rec.height - rec.paddingTop - rec.paddingBottom);
|
|
16413
16569
|
const content = new Constraints(contentWidth, contentWidth, contentHeight, contentHeight);
|
|
16414
|
-
const
|
|
16570
|
+
const kept = this.takeArrangement(rec, "grid", content);
|
|
16571
|
+
const grid = kept !== null && kept.subgridColumns === rec.subgridColumns ? kept.grid : this.layoutGrid(node, content, contentWidth, contentHeight);
|
|
16415
16572
|
const gridX = parseCrossAxisAlignment(node.properties.get("x")) ?? 3;
|
|
16416
16573
|
const gridY = parseCrossAxisAlignment(node.properties.get("y")) ?? 3;
|
|
16417
16574
|
const mirrored = this.startEdge(node) === "right";
|
|
@@ -16673,6 +16830,34 @@ var LayoutEngine = class {
|
|
|
16673
16830
|
const paddingV = rec.paddingTop + rec.paddingBottom;
|
|
16674
16831
|
return new Constraints(Math.max(0, effective.minWidth - paddingH), Math.max(0, effective.maxWidth - paddingH), Math.max(0, effective.minHeight - paddingV), Math.max(0, effective.maxHeight - paddingV));
|
|
16675
16832
|
}
|
|
16833
|
+
/**
|
|
16834
|
+
* The arrangement a container's measurement kept, when placing it in
|
|
16835
|
+
* `content` would work out the same one again; null otherwise.
|
|
16836
|
+
* Cleared from the record either way, so it is used at most once:
|
|
16837
|
+
* placement shares auto margins out and stretches items in the lines
|
|
16838
|
+
* it is handed, and a second placement in the same pass (a relayout
|
|
16839
|
+
* root inside one already laid out) must start from fresh ones.
|
|
16840
|
+
*
|
|
16841
|
+
* What it is checked against is everything the work reads that is
|
|
16842
|
+
* not fixed for the length of a pass. The pass number stands for the
|
|
16843
|
+
* tree and every property in it, which a pass never changes, and so
|
|
16844
|
+
* for the children, their order and the container's own settings.
|
|
16845
|
+
* The content box is the constraints the children were measured
|
|
16846
|
+
* under and the base their percentages resolved against. The
|
|
16847
|
+
* container's `contentMatters` decided its items' flags, and a parent
|
|
16848
|
+
* can change it between the two (`clearBoundaries`). The children's
|
|
16849
|
+
* records need no check: only this container measures them, so they
|
|
16850
|
+
* are still as its last run left them, which is the run kept. (A
|
|
16851
|
+
* subgrid's cells are the exception, measured unbounded by the grid
|
|
16852
|
+
* around it as well, but `placeGrid` measures each item again before
|
|
16853
|
+
* it reads anything off its record.)
|
|
16854
|
+
*/
|
|
16855
|
+
takeArrangement(rec, kind, content) {
|
|
16856
|
+
const kept = rec.arrangement;
|
|
16857
|
+
if (kept === null) return null;
|
|
16858
|
+
rec.arrangement = null;
|
|
16859
|
+
return kept.kind === kind && kept.pass === this.layoutPass && kept.contentMatters === rec.contentMatters && constraintsEqual(kept.content, content) ? kept : null;
|
|
16860
|
+
}
|
|
16676
16861
|
measureFlex(node, rec, content, direction) {
|
|
16677
16862
|
const row = direction === 0;
|
|
16678
16863
|
const paddingMain = row ? rec.paddingLeft + rec.paddingRight : rec.paddingTop + rec.paddingBottom;
|
|
@@ -16683,6 +16868,7 @@ var LayoutEngine = class {
|
|
|
16683
16868
|
const mainBounded = isFinite(mainMax);
|
|
16684
16869
|
const mainDefinite = mainBounded && mainMin === mainMax;
|
|
16685
16870
|
const crossDefinite = row ? isFinite(content.maxHeight) && content.minHeight === content.maxHeight : isFinite(content.maxWidth) && content.minWidth === content.maxWidth;
|
|
16871
|
+
rec.arrangement = null;
|
|
16686
16872
|
const items = this.collectFlexItems(node, content, direction, config, crossDefinite && !config.wrap);
|
|
16687
16873
|
if (items.length === 0) {
|
|
16688
16874
|
rec.minContentWidth = rec.paddingLeft + rec.paddingRight;
|
|
@@ -16698,7 +16884,7 @@ var LayoutEngine = class {
|
|
|
16698
16884
|
const lineTotal = this.lineOuterMain(line, config.gapMain, "hypothetical");
|
|
16699
16885
|
const lineWanted = this.lineMaxContentMain(line, config.gapMain);
|
|
16700
16886
|
if (mainBounded && (mainDefinite || lineTotal > mainMax || lineWanted > mainMax)) {
|
|
16701
|
-
this.resolveLine(line, mainMax - config.gapMain * (line.items.length - 1), config);
|
|
16887
|
+
line.free = this.resolveLine(line, mainMax - config.gapMain * (line.items.length - 1), config);
|
|
16702
16888
|
this.measureFlexedItems(line.items, content, direction, crossDefinite && !config.wrap ? row ? content.maxHeight : content.maxWidth : void 0);
|
|
16703
16889
|
contentMain = Math.max(contentMain, this.lineOuterMain(line, config.gapMain, "final"));
|
|
16704
16890
|
} else {
|
|
@@ -16714,6 +16900,13 @@ var LayoutEngine = class {
|
|
|
16714
16900
|
contentCross += line.cross;
|
|
16715
16901
|
}
|
|
16716
16902
|
contentCross += config.gapLine * (lines.length - 1);
|
|
16903
|
+
if (mainDefinite && crossDefinite) rec.arrangement = {
|
|
16904
|
+
kind: "flex",
|
|
16905
|
+
pass: this.layoutPass,
|
|
16906
|
+
content,
|
|
16907
|
+
contentMatters: rec.contentMatters,
|
|
16908
|
+
lines
|
|
16909
|
+
};
|
|
16717
16910
|
this.setFlexBaseline(rec, lines[0].items, row);
|
|
16718
16911
|
rec.minContentWidth = this.flexMinContentWidth(rec, items, row, config);
|
|
16719
16912
|
rec.minContentHeight = row && config.wrap ? paddingCross + contentCross : this.flexMinContentHeight(rec, items, row, config);
|
|
@@ -18021,14 +18214,21 @@ var LayoutEngine = class {
|
|
|
18021
18214
|
const contentMain = Math.max(0, (row ? rec.width : rec.height) - (row ? paddingH : paddingV));
|
|
18022
18215
|
const contentCross = Math.max(0, (row ? rec.height : rec.width) - (row ? paddingV : paddingH));
|
|
18023
18216
|
const content = row ? new Constraints(contentMain, contentMain, contentCross, contentCross) : new Constraints(contentCross, contentCross, contentMain, contentMain);
|
|
18024
|
-
const
|
|
18025
|
-
|
|
18026
|
-
|
|
18027
|
-
|
|
18028
|
-
|
|
18029
|
-
|
|
18030
|
-
this.
|
|
18031
|
-
|
|
18217
|
+
const kept = this.takeArrangement(rec, "flex", content);
|
|
18218
|
+
let lines;
|
|
18219
|
+
if (kept !== null) {
|
|
18220
|
+
lines = kept.lines;
|
|
18221
|
+
for (const line of lines) this.distributeAutoMargins(line);
|
|
18222
|
+
} else {
|
|
18223
|
+
const items = this.collectFlexItems(node, content, direction, config, !config.wrap);
|
|
18224
|
+
if (items.length === 0) return;
|
|
18225
|
+
lines = this.breakLines(items, config, contentMain);
|
|
18226
|
+
for (const line of lines) {
|
|
18227
|
+
line.free = this.resolveLine(line, contentMain - config.gapMain * (line.items.length - 1), config);
|
|
18228
|
+
this.distributeAutoMargins(line);
|
|
18229
|
+
this.measureFlexedItems(line.items, content, direction, config.wrap ? void 0 : contentCross);
|
|
18230
|
+
line.cross = this.flexLineCross(line.items, row);
|
|
18231
|
+
}
|
|
18032
18232
|
}
|
|
18033
18233
|
this.markFlexBoundaries(lines);
|
|
18034
18234
|
if (lines.length === 1 && !config.wrap) lines[0].cross = contentCross;
|
|
@@ -20901,7 +21101,8 @@ var ScrollLayerCache = class {
|
|
|
20901
21101
|
scrollX: snapScroll(rec.scrollX, this.dpr),
|
|
20902
21102
|
scrollY: snapScroll(rec.scrollY, this.dpr),
|
|
20903
21103
|
used: true,
|
|
20904
|
-
items: /* @__PURE__ */ new Map()
|
|
21104
|
+
items: /* @__PURE__ */ new Map(),
|
|
21105
|
+
stuck: /* @__PURE__ */ new Map()
|
|
20905
21106
|
};
|
|
20906
21107
|
this.layers.set(node, layer);
|
|
20907
21108
|
this.stats.built++;
|
|
@@ -21001,6 +21202,14 @@ var ScrollLayerCache = class {
|
|
|
21001
21202
|
else if (!sameBox(was, now)) boxes.push(was, now);
|
|
21002
21203
|
}
|
|
21003
21204
|
for (const [item, was] of layer.items) if (!seen.has(item)) boxes.push(was);
|
|
21205
|
+
const stuck = stuckIn(container, layout);
|
|
21206
|
+
if (stuck === null) return "all";
|
|
21207
|
+
for (const [node, now] of stuck) {
|
|
21208
|
+
const was = layer.stuck.get(node);
|
|
21209
|
+
if (was === void 0) boxes.push(now);
|
|
21210
|
+
else if (!sameBox(was, now)) boxes.push(was, now);
|
|
21211
|
+
}
|
|
21212
|
+
for (const [node, was] of layer.stuck) if (!stuck.has(node)) boxes.push(was);
|
|
21004
21213
|
const rects = [];
|
|
21005
21214
|
let area = 0;
|
|
21006
21215
|
for (const box of boxes) {
|
|
@@ -21019,6 +21228,7 @@ var ScrollLayerCache = class {
|
|
|
21019
21228
|
const box = boxOf(layout, item);
|
|
21020
21229
|
if (box !== void 0) layer.items.set(item, box);
|
|
21021
21230
|
}
|
|
21231
|
+
layer.stuck = stuckIn(container, layout) ?? /* @__PURE__ */ new Map();
|
|
21022
21232
|
}
|
|
21023
21233
|
/** An item's box in the layer's pixels, widened for what paints past it, or null off the layer. */
|
|
21024
21234
|
toLayer(layer, box) {
|
|
@@ -21099,6 +21309,42 @@ function itemHolding(container, node) {
|
|
|
21099
21309
|
}
|
|
21100
21310
|
return null;
|
|
21101
21311
|
}
|
|
21312
|
+
/**
|
|
21313
|
+
* Where each sticky node inside a container is drawn, in the
|
|
21314
|
+
* container's children's coordinates: its box moved by its own shift
|
|
21315
|
+
* and by every sticky ancestor's up to the container. Null when the
|
|
21316
|
+
* reader cannot say which nodes are sticky, which no layer can survive.
|
|
21317
|
+
*/
|
|
21318
|
+
function stuckIn(container, layout) {
|
|
21319
|
+
const sticky = layout.allStickyNodes?.();
|
|
21320
|
+
if (sticky === void 0) return null;
|
|
21321
|
+
const drawn = /* @__PURE__ */ new Map();
|
|
21322
|
+
for (const node of sticky) {
|
|
21323
|
+
const rec = layout.recordFor(node);
|
|
21324
|
+
if (rec === void 0) continue;
|
|
21325
|
+
let x = rec.x + rec.stickyOffsetX;
|
|
21326
|
+
let y = rec.y + rec.stickyOffsetY;
|
|
21327
|
+
let inside = false;
|
|
21328
|
+
for (let current = node.parent; current !== null; current = current.parent) {
|
|
21329
|
+
if (current === container) {
|
|
21330
|
+
inside = true;
|
|
21331
|
+
break;
|
|
21332
|
+
}
|
|
21333
|
+
const above = layout.recordFor(current);
|
|
21334
|
+
if (above !== void 0) {
|
|
21335
|
+
x += above.stickyOffsetX;
|
|
21336
|
+
y += above.stickyOffsetY;
|
|
21337
|
+
}
|
|
21338
|
+
}
|
|
21339
|
+
if (inside) drawn.set(node, {
|
|
21340
|
+
x,
|
|
21341
|
+
y,
|
|
21342
|
+
width: rec.width,
|
|
21343
|
+
height: rec.height
|
|
21344
|
+
});
|
|
21345
|
+
}
|
|
21346
|
+
return drawn;
|
|
21347
|
+
}
|
|
21102
21348
|
function sameBox(a, b) {
|
|
21103
21349
|
return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
|
|
21104
21350
|
}
|
|
@@ -22335,4 +22581,4 @@ function createCanvasSurface(host) {
|
|
|
22335
22581
|
//#endregion
|
|
22336
22582
|
export { isImeKey as $, visualStatesEqual as $a, scaleSpacing as $i, spannedRunsFor as $n, transformIsIdentity as $r, registerFontStack as $t, withOverrideSource as A, UiBasicColors as Aa, noInsets as Ai, clearLinkHover as An, inheritedPropertyFlags as Ar, adjacentField as At, FlexDirection as B, findEnvironmentKey as Ba, withDensity as Bi, editorFor as Bn, isUiSemanticState as Br, createCanvasTextStyle as Bt, SCROLLBAR_LINGER_MS as C, spansDifferOnlyInPaint as Ca, normalizeBorderRadius as Ci, isNodeInert as Cn, resolveNumber as Cr, hasDrawnText as Ct, formatExplanation as D, colorsEqualPalette as Da, UiEnvironmentKeys as Di, isSubtreeInert as Dn, closestPropertyName as Dr, selectionRectsIn as Dt, formatConstraints as E, textStylesEqual as Ea, propertyValuesEqual as Ei, isPressable as En, resolveString as Er, paragraphGeometryFrom as Et, clampSize as F, normalizeColor as Fa, unknownContainerSize as Fi, setLinkHover as Fn, propertyValuesEqualByName as Fr, detectEditingPlatform as Ft, CrossAxisAlignment as G, overrideSources as Ga, themeExtensionsEqual as Gi, maskText as Gn, UI_SUBGRID_AXES as Gr, runFontString as Gt, placeGridItems as H, UiNode as Ha, hasThemeExtension as Hi, isEditableNode as Hn, statesEqual as Hr, fillTextRects as Ht, constraintsEqual as I, parseColor as Ia, darkTheme as Ii, CARET_BLINK_MS as In, UiProperties as Ir, isPrintable as It, parseCrossAxisAlignment as J, writeOverrideProperty as Ja, highContrastColors as Ji, resolveColorValue as Jn, paintValuesEqual as Jr, textRunBackgrounds as Jt, MainAxisAlignment as K, resetOverrideWarnings as Ka, withThemeExtension as Ki, nextCaretToggle as Kn, validateSubgrid as Kr, spanOf as Kt, tightenConstraints as L, rgb8 as La, lightTheme as Li, CARET_WIDTH as Ln, UI_ROLES as Lr, EditableLayout as Lt, contentOffset as M, colorToRgba as Ma, UiContainerSizeSource as Mi, linkHoverOf as Mn, propertyEffects as Mr, edgeField as Mt, LayoutRecord as N, colorValuesEqual as Na, bandOf as Ni, linkOf as Nn, propertyIsInherited as Nr, editingGroupOf as Nt, formatNumber as O, darkColors as Oa, UiInsetRegistry as Oi, pointerEventsOf as On, findPropertyDefinition as Or, wordRangeIn as Ot, Constraints as P, colorsEqual as Pa, containerBands as Pi, linkRunAtPointIn as Pn, propertyNarrowers as Pr, commandForKey as Pt, capturePointer as Q, visualState as Qa, defaultSpacing as Qi, ParagraphTextMeasurer as Qn, transform as Qr, fontStackFor as Qt, MAX_MEASURES_PER_CHILD as R, rgba as Ra, themesEqual as Ri, EDITOR_PROP as Rn, UI_SEMANTIC_STATES as Rr, applyCanvasTextStyle as Rt, SCROLLBAR_FADE_MS as S, spannedTextOf as Sa, borderRadiusValuesEqual as Si, isNodeHitTestable as Sn, resolveBoolean as Sr, UiInputDispatcher as St, describeOverrides as T, textSpansEqual as Ta, defineProperty as Ti, isNodeTabStop as Tn, resolvePropertyByName as Tr, paragraphGeometry as Tt, sizeGridTracks as U, DirtyNodeSet as Ua, noThemeExtensions as Ui, isMultiline as Un, validateRole as Ur, layoutTextLines as Ut, parseFlexDirection as V, UiEnvironment as Va, defineThemeExtension as Vi, editorOf as Vn, normalizeStates as Vr, drawText as Vt, AlignContent as W, clearOverrideProperty as Wa, themeExtension as Wi, isReadOnly as Wn, validateStates as Wr, runCanvasStyleInto as Wt, CanvasPlatformSurface as X, defaultVisualState as Xa, relativeLuminance as Xi, videoFrameSize as Xn, UiTransforms as Xr, bumpFontStack as Xt, parseMainAxisAlignment as Y, UiVisualState as Ya, raiseContrast as Yi, isVideoSurface as Yn, pathValuesEqual as Yr, textRunDecorations as Yt, UiPlatformAdapter as Z, hasVisualState as Za, densityFactors as Zi, CharacterCountTextMeasurer as Zn, parseTransform as Zr, clearFontStacks as Zt, LABEL_PADDING_X as _, editableSpansOf as _a, UiBorderRadiuses as _i, selectableTextNodes as _n, UiNodeType as _o, previousGraphemeStart as _r, scrollLeaderOf as _t, PaintPictureCache as a, boxShadow as aa, radialGradient as ai, computeObjectFitRect as an, UiGestureEvent as ao, lineIndexForOffset as ar, UiGestureRecognizer as at, snapScroll as b, resolvedSpansOf as ba, borderRadiusEqual as bi, setSelectionRange as bn, UiGraph as br, scrollbarThumbs as bt, EMPTY_RECORDING as c, boxShadowReach as ca, fr as ci, normalizeTextAlign as cn, UiPasteEvent as co, offsetAtX as cr, isScrollContainer as ct, tracePathData as d, isShapeName as da, isMinMaxTrack as di, TEXT_MATCHES_PROP as dn, UiSelectionChangeEvent as do, EditableTextModel as dr, UiFocusManager as dt, spacingEqual as ea, transformsEqual as ei, DEFAULT_FONT_FAMILY as en, MOUSE_POINTER as eo, ELLIPSIS as er, pointerDeviceOf as et, ScaledImageCache as f, shapesEqual as fa, isPercentLength as fi, clearMatchRanges as fn, UiTextChangeEvent as fo, graphemeBoundaries as fr, UiHitTester as ft, paintsAfterChildren as g, defaultTextStyle as ga, resolveLength as gi, clearSelectionRange as gn, wheelDeltaYOf as go, nextWordEnd as gr, SCROLLBAR_THICKNESS as gt, hasDecorationPhase as h, typographyEqual as ha, repeat as hi, TEXT_SELECTION_PROP as hn, noKeyModifiers as ho, nextGraphemeEnd as hr, SCROLLBAR_MIN_THUMB as ht, traceRoundedRect as i, BOX_SHADOW_BLUR_REACH as ia, linearGradient as ii, colorToCss as in, UiFocusEvent as io, lineIndexAtY as ir, UiTouchScroller as it, accumulatedOffsetTo as j, colorToHex as ja, observeViewportInsets as ji, hasTextLinks as jn, inheritedPropertyNames as jr, comparePositions as jt, labelNode as k, lightColors as ka, insetsEqual as ki, resolveCursor as kn, getPropertyNames as kr, textInputOf as kt, PaintRecorder as l, boxShadowsEqual as la, isAutoLength as li, normalizeVerticalAlign as ln, UiPinchEvent as lo, offsetForVerticalMove as lr, UiKeyboardController as lt, decorationRect as m, isTypographyRole as ma, percent as mi, setMatchRanges as mn, UiWheelEvent as mo, lineStartAt as mr, SCROLLBAR_INSET as mt, createCanvasSurface as n, defaultShadows as na, gradientPaint as ni, DEFAULT_FONT_WEIGHT as nn, UiCompositionEvent as no, proportionalFontMetrics as nr, touchActionFor as nt, paintPictures as o, boxShadowArraysEqual as oa, validateGradient as oi, createPaintState as on, UiInputEvent as oo, lineLimit as or, UiPinchRecognizer as ot, decorationColor as p, defaultTypography as pa, minmax as pi, matchRangesOf as pn, UiWheelDeltaMode as po, lineEndAt as pr, SCROLLBAR_HOVER_ZONE as pt, parseAlignContent as q, writeDeclaredProperty as qa, contrastRatio as qi, syncEditorValue as qn, inputsEqual as qr, textMeasureRequest as qt, Canvas2DRenderer as r, shadowsEqual as ra, gradientsEqual as ri, DEFAULT_TEXT_COLOR as rn, UiEventType as ro, caretRectFor as rr, UiEditingController as rt, PaintTarget as s, boxShadowRadius as sa, auto as si, isPaintVisible as sn, UiKeyboardEvent as so, offsetAtPoint as sr, UiWheelController as st, CanvasSurface as t, spacingSteps as ta, MAX_GRADIENT_STOPS as ti, DEFAULT_FONT_SIZE as tn, UiBeforeInputEvent as to, layoutParagraph as tr, prepareInputSurface as tt, replayPaint as u, defaultShapes as ua, isFrLength as ui, resolvePaintState as un, UiPointerEvent as uo, selectionRects as ur, UiPointerController as ut, drawOverlayShapes as v, flattenTextSpans as va, borderRadius as vi, selectableTextOf as vn, DirtyFlags as vo, previousWordStart as vr, scrollRange as vt, describeLength as w, textContentOf as wa, uniformBorderRadius as wi, isNodeSelectable as wn, resolveProperty as wr, offsetAtPointIn as wt, LayoutEngine as x, spanAtOffset as xa, borderRadiusIsZero as xi, isNodeFocusable as xn, DEFAULT_LINE_HEIGHT_FACTOR as xr, scrollbarZoneAt as xt, labelOrigin as y, hiddenRangesOf as ya, borderRadiusCorners as yi, selectionRangeOf as yn, UiBinding as yo, wordRangeAt as yr, scrollbarThumb as yt, isLayoutProtocol as z, createEnvironmentKey as za, withContrast as zi, caretVisibleAt as zn, isUiRole as zr, buildFontString as zt };
|
|
22337
22583
|
|
|
22338
|
-
//# sourceMappingURL=CanvasSurface-
|
|
22584
|
+
//# sourceMappingURL=CanvasSurface-D5QaKaWH.js.map
|