@react-x11/components 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/code-editor/node.d.ts +13 -0
- package/dist/code-editor/node.d.ts.map +1 -1
- package/dist/code-editor/node.js +23 -5
- package/dist/code-editor/node.js.map +1 -1
- package/dist/html/css/cascade.d.ts +209 -23
- package/dist/html/css/cascade.d.ts.map +1 -1
- package/dist/html/css/cascade.js +873 -175
- package/dist/html/css/cascade.js.map +1 -1
- package/dist/html/css/color.d.ts +25 -0
- package/dist/html/css/color.d.ts.map +1 -1
- package/dist/html/css/color.js +307 -19
- package/dist/html/css/color.js.map +1 -1
- package/dist/html/css/content.d.ts +11 -6
- package/dist/html/css/content.d.ts.map +1 -1
- package/dist/html/css/content.js +171 -12
- package/dist/html/css/content.js.map +1 -1
- package/dist/html/css/parse.d.ts.map +1 -1
- package/dist/html/css/parse.js +62 -9
- package/dist/html/css/parse.js.map +1 -1
- package/dist/html/css/shapes.d.ts +62 -0
- package/dist/html/css/shapes.d.ts.map +1 -0
- package/dist/html/css/shapes.js +214 -0
- package/dist/html/css/shapes.js.map +1 -0
- package/dist/html/css/style.d.ts +42 -5
- package/dist/html/css/style.d.ts.map +1 -1
- package/dist/html/css/style.js +75 -27
- package/dist/html/css/style.js.map +1 -1
- package/dist/html/css/ua.js +15 -0
- package/dist/html/css/ua.js.map +1 -1
- package/dist/html/css/values.d.ts +5 -0
- package/dist/html/css/values.d.ts.map +1 -1
- package/dist/html/css/values.js +18 -9
- package/dist/html/css/values.js.map +1 -1
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +7 -0
- package/dist/html/index.js.map +1 -1
- package/dist/html/layout/block.d.ts +38 -7
- package/dist/html/layout/block.d.ts.map +1 -1
- package/dist/html/layout/block.js +160 -50
- package/dist/html/layout/block.js.map +1 -1
- package/dist/html/layout/boxes.d.ts +29 -2
- package/dist/html/layout/boxes.d.ts.map +1 -1
- package/dist/html/layout/boxes.js +159 -20
- package/dist/html/layout/boxes.js.map +1 -1
- package/dist/html/layout/css-grid.d.ts.map +1 -1
- package/dist/html/layout/css-grid.js +69 -19
- package/dist/html/layout/css-grid.js.map +1 -1
- package/dist/html/layout/flex.d.ts.map +1 -1
- package/dist/html/layout/flex.js +1648 -225
- package/dist/html/layout/flex.js.map +1 -1
- package/dist/html/layout/inline.d.ts +15 -3
- package/dist/html/layout/inline.d.ts.map +1 -1
- package/dist/html/layout/inline.js +23 -8
- package/dist/html/layout/inline.js.map +1 -1
- package/dist/html/layout/table.d.ts +27 -1
- package/dist/html/layout/table.d.ts.map +1 -1
- package/dist/html/layout/table.js +907 -323
- package/dist/html/layout/table.js.map +1 -1
- package/dist/html/node.d.ts +36 -4
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +174 -37
- package/dist/html/node.js.map +1 -1
- package/dist/html/paint.d.ts +4 -1
- package/dist/html/paint.d.ts.map +1 -1
- package/dist/html/paint.js +769 -204
- package/dist/html/paint.js.map +1 -1
- package/dist/html/resources.js +14 -1
- package/dist/html/resources.js.map +1 -1
- package/dist/html/svg.d.ts +50 -17
- package/dist/html/svg.d.ts.map +1 -1
- package/dist/html/svg.js +501 -83
- package/dist/html/svg.js.map +1 -1
- package/dist/html/widgets.d.ts.map +1 -1
- package/dist/html/widgets.js +57 -4
- package/dist/html/widgets.js.map +1 -1
- package/package.json +3 -3
- package/src/code-editor/node.ts +24 -5
- package/src/html/css/cascade.ts +987 -176
- package/src/html/css/color.ts +345 -18
- package/src/html/css/content.ts +173 -15
- package/src/html/css/parse.ts +60 -8
- package/src/html/css/shapes.ts +273 -0
- package/src/html/css/style.ts +123 -30
- package/src/html/css/ua.ts +15 -0
- package/src/html/css/values.ts +23 -9
- package/src/html/index.ts +7 -0
- package/src/html/layout/block.ts +169 -56
- package/src/html/layout/boxes.ts +198 -24
- package/src/html/layout/css-grid.ts +89 -22
- package/src/html/layout/flex.ts +1863 -219
- package/src/html/layout/inline.ts +27 -7
- package/src/html/layout/table.ts +989 -333
- package/src/html/node.ts +204 -37
- package/src/html/paint.ts +999 -252
- package/src/html/resources.ts +13 -1
- package/src/html/svg.ts +600 -78
- package/src/html/widgets.ts +61 -4
package/dist/html/node.js
CHANGED
|
@@ -40,10 +40,10 @@ import { registerElement, registeredElements } from 'react-x11/host';
|
|
|
40
40
|
import { Node } from 'react-x11/node';
|
|
41
41
|
import { codePointAtOffset, codeUnitOffsets } from '../internal/text.js';
|
|
42
42
|
import { attr, HtmlSource, imageUrlOf, isElement, tagOf } from './dom.js';
|
|
43
|
-
import { Cascade, HOVER_FOLLOWED, HOVER_PSEUDO_NONE, HOVER_PSEUDO_OTHER, HOVER_UNTOUCHED, } from './css/cascade.js';
|
|
43
|
+
import { Cascade, HOVER_FOLLOWED, HOVER_PSEUDO_NONE, HOVER_PSEUDO_OTHER, HOVER_UNTOUCHED, NO_FOCUS, } from './css/cascade.js';
|
|
44
44
|
import { mediaMatches, parseStylesheet } from './css/parse.js';
|
|
45
45
|
import { uaStylesheet } from './css/ua.js';
|
|
46
|
-
import { BOX_RAISES, buildBoxes, CONTENT_IMAGES, CLEARED_FROM, COLUMN_LINES, COLUMN_PIECES, COLUMN_ROWS, CUT_BLOCKS, GENERATED_FROM, INLINE_OFFSETS, LINE_BOX_RAISES, SHIFTED_LINES, TEXT_SHIFTS, columned, } from './layout/boxes.js';
|
|
46
|
+
import { BOX_RAISES, buildBoxes, CONTENT_IMAGES, CLEARED_FROM, COLUMN_LINES, COLUMN_PIECES, COLUMN_ROWS, CUT_BLOCKS, GENERATED_FROM, INLINE_OFFSETS, LINE_BOX_RAISES, SHAPE_STYLES, SHIFTED_LINES, TEXT_SHIFTS, columned, } from './layout/boxes.js';
|
|
47
47
|
import { layoutDocument, placedMatrix, retranslate } from './layout/block.js';
|
|
48
48
|
import { invert, mapPoint, mapRect, transformed } from './css/transform.js';
|
|
49
49
|
import { TextLayoutCache } from './layout/cache.js';
|
|
@@ -56,7 +56,7 @@ import { faceExtentOf, inlineDecoration, runFor } from './layout/inline.js';
|
|
|
56
56
|
import { documentOffsetOf, layoutOffsetOf, layoutOffsets as layoutOffsetsOf, } from './layout/inline.js';
|
|
57
57
|
import { lineBands as bandsFor } from '../richtext/runs.js';
|
|
58
58
|
import { clipsOverflow, computePaintBounds, containingBlockOf, FIXED_BOXES, fixedToViewport, forgetDecoratedAncestors, hasRect, hoistNegative, holds, holdsAbsolute, inClip, inClipPath, onLine, ownBounds, paintDocument, pathClips, queryChildIndex, selectionRows, stackLayers, stacksLayers, } from './paint.js';
|
|
59
|
-
import { controlRectsOf, measureControl } from './controls.js';
|
|
59
|
+
import { controlRectsOf, measureControl, styledField } from './controls.js';
|
|
60
60
|
import { ResourceStore } from './resources.js';
|
|
61
61
|
import { WebFonts } from './fonts.js';
|
|
62
62
|
import { resolveUrl, UrlResolver } from './url.js';
|
|
@@ -156,6 +156,8 @@ export class HtmlViewNode extends Node {
|
|
|
156
156
|
* the text carries surrogate pairs. null until checked. */
|
|
157
157
|
_pointsAreUnits = null;
|
|
158
158
|
_hovered = [];
|
|
159
|
+
/** Which element's widget holds the focus (`setFocus`). */
|
|
160
|
+
_focus = NO_FOCUS;
|
|
159
161
|
/** Where the pointer last moved to, in logical window pixels, while it
|
|
160
162
|
* is over the element (`defaultMouseMove`). */
|
|
161
163
|
_pointerAt = null;
|
|
@@ -249,6 +251,12 @@ export class HtmlViewNode extends Node {
|
|
|
249
251
|
controlBorder: look.controlBorder * s,
|
|
250
252
|
controlRadius: look.controlRadius * s,
|
|
251
253
|
controlFontSize: (look.controlFontSize ?? look.fontSize) * s,
|
|
254
|
+
...(look.focusRingWidth !== undefined && {
|
|
255
|
+
focusRingWidth: look.focusRingWidth * s,
|
|
256
|
+
}),
|
|
257
|
+
...(look.focusRingOffset !== undefined && {
|
|
258
|
+
focusRingOffset: look.focusRingOffset * s,
|
|
259
|
+
}),
|
|
252
260
|
};
|
|
253
261
|
this._deviceLookFor = look;
|
|
254
262
|
this._deviceLookAt = s;
|
|
@@ -538,6 +546,7 @@ export class HtmlViewNode extends Node {
|
|
|
538
546
|
hovered: new Set(this._hovered),
|
|
539
547
|
active: EMPTY_SET,
|
|
540
548
|
});
|
|
549
|
+
this._cascade.setFocus(this._focus);
|
|
541
550
|
this._mediaBand = this._cascade.mediaBand(width);
|
|
542
551
|
}
|
|
543
552
|
/**
|
|
@@ -828,6 +837,10 @@ export class HtmlViewNode extends Node {
|
|
|
828
837
|
scale: this._scale,
|
|
829
838
|
imageSize: (el) => this._resources.imageSize(imageUrlOf(el) ?? ''),
|
|
830
839
|
urlSize: (url) => this._resources.imageSize(url),
|
|
840
|
+
faceAscent: (style) => {
|
|
841
|
+
const fonts = this._fonts();
|
|
842
|
+
return fonts ? faceExtentOf(fonts, style).ascent : undefined;
|
|
843
|
+
},
|
|
831
844
|
controlSize: (el, kind, style) => measureControl(el, kind, style, this._fonts(), look),
|
|
832
845
|
});
|
|
833
846
|
this._tree = build();
|
|
@@ -1309,37 +1322,97 @@ export class HtmlViewNode extends Node {
|
|
|
1309
1322
|
* with the styles of every element the move did not reach kept.
|
|
1310
1323
|
*/
|
|
1311
1324
|
_restyleHover(was, now) {
|
|
1325
|
+
const cascade = this._cascade;
|
|
1312
1326
|
const reach = this._hoverReach(was, now);
|
|
1313
|
-
if (reach !== null) {
|
|
1327
|
+
if (reach !== null && cascade) {
|
|
1314
1328
|
if (!reach.size)
|
|
1315
1329
|
return;
|
|
1316
|
-
|
|
1330
|
+
const before = { hovered: new Set(was), active: EMPTY_SET };
|
|
1331
|
+
if (this._hoverInPlace(reach, before, this._focus, cascade.hoverPseudo)) {
|
|
1317
1332
|
return;
|
|
1333
|
+
}
|
|
1318
1334
|
}
|
|
1319
1335
|
this._invalidate(Stale.Boxes, reach);
|
|
1320
1336
|
}
|
|
1337
|
+
/** The element whose widget holds the focus, or null (`setFocus`). */
|
|
1338
|
+
get focusedElement() {
|
|
1339
|
+
return this._focus.element;
|
|
1340
|
+
}
|
|
1341
|
+
/**
|
|
1342
|
+
* The focus moved: `element`'s widget took it, or, given null, no widget
|
|
1343
|
+
* of this document holds it now — it went to something else in the
|
|
1344
|
+
* window, or nowhere. `visible` is whether it shows, `:focus-visible`,
|
|
1345
|
+
* which it always does in a text field. Restyles what `:focus` and its
|
|
1346
|
+
* kin reach as a hover does (`_restyleHover`), and returns whether the
|
|
1347
|
+
* cascade's answer could have changed.
|
|
1348
|
+
*
|
|
1349
|
+
* No element of a document takes the focus: a control's widget, mounted
|
|
1350
|
+
* beside it, does, and says so here. Only a text field's does, so far —
|
|
1351
|
+
* the widgets core draws as components keep their own focus to
|
|
1352
|
+
* themselves.
|
|
1353
|
+
*/
|
|
1354
|
+
setFocus(element, visible = true) {
|
|
1355
|
+
const was = this._focus;
|
|
1356
|
+
if (was.element === element && (!element || was.visible === visible)) {
|
|
1357
|
+
return false;
|
|
1358
|
+
}
|
|
1359
|
+
const within = new Set();
|
|
1360
|
+
for (let at = element; at; at = isElement(at.parent) ? at.parent : null) {
|
|
1361
|
+
within.add(at);
|
|
1362
|
+
}
|
|
1363
|
+
const now = element ? { element, visible, within } : NO_FOCUS;
|
|
1364
|
+
this._focus = now;
|
|
1365
|
+
const cascade = this._cascade;
|
|
1366
|
+
cascade?.setFocus(now);
|
|
1367
|
+
if (!cascade || !cascade.focusSensitive)
|
|
1368
|
+
return false;
|
|
1369
|
+
const reach = cascade.focusLocal
|
|
1370
|
+
? this._stateReach([...was.within], [...now.within],
|
|
1371
|
+
// one element, whose ring came or went
|
|
1372
|
+
was.element === element ? element : null, (el) => cascade.focusTouches(el), (el, into) => cascade.focusAnchors(el, into))
|
|
1373
|
+
: null;
|
|
1374
|
+
if (reach !== null) {
|
|
1375
|
+
if (!reach.size)
|
|
1376
|
+
return true;
|
|
1377
|
+
const pointer = { hovered: new Set(this._hovered), active: EMPTY_SET };
|
|
1378
|
+
if (this._hoverInPlace(reach, pointer, was, cascade.focusPseudo)) {
|
|
1379
|
+
return true;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
this._invalidate(Stale.Boxes, reach);
|
|
1383
|
+
return true;
|
|
1384
|
+
}
|
|
1321
1385
|
/**
|
|
1322
1386
|
* The elements whose styles a move of the hovered chain can change, or
|
|
1323
1387
|
* null where that cannot be said (`Cascade.hoverLocal`).
|
|
1388
|
+
*/
|
|
1389
|
+
_hoverReach(was, now) {
|
|
1390
|
+
const cascade = this._cascade;
|
|
1391
|
+
if (!cascade || !cascade.hoverLocal)
|
|
1392
|
+
return null;
|
|
1393
|
+
return this._stateReach(was, now, null, (el) => cascade.hoverTouches(el), (el, into) => cascade.hoverAnchors(el, into));
|
|
1394
|
+
}
|
|
1395
|
+
/**
|
|
1396
|
+
* The elements whose styles a move of the hovered chain can change, or
|
|
1397
|
+
* of the focus's chain.
|
|
1324
1398
|
*
|
|
1325
1399
|
* Only an element whose hover state flipped and that a compound testing
|
|
1326
1400
|
* the pointer could match can change (`Cascade.hoverTouches`), with its
|
|
1327
1401
|
* subtree, and its later siblings' where a sibling combinator is in play;
|
|
1328
1402
|
* and the elements a `:has()` testing the pointer may flip, which are
|
|
1329
1403
|
* around the ones that changed. A move between two paragraphs under
|
|
1330
|
-
* `a:hover` reaches nothing.
|
|
1404
|
+
* `a:hover` reaches nothing. The focus's the same way, its chain the
|
|
1405
|
+
* focused element and every element around it, and `also` one whose
|
|
1406
|
+
* state flipped though it is in both — the ring coming or going.
|
|
1331
1407
|
*/
|
|
1332
|
-
|
|
1333
|
-
const cascade = this._cascade;
|
|
1334
|
-
if (!cascade || !cascade.hoverLocal)
|
|
1335
|
-
return null;
|
|
1408
|
+
_stateReach(was, now, also, touches, anchors) {
|
|
1336
1409
|
const before = new Set(was);
|
|
1337
1410
|
const after = new Set(now);
|
|
1338
1411
|
const roots = new Map();
|
|
1339
1412
|
const flipped = (el, other) => {
|
|
1340
|
-
if (other
|
|
1413
|
+
if (other?.has(el))
|
|
1341
1414
|
return;
|
|
1342
|
-
const touch =
|
|
1415
|
+
const touch = touches(el);
|
|
1343
1416
|
if (touch > (roots.get(el) ?? HOVER_UNTOUCHED))
|
|
1344
1417
|
roots.set(el, touch);
|
|
1345
1418
|
};
|
|
@@ -1352,10 +1425,14 @@ export class HtmlViewNode extends Node {
|
|
|
1352
1425
|
const deepest = (chain, other) => {
|
|
1353
1426
|
const el = chain[0];
|
|
1354
1427
|
if (el && !other.has(el))
|
|
1355
|
-
|
|
1428
|
+
anchors(el, roots);
|
|
1356
1429
|
};
|
|
1357
1430
|
deepest(was, after);
|
|
1358
1431
|
deepest(now, before);
|
|
1432
|
+
if (also) {
|
|
1433
|
+
flipped(also, null);
|
|
1434
|
+
anchors(also, roots);
|
|
1435
|
+
}
|
|
1359
1436
|
// the roots' subtrees, which inherit from them and a descendant
|
|
1360
1437
|
// combinator reaches, and their later siblings' too where a sibling
|
|
1361
1438
|
// combinator follows the compound that tests the pointer
|
|
@@ -1402,8 +1479,10 @@ export class HtmlViewNode extends Node {
|
|
|
1402
1479
|
* - The boxes take their new styles: an element's own, the text in it,
|
|
1403
1480
|
* the anonymous boxes the fix-up made around what is in it, and its
|
|
1404
1481
|
* `::before` and `::after`, styled again by their own rules. A box
|
|
1405
|
-
* whose style is derived some other way — a marker, a first letter
|
|
1406
|
-
*
|
|
1482
|
+
* whose style is derived some other way — a marker, a first letter —
|
|
1483
|
+
* is not one to restyle here. A control's is, and its widget is told
|
|
1484
|
+
* (`_reportControls`), unless the page took to drawing the field or
|
|
1485
|
+
* stopped.
|
|
1407
1486
|
* - Each layout of their text is made again from the runs it was made
|
|
1408
1487
|
* from (`TextLayoutCache.inputsOf`) with the new ink (`runFor`), where
|
|
1409
1488
|
* its geometry comes out the same.
|
|
@@ -1413,8 +1492,12 @@ export class HtmlViewNode extends Node {
|
|
|
1413
1492
|
* costs what it changed, in a document of any length. True where it was
|
|
1414
1493
|
* restyled here, or had nothing to restyle; false where the boxes have to
|
|
1415
1494
|
* be built again.
|
|
1495
|
+
*
|
|
1496
|
+
* A focus change is answered the same way (`setFocus`): `before` and
|
|
1497
|
+
* `beforeFocus` are the states the change was from, and `pseudoRules`
|
|
1498
|
+
* which pseudo-elements' rules test the state that changed.
|
|
1416
1499
|
*/
|
|
1417
|
-
_hoverInPlace(reach,
|
|
1500
|
+
_hoverInPlace(reach, before, beforeFocus, pseudoRules) {
|
|
1418
1501
|
const cascade = this._cascade;
|
|
1419
1502
|
const tree = this._tree;
|
|
1420
1503
|
const layouts = this._layouts;
|
|
@@ -1425,17 +1508,15 @@ export class HtmlViewNode extends Node {
|
|
|
1425
1508
|
if (reach.size > HOVER_RESTYLE_LIMIT)
|
|
1426
1509
|
return false;
|
|
1427
1510
|
// a first line's, a first letter's and a marker's styles are layout's
|
|
1428
|
-
const pseudoRules = cascade.hoverPseudo;
|
|
1429
1511
|
if (pseudoRules === HOVER_PSEUDO_OTHER)
|
|
1430
1512
|
return false;
|
|
1431
|
-
// whether the rules that test the pointer
|
|
1432
|
-
// element than they did before the
|
|
1433
|
-
const before = { hovered: new Set(was), active: EMPTY_SET };
|
|
1513
|
+
// whether the rules that test the pointer or the focus answer
|
|
1514
|
+
// differently for an element than they did before the change
|
|
1434
1515
|
const flips = new Map();
|
|
1435
1516
|
const flipped = (el) => {
|
|
1436
1517
|
let flip = flips.get(el);
|
|
1437
1518
|
if (flip === undefined) {
|
|
1438
|
-
flip = cascade.pointerChanged(el, before);
|
|
1519
|
+
flip = cascade.pointerChanged(el, before, beforeFocus);
|
|
1439
1520
|
flips.set(el, flip);
|
|
1440
1521
|
}
|
|
1441
1522
|
return flip;
|
|
@@ -1452,6 +1533,8 @@ export class HtmlViewNode extends Node {
|
|
|
1452
1533
|
let reaches = false;
|
|
1453
1534
|
let reorders = false;
|
|
1454
1535
|
const moving = new Set();
|
|
1536
|
+
/** Whether a control's box was restyled: its widget is told. */
|
|
1537
|
+
let widgets = false;
|
|
1455
1538
|
const styleOf = (el) => {
|
|
1456
1539
|
const kept = tree.styles.get(el);
|
|
1457
1540
|
if (!kept)
|
|
@@ -1497,8 +1580,45 @@ export class HtmlViewNode extends Node {
|
|
|
1497
1580
|
if (refused)
|
|
1498
1581
|
return false;
|
|
1499
1582
|
}
|
|
1500
|
-
|
|
1583
|
+
// The drawings the move reached. What the rules give the shapes in one
|
|
1584
|
+
// is no box's style (`BoxTree.shapeStyler`), so it is asked for again:
|
|
1585
|
+
// of a drawing whose own style changed — its colour, a custom property
|
|
1586
|
+
// — and of each where a rule that reaches into a drawing tests the
|
|
1587
|
+
// pointer, `a:hover svg path`. One with another answer is painted
|
|
1588
|
+
// again; one never painted has none yet, and asks when it is.
|
|
1589
|
+
const redrawn = [];
|
|
1590
|
+
if (tree.shapeStyler) {
|
|
1591
|
+
for (const el of reach) {
|
|
1592
|
+
if (tagOf(el) !== 'svg')
|
|
1593
|
+
continue;
|
|
1594
|
+
const style = fresh.get(el);
|
|
1595
|
+
if (!style)
|
|
1596
|
+
continue;
|
|
1597
|
+
if (!changed.has(el) && !cascade.shapesFollowPointer)
|
|
1598
|
+
continue;
|
|
1599
|
+
const box = this._firstBoxesOf(tree).get(el);
|
|
1600
|
+
const was = box && SHAPE_STYLES.get(box);
|
|
1601
|
+
if (!box || was === undefined)
|
|
1602
|
+
continue;
|
|
1603
|
+
const shapes = cascade.shapeStyles(el, style, tree.shapeCopies);
|
|
1604
|
+
if (shapes?.key !== was?.key)
|
|
1605
|
+
redrawn.push([box, shapes]);
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
const redraw = () => {
|
|
1609
|
+
const inks = [];
|
|
1610
|
+
for (const [box, shapes] of redrawn) {
|
|
1611
|
+
SHAPE_STYLES.set(box, shapes);
|
|
1612
|
+
const ink = inkOf(box);
|
|
1613
|
+
if (ink)
|
|
1614
|
+
inks.push(ink);
|
|
1615
|
+
}
|
|
1616
|
+
return inks;
|
|
1617
|
+
};
|
|
1618
|
+
if (!changed.size && pseudoRules === HOVER_PSEUDO_NONE) {
|
|
1619
|
+
this._repaintInk(redraw());
|
|
1501
1620
|
return true;
|
|
1621
|
+
}
|
|
1502
1622
|
for (const el of changed.keys()) {
|
|
1503
1623
|
const tag = tagOf(el);
|
|
1504
1624
|
// their backgrounds are the canvas's
|
|
@@ -1585,13 +1705,22 @@ export class HtmlViewNode extends Node {
|
|
|
1585
1705
|
continue;
|
|
1586
1706
|
const kept = tree.styles.get(el).style;
|
|
1587
1707
|
// a style derived from the element's, or drawn from it somewhere
|
|
1588
|
-
// else
|
|
1589
|
-
// it
|
|
1590
|
-
//
|
|
1708
|
+
// else. A widget mounted beside the document takes its look from
|
|
1709
|
+
// it, and is told again once it is restyled — unless the page took
|
|
1710
|
+
// to drawing the field, or stopped, which is another size of box.
|
|
1711
|
+
// An image, a drawing or a rule is drawn here, from its box, like
|
|
1712
|
+
// any.
|
|
1591
1713
|
if (box.style !== kept)
|
|
1592
1714
|
return false;
|
|
1593
|
-
if (box.marker
|
|
1715
|
+
if (box.marker)
|
|
1594
1716
|
return false;
|
|
1717
|
+
if (WIDGETS.has(box.replaced)) {
|
|
1718
|
+
const kind = box.replaced;
|
|
1719
|
+
if (styledField(kind, kept) !== styledField(kind, style)) {
|
|
1720
|
+
return false;
|
|
1721
|
+
}
|
|
1722
|
+
widgets = true;
|
|
1723
|
+
}
|
|
1595
1724
|
if (moving.has(el) && !movable(box, kept, style))
|
|
1596
1725
|
return false;
|
|
1597
1726
|
ink = !quiet.has(el);
|
|
@@ -1643,8 +1772,10 @@ export class HtmlViewNode extends Node {
|
|
|
1643
1772
|
}
|
|
1644
1773
|
}
|
|
1645
1774
|
}
|
|
1646
|
-
if (!restyled.length)
|
|
1775
|
+
if (!restyled.length) {
|
|
1776
|
+
this._repaintInk(redraw());
|
|
1647
1777
|
return true;
|
|
1778
|
+
}
|
|
1648
1779
|
// the text: each layout holding a run of a restyled box's, made again
|
|
1649
1780
|
// with its new ink, where it comes out the same shape
|
|
1650
1781
|
const relaid = new Map();
|
|
@@ -1702,6 +1833,8 @@ export class HtmlViewNode extends Node {
|
|
|
1702
1833
|
for (const [el, style] of changed) {
|
|
1703
1834
|
tree.styles.set(el, { style, inFlex: tree.styles.get(el).inFlex });
|
|
1704
1835
|
}
|
|
1836
|
+
for (const ink of redraw())
|
|
1837
|
+
inks.push(ink);
|
|
1705
1838
|
// A box that moved moves what is in it, as layout moved it the first
|
|
1706
1839
|
// time (`applyRelativeOffsets`), and a later layout moves it the same
|
|
1707
1840
|
// way; where it reached the document's end, before or after, the
|
|
@@ -1727,7 +1860,7 @@ export class HtmlViewNode extends Node {
|
|
|
1727
1860
|
relayout = true;
|
|
1728
1861
|
}
|
|
1729
1862
|
}
|
|
1730
|
-
if (moved.length)
|
|
1863
|
+
if (moved.length || widgets)
|
|
1731
1864
|
this._reportControls();
|
|
1732
1865
|
if (relayout) {
|
|
1733
1866
|
this._invalidate(Stale.Layout);
|
|
@@ -1744,14 +1877,7 @@ export class HtmlViewNode extends Node {
|
|
|
1744
1877
|
/** An element's first box in document order, for the tree it was asked
|
|
1745
1878
|
* of: made on the first move over a tree, which is one walk of it. */
|
|
1746
1879
|
_firstBoxes = null;
|
|
1747
|
-
|
|
1748
|
-
* The blocks a restyle of `changed` has to look in: for each element, the
|
|
1749
|
-
* box its text is set in the lines of — the nearest box around its first
|
|
1750
|
-
* that is not an inline one — which holds every box that takes its style
|
|
1751
|
-
* from it, the pieces a block in it broke it into among them
|
|
1752
|
-
* (`breakAround`). One that is inside another is left to it.
|
|
1753
|
-
*/
|
|
1754
|
-
_blocksOf(tree, changed) {
|
|
1880
|
+
_firstBoxesOf(tree) {
|
|
1755
1881
|
let index = this._firstBoxes;
|
|
1756
1882
|
if (index?.tree !== tree) {
|
|
1757
1883
|
const of = new Map();
|
|
@@ -1766,9 +1892,20 @@ export class HtmlViewNode extends Node {
|
|
|
1766
1892
|
}
|
|
1767
1893
|
index = this._firstBoxes = { tree, of };
|
|
1768
1894
|
}
|
|
1895
|
+
return index.of;
|
|
1896
|
+
}
|
|
1897
|
+
/**
|
|
1898
|
+
* The blocks a restyle of `changed` has to look in: for each element, the
|
|
1899
|
+
* box its text is set in the lines of — the nearest box around its first
|
|
1900
|
+
* that is not an inline one — which holds every box that takes its style
|
|
1901
|
+
* from it, the pieces a block in it broke it into among them
|
|
1902
|
+
* (`breakAround`). One that is inside another is left to it.
|
|
1903
|
+
*/
|
|
1904
|
+
_blocksOf(tree, changed) {
|
|
1905
|
+
const first = this._firstBoxesOf(tree);
|
|
1769
1906
|
const blocks = new Set();
|
|
1770
1907
|
for (const el of changed) {
|
|
1771
|
-
let box =
|
|
1908
|
+
let box = first.get(el) ?? null;
|
|
1772
1909
|
while (box?.parent &&
|
|
1773
1910
|
(box.kind === 'inline' || box.kind === 'text' || box.kind === 'break')) {
|
|
1774
1911
|
box = box.parent;
|