@react-x11/components 0.11.0 → 0.13.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.
Files changed (126) hide show
  1. package/dist/flow/node.d.ts +14 -6
  2. package/dist/flow/node.d.ts.map +1 -1
  3. package/dist/flow/node.js +82 -64
  4. package/dist/flow/node.js.map +1 -1
  5. package/dist/html/controls.d.ts +38 -10
  6. package/dist/html/controls.d.ts.map +1 -1
  7. package/dist/html/controls.js +43 -58
  8. package/dist/html/controls.js.map +1 -1
  9. package/dist/html/css/cascade.d.ts +134 -20
  10. package/dist/html/css/cascade.d.ts.map +1 -1
  11. package/dist/html/css/cascade.js +538 -128
  12. package/dist/html/css/cascade.js.map +1 -1
  13. package/dist/html/css/color.d.ts +19 -0
  14. package/dist/html/css/color.d.ts.map +1 -1
  15. package/dist/html/css/color.js +86 -0
  16. package/dist/html/css/color.js.map +1 -1
  17. package/dist/html/css/parse.d.ts +40 -2
  18. package/dist/html/css/parse.d.ts.map +1 -1
  19. package/dist/html/css/parse.js +391 -13
  20. package/dist/html/css/parse.js.map +1 -1
  21. package/dist/html/css/style.d.ts +52 -1
  22. package/dist/html/css/style.d.ts.map +1 -1
  23. package/dist/html/css/style.js +328 -11
  24. package/dist/html/css/style.js.map +1 -1
  25. package/dist/html/css/ua.d.ts +11 -1
  26. package/dist/html/css/ua.d.ts.map +1 -1
  27. package/dist/html/css/ua.js +73 -7
  28. package/dist/html/css/ua.js.map +1 -1
  29. package/dist/html/css/values.d.ts +10 -1
  30. package/dist/html/css/values.d.ts.map +1 -1
  31. package/dist/html/css/values.js +27 -2
  32. package/dist/html/css/values.js.map +1 -1
  33. package/dist/html/css/vars.d.ts +5 -0
  34. package/dist/html/css/vars.d.ts.map +1 -1
  35. package/dist/html/css/vars.js +2 -2
  36. package/dist/html/css/vars.js.map +1 -1
  37. package/dist/html/dom.d.ts.map +1 -1
  38. package/dist/html/dom.js +38 -3
  39. package/dist/html/dom.js.map +1 -1
  40. package/dist/html/fonts.d.ts +25 -1
  41. package/dist/html/fonts.d.ts.map +1 -1
  42. package/dist/html/fonts.js +99 -6
  43. package/dist/html/fonts.js.map +1 -1
  44. package/dist/html/form.d.ts +200 -0
  45. package/dist/html/form.d.ts.map +1 -0
  46. package/dist/html/form.js +801 -0
  47. package/dist/html/form.js.map +1 -0
  48. package/dist/html/index.d.ts +12 -0
  49. package/dist/html/index.d.ts.map +1 -1
  50. package/dist/html/index.js +30 -264
  51. package/dist/html/index.js.map +1 -1
  52. package/dist/html/layout/block.d.ts +11 -2
  53. package/dist/html/layout/block.d.ts.map +1 -1
  54. package/dist/html/layout/block.js +186 -19
  55. package/dist/html/layout/block.js.map +1 -1
  56. package/dist/html/layout/boxes.d.ts +65 -7
  57. package/dist/html/layout/boxes.d.ts.map +1 -1
  58. package/dist/html/layout/boxes.js +87 -22
  59. package/dist/html/layout/boxes.js.map +1 -1
  60. package/dist/html/layout/cache.d.ts +2 -2
  61. package/dist/html/layout/cache.d.ts.map +1 -1
  62. package/dist/html/layout/cache.js +8 -3
  63. package/dist/html/layout/cache.js.map +1 -1
  64. package/dist/html/layout/flex.js +4 -1
  65. package/dist/html/layout/flex.js.map +1 -1
  66. package/dist/html/layout/floats.d.ts +4 -0
  67. package/dist/html/layout/floats.d.ts.map +1 -1
  68. package/dist/html/layout/floats.js +26 -0
  69. package/dist/html/layout/floats.js.map +1 -1
  70. package/dist/html/layout/inline.d.ts +26 -2
  71. package/dist/html/layout/inline.d.ts.map +1 -1
  72. package/dist/html/layout/inline.js +1232 -115
  73. package/dist/html/layout/inline.js.map +1 -1
  74. package/dist/html/node.d.ts +120 -15
  75. package/dist/html/node.d.ts.map +1 -1
  76. package/dist/html/node.js +993 -174
  77. package/dist/html/node.js.map +1 -1
  78. package/dist/html/paint.d.ts +75 -2
  79. package/dist/html/paint.d.ts.map +1 -1
  80. package/dist/html/paint.js +836 -200
  81. package/dist/html/paint.js.map +1 -1
  82. package/dist/html/surfaces.d.ts +7 -2
  83. package/dist/html/surfaces.d.ts.map +1 -1
  84. package/dist/html/surfaces.js +16 -0
  85. package/dist/html/surfaces.js.map +1 -1
  86. package/dist/html/widgets.d.ts +29 -0
  87. package/dist/html/widgets.d.ts.map +1 -0
  88. package/dist/html/widgets.js +620 -0
  89. package/dist/html/widgets.js.map +1 -0
  90. package/dist/index.d.ts +1 -1
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js.map +1 -1
  93. package/dist/internal/window.d.ts +22 -0
  94. package/dist/internal/window.d.ts.map +1 -1
  95. package/dist/internal/window.js +35 -8
  96. package/dist/internal/window.js.map +1 -1
  97. package/dist/richtext/node.d.ts +7 -0
  98. package/dist/richtext/node.d.ts.map +1 -1
  99. package/dist/richtext/node.js.map +1 -1
  100. package/package.json +6 -4
  101. package/src/flow/node.ts +80 -64
  102. package/src/html/controls.ts +79 -58
  103. package/src/html/css/cascade.ts +610 -146
  104. package/src/html/css/color.ts +87 -0
  105. package/src/html/css/parse.ts +431 -13
  106. package/src/html/css/style.ts +367 -11
  107. package/src/html/css/ua.ts +76 -8
  108. package/src/html/css/values.ts +31 -3
  109. package/src/html/css/vars.ts +2 -2
  110. package/src/html/dom.ts +41 -3
  111. package/src/html/fonts.ts +116 -6
  112. package/src/html/form.ts +962 -0
  113. package/src/html/index.ts +49 -300
  114. package/src/html/layout/block.ts +231 -16
  115. package/src/html/layout/boxes.ts +133 -32
  116. package/src/html/layout/cache.ts +8 -3
  117. package/src/html/layout/flex.ts +4 -1
  118. package/src/html/layout/floats.ts +24 -0
  119. package/src/html/layout/inline.ts +1445 -108
  120. package/src/html/node.ts +1010 -166
  121. package/src/html/paint.ts +980 -270
  122. package/src/html/surfaces.ts +21 -1
  123. package/src/html/widgets.ts +735 -0
  124. package/src/index.ts +1 -0
  125. package/src/internal/window.ts +36 -8
  126. package/src/richtext/node.ts +7 -0
@@ -28,7 +28,12 @@ import {
28
28
  NON_RENDERED,
29
29
  tagOf,
30
30
  } from '../dom.js';
31
- import type { Cascade, FirstLetterRules } from '../css/cascade.js';
31
+ import type {
32
+ Cascade,
33
+ FirstLetterRules,
34
+ KeptStyles,
35
+ SelectionStyle,
36
+ } from '../css/cascade.js';
32
37
  import type { CollapsedTable } from './collapse.js';
33
38
  import { quoteAt } from '../css/content.js';
34
39
  import type { CounterStyles } from '../css/counter-styles.js';
@@ -36,6 +41,7 @@ import type { ContentItem } from '../css/content.js';
36
41
  import {
37
42
  CONTAIN_STYLE,
38
43
  FIRST_LINE_INHERITED,
44
+ NO_MASK,
39
45
  copyStyle,
40
46
  firstLineParent,
41
47
  inherit,
@@ -187,6 +193,15 @@ export interface LineText {
187
193
  * spacer: a unit of the layout that is no text of the document's
188
194
  * (`documentOffsetOf`, `layoutOffsetOf`). */
189
195
  gaps?: number[];
196
+ /**
197
+ * The spaces `pre-wrap` keeps that this fragment's line ends on, which an
198
+ * engine strips from a line's end as though CSS removed them there: each
199
+ * one's offset in the layout's text and where it is, from the layout's
200
+ * origin, beside the line's end in logical order (`hangPreserved`). They
201
+ * are their inline box's, whose background and border cover them, and
202
+ * the ones before a forced break that fit take room on the line.
203
+ */
204
+ hung?: { at: number; x: number; width: number }[];
190
205
  /** Any offset in the layout's own text as a document index — how a run
191
206
  * under the pointer finds the element whose text it is. Per pass: the
192
207
  * layout may be one an earlier pass made (`TextLayoutCache`), and the
@@ -233,6 +248,10 @@ export interface TextLayoutLike {
233
248
  height: number;
234
249
  baseline: number;
235
250
  width: number;
251
+ /** Its width with the white space it ends on kept, in the item it
252
+ * ends: how far it moves the pen where text goes on after it on the
253
+ * same line. ntk's, from 8.17.0; an engine without it leaves it out. */
254
+ advance?: number;
236
255
  ascent: number;
237
256
  descent: number;
238
257
  start: number;
@@ -542,6 +561,10 @@ export type FirstLineStyler = (
542
561
  parent: ComputedStyle,
543
562
  ) => ComputedStyle;
544
563
 
564
+ /** The `::selection` of the element a box's text is in, or null for the
565
+ * palette's highlight (`Cascade.selectionStyle`). */
566
+ export type SelectionStyler = (box: Box | null) => SelectionStyle | null;
567
+
545
568
  /** The url of an image generated content put in a pseudo-element: it has
546
569
  * no element of its own to name it (`imageUrlOf`). */
547
570
  export const CONTENT_IMAGES = new WeakMap<Box, string>();
@@ -581,6 +604,12 @@ export const BOX_RAISES = new WeakMap<Box, number>();
581
604
  * background, drawn from its baseline, is put there by line. */
582
605
  export const LINE_BOX_RAISES = new WeakMap<LineBox, Map<Box, number>>();
583
606
 
607
+ /** The face of an inline box with padding above or below its text and
608
+ * nothing to paint behind it, which has no `decoration`: its fragments
609
+ * still reach past its lines by the padding, and count in the scrollable
610
+ * overflow of the block they are in (`computePaintBounds`). */
611
+ export const PADDED_FACES = new WeakMap<Box, InlineDecoration>();
612
+
584
613
  /** The table cells wholly in columns `visibility: collapse` took out of
585
614
  * their table (CSS 2.1 17.5.5), which the paint pass leaves out: a cell is
586
615
  * no descendant of its column and inherits nothing from it, so its own
@@ -615,11 +644,23 @@ export const GRID_TRACKS = new WeakMap<Box, GridTracks>();
615
644
  * `order` moves any: an absolutely positioned child's is 0. */
616
645
  export const PAINT_ORDER = new WeakMap<Box, Box[]>();
617
646
 
618
- /** The blocks that broke a relatively positioned inline box in pieces,
619
- * under its first piece: its offset moves them too (CSS 2.1 9.2.1.1),
620
- * though they stand outside it (`breakAround`). */
647
+ /** The blocks that broke an inline box in pieces, under its first piece
648
+ * (`breakAround`): a relative offset of the box moves them too (CSS 2.1
649
+ * 9.2.1.1), though they stand outside it, and its rect takes them in, as
650
+ * a browser's does (`elementRect`). */
621
651
  export const CUT_BLOCKS = new WeakMap<Box, Box[]>();
622
652
 
653
+ /** Where a block that clearance moved below the floats would have stood
654
+ * without it, its border edge's top (CSS 2.1 9.5.2): a browser's
655
+ * fragment of an inline box around such a block starts there, and takes
656
+ * the clearance in (`elementRect`). Only the blocks that had clearance. */
657
+ export const CLEARED_FROM = new WeakMap<Box, number>();
658
+
659
+ /** The element a pseudo-element's box is generated from, which has no
660
+ * element of its own (`Box.pseudo`): whose the images its styles name are,
661
+ * when the host is asked for them. */
662
+ export const GENERATED_FROM = new WeakMap<Box, Element>();
663
+
623
664
  /** The blocks that broke an inline box under full opacity in pieces, and
624
665
  * the opacity they take from it — from each such inline box around them,
625
666
  * multiplied. They stand outside it (CSS 2.1 9.2.1.1) and are still its
@@ -647,9 +688,14 @@ export interface BoxTree {
647
688
  controls: Box[];
648
689
  /** Every box carrying an `href`, for click and hover. */
649
690
  links: Box[];
650
- /** Every element's box with a `background-image` or a border image,
651
- * for the host to be asked for: a document has a handful, and finding
652
- * them was a walk over every box after every build. */
691
+ /** The style of an anonymous box under a parent's (`anonymousStyles`):
692
+ * the one the fix-up gave each it made, and what such a box takes when
693
+ * its parent's style changes where it is (`HtmlViewNode._hoverInPlace`). */
694
+ anonymous: AnonymousStyle;
695
+ /** Every box with a `background-image`, a border image or a mask image,
696
+ * an element's or a pseudo-element's, for the host to be asked for: a
697
+ * document has a handful, and finding them was a walk over every box
698
+ * after every build. */
653
699
  backgrounds: Box[];
654
700
  /** Every image generated content names, the element whose
655
701
  * pseudo-element names it, for the host to be asked for, and whether its
@@ -667,6 +713,10 @@ export interface BoxTree {
667
713
  /** Each box's style on a first line (`FirstLineStyler`), where any
668
714
  * block has a `::first-line`. */
669
715
  firstLineStyler: FirstLineStyler | null;
716
+ /** Each box's `::selection` (`SelectionStyler`), where any rule styles
717
+ * one: worked out as a selection is first painted over it, not as the
718
+ * tree is built, since most builds are never selected in. */
719
+ selectionStyler: SelectionStyler | null;
670
720
  /** Whether a float or an out-of-flow box sits in an inline box: where
671
721
  * none does, layout looks for them among a block's own children and
672
722
  * goes through no inline box to find them. */
@@ -687,6 +737,9 @@ export interface BoxTree {
687
737
 
688
738
  export interface BuildOptions {
689
739
  cascade: Cascade;
740
+ /** The styles of the tree this one replaces, where only some elements'
741
+ * can have changed since (`Cascade.beginSharing`). */
742
+ kept?: KeptStyles | null;
690
743
  /** Device pixels per CSS pixel. An image's pixels and a `width="600"`
691
744
  * attribute are CSS pixels; every box is device, so both are multiplied
692
745
  * on the way in. Default 1. */
@@ -786,7 +839,7 @@ class Builder {
786
839
 
787
840
  run(root: Element): BoxTree {
788
841
  const cascade = this._options.cascade;
789
- cascade.beginSharing();
842
+ cascade.beginSharing(this._options.kept ?? null);
790
843
  const { style: rootStyle, html: impliedHtml } = cascade.rootStyle(
791
844
  hasBody(root),
792
845
  hasHtml(root),
@@ -805,10 +858,13 @@ class Builder {
805
858
  // it carries no margins of its own and cannot collapse with anything.
806
859
  this._children(root, rootBox, rootStyle, false, null, ROOT_SHARE_KEY);
807
860
  this._endLine();
808
- fixUp(rootBox, anonymousStyles(cascade.initial));
861
+ cascade.endSharing();
862
+ const anonymous = anonymousStyles(cascade.initial);
863
+ fixUp(rootBox, anonymous);
809
864
  assignSubtreeRanges(rootBox);
810
865
  return {
811
866
  root: rootBox,
867
+ anonymous,
812
868
  text: this._chunks.join(''),
813
869
  textBoxes: this._textBoxes,
814
870
  textStyles: this._textStyles,
@@ -821,6 +877,7 @@ class Builder {
821
877
  negative: this._negative,
822
878
  firstLine: this._firstLine,
823
879
  firstLineStyler: this._firstLine ? this._firstLineStyler() : null,
880
+ selectionStyler: cascade.hasSelection ? this._selectionStyler() : null,
824
881
  nestedOutOfLine: this._nestedOutOfLine,
825
882
  movedInline: this._movedInline,
826
883
  clipText: this._clipText,
@@ -828,6 +885,30 @@ class Builder {
828
885
  };
829
886
  }
830
887
 
888
+ /** `BoxTree.selectionStyler`, over this build's cascade: an element's
889
+ * over its parent's, each once. A box with no element of its own — text,
890
+ * an anonymous box — is its nearest element's. */
891
+ private _selectionStyler(): SelectionStyler {
892
+ const cascade = this._options.cascade;
893
+ const styles = this._styles;
894
+ const known = new Map<Element, SelectionStyle | null>();
895
+ const of = (el: Element): SelectionStyle | null => {
896
+ let found = known.get(el);
897
+ if (found !== undefined) return found;
898
+ // the parser keeps a document to 256 elements deep (`dom.ts`)
899
+ const parent = isElement(el.parent) ? of(el.parent) : null;
900
+ const own = styles.get(el)?.style;
901
+ found = own ? cascade.selectionStyle(el, own, parent) : parent;
902
+ known.set(el, found);
903
+ return found;
904
+ };
905
+ return (box) => {
906
+ let at = box;
907
+ while (at && !at.el) at = at.parent;
908
+ return at?.el ? of(at.el) : null;
909
+ };
910
+ }
911
+
831
912
  /** `BoxTree.firstLineStyler`, over this build's cascade. */
832
913
  private _firstLineStyler(): FirstLineStyler {
833
914
  const cascade = this._options.cascade;
@@ -997,7 +1078,9 @@ class Builder {
997
1078
  }
998
1079
 
999
1080
  // an `<object>` is its image once it has one, and its content until;
1000
- // an `<embed>` its image, and a `<video>` its poster, or a frame
1081
+ // an `<embed>` its image, and a `<video>` its poster, or a frame; an
1082
+ // image button its image, and a button saying what it is for until it
1083
+ // has one, so it can be pressed either way
1001
1084
  const replaced =
1002
1085
  tag === 'object'
1003
1086
  ? this._options.imageSize(el)
@@ -1005,7 +1088,11 @@ class Builder {
1005
1088
  : 'none'
1006
1089
  : (tag === 'embed' || tag === 'video') && this._options.imageSize(el)
1007
1090
  ? 'image'
1008
- : replacedKind(el, tag);
1091
+ : isImageButton(el, tag)
1092
+ ? this._options.imageSize(el)
1093
+ ? 'image'
1094
+ : 'button'
1095
+ : replacedKind(el, tag);
1009
1096
  if (replaced !== 'none') {
1010
1097
  this._replaced(el, tag, replaced, style, into);
1011
1098
  return;
@@ -1025,13 +1112,7 @@ class Builder {
1025
1112
  this._firstLine = true;
1026
1113
  }
1027
1114
  }
1028
- if (
1029
- style.backgroundImage ||
1030
- style.backgroundImages ||
1031
- typeof style.borderImage.source === 'string'
1032
- ) {
1033
- this._backgrounds.push(box);
1034
- }
1115
+ if (namesImages(style)) this._backgrounds.push(box);
1035
1116
  if (style.position === 'absolute' || style.position === 'fixed')
1036
1117
  box.outOfFlow = true;
1037
1118
  else if (style.float !== 'none') box.isFloat = true;
@@ -1158,13 +1239,7 @@ class Builder {
1158
1239
  const box = new Box('replaced', el, style);
1159
1240
  box.replaced = replaced;
1160
1241
  into.append(box);
1161
- if (
1162
- style.backgroundImage ||
1163
- style.backgroundImages ||
1164
- typeof style.borderImage.source === 'string'
1165
- ) {
1166
- this._backgrounds.push(box);
1167
- }
1242
+ if (namesImages(style)) this._backgrounds.push(box);
1168
1243
  if (style.position === 'absolute' || style.position === 'fixed')
1169
1244
  box.outOfFlow = true;
1170
1245
  else if (style.float !== 'none') box.isFloat = true;
@@ -1295,6 +1370,10 @@ class Builder {
1295
1370
  const box = new Box(boxKindFor(style.display), null, style);
1296
1371
  box.pseudo = which;
1297
1372
  into.append(box);
1373
+ // its images are its element's to ask for: a `::after` with no content
1374
+ // but a background, which designs hang a picture on, drew nothing
1375
+ GENERATED_FROM.set(box, el);
1376
+ if (namesImages(style)) this._backgrounds.push(box);
1298
1377
  // a list item it generates has a marker as an element's has, of the
1299
1378
  // `list-item` counter it has just counted (CSS 2.1 12.5): outside it,
1300
1379
  // or at the start of its content
@@ -1714,6 +1793,10 @@ class Builder {
1714
1793
  const letterStyle = cascade.firstLetterStyle(search.rules, style);
1715
1794
  const box = new Box(boxKindFor(letterStyle.display), null, letterStyle);
1716
1795
  box.pseudo = 'first-letter';
1796
+ if (owner) {
1797
+ GENERATED_FROM.set(box, owner);
1798
+ if (namesImages(letterStyle)) this._backgrounds.push(box);
1799
+ }
1717
1800
  if (letterStyle.float !== 'none') {
1718
1801
  box.isFloat = true;
1719
1802
  if (into.kind === 'inline') this._nestedOutOfLine = true;
@@ -2336,6 +2419,13 @@ function setIntrinsics(box: Box, size: IntrinsicSize, scale: number): void {
2336
2419
  };
2337
2420
  }
2338
2421
 
2422
+ /** An `<input type=image>`: a picture that submits its form. */
2423
+ function isImageButton(el: Element, tag: string): boolean {
2424
+ return (
2425
+ tag === 'input' && (attr(el, 'type') ?? '').trim().toLowerCase() === 'image'
2426
+ );
2427
+ }
2428
+
2339
2429
  function replacedKind(el: Element, tag: string): ReplacedKind {
2340
2430
  switch (tag) {
2341
2431
  case 'img':
@@ -2608,7 +2698,7 @@ function breakAround(inline: Box): Box[] | null {
2608
2698
  for (let i = 0; i < pieces.length; i += 1) {
2609
2699
  pieces[i].cut = (i > 0 ? 1 : 0) | (i < pieces.length - 1 ? 2 : 0);
2610
2700
  }
2611
- if (isRelative(inline.style)) CUT_BLOCKS.set(pieces[0], blocks);
2701
+ CUT_BLOCKS.set(pieces[0], blocks);
2612
2702
  const fade = inline.style.opacity;
2613
2703
  if (fade < 1) {
2614
2704
  for (const block of blocks) {
@@ -2618,6 +2708,17 @@ function breakAround(inline: Box): Box[] | null {
2618
2708
  return out;
2619
2709
  }
2620
2710
 
2711
+ /** Whether a style names an image for its box to be drawn with: a
2712
+ * background's, a border's, or a mask's. */
2713
+ function namesImages(style: ComputedStyle): boolean {
2714
+ return (
2715
+ !!style.backgroundImage ||
2716
+ !!style.backgroundImages ||
2717
+ typeof style.borderImage.source === 'string' ||
2718
+ style.mask !== NO_MASK
2719
+ );
2720
+ }
2721
+
2621
2722
  /**
2622
2723
  * The style of an anonymous box inside a parent: what the parent passes on
2623
2724
  * by inheritance, and every other property at its initial value, as CSS 2.1
@@ -2628,24 +2729,24 @@ function breakAround(inline: Box): Box[] | null {
2628
2729
  * paragraph after it the height of the div further down. One per parent
2629
2730
  * style, which the cascade already shares between elements.
2630
2731
  */
2631
- type AnonymousStyle = (
2632
- parent: Box,
2732
+ export type AnonymousStyle = (
2733
+ parent: ComputedStyle,
2633
2734
  display: ComputedStyle['display'],
2634
2735
  ) => ComputedStyle;
2635
2736
 
2636
2737
  function anonymousStyles(initial: ComputedStyle): AnonymousStyle {
2637
2738
  const made = new WeakMap<ComputedStyle, Map<string, ComputedStyle>>();
2638
2739
  return (parent, display) => {
2639
- let byDisplay = made.get(parent.style);
2740
+ let byDisplay = made.get(parent);
2640
2741
  if (!byDisplay) {
2641
2742
  byDisplay = new Map();
2642
- made.set(parent.style, byDisplay);
2743
+ made.set(parent, byDisplay);
2643
2744
  }
2644
2745
  let style = byDisplay.get(display);
2645
2746
  if (!style) {
2646
2747
  // `display` is the one property it does not start from: it is the
2647
2748
  // box the fix-up made, and layout asks the style what a box is
2648
- style = inherit(parent.style, initial);
2749
+ style = inherit(parent, initial);
2649
2750
  style.display = display;
2650
2751
  byDisplay.set(display, style);
2651
2752
  }
@@ -2753,7 +2854,7 @@ function anonymousOf(
2753
2854
  anonymous: AnonymousStyle,
2754
2855
  display: ComputedStyle['display'] = kind as ComputedStyle['display'],
2755
2856
  ): Box {
2756
- const box = new Box(kind, null, anonymous(parent, display));
2857
+ const box = new Box(kind, null, anonymous(parent.style, display));
2757
2858
  box.parent = parent;
2758
2859
  for (const child of run) {
2759
2860
  child.parent = box;
@@ -190,6 +190,7 @@ export const RUN_FIELDS = [
190
190
  'features',
191
191
  'nowrap',
192
192
  'shapeApart',
193
+ 'kernAcross',
193
194
  ] as const satisfies readonly (keyof TextRun)[];
194
195
 
195
196
  /** A field of `TextRun` missing from `RUN_FIELDS` names itself here. */
@@ -223,7 +224,8 @@ function sameRun(a: TextRun, b: TextRun): boolean {
223
224
  a.href === b.href &&
224
225
  a.features === b.features &&
225
226
  a.nowrap === b.nowrap &&
226
- a.shapeApart === b.shapeApart
227
+ a.shapeApart === b.shapeApart &&
228
+ a.kernAcross === b.kernAcross
227
229
  );
228
230
  }
229
231
 
@@ -250,7 +252,8 @@ function sameStyle(
250
252
  a.href === b.href &&
251
253
  a.features === b.features &&
252
254
  a.nowrap === b.nowrap &&
253
- a.shapeApart === b.shapeApart
255
+ a.shapeApart === b.shapeApart &&
256
+ a.kernAcross === b.kernAcross
254
257
  );
255
258
  }
256
259
 
@@ -265,6 +268,7 @@ export const OPTION_FIELDS = [
265
268
  'overflow',
266
269
  'overflowWrap',
267
270
  'wrap',
271
+ 'fit',
268
272
  ] as const satisfies readonly (keyof Options)[];
269
273
 
270
274
  /** An option missing from `OPTION_FIELDS` names itself here. */
@@ -284,6 +288,7 @@ function sameOptions(a: Options, b: Options): boolean {
284
288
  a.maxLines === b.maxLines &&
285
289
  a.overflow === b.overflow &&
286
290
  a.overflowWrap === b.overflowWrap &&
287
- a.wrap === b.wrap
291
+ a.wrap === b.wrap &&
292
+ a.fit === b.fit
288
293
  );
289
294
  }
@@ -478,7 +478,10 @@ function placeItems(
478
478
  definite,
479
479
  !row,
480
480
  );
481
- bottom = Math.max(bottom, top + child.height);
481
+ // to the end of its margin box, as Yoga measured the box: a negative
482
+ // margin takes the item's end back in, which Codex's search field
483
+ // hangs a pixel over its form's border with, top and bottom
484
+ bottom = Math.max(bottom, top + child.height + child.marginBottom);
482
485
  }
483
486
  return bottom;
484
487
  }
@@ -153,6 +153,30 @@ export class FloatContext {
153
153
  return lowest;
154
154
  }
155
155
 
156
+ /** Move the floats placed since `mark` down by `dy`, with the block they
157
+ * were placed in: a list item's first block goes lower to make room
158
+ * for its marker once it is laid out (`layoutChildren`). */
159
+ moveSince(mark: number, dy: number): void {
160
+ if (!dy || mark >= this._boxes.length) return;
161
+ for (let i = mark; i < this._boxes.length; i += 1) {
162
+ const float = this._boxes[i];
163
+ this._boxes[i] = {
164
+ ...float,
165
+ top: float.top + dy,
166
+ bottom: float.bottom + dy,
167
+ };
168
+ }
169
+ this._lowestLeft = -Infinity;
170
+ this._lowestRight = -Infinity;
171
+ this._lastTop = -Infinity;
172
+ for (const float of this._boxes) {
173
+ if (float.top > this._lastTop) this._lastTop = float.top;
174
+ if (float.side === 'left')
175
+ this._lowestLeft = Math.max(this._lowestLeft, float.bottom);
176
+ else this._lowestRight = Math.max(this._lowestRight, float.bottom);
177
+ }
178
+ }
179
+
156
180
  /** How far down the floats reach — what a container that establishes a
157
181
  * BFC has to grow to, so it does not end above its own floats. */
158
182
  get bottom(): number {