gesso-core 0.6.20 → 0.6.22
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 +20 -0
- package/dist/{CanvasSurface-VUJRrcXl.js → CanvasSurface-BxHC-NQ8.js} +456 -146
- package/dist/CanvasSurface-BxHC-NQ8.js.map +1 -0
- package/dist/{index-lzNLHD-1.d.ts → index-BtTF_OxB.d.ts} +501 -358
- package/dist/index.d.ts +1 -1
- package/dist/index.js +31 -6
- 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-VUJRrcXl.js.map +0 -1
|
@@ -881,9 +881,24 @@ var UiNode = class {
|
|
|
881
881
|
* opacity → 0.5
|
|
882
882
|
* visible → true
|
|
883
883
|
* width → 200
|
|
884
|
+
*
|
|
885
|
+
* Read it directly; write it through `setProperty` and
|
|
886
|
+
* `removeProperty`, which count the change in `propertyVersion`.
|
|
884
887
|
*/
|
|
885
888
|
properties = /* @__PURE__ */ new Map();
|
|
886
889
|
/**
|
|
890
|
+
* Counts writes to `properties`.
|
|
891
|
+
*
|
|
892
|
+
* Lets something derived from a node's own properties tell that it
|
|
893
|
+
* is still right without reading them again. The layout engine
|
|
894
|
+
* resolves forty of them into each record, and on a full pass over a
|
|
895
|
+
* tree where nothing changed that reading was most of a sixth of the
|
|
896
|
+
* pass. A counter is exact where a dirty flag is not: flags are
|
|
897
|
+
* cleared by whichever pass runs next, and a record is resolved by
|
|
898
|
+
* whichever pass reaches it.
|
|
899
|
+
*/
|
|
900
|
+
propertyVersion = 0;
|
|
901
|
+
/**
|
|
887
902
|
* Values a modifier has written over the element's own.
|
|
888
903
|
*
|
|
889
904
|
* Null until the first modifier writes, so a tree without modifiers
|
|
@@ -929,6 +944,13 @@ var UiNode = class {
|
|
|
929
944
|
}
|
|
930
945
|
setProperty(property, value) {
|
|
931
946
|
this.properties.set(property, value);
|
|
947
|
+
this.propertyVersion++;
|
|
948
|
+
}
|
|
949
|
+
/** Removes a property; whether it was there. */
|
|
950
|
+
removeProperty(property) {
|
|
951
|
+
if (!this.properties.delete(property)) return false;
|
|
952
|
+
this.propertyVersion++;
|
|
953
|
+
return true;
|
|
932
954
|
}
|
|
933
955
|
};
|
|
934
956
|
//#endregion
|
|
@@ -1613,6 +1635,7 @@ function resolvedSpansOf(node) {
|
|
|
1613
1635
|
* as soon as the application catches up.
|
|
1614
1636
|
*/
|
|
1615
1637
|
function editableSpansOf(node, text, composition) {
|
|
1638
|
+
if (node.properties.get("secret") === true) return EMPTY_SPANS;
|
|
1616
1639
|
const spanned = spannedTextOf(node);
|
|
1617
1640
|
if (spanned === void 0) return EMPTY_SPANS;
|
|
1618
1641
|
if (spanned.text === text) return spanned.spans;
|
|
@@ -4219,6 +4242,17 @@ const UiProperties = {
|
|
|
4219
4242
|
inherited: false,
|
|
4220
4243
|
affects: 64
|
|
4221
4244
|
}),
|
|
4245
|
+
/**
|
|
4246
|
+
* A password field: every character is drawn as a bullet, copy and
|
|
4247
|
+
* cut take nothing, and the shell edits it through a password input.
|
|
4248
|
+
* The value itself is unchanged. Single-line only.
|
|
4249
|
+
*/
|
|
4250
|
+
secret: defineProperty({
|
|
4251
|
+
name: "secret",
|
|
4252
|
+
defaultValue: void 0,
|
|
4253
|
+
inherited: false,
|
|
4254
|
+
affects: 262
|
|
4255
|
+
}),
|
|
4222
4256
|
/** Colour of the caret; defaults to the text colour. */
|
|
4223
4257
|
caretColor: defineProperty({
|
|
4224
4258
|
name: "caretColor",
|
|
@@ -4966,39 +5000,6 @@ function createFallbackKey(definition) {
|
|
|
4966
5000
|
* no line height is set. Shared by ParagraphLayout and PaintState.
|
|
4967
5001
|
*/
|
|
4968
5002
|
const DEFAULT_LINE_HEIGHT_FACTOR = 1.2;
|
|
4969
|
-
/**
|
|
4970
|
-
* Resolves a node's font the one way layout and paint both use.
|
|
4971
|
-
*
|
|
4972
|
-
* Font size, family, weight and letter spacing inherit through the
|
|
4973
|
-
* environment's text style. Line height is the subtle one: a text
|
|
4974
|
-
* style carries a line height that belongs with its font size, so a
|
|
4975
|
-
* node that inherits the style takes it whole. A node that sets its
|
|
4976
|
-
* own `fontSize` without a `lineHeight` gets a normal line height for
|
|
4977
|
-
* that size, `fontSize × 1.2`, rather than the inherited pixel value
|
|
4978
|
-
* sized for a different font — the inherited 16.8px of the default
|
|
4979
|
-
* style is right for 14px text and wrong for 22px. An explicit
|
|
4980
|
-
* `lineHeight` always wins.
|
|
4981
|
-
*
|
|
4982
|
-
* Before this, layout read the raw props (unset line height → ×1.2)
|
|
4983
|
-
* and paint read the inherited ones (→ 16.8px), so any text whose size
|
|
4984
|
-
* differed from the style's was measured in one line box and drawn in
|
|
4985
|
-
* another, and sat high or low inside it.
|
|
4986
|
-
*/
|
|
4987
|
-
function resolveFont(node) {
|
|
4988
|
-
const out = {
|
|
4989
|
-
fontSize: 0,
|
|
4990
|
-
fontFamily: "",
|
|
4991
|
-
fontWeight: "normal",
|
|
4992
|
-
lineHeight: 0,
|
|
4993
|
-
letterSpacing: 0,
|
|
4994
|
-
fontStyle: "normal",
|
|
4995
|
-
fontStretch: "normal",
|
|
4996
|
-
fontVariant: "normal",
|
|
4997
|
-
fontKerning: "auto"
|
|
4998
|
-
};
|
|
4999
|
-
resolveFontInto(node, out);
|
|
5000
|
-
return out;
|
|
5001
|
-
}
|
|
5002
5003
|
/** `resolveFont`, writing into a target the caller owns. */
|
|
5003
5004
|
function resolveFontInto(node, out) {
|
|
5004
5005
|
const fontSize = positive$1(resolveProperty(node, UiProperties.fontSize)) ?? UiProperties.fontSize.defaultValue;
|
|
@@ -5473,7 +5474,7 @@ var UiGraph = class {
|
|
|
5473
5474
|
applyResolvedProperty(node, property, present, value, dirtyFlags) {
|
|
5474
5475
|
if (!present) {
|
|
5475
5476
|
if (!node.properties.has(property)) return false;
|
|
5476
|
-
node.
|
|
5477
|
+
node.removeProperty(property);
|
|
5477
5478
|
this.markDirty(node, this.withProvidedFlags(property, dirtyFlags));
|
|
5478
5479
|
return true;
|
|
5479
5480
|
}
|
|
@@ -6848,7 +6849,10 @@ const FIT_EPSILON = 1 / 64;
|
|
|
6848
6849
|
* narrower than the widest segment. When a segment is wider than the
|
|
6849
6850
|
* available width the paragraph grows to it, and every line wraps
|
|
6850
6851
|
* against that grown width rather than the one asked for, because that
|
|
6851
|
-
* is the box the lines will be painted in.
|
|
6852
|
+
* is the box the lines will be painted in. When the width is the box's
|
|
6853
|
+
* own (`exactWidth`: a width set from outside, or the box being
|
|
6854
|
+
* painted), it does not grow: the lines wrap against it and the wide
|
|
6855
|
+
* segment overflows alone, as CSS wraps text in a box of a fixed width.
|
|
6852
6856
|
*
|
|
6853
6857
|
* The first baseline sits half the leading below the line top, plus the
|
|
6854
6858
|
* ascent, with the half-leading floored to a whole pixel. That floor is
|
|
@@ -6914,7 +6918,7 @@ function layoutParagraph(request, runs) {
|
|
|
6914
6918
|
if (paragraphEnd >= text.length) break;
|
|
6915
6919
|
paragraphStart = paragraphEnd + 1;
|
|
6916
6920
|
}
|
|
6917
|
-
const available = Math.max(maxWidth, minContentWidth);
|
|
6921
|
+
const available = request.exactWidth === true ? maxWidth : Math.max(maxWidth, minContentWidth);
|
|
6918
6922
|
const unwrapped = wrap === "none" || !isFinite(available);
|
|
6919
6923
|
const lines = [];
|
|
6920
6924
|
for (const paragraph of paragraphs) {
|
|
@@ -6923,7 +6927,7 @@ function layoutParagraph(request, runs) {
|
|
|
6923
6927
|
const key = unwrapped ? -1 : available;
|
|
6924
6928
|
let relative = paragraph.cached.lines.get(key);
|
|
6925
6929
|
if (relative === void 0) {
|
|
6926
|
-
relative = breakHardLine(paragraph.text, paragraph.segments, width, unwrapped, measure);
|
|
6930
|
+
relative = breakHardLine(paragraph.cached.text, paragraph.segments, width, unwrapped, measure);
|
|
6927
6931
|
if (paragraph.cached.lines.size >= WIDTHS_PER_LINE) paragraph.cached.lines.clear();
|
|
6928
6932
|
paragraph.cached.lines.set(key, relative);
|
|
6929
6933
|
}
|
|
@@ -6997,12 +7001,14 @@ function hardLine(memo, style, text, wrap, measure) {
|
|
|
6997
7001
|
memo.set(key, cached);
|
|
6998
7002
|
return cached;
|
|
6999
7003
|
}
|
|
7000
|
-
const
|
|
7004
|
+
const own = ownCopy(text);
|
|
7005
|
+
const segments = segmentParagraph(own, wrap);
|
|
7001
7006
|
let minContentWidth = 0;
|
|
7002
|
-
for (const segment of segments) minContentWidth = Math.max(minContentWidth, measure(
|
|
7007
|
+
for (const segment of segments) minContentWidth = Math.max(minContentWidth, measure(own.slice(segment.start, segment.end), segment.start, segment.end));
|
|
7003
7008
|
const entry = {
|
|
7009
|
+
text: own,
|
|
7004
7010
|
segments,
|
|
7005
|
-
maxContentWidth: measure(
|
|
7011
|
+
maxContentWidth: measure(own, 0, own.length),
|
|
7006
7012
|
minContentWidth,
|
|
7007
7013
|
lines: /* @__PURE__ */ new Map()
|
|
7008
7014
|
};
|
|
@@ -7013,6 +7019,23 @@ function hardLine(memo, style, text, wrap, measure) {
|
|
|
7013
7019
|
memo.set(key, entry);
|
|
7014
7020
|
return entry;
|
|
7015
7021
|
}
|
|
7022
|
+
/**
|
|
7023
|
+
* `text` in a string of its own.
|
|
7024
|
+
*
|
|
7025
|
+
* A hard line arrives as a slice of the whole paragraph, and a slice
|
|
7026
|
+
* in V8 is a view that keeps the string it was cut from alive. The
|
|
7027
|
+
* memo outlives the paragraph — it is what a later edit finds the
|
|
7028
|
+
* unchanged lines in — so each line it remembered, and every line
|
|
7029
|
+
* broken from it, held on to the whole text it came from. Typing into
|
|
7030
|
+
* a 115 KB field kept every version of it: 100 MB over 4,096 edits.
|
|
7031
|
+
* Prefixing a character makes a new string that has to be flattened
|
|
7032
|
+
* before it can be sliced, and the slice is then of that copy. A short
|
|
7033
|
+
* line is copied by `slice` anyway, and an engine that copies every
|
|
7034
|
+
* slice loses nothing.
|
|
7035
|
+
*/
|
|
7036
|
+
function ownCopy(text) {
|
|
7037
|
+
return text.length < 16 ? text : (" " + text).slice(1);
|
|
7038
|
+
}
|
|
7016
7039
|
/** Breaks one hard line on its own, as if it were the whole text. */
|
|
7017
7040
|
function breakHardLine(text, segments, available, unwrapped, measure) {
|
|
7018
7041
|
const lines = [];
|
|
@@ -7313,8 +7336,58 @@ function spannedRunsFor(request, runs) {
|
|
|
7313
7336
|
}
|
|
7314
7337
|
};
|
|
7315
7338
|
}
|
|
7316
|
-
/**
|
|
7317
|
-
|
|
7339
|
+
/**
|
|
7340
|
+
* How much the paragraph cache holds before the least recently asked
|
|
7341
|
+
* for is forgotten: a number of paragraphs, and their text counted in
|
|
7342
|
+
* UTF-16 code units, whichever runs out first.
|
|
7343
|
+
*
|
|
7344
|
+
* A count alone treated a two-word label and a whole document as the
|
|
7345
|
+
* same size. Every keystroke in a long field is a new request, its key
|
|
7346
|
+
* the whole text, so 4,096 edits to a 115 KB field held 4,096 copies of
|
|
7347
|
+
* it, keys and lines: 1.1 GB of heap, for paragraphs nobody would ask
|
|
7348
|
+
* for again. The text budget keeps a handful of those; the count is
|
|
7349
|
+
* what bounds a screen of labels, and is larger than it was, since a
|
|
7350
|
+
* label costs a few hundred bytes and a list that remounts its rows
|
|
7351
|
+
* should find them still here.
|
|
7352
|
+
*/
|
|
7353
|
+
const PARAGRAPH_CACHE_ENTRIES = 16384;
|
|
7354
|
+
const PARAGRAPH_CACHE_TEXT = 1 << 20;
|
|
7355
|
+
/** A least-recently-used map of paragraphs, bounded by count and by text; see `PARAGRAPH_CACHE_ENTRIES`. */
|
|
7356
|
+
var ParagraphCache = class {
|
|
7357
|
+
entries = /* @__PURE__ */ new Map();
|
|
7358
|
+
text = 0;
|
|
7359
|
+
get size() {
|
|
7360
|
+
return this.entries.size;
|
|
7361
|
+
}
|
|
7362
|
+
get(key) {
|
|
7363
|
+
const entry = this.entries.get(key);
|
|
7364
|
+
if (entry === void 0) return;
|
|
7365
|
+
this.entries.delete(key);
|
|
7366
|
+
this.entries.set(key, entry);
|
|
7367
|
+
return entry.paragraph;
|
|
7368
|
+
}
|
|
7369
|
+
set(key, paragraph, text) {
|
|
7370
|
+
const previous = this.entries.get(key);
|
|
7371
|
+
if (previous !== void 0) {
|
|
7372
|
+
this.entries.delete(key);
|
|
7373
|
+
this.text -= previous.text;
|
|
7374
|
+
}
|
|
7375
|
+
while (this.entries.size > 0 && (this.entries.size >= PARAGRAPH_CACHE_ENTRIES || this.text + text > PARAGRAPH_CACHE_TEXT)) {
|
|
7376
|
+
const [oldest, entry] = this.entries.entries().next().value;
|
|
7377
|
+
this.entries.delete(oldest);
|
|
7378
|
+
this.text -= entry.text;
|
|
7379
|
+
}
|
|
7380
|
+
this.entries.set(key, {
|
|
7381
|
+
paragraph,
|
|
7382
|
+
text
|
|
7383
|
+
});
|
|
7384
|
+
this.text += text;
|
|
7385
|
+
}
|
|
7386
|
+
clear() {
|
|
7387
|
+
this.entries.clear();
|
|
7388
|
+
this.text = 0;
|
|
7389
|
+
}
|
|
7390
|
+
};
|
|
7318
7391
|
/**
|
|
7319
7392
|
* Base class for measurers: implement the two primitives and the
|
|
7320
7393
|
* paragraph algorithm does the rest.
|
|
@@ -7336,21 +7409,31 @@ const PARAGRAPH_CACHE_ENTRIES = 4096;
|
|
|
7336
7409
|
* The result is shared between callers and must not be mutated.
|
|
7337
7410
|
*/
|
|
7338
7411
|
var ParagraphTextMeasurer = class {
|
|
7339
|
-
paragraphs =
|
|
7412
|
+
paragraphs = new ParagraphCache();
|
|
7413
|
+
/**
|
|
7414
|
+
* Paragraphs that came out the same at every width they fit in, by
|
|
7415
|
+
* their key without the width; see `layoutFitsAnyWidth`.
|
|
7416
|
+
*
|
|
7417
|
+
* A resize asks every paragraph again at a width a few pixels from
|
|
7418
|
+
* the last, and a title, a caption or a label that fitted before
|
|
7419
|
+
* fits still: its lines, its box and everything else are what they
|
|
7420
|
+
* were. Keyed by its width as well, each of those missed on every
|
|
7421
|
+
* step of a dragged window edge and was laid out again, and the
|
|
7422
|
+
* box it was then painted in (its own width, exact) missed once
|
|
7423
|
+
* more.
|
|
7424
|
+
*/
|
|
7425
|
+
fitting = new ParagraphCache();
|
|
7426
|
+
generations = 0;
|
|
7340
7427
|
layout(request) {
|
|
7341
|
-
const
|
|
7428
|
+
const style = paragraphStyleKey(request);
|
|
7429
|
+
const key = `${request.maxWidth ?? ""}\0${request.exactWidth === true ? 1 : ""}\0${style}`;
|
|
7342
7430
|
const cached = this.paragraphs.get(key);
|
|
7343
|
-
if (cached !== void 0)
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
return cached;
|
|
7347
|
-
}
|
|
7431
|
+
if (cached !== void 0) return cached;
|
|
7432
|
+
const fitted = this.fitting.get(style);
|
|
7433
|
+
if (fitted !== void 0 && fitsWidth(fitted, request.maxWidth)) return fitted;
|
|
7348
7434
|
const paragraph = layoutParagraph(request, this);
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
if (oldest !== void 0) this.paragraphs.delete(oldest);
|
|
7352
|
-
}
|
|
7353
|
-
this.paragraphs.set(key, paragraph);
|
|
7435
|
+
this.paragraphs.set(key, paragraph, request.text.length);
|
|
7436
|
+
if (layoutFitsAnyWidth(request, paragraph)) this.fitting.set(style, paragraph, request.text.length);
|
|
7354
7437
|
return paragraph;
|
|
7355
7438
|
}
|
|
7356
7439
|
measure(request) {
|
|
@@ -7364,6 +7447,9 @@ var ParagraphTextMeasurer = class {
|
|
|
7364
7447
|
get cachedParagraphs() {
|
|
7365
7448
|
return this.paragraphs.size;
|
|
7366
7449
|
}
|
|
7450
|
+
get generation() {
|
|
7451
|
+
return this.generations;
|
|
7452
|
+
}
|
|
7367
7453
|
/**
|
|
7368
7454
|
* Forgets every laid-out paragraph. A subclass that caches its own
|
|
7369
7455
|
* primitives overrides this and calls it, so a font that finished
|
|
@@ -7371,13 +7457,47 @@ var ParagraphTextMeasurer = class {
|
|
|
7371
7457
|
* built from.
|
|
7372
7458
|
*/
|
|
7373
7459
|
invalidate() {
|
|
7460
|
+
this.generations++;
|
|
7374
7461
|
this.paragraphs.clear();
|
|
7462
|
+
this.fitting.clear();
|
|
7375
7463
|
forgetHardLines(this);
|
|
7376
7464
|
}
|
|
7377
7465
|
};
|
|
7378
|
-
/**
|
|
7379
|
-
|
|
7380
|
-
|
|
7466
|
+
/**
|
|
7467
|
+
* Whether `paragraph`, laid out for `request`, is what a request
|
|
7468
|
+
* differing only in its width would get at any width it fits in.
|
|
7469
|
+
*
|
|
7470
|
+
* A paragraph's width enters its layout in four places, and none of
|
|
7471
|
+
* them can tell two widths apart once every hard line fits whole:
|
|
7472
|
+
* nothing breaks (a line that fits is not broken, `exactWidth` or
|
|
7473
|
+
* not); the box is fit-content, which is the natural width; no line is
|
|
7474
|
+
* wider than the box, so none is ellipsised in place; and the one
|
|
7475
|
+
* ellipsis that is fitted to the width — the last line kept by
|
|
7476
|
+
* `maxLines` — is excluded here, because it is only drawn when there
|
|
7477
|
+
* were more hard lines than that. An unbounded request is left out:
|
|
7478
|
+
* it is laid out unwrapped, which is a different path, and it has a
|
|
7479
|
+
* key of its own that never changes anyway.
|
|
7480
|
+
*/
|
|
7481
|
+
function layoutFitsAnyWidth(request, paragraph) {
|
|
7482
|
+
if (!fitsWidth(paragraph, request.maxWidth)) return false;
|
|
7483
|
+
const maxLines = request.maxLines;
|
|
7484
|
+
return request.overflow !== "ellipsis" || maxLines === void 0 || maxLines < 1 || !hasMoreHardLines(request.text, maxLines);
|
|
7485
|
+
}
|
|
7486
|
+
/** Whether a paragraph with nothing in it that depends on the width fits at `maxWidth`. */
|
|
7487
|
+
function fitsWidth(paragraph, maxWidth) {
|
|
7488
|
+
return maxWidth !== void 0 && maxWidth >= 0 && paragraph.maxContentWidth <= maxWidth;
|
|
7489
|
+
}
|
|
7490
|
+
function hasMoreHardLines(text, count) {
|
|
7491
|
+
let at = -1;
|
|
7492
|
+
for (let i = 0; i < count; i++) {
|
|
7493
|
+
at = text.indexOf("\n", at + 1);
|
|
7494
|
+
if (at < 0) return false;
|
|
7495
|
+
}
|
|
7496
|
+
return true;
|
|
7497
|
+
}
|
|
7498
|
+
/** Every field of a request but its width, in a fixed order; two requests that lay out alike at one width share a key. */
|
|
7499
|
+
function paragraphStyleKey(request) {
|
|
7500
|
+
return `${request.fontSize}\0${request.fontFamily ?? ""}\0${request.fontWeight ?? ""}\0${request.lineHeight ?? ""}\0${request.letterSpacing ?? ""}\0${request.wrap ?? ""}\0${request.maxLines ?? ""}\0${request.overflow ?? ""}\0${request.fontStyle ?? ""}\0${request.fontStretch ?? ""}\0${request.fontVariant ?? ""}\0${request.fontKerning ?? ""}\0${spansKey(request.spans)}\0${request.text}`;
|
|
7381
7501
|
}
|
|
7382
7502
|
/**
|
|
7383
7503
|
* The runs' part of a paragraph key, remembered by the identity of the
|
|
@@ -7629,7 +7749,7 @@ function editorFor(node) {
|
|
|
7629
7749
|
let model = node.properties.get(EDITOR_PROP);
|
|
7630
7750
|
if (!(model instanceof EditableTextModel)) {
|
|
7631
7751
|
model = new EditableTextModel();
|
|
7632
|
-
node.
|
|
7752
|
+
node.setProperty(EDITOR_PROP, model);
|
|
7633
7753
|
}
|
|
7634
7754
|
syncEditorValue(node, model);
|
|
7635
7755
|
syncEditorHidden(node, model);
|
|
@@ -7659,12 +7779,33 @@ function syncEditorHidden(node, model) {
|
|
|
7659
7779
|
function isEditableNode(node) {
|
|
7660
7780
|
return node.type === "editable-text";
|
|
7661
7781
|
}
|
|
7782
|
+
/** Whether Enter inserts a newline. Never in a secret field, which is one line, as a password input is. */
|
|
7662
7783
|
function isMultiline(node) {
|
|
7663
|
-
return node.properties.get("multiline") === true;
|
|
7784
|
+
return node.properties.get("multiline") === true && !isSecret(node);
|
|
7664
7785
|
}
|
|
7665
7786
|
function isReadOnly(node) {
|
|
7666
7787
|
return node.properties.get("readOnly") === true;
|
|
7667
7788
|
}
|
|
7789
|
+
function isSecret(node) {
|
|
7790
|
+
return node.properties.get("secret") === true;
|
|
7791
|
+
}
|
|
7792
|
+
/**
|
|
7793
|
+
* A secret field's text as it is drawn: one bullet per UTF-16 code
|
|
7794
|
+
* unit, not per character. Every offset the editor works in (caret,
|
|
7795
|
+
* selection, hit-testing, the shell's mirror) is a code unit offset
|
|
7796
|
+
* into the model's text, and a mask of the same length keeps each of
|
|
7797
|
+
* them meaning the same position in both strings. A character outside
|
|
7798
|
+
* the BMP draws as two bullets, which says a little about it; counting
|
|
7799
|
+
* graphemes instead would need a map between the two strings' offsets
|
|
7800
|
+
* in every one of those places.
|
|
7801
|
+
*/
|
|
7802
|
+
function maskText(text) {
|
|
7803
|
+
return "•".repeat(text.length);
|
|
7804
|
+
}
|
|
7805
|
+
/** The text an editable draws and measures: its model's, masked when it is secret. */
|
|
7806
|
+
function shownTextOf(node, model) {
|
|
7807
|
+
return isSecret(node) ? maskText(model.text) : model.text;
|
|
7808
|
+
}
|
|
7668
7809
|
/**
|
|
7669
7810
|
* Whether the caret is in the visible half of its blink at `now`. It
|
|
7670
7811
|
* is always visible while a composition is open — the IME caret must
|
|
@@ -7702,8 +7843,8 @@ function linkHoverOf(node) {
|
|
|
7702
7843
|
/** Records the hovered run. Returns whether it changed. */
|
|
7703
7844
|
function setLinkHover(node, index) {
|
|
7704
7845
|
if (linkHoverOf(node) === index) return false;
|
|
7705
|
-
if (index < 0) node.
|
|
7706
|
-
else node.
|
|
7846
|
+
if (index < 0) node.removeProperty(TEXT_LINK_HOVER_PROP);
|
|
7847
|
+
else node.setProperty(TEXT_LINK_HOVER_PROP, index);
|
|
7707
7848
|
return true;
|
|
7708
7849
|
}
|
|
7709
7850
|
/** Forgets the hovered run. Returns whether there was one. */
|
|
@@ -7904,7 +8045,7 @@ function selectionRangeOf(node) {
|
|
|
7904
8045
|
function setSelectionRange(node, start, end) {
|
|
7905
8046
|
const current = selectionRangeOf(node);
|
|
7906
8047
|
if (current !== void 0 && current.start === start && current.end === end) return false;
|
|
7907
|
-
node.
|
|
8048
|
+
node.setProperty(TEXT_SELECTION_PROP, {
|
|
7908
8049
|
start,
|
|
7909
8050
|
end
|
|
7910
8051
|
});
|
|
@@ -7912,7 +8053,7 @@ function setSelectionRange(node, start, end) {
|
|
|
7912
8053
|
}
|
|
7913
8054
|
/** Clears a node's selected range. Returns whether it had one. */
|
|
7914
8055
|
function clearSelectionRange(node) {
|
|
7915
|
-
return node.
|
|
8056
|
+
return node.removeProperty(TEXT_SELECTION_PROP);
|
|
7916
8057
|
}
|
|
7917
8058
|
/**
|
|
7918
8059
|
* The text a `Text` node draws, when the user may select it.
|
|
@@ -7982,12 +8123,12 @@ function setMatchRanges(node, ranges) {
|
|
|
7982
8123
|
const current = matchRangesOf(node);
|
|
7983
8124
|
if (current !== void 0 && rangesEqual(current, ranges)) return false;
|
|
7984
8125
|
if (ranges.length === 0) return clearMatchRanges(node);
|
|
7985
|
-
node.
|
|
8126
|
+
node.setProperty(TEXT_MATCHES_PROP, ranges);
|
|
7986
8127
|
return true;
|
|
7987
8128
|
}
|
|
7988
8129
|
/** Clears a node's matched ranges. Returns whether it had any. */
|
|
7989
8130
|
function clearMatchRanges(node) {
|
|
7990
|
-
return node.
|
|
8131
|
+
return node.removeProperty(TEXT_MATCHES_PROP);
|
|
7991
8132
|
}
|
|
7992
8133
|
function rangesEqual(a, b) {
|
|
7993
8134
|
if (a.length !== b.length) return false;
|
|
@@ -8092,7 +8233,7 @@ function resolvePaintState(node, out) {
|
|
|
8092
8233
|
if (isEditableNode(node)) {
|
|
8093
8234
|
const model = editorFor(node);
|
|
8094
8235
|
out.editor = model;
|
|
8095
|
-
out.text = model
|
|
8236
|
+
out.text = shownTextOf(node, model);
|
|
8096
8237
|
out.placeholder = resolveString(node, "placeholder");
|
|
8097
8238
|
out.placeholderColor = resolveColor(node, UiProperties.placeholderColor) ?? themeColor(node, "textMuted") ?? DEFAULT_PLACEHOLDER_COLOR;
|
|
8098
8239
|
out.selectionColor = resolveColor(node, UiProperties.selectionColor) ?? defaultSelectionColor(node);
|
|
@@ -8554,6 +8695,7 @@ function textMeasureRequest(text, state, box) {
|
|
|
8554
8695
|
fontVariant: state.fontVariant,
|
|
8555
8696
|
fontKerning: state.fontKerning,
|
|
8556
8697
|
maxWidth: box.width > 0 ? box.width : void 0,
|
|
8698
|
+
exactWidth: box.width > 0,
|
|
8557
8699
|
wrap: state.textWrap,
|
|
8558
8700
|
maxLines: state.maxLines,
|
|
8559
8701
|
overflow: state.textOverflow,
|
|
@@ -8881,23 +9023,32 @@ var EditableLayout = class {
|
|
|
8881
9023
|
placeholderLines;
|
|
8882
9024
|
measure;
|
|
8883
9025
|
rtl;
|
|
9026
|
+
/**
|
|
9027
|
+
* The text as drawn: the model's, or a secret field's mask of it
|
|
9028
|
+
* (see `maskText`). The geometry is the drawing's, so it is measured
|
|
9029
|
+
* from this; the two are the same length, so its offsets are the
|
|
9030
|
+
* model's.
|
|
9031
|
+
*/
|
|
9032
|
+
text;
|
|
8884
9033
|
constructor(model, box, state, measurer) {
|
|
8885
9034
|
this.model = model;
|
|
8886
9035
|
this.box = box;
|
|
8887
|
-
const
|
|
9036
|
+
const text = state.text ?? model.text;
|
|
9037
|
+
this.text = text;
|
|
9038
|
+
const request = textMeasureRequest(text, state, box);
|
|
8888
9039
|
request.maxLines = void 0;
|
|
8889
9040
|
request.overflow = "clip";
|
|
8890
9041
|
this.lines = placeLines(box, state, measurer.layout(request));
|
|
8891
9042
|
const spanned = spannedRunsFor(request, measurer);
|
|
8892
|
-
this.measure = (text, start) => text.length === 0 ? 0 : spanned === void 0 || start === void 0 ? measurer.measureRunWidth(text, request) : spanned.width(
|
|
9043
|
+
this.measure = (text, start) => text.length === 0 ? 0 : spanned === void 0 || start === void 0 ? measurer.measureRunWidth(text, request) : spanned.width(this.text, start, start + text.length);
|
|
8893
9044
|
this.rtl = state.rtl;
|
|
8894
|
-
this.placeholderLines =
|
|
9045
|
+
this.placeholderLines = text.length === 0 && state.placeholder !== void 0 && state.placeholder.length > 0 ? placeLines(box, state, measurer.layout({
|
|
8895
9046
|
...request,
|
|
8896
9047
|
text: state.placeholder
|
|
8897
9048
|
})) : [];
|
|
8898
9049
|
}
|
|
8899
9050
|
caretRect(offset = this.model.focus) {
|
|
8900
|
-
return caretRectFor(this.lines, this.
|
|
9051
|
+
return caretRectFor(this.lines, this.text, offset, this.measure, this.rtl);
|
|
8901
9052
|
}
|
|
8902
9053
|
/**
|
|
8903
9054
|
* The caret position nearest a point. Where hidden text sits at the
|
|
@@ -8908,10 +9059,10 @@ var EditableLayout = class {
|
|
|
8908
9059
|
* apart. Never inside hidden text.
|
|
8909
9060
|
*/
|
|
8910
9061
|
offsetAt(x, y) {
|
|
8911
|
-
return this.model.caretOffsetNear(offsetAtPoint(this.lines, this.
|
|
9062
|
+
return this.model.caretOffsetNear(offsetAtPoint(this.lines, this.text, x, y, this.measure, this.rtl));
|
|
8912
9063
|
}
|
|
8913
9064
|
verticalMove(offset, direction, goalX) {
|
|
8914
|
-
const move = offsetForVerticalMove(this.lines, this.
|
|
9065
|
+
const move = offsetForVerticalMove(this.lines, this.text, offset, direction, this.measure, this.rtl, goalX);
|
|
8915
9066
|
return move === null ? null : {
|
|
8916
9067
|
offset: this.model.caretOffsetNear(move.offset),
|
|
8917
9068
|
x: move.x
|
|
@@ -8924,13 +9075,13 @@ var EditableLayout = class {
|
|
|
8924
9075
|
selectionBoxes(range) {
|
|
8925
9076
|
const start = range?.start ?? this.model.start;
|
|
8926
9077
|
const end = range?.end ?? this.model.end;
|
|
8927
|
-
return selectionRects(this.lines, this.
|
|
9078
|
+
return selectionRects(this.lines, this.text, start, end, this.measure, this.rtl);
|
|
8928
9079
|
}
|
|
8929
9080
|
/** Boxes under the text the IME is composing, for its underline. */
|
|
8930
9081
|
compositionBoxes() {
|
|
8931
9082
|
const range = this.model.composition;
|
|
8932
9083
|
if (range === null) return [];
|
|
8933
|
-
return selectionRects(this.lines, this.
|
|
9084
|
+
return selectionRects(this.lines, this.text, range.start, range.end, this.measure, this.rtl);
|
|
8934
9085
|
}
|
|
8935
9086
|
};
|
|
8936
9087
|
//#endregion
|
|
@@ -10157,8 +10308,21 @@ var UiFocusManager = class {
|
|
|
10157
10308
|
* when that scope was pushed, when that node is still in the tree
|
|
10158
10309
|
* and still focusable. Otherwise focus is dropped rather than left
|
|
10159
10310
|
* on a node the scope was hiding.
|
|
10160
|
-
|
|
10161
|
-
|
|
10311
|
+
*
|
|
10312
|
+
* Given its root, only that scope ends: none, when it has gone already
|
|
10313
|
+
* (its subtree removed, which pops it), so a trap released after its
|
|
10314
|
+
* content was taken away cannot end the one under it, a submenu's
|
|
10315
|
+
* menu's; and one under another is taken out where it is.
|
|
10316
|
+
*/
|
|
10317
|
+
popScope(root) {
|
|
10318
|
+
if (root !== void 0 && this.scopes.at(-1)?.root !== root) {
|
|
10319
|
+
const at = this.scopes.findIndex((each) => each.root === root);
|
|
10320
|
+
if (at >= 0) {
|
|
10321
|
+
this.scopes.splice(at, 1);
|
|
10322
|
+
this.notifyScope();
|
|
10323
|
+
}
|
|
10324
|
+
return;
|
|
10325
|
+
}
|
|
10162
10326
|
const scope = this.scopes.pop();
|
|
10163
10327
|
if (scope === void 0) return;
|
|
10164
10328
|
const restore = scope.restore;
|
|
@@ -12099,9 +12263,13 @@ var UiEditingController = class {
|
|
|
12099
12263
|
if (command === null) return false;
|
|
12100
12264
|
return this.execute(node, command);
|
|
12101
12265
|
}
|
|
12102
|
-
execute(node,
|
|
12266
|
+
execute(node, keyed) {
|
|
12103
12267
|
const model = editorFor(node);
|
|
12104
12268
|
const readOnly = isReadOnly(node);
|
|
12269
|
+
const command = (keyed.kind === "move" || keyed.kind === "delete") && keyed.unit === "word" ? {
|
|
12270
|
+
...keyed,
|
|
12271
|
+
unit: secretWordUnit(node)
|
|
12272
|
+
} : keyed;
|
|
12105
12273
|
switch (command.kind) {
|
|
12106
12274
|
case "move":
|
|
12107
12275
|
if (this.span !== null && !command.extend) {
|
|
@@ -12272,7 +12440,8 @@ var UiEditingController = class {
|
|
|
12272
12440
|
case "deleteByCut":
|
|
12273
12441
|
case "deleteByDrag": {
|
|
12274
12442
|
if (readOnly) return true;
|
|
12275
|
-
|
|
12443
|
+
if (inputType === "deleteByCut" && isSecret(node)) return true;
|
|
12444
|
+
const unit = /Word/.test(inputType) ? secretWordUnit(node) : /Line/.test(inputType) ? "line" : "grapheme";
|
|
12276
12445
|
const forward = /Forward/.test(inputType);
|
|
12277
12446
|
return this.applyEdit(node, model, inputType, null, () => {
|
|
12278
12447
|
if (inputType === "deleteContent" || inputType === "deleteByCut" || inputType === "deleteByDrag") model.replaceRange(model.start, model.end, "");
|
|
@@ -12477,6 +12646,7 @@ var UiEditingController = class {
|
|
|
12477
12646
|
};
|
|
12478
12647
|
this.dragging = node;
|
|
12479
12648
|
if (modifiers.shift) model.moveTo(offset, true);
|
|
12649
|
+
else if (count === 2 && isSecret(node)) model.selectAll();
|
|
12480
12650
|
else if (count === 2) {
|
|
12481
12651
|
const word = visibleWordRange(model.text, model.hidden, offset);
|
|
12482
12652
|
model.select(word.start, word.end);
|
|
@@ -12542,6 +12712,16 @@ var UiEditingController = class {
|
|
|
12542
12712
|
...html === void 0 ? {} : { html }
|
|
12543
12713
|
};
|
|
12544
12714
|
}
|
|
12715
|
+
if (isSecret(node)) return {
|
|
12716
|
+
text: maskText(model.text),
|
|
12717
|
+
selectionStart: model.start,
|
|
12718
|
+
selectionEnd: model.end,
|
|
12719
|
+
caret,
|
|
12720
|
+
multiline: false,
|
|
12721
|
+
composing: model.composing,
|
|
12722
|
+
clipboard: "",
|
|
12723
|
+
secret: true
|
|
12724
|
+
};
|
|
12545
12725
|
const html = model.collapsed || model.composing ? void 0 : this.fieldHtml(node, model.start, model.end);
|
|
12546
12726
|
return {
|
|
12547
12727
|
text: model.text,
|
|
@@ -12812,10 +12992,11 @@ var UiEditingController = class {
|
|
|
12812
12992
|
const end = forward ? span.focus : span.anchor;
|
|
12813
12993
|
const key = [span];
|
|
12814
12994
|
for (const node of span.lit) key.push(editorFor(node).text);
|
|
12995
|
+
const textOf = (node) => isSecret(node) ? maskText(editorFor(node).text) : editorFor(node).text;
|
|
12815
12996
|
return this.cachedCopy(key, () => {
|
|
12816
12997
|
return {
|
|
12817
12998
|
text: span.group.copyText !== void 0 ? span.group.copyText(start, end) : span.lit.map((node) => {
|
|
12818
|
-
const text =
|
|
12999
|
+
const text = textOf(node);
|
|
12819
13000
|
return text.slice(node === start.node ? start.offset : 0, node === end.node ? end.offset : text.length);
|
|
12820
13001
|
}).join("\n"),
|
|
12821
13002
|
html: span.group.copyHtml?.(start, end) ?? void 0
|
|
@@ -12972,6 +13153,13 @@ var UiEditingController = class {
|
|
|
12972
13153
|
return new EditableLayout(state.editor, box, state, this.host.measurer);
|
|
12973
13154
|
}
|
|
12974
13155
|
};
|
|
13156
|
+
/**
|
|
13157
|
+
* The unit a word move or delete takes in a field: the whole text in a
|
|
13158
|
+
* secret one, whose word boundaries the caret stopping at would show.
|
|
13159
|
+
*/
|
|
13160
|
+
function secretWordUnit(node) {
|
|
13161
|
+
return isSecret(node) ? "document" : "word";
|
|
13162
|
+
}
|
|
12975
13163
|
function deleteInputType(unit, direction) {
|
|
12976
13164
|
const side = direction < 0 ? "Backward" : "Forward";
|
|
12977
13165
|
switch (unit) {
|
|
@@ -14142,6 +14330,23 @@ var LayoutRecord = class {
|
|
|
14142
14330
|
/** Constraints this record was last measured under. */
|
|
14143
14331
|
lastConstraints = NEVER_MEASURED;
|
|
14144
14332
|
/**
|
|
14333
|
+
* The paragraphs a text leaf was last measured as, one asked with a
|
|
14334
|
+
* width and one without; see `LayoutEngine.measureLeaf`. Flex asks
|
|
14335
|
+
* an item both questions every pass (its max-content basis, then its
|
|
14336
|
+
* final width), so one slot would be overwritten by the other every
|
|
14337
|
+
* time. Null until the node is measured as text that way.
|
|
14338
|
+
*
|
|
14339
|
+
* **Not reset.** These are the one thing a record carries from one
|
|
14340
|
+
* full pass into the next, on purpose: a full pass re-asks every
|
|
14341
|
+
* text leaf, and a memo that every pass cleared would answer
|
|
14342
|
+
* nothing a resize asks. They are safe to keep because they check
|
|
14343
|
+
* themselves — a memo is used only when every field of the request
|
|
14344
|
+
* it was laid out for matches and the measurer has not been
|
|
14345
|
+
* invalidated since — rather than trusting that nothing changed.
|
|
14346
|
+
*/
|
|
14347
|
+
textBounded = null;
|
|
14348
|
+
textUnbounded = null;
|
|
14349
|
+
/**
|
|
14145
14350
|
* The percentage base the current measurement resolved against, and
|
|
14146
14351
|
* whether the node has a length that resolves against one.
|
|
14147
14352
|
*
|
|
@@ -14257,6 +14462,20 @@ var LayoutRecord = class {
|
|
|
14257
14462
|
propsBaseWidth = void 0;
|
|
14258
14463
|
propsBaseHeight = void 0;
|
|
14259
14464
|
/**
|
|
14465
|
+
* The node's `propertyVersion` when its layout properties were last
|
|
14466
|
+
* resolved, and whether that resolution read the node and nothing
|
|
14467
|
+
* else (no inherited direction, no scroll leader). Together with the
|
|
14468
|
+
* percentage base they let a later pass, a full one included, keep
|
|
14469
|
+
* what the last one resolved instead of reading forty properties
|
|
14470
|
+
* again; see `LayoutEngine.resolveLayoutProps`.
|
|
14471
|
+
*
|
|
14472
|
+
* **Not reset,** with the fields they vouch for: `reset()` leaves
|
|
14473
|
+
* every field `resolveLayoutProps` writes as it was, because these
|
|
14474
|
+
* say whether it is still right.
|
|
14475
|
+
*/
|
|
14476
|
+
propsVersion = -1;
|
|
14477
|
+
propsFromNodeAlone = false;
|
|
14478
|
+
/**
|
|
14260
14479
|
* Returns the record to the state a freshly constructed one is in,
|
|
14261
14480
|
* so a full layout can reuse the object instead of replacing it.
|
|
14262
14481
|
*
|
|
@@ -14270,7 +14489,9 @@ var LayoutRecord = class {
|
|
|
14270
14489
|
* never reused across.
|
|
14271
14490
|
*
|
|
14272
14491
|
* **Every field above has to appear here, with the value it is
|
|
14273
|
-
* declared with
|
|
14492
|
+
* declared with,** but the two text memos and the resolved layout
|
|
14493
|
+
* properties, which check themselves and are kept across passes on
|
|
14494
|
+
* purpose. A field that is added and not reset would carry
|
|
14274
14495
|
* one pass's answer into the next, which is the kind of fault that
|
|
14275
14496
|
* shows as a stale box on a screen and as nothing at all in a test
|
|
14276
14497
|
* that lays out once. `LayoutRecord.spec.ts` compares a reset record
|
|
@@ -14285,28 +14506,6 @@ var LayoutRecord = class {
|
|
|
14285
14506
|
this.measuredHeight = 0;
|
|
14286
14507
|
this.outerWidth = 0;
|
|
14287
14508
|
this.outerHeight = 0;
|
|
14288
|
-
this.paddingLeft = 0;
|
|
14289
|
-
this.paddingRight = 0;
|
|
14290
|
-
this.paddingTop = 0;
|
|
14291
|
-
this.paddingBottom = 0;
|
|
14292
|
-
this.marginLeft = 0;
|
|
14293
|
-
this.marginRight = 0;
|
|
14294
|
-
this.marginTop = 0;
|
|
14295
|
-
this.marginBottom = 0;
|
|
14296
|
-
this.minWidth = 0;
|
|
14297
|
-
this.maxWidth = Infinity;
|
|
14298
|
-
this.minHeight = 0;
|
|
14299
|
-
this.maxHeight = Infinity;
|
|
14300
|
-
this.flexGrow = 0;
|
|
14301
|
-
this.flexShrink = 1;
|
|
14302
|
-
this.flexBasisZero = false;
|
|
14303
|
-
this.minWidthAuto = true;
|
|
14304
|
-
this.minHeightAuto = true;
|
|
14305
|
-
this.marginLeftAuto = false;
|
|
14306
|
-
this.marginRightAuto = false;
|
|
14307
|
-
this.marginTopAuto = false;
|
|
14308
|
-
this.marginBottomAuto = false;
|
|
14309
|
-
this.aspectRatio = void 0;
|
|
14310
14509
|
this.hasBaseline = false;
|
|
14311
14510
|
this.baseline = 0;
|
|
14312
14511
|
this.minContentWidth = 0;
|
|
@@ -14319,16 +14518,6 @@ var LayoutRecord = class {
|
|
|
14319
14518
|
this.flexMin = 0;
|
|
14320
14519
|
this.flexMax = Infinity;
|
|
14321
14520
|
this.flexMinAuto = false;
|
|
14322
|
-
this.positioned = false;
|
|
14323
|
-
this.absolute = false;
|
|
14324
|
-
this.top = void 0;
|
|
14325
|
-
this.right = void 0;
|
|
14326
|
-
this.bottom = void 0;
|
|
14327
|
-
this.left = void 0;
|
|
14328
|
-
this.zIndex = 0;
|
|
14329
|
-
this.lifted = false;
|
|
14330
|
-
this.liftBoundary = false;
|
|
14331
|
-
this.clips = false;
|
|
14332
14521
|
this.extentMinX = 0;
|
|
14333
14522
|
this.extentMinY = 0;
|
|
14334
14523
|
this.extentMaxX = 0;
|
|
@@ -14337,12 +14526,6 @@ var LayoutRecord = class {
|
|
|
14337
14526
|
this.paintReachTop = 0;
|
|
14338
14527
|
this.paintReachRight = 0;
|
|
14339
14528
|
this.paintReachBottom = 0;
|
|
14340
|
-
this.scrollable = false;
|
|
14341
|
-
this.scrollsText = false;
|
|
14342
|
-
this.hidesScrollbars = false;
|
|
14343
|
-
this.textScrollbars = false;
|
|
14344
|
-
this.mirrored = false;
|
|
14345
|
-
this.sticky = false;
|
|
14346
14529
|
this.stickyOffsetX = 0;
|
|
14347
14530
|
this.stickyOffsetY = 0;
|
|
14348
14531
|
this.scrollbarVisibleUntil = 0;
|
|
@@ -14361,8 +14544,6 @@ var LayoutRecord = class {
|
|
|
14361
14544
|
this.lastConstraints = NEVER_MEASURED;
|
|
14362
14545
|
this.lastBaseWidth = void 0;
|
|
14363
14546
|
this.lastBaseHeight = void 0;
|
|
14364
|
-
this.percentWidth = false;
|
|
14365
|
-
this.percentHeight = false;
|
|
14366
14547
|
this.alternates = null;
|
|
14367
14548
|
this.contentMatters = true;
|
|
14368
14549
|
this.relayoutBoundary = false;
|
|
@@ -14371,8 +14552,6 @@ var LayoutRecord = class {
|
|
|
14371
14552
|
this.placeDirty = true;
|
|
14372
14553
|
this.transformDirty = false;
|
|
14373
14554
|
this.propsPass = 0;
|
|
14374
|
-
this.propsBaseWidth = void 0;
|
|
14375
|
-
this.propsBaseHeight = void 0;
|
|
14376
14555
|
}
|
|
14377
14556
|
};
|
|
14378
14557
|
/** How many earlier measurements a record remembers besides the current one. */
|
|
@@ -15267,6 +15446,18 @@ var LayoutEngine = class {
|
|
|
15267
15446
|
*/
|
|
15268
15447
|
stickyShifted = /* @__PURE__ */ new Set();
|
|
15269
15448
|
textMeasurer;
|
|
15449
|
+
/** Where `measureLeaf` resolves a text node's font; read before anything else can resolve one. */
|
|
15450
|
+
fontScratch = {
|
|
15451
|
+
fontSize: 0,
|
|
15452
|
+
fontFamily: "",
|
|
15453
|
+
fontWeight: "normal",
|
|
15454
|
+
lineHeight: 0,
|
|
15455
|
+
letterSpacing: 0,
|
|
15456
|
+
fontStyle: "normal",
|
|
15457
|
+
fontStretch: "normal",
|
|
15458
|
+
fontVariant: "normal",
|
|
15459
|
+
fontKerning: "auto"
|
|
15460
|
+
};
|
|
15270
15461
|
/**
|
|
15271
15462
|
* The definite size percentages resolve against while a container's
|
|
15272
15463
|
* children are measured: its content box. Undefined on an axis whose
|
|
@@ -15308,6 +15499,14 @@ var LayoutEngine = class {
|
|
|
15308
15499
|
return this.records.get(node);
|
|
15309
15500
|
}
|
|
15310
15501
|
/**
|
|
15502
|
+
* Every `position: 'sticky'` node in the tree. A sticky node moves
|
|
15503
|
+
* with a scroll without its box moving, so a renderer keeping a
|
|
15504
|
+
* scroll container's pixels has to be told where they are.
|
|
15505
|
+
*/
|
|
15506
|
+
allStickyNodes() {
|
|
15507
|
+
return this.stickyNodes;
|
|
15508
|
+
}
|
|
15509
|
+
/**
|
|
15311
15510
|
* A box around everything in a node's subtree that could take a
|
|
15312
15511
|
* point, so a hit test can pass the subtree over instead of
|
|
15313
15512
|
* descending into it. Undefined for a node with no record, and
|
|
@@ -17105,37 +17304,79 @@ var LayoutEngine = class {
|
|
|
17105
17304
|
const paddingV = rec.paddingTop + rec.paddingBottom;
|
|
17106
17305
|
const editable = node.type === "editable-text";
|
|
17107
17306
|
if (node.type === "text" || node.type === "button" || editable) {
|
|
17108
|
-
const typed = editable ? editorFor(node)
|
|
17307
|
+
const typed = editable ? shownTextOf(node, editorFor(node)) : "";
|
|
17109
17308
|
const spans = editable ? editableSpansOf(node, typed, editorFor(node).composition) : resolvedSpansOf(node);
|
|
17110
17309
|
const text = editable ? typed : spans.length > 0 ? textContentOf(node) : String(node.properties.get("text") ?? "");
|
|
17111
17310
|
const placeholderProp = node.properties.get("placeholder");
|
|
17112
17311
|
const placeholder = editable && text.length === 0 && typeof placeholderProp === "string" ? placeholderProp : void 0;
|
|
17113
|
-
const font =
|
|
17312
|
+
const font = this.fontScratch;
|
|
17313
|
+
resolveFontInto(node, font);
|
|
17114
17314
|
const maxLines = editable ? void 0 : this.numberProp(node, "maxLines");
|
|
17115
|
-
const
|
|
17116
|
-
|
|
17117
|
-
|
|
17118
|
-
|
|
17119
|
-
|
|
17120
|
-
|
|
17121
|
-
|
|
17122
|
-
|
|
17123
|
-
|
|
17124
|
-
|
|
17125
|
-
|
|
17126
|
-
|
|
17127
|
-
|
|
17128
|
-
|
|
17129
|
-
|
|
17130
|
-
|
|
17131
|
-
|
|
17132
|
-
|
|
17315
|
+
const maxWidth = isFinite(effective.maxWidth) ? Math.max(0, effective.maxWidth - paddingH) : void 0;
|
|
17316
|
+
const exactWidth = isFinite(effective.maxWidth) && effective.minWidth === effective.maxWidth;
|
|
17317
|
+
const wrap = this.textWrapProp(node);
|
|
17318
|
+
const lines = maxLines !== void 0 && maxLines >= 1 ? Math.floor(maxLines) : void 0;
|
|
17319
|
+
const overflow = editable ? "clip" : this.textOverflowProp(node);
|
|
17320
|
+
const runs = spans.length > 0 ? spans : void 0;
|
|
17321
|
+
/**
|
|
17322
|
+
* The node's own last paragraph, when nothing it was laid out
|
|
17323
|
+
* from has changed.
|
|
17324
|
+
*
|
|
17325
|
+
* Flex asks a text leaf three or four questions a pass (its
|
|
17326
|
+
* basis, its min- and max-content sizes, its final size), and
|
|
17327
|
+
* each one went to the measurer as a new request, whose cache
|
|
17328
|
+
* key spells out every field and the whole text before it can
|
|
17329
|
+
* look anything up. That was a fifth of a full layout pass over
|
|
17330
|
+
* the benchmark list with every answer already cached. Compared
|
|
17331
|
+
* field by field here it is a handful of identity checks, and a
|
|
17332
|
+
* paragraph that fits at the width it was laid out at also
|
|
17333
|
+
* answers any wider question, which is most of the questions a
|
|
17334
|
+
* row of labels is asked.
|
|
17335
|
+
*/
|
|
17336
|
+
const generation = this.textMeasurer.generation;
|
|
17337
|
+
const memo = maxWidth === void 0 ? rec.textUnbounded : rec.textBounded;
|
|
17338
|
+
const last = memo?.request;
|
|
17339
|
+
let paragraph;
|
|
17340
|
+
let asked;
|
|
17341
|
+
if (memo !== null && last !== void 0 && generation !== void 0 && memo.generation === generation && last.text === text && last.fontSize === font.fontSize && last.fontFamily === font.fontFamily && last.fontWeight === font.fontWeight && last.lineHeight === font.lineHeight && last.letterSpacing === font.letterSpacing && last.fontStyle === font.fontStyle && last.fontStretch === font.fontStretch && last.fontVariant === font.fontVariant && last.fontKerning === font.fontKerning && last.wrap === wrap && last.maxLines === lines && last.overflow === overflow && last.spans === runs && (last.maxWidth === maxWidth && last.exactWidth === exactWidth || memo.fitsAnyWidth && fitsWidth(memo.paragraph, maxWidth))) {
|
|
17342
|
+
paragraph = memo.paragraph;
|
|
17343
|
+
asked = last;
|
|
17344
|
+
} else {
|
|
17345
|
+
const request = {
|
|
17346
|
+
text,
|
|
17347
|
+
fontSize: font.fontSize,
|
|
17348
|
+
fontFamily: font.fontFamily,
|
|
17349
|
+
fontWeight: font.fontWeight,
|
|
17350
|
+
lineHeight: font.lineHeight,
|
|
17351
|
+
letterSpacing: font.letterSpacing,
|
|
17352
|
+
fontStyle: font.fontStyle,
|
|
17353
|
+
fontStretch: font.fontStretch,
|
|
17354
|
+
fontVariant: font.fontVariant,
|
|
17355
|
+
fontKerning: font.fontKerning,
|
|
17356
|
+
maxWidth,
|
|
17357
|
+
exactWidth,
|
|
17358
|
+
wrap,
|
|
17359
|
+
maxLines: lines,
|
|
17360
|
+
overflow,
|
|
17361
|
+
spans: runs
|
|
17362
|
+
};
|
|
17363
|
+
paragraph = this.textMeasurer.layout(request);
|
|
17364
|
+
asked = request;
|
|
17365
|
+
const fresh = {
|
|
17366
|
+
request,
|
|
17367
|
+
paragraph,
|
|
17368
|
+
generation: generation ?? -1,
|
|
17369
|
+
fitsAnyWidth: layoutFitsAnyWidth(request, paragraph)
|
|
17370
|
+
};
|
|
17371
|
+
if (maxWidth === void 0) rec.textUnbounded = fresh;
|
|
17372
|
+
else rec.textBounded = fresh;
|
|
17373
|
+
}
|
|
17133
17374
|
let width = paragraph.width;
|
|
17134
17375
|
let minContentWidth = paragraph.minContentWidth;
|
|
17135
17376
|
let maxContentWidth = paragraph.maxContentWidth;
|
|
17136
17377
|
if (placeholder !== void 0 && placeholder.length > 0) {
|
|
17137
17378
|
const hint = this.textMeasurer.layout({
|
|
17138
|
-
...
|
|
17379
|
+
...asked,
|
|
17139
17380
|
text: placeholder
|
|
17140
17381
|
});
|
|
17141
17382
|
width = Math.max(width, hint.width);
|
|
@@ -18318,7 +18559,28 @@ var LayoutEngine = class {
|
|
|
18318
18559
|
const props = node.properties;
|
|
18319
18560
|
const base = this.percentBase;
|
|
18320
18561
|
if (rec.propsPass === this.layoutPass && rec.propsBaseWidth === base.width && rec.propsBaseHeight === base.height) return;
|
|
18562
|
+
/**
|
|
18563
|
+
* What an earlier pass resolved, when none of what it read has
|
|
18564
|
+
* changed: the node's own properties (`propertyVersion`), and the
|
|
18565
|
+
* percentage base only on an axis that has a percentage.
|
|
18566
|
+
*
|
|
18567
|
+
* Each pass used to read every property below again for every node
|
|
18568
|
+
* it reached, and a full pass reaches all of them: a sixth of a full
|
|
18569
|
+
* pass over the benchmark list, where nothing had changed since the
|
|
18570
|
+
* last. A node whose resolution read anything inherited (a logical
|
|
18571
|
+
* edge or a scroll container's direction) or another node (a scroll
|
|
18572
|
+
* leader) is resolved again every pass, as it always was; they are
|
|
18573
|
+
* few. The record keeps these fields across `reset()` for this.
|
|
18574
|
+
*/
|
|
18575
|
+
if (rec.propsFromNodeAlone && rec.propsVersion === node.propertyVersion && (!rec.percentWidth || rec.propsBaseWidth === base.width) && (!rec.percentHeight || rec.propsBaseHeight === base.height)) {
|
|
18576
|
+
rec.propsPass = this.layoutPass;
|
|
18577
|
+
rec.propsBaseWidth = base.width;
|
|
18578
|
+
rec.propsBaseHeight = base.height;
|
|
18579
|
+
if (rec.lifted) this.liftedNodes.add(node);
|
|
18580
|
+
return;
|
|
18581
|
+
}
|
|
18321
18582
|
rec.propsPass = this.layoutPass;
|
|
18583
|
+
rec.propsVersion = node.propertyVersion;
|
|
18322
18584
|
rec.propsBaseWidth = base.width;
|
|
18323
18585
|
rec.propsBaseHeight = base.height;
|
|
18324
18586
|
rec.percentWidth = hasPercentLength(props, WIDTH_RELATIVE);
|
|
@@ -18371,9 +18633,11 @@ var LayoutEngine = class {
|
|
|
18371
18633
|
rec.left = this.lengthProp(node, "left", base.width) ?? insetH;
|
|
18372
18634
|
rec.zIndex = this.numberProp(node, "zIndex") ?? 0;
|
|
18373
18635
|
this.setLifted(node, rec, node.properties.get("lift") === true);
|
|
18636
|
+
if (rec.lifted) this.liftedNodes.add(node);
|
|
18374
18637
|
rec.liftBoundary = node.properties.get("liftBoundary") === true;
|
|
18375
18638
|
const ratio = this.numberProp(node, "aspectRatio");
|
|
18376
18639
|
rec.aspectRatio = ratio !== void 0 && ratio > 0 ? ratio : void 0;
|
|
18640
|
+
rec.propsFromNodeAlone = !hasLogicalSpacing(props) && !rec.scrollable && !rec.textScrollbars && overflow !== "hidden";
|
|
18377
18641
|
}
|
|
18378
18642
|
/**
|
|
18379
18643
|
* Sizes with a fixed width:height ratio (CSS `aspect-ratio`). The
|
|
@@ -20645,7 +20909,8 @@ var ScrollLayerCache = class {
|
|
|
20645
20909
|
scrollX: snapScroll(rec.scrollX, this.dpr),
|
|
20646
20910
|
scrollY: snapScroll(rec.scrollY, this.dpr),
|
|
20647
20911
|
used: true,
|
|
20648
|
-
items: /* @__PURE__ */ new Map()
|
|
20912
|
+
items: /* @__PURE__ */ new Map(),
|
|
20913
|
+
stuck: /* @__PURE__ */ new Map()
|
|
20649
20914
|
};
|
|
20650
20915
|
this.layers.set(node, layer);
|
|
20651
20916
|
this.stats.built++;
|
|
@@ -20745,6 +21010,14 @@ var ScrollLayerCache = class {
|
|
|
20745
21010
|
else if (!sameBox(was, now)) boxes.push(was, now);
|
|
20746
21011
|
}
|
|
20747
21012
|
for (const [item, was] of layer.items) if (!seen.has(item)) boxes.push(was);
|
|
21013
|
+
const stuck = stuckIn(container, layout);
|
|
21014
|
+
if (stuck === null) return "all";
|
|
21015
|
+
for (const [node, now] of stuck) {
|
|
21016
|
+
const was = layer.stuck.get(node);
|
|
21017
|
+
if (was === void 0) boxes.push(now);
|
|
21018
|
+
else if (!sameBox(was, now)) boxes.push(was, now);
|
|
21019
|
+
}
|
|
21020
|
+
for (const [node, was] of layer.stuck) if (!stuck.has(node)) boxes.push(was);
|
|
20748
21021
|
const rects = [];
|
|
20749
21022
|
let area = 0;
|
|
20750
21023
|
for (const box of boxes) {
|
|
@@ -20763,6 +21036,7 @@ var ScrollLayerCache = class {
|
|
|
20763
21036
|
const box = boxOf(layout, item);
|
|
20764
21037
|
if (box !== void 0) layer.items.set(item, box);
|
|
20765
21038
|
}
|
|
21039
|
+
layer.stuck = stuckIn(container, layout) ?? /* @__PURE__ */ new Map();
|
|
20766
21040
|
}
|
|
20767
21041
|
/** An item's box in the layer's pixels, widened for what paints past it, or null off the layer. */
|
|
20768
21042
|
toLayer(layer, box) {
|
|
@@ -20843,6 +21117,42 @@ function itemHolding(container, node) {
|
|
|
20843
21117
|
}
|
|
20844
21118
|
return null;
|
|
20845
21119
|
}
|
|
21120
|
+
/**
|
|
21121
|
+
* Where each sticky node inside a container is drawn, in the
|
|
21122
|
+
* container's children's coordinates: its box moved by its own shift
|
|
21123
|
+
* and by every sticky ancestor's up to the container. Null when the
|
|
21124
|
+
* reader cannot say which nodes are sticky, which no layer can survive.
|
|
21125
|
+
*/
|
|
21126
|
+
function stuckIn(container, layout) {
|
|
21127
|
+
const sticky = layout.allStickyNodes?.();
|
|
21128
|
+
if (sticky === void 0) return null;
|
|
21129
|
+
const drawn = /* @__PURE__ */ new Map();
|
|
21130
|
+
for (const node of sticky) {
|
|
21131
|
+
const rec = layout.recordFor(node);
|
|
21132
|
+
if (rec === void 0) continue;
|
|
21133
|
+
let x = rec.x + rec.stickyOffsetX;
|
|
21134
|
+
let y = rec.y + rec.stickyOffsetY;
|
|
21135
|
+
let inside = false;
|
|
21136
|
+
for (let current = node.parent; current !== null; current = current.parent) {
|
|
21137
|
+
if (current === container) {
|
|
21138
|
+
inside = true;
|
|
21139
|
+
break;
|
|
21140
|
+
}
|
|
21141
|
+
const above = layout.recordFor(current);
|
|
21142
|
+
if (above !== void 0) {
|
|
21143
|
+
x += above.stickyOffsetX;
|
|
21144
|
+
y += above.stickyOffsetY;
|
|
21145
|
+
}
|
|
21146
|
+
}
|
|
21147
|
+
if (inside) drawn.set(node, {
|
|
21148
|
+
x,
|
|
21149
|
+
y,
|
|
21150
|
+
width: rec.width,
|
|
21151
|
+
height: rec.height
|
|
21152
|
+
});
|
|
21153
|
+
}
|
|
21154
|
+
return drawn;
|
|
21155
|
+
}
|
|
20846
21156
|
function sameBox(a, b) {
|
|
20847
21157
|
return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
|
|
20848
21158
|
}
|
|
@@ -22077,6 +22387,6 @@ function createCanvasSurface(host) {
|
|
|
22077
22387
|
return new CanvasSurface(host);
|
|
22078
22388
|
}
|
|
22079
22389
|
//#endregion
|
|
22080
|
-
export { isImeKey as $,
|
|
22390
|
+
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 };
|
|
22081
22391
|
|
|
22082
|
-
//# sourceMappingURL=CanvasSurface-
|
|
22392
|
+
//# sourceMappingURL=CanvasSurface-BxHC-NQ8.js.map
|