@alchemy.run/sigil 0.0.0-alpha.1 → 0.0.0-alpha.2

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 (121) hide show
  1. package/README.md +299 -299
  2. package/dist/ansi.d.ts +223 -0
  3. package/dist/ansi.js +2 -0
  4. package/dist/{devtools-QpCMm9JH.mjs → devtools-BhYGjb7h.js} +1 -1
  5. package/dist/index-DDVME65c.d.ts +919 -0
  6. package/dist/index.d.ts +1657 -0
  7. package/dist/index.js +4643 -0
  8. package/dist/sgr-CMfEpjSk.d.ts +91 -0
  9. package/dist/truncate-CBiyyZzw.js +2156 -0
  10. package/dist/yoga-5jKhYCJC.js +3465 -0
  11. package/dist/yoga.d.ts +2 -0
  12. package/dist/yoga.js +2 -0
  13. package/package.json +37 -17
  14. package/src/ansi/chalk.ts +179 -0
  15. package/src/ansi/cursor.ts +48 -0
  16. package/src/ansi/east-asian-width.ts +215 -0
  17. package/src/ansi/escapes.ts +128 -0
  18. package/src/ansi/index.ts +27 -0
  19. package/src/ansi/sgr.ts +237 -0
  20. package/src/ansi/slice.ts +43 -0
  21. package/src/ansi/string-width.ts +236 -0
  22. package/src/ansi/strip.ts +33 -0
  23. package/src/ansi/supports-color.ts +213 -0
  24. package/src/ansi/tokenize.ts +453 -0
  25. package/src/ansi/truncate.ts +194 -0
  26. package/src/ansi/widest-line.ts +12 -0
  27. package/src/ansi/wrap.ts +766 -0
  28. package/src/ansi-tokenizer.ts +510 -0
  29. package/src/auto-bind.ts +41 -0
  30. package/src/boxes.ts +100 -0
  31. package/src/code-excerpt.ts +39 -0
  32. package/src/colorize.ts +60 -0
  33. package/src/components/AccessibilityContext.ts +5 -0
  34. package/src/components/AnimationContext.ts +24 -0
  35. package/src/components/App.tsx +781 -0
  36. package/src/components/AppContext.ts +111 -0
  37. package/src/components/BackgroundContext.ts +8 -0
  38. package/src/components/Box.tsx +116 -0
  39. package/src/components/CursorContext.ts +19 -0
  40. package/src/components/ErrorBoundary.tsx +38 -0
  41. package/src/components/ErrorOverview.tsx +133 -0
  42. package/src/components/FocusContext.ts +30 -0
  43. package/src/components/Newline.tsx +15 -0
  44. package/src/components/Spacer.tsx +10 -0
  45. package/src/components/Static.tsx +59 -0
  46. package/src/components/StderrContext.ts +26 -0
  47. package/src/components/StdinContext.ts +49 -0
  48. package/src/components/StdoutContext.ts +28 -0
  49. package/src/components/Text.tsx +144 -0
  50. package/src/components/Transform.tsx +37 -0
  51. package/src/cursor-position.ts +103 -0
  52. package/src/devtools-window-polyfill.ts +73 -0
  53. package/src/devtools.ts +43 -0
  54. package/src/dom.ts +292 -0
  55. package/src/get-max-width.ts +11 -0
  56. package/src/global.d.ts +36 -0
  57. package/src/hooks/use-animation.ts +142 -0
  58. package/src/hooks/use-app.ts +8 -0
  59. package/src/hooks/use-box-metrics.ts +134 -0
  60. package/src/hooks/use-cursor.ts +33 -0
  61. package/src/hooks/use-focus-manager.ts +62 -0
  62. package/src/hooks/use-focus.ts +83 -0
  63. package/src/hooks/use-input.ts +267 -0
  64. package/src/hooks/use-is-screen-reader-enabled.ts +12 -0
  65. package/src/hooks/use-paste.ts +78 -0
  66. package/src/hooks/use-stderr.ts +8 -0
  67. package/src/hooks/use-stdin.ts +10 -0
  68. package/src/hooks/use-stdout.ts +8 -0
  69. package/src/hooks/use-window-size.ts +41 -0
  70. package/src/indent-string.ts +16 -0
  71. package/src/index.ts +44 -0
  72. package/src/ink.tsx +1506 -0
  73. package/src/input-parser.ts +283 -0
  74. package/src/instances.ts +9 -0
  75. package/src/is-in-ci.ts +7 -0
  76. package/src/kitty-keyboard.ts +57 -0
  77. package/src/log-update.ts +370 -0
  78. package/src/measure-element.ts +62 -0
  79. package/src/measure-text.ts +31 -0
  80. package/src/output.ts +308 -0
  81. package/src/parse-keypress.ts +516 -0
  82. package/src/parse-stack-line.ts +139 -0
  83. package/src/patch-console.ts +62 -0
  84. package/src/quick-lru.ts +85 -0
  85. package/src/reconciler.ts +451 -0
  86. package/src/render-background.ts +38 -0
  87. package/src/render-border.ts +134 -0
  88. package/src/render-node-to-output.ts +191 -0
  89. package/src/render-to-string.ts +131 -0
  90. package/src/render.ts +276 -0
  91. package/src/renderer.ts +73 -0
  92. package/src/sanitize-ansi.ts +33 -0
  93. package/src/signal-exit.ts +107 -0
  94. package/src/squash-text-nodes.ts +40 -0
  95. package/src/stream.ts +30 -0
  96. package/src/styles.ts +748 -0
  97. package/src/terminal-size.ts +57 -0
  98. package/src/throttle.ts +73 -0
  99. package/src/types.ts +15 -0
  100. package/src/utils.ts +40 -0
  101. package/src/wrap-text.ts +50 -0
  102. package/src/write-synchronized.ts +9 -0
  103. package/src/yoga/config.ts +57 -0
  104. package/src/yoga/core/absoluteLayout.ts +626 -0
  105. package/src/yoga/core/baseline.ts +66 -0
  106. package/src/yoga/core/cache.ts +136 -0
  107. package/src/yoga/core/calculateLayout.ts +2920 -0
  108. package/src/yoga/core/config.ts +104 -0
  109. package/src/yoga/core/flexLine.ts +177 -0
  110. package/src/yoga/core/helpers.ts +293 -0
  111. package/src/yoga/core/layoutResults.ts +167 -0
  112. package/src/yoga/core/node.ts +611 -0
  113. package/src/yoga/core/numeric.ts +44 -0
  114. package/src/yoga/core/pixelGrid.ts +151 -0
  115. package/src/yoga/core/style.ts +887 -0
  116. package/src/yoga/core/types.ts +224 -0
  117. package/src/yoga/generated/YGEnums.ts +263 -0
  118. package/src/yoga/index.ts +19 -0
  119. package/src/yoga/node.ts +1140 -0
  120. package/dist/index.d.mts +0 -2379
  121. package/dist/index.mjs +0 -10072
@@ -0,0 +1,887 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Derived from Yoga. See THIRD_PARTY_NOTICES.md.
3
+
4
+ // Port of yoga/style/Style.h (grid properties omitted — the JS binding does
5
+ // not expose them and no algorithm consumes them).
6
+
7
+ import {
8
+ Align,
9
+ BoxSizing,
10
+ Dimension,
11
+ Direction,
12
+ Display,
13
+ Edge,
14
+ FlexDirection,
15
+ Gutter,
16
+ Justify,
17
+ Overflow,
18
+ PositionType,
19
+ Unit,
20
+ Wrap,
21
+ } from "../generated/YGEnums.ts";
22
+ import {
23
+ PhysicalEdge,
24
+ flexStartEdge,
25
+ flexEndEdge,
26
+ inlineStartEdge,
27
+ inlineEndEdge,
28
+ isRow,
29
+ } from "./helpers.ts";
30
+ import { isDefined, maxOrDefined } from "./numeric.ts";
31
+ import { StyleLength, StyleSizeLength } from "./types.ts";
32
+
33
+ const EDGE_COUNT = 9;
34
+ const GUTTER_COUNT = 3;
35
+
36
+ function undefinedLengths(count: number): StyleLength[] {
37
+ return Array.from<StyleLength>({ length: count }).fill(StyleLength.undefined());
38
+ }
39
+
40
+ // Physical-edge resolution results for one edge collection: the resolved
41
+ // StyleLength per [direction * 4 + physicalEdge], plus parallel primitive
42
+ // unit/value views for allocation-free numeric resolution.
43
+ interface ResolvedEdges {
44
+ lengths: StyleLength[];
45
+ units: Uint8Array;
46
+ values: number[];
47
+ }
48
+
49
+ export class Style {
50
+ static readonly DefaultFlexGrow = 0.0;
51
+ static readonly DefaultFlexShrink = 0.0;
52
+ static readonly WebDefaultFlexShrink = 1.0;
53
+
54
+ private direction_: Direction = Direction.Inherit;
55
+ private flexDirection_: FlexDirection = FlexDirection.Column;
56
+ private justifyContent_: Justify = Justify.FlexStart;
57
+ private justifyItems_: Justify = Justify.Stretch;
58
+ private justifySelf_: Justify = Justify.Auto;
59
+ private alignContent_: Align = Align.FlexStart;
60
+ private alignItems_: Align = Align.Stretch;
61
+ private alignSelf_: Align = Align.Auto;
62
+ private positionType_: PositionType = PositionType.Relative;
63
+ private flexWrap_: Wrap = Wrap.NoWrap;
64
+ private overflow_: Overflow = Overflow.Visible;
65
+ private display_: Display = Display.Flex;
66
+ private boxSizing_: BoxSizing = BoxSizing.BorderBox;
67
+
68
+ private flex_ = NaN;
69
+ private flexGrow_ = NaN;
70
+ private flexShrink_ = NaN;
71
+ private flexBasis_: StyleSizeLength = StyleSizeLength.ofAuto();
72
+ // Edge arrays are allocated lazily on first set — most nodes never define
73
+ // most of these, and a null array reads as all-undefined.
74
+ private margin_: StyleLength[] | null = null;
75
+ private position_: StyleLength[] | null = null;
76
+ private padding_: StyleLength[] | null = null;
77
+ private border_: StyleLength[] | null = null;
78
+ private gap_: StyleLength[] | null = null;
79
+
80
+ // Memoized physical-edge resolution (a pure function of the 9 logical-edge
81
+ // slots and the direction). Indexed [direction * 4 + physicalEdge];
82
+ // invalidated whenever the corresponding edge array is written. The
83
+ // parallel unit/value arrays let hot paths resolve without object hops.
84
+ private marginResolved_: ResolvedEdges | null = null;
85
+ private positionResolved_: ResolvedEdges | null = null;
86
+ private paddingResolved_: ResolvedEdges | null = null;
87
+ private borderResolved_: ResolvedEdges | null = null;
88
+ // Width/height, min-width/min-height, max-width/max-height.
89
+ private dimensions_: StyleSizeLength[] = [
90
+ StyleSizeLength.ofAuto(),
91
+ StyleSizeLength.ofAuto(),
92
+ StyleSizeLength.undefined(),
93
+ StyleSizeLength.undefined(),
94
+ StyleSizeLength.undefined(),
95
+ StyleSizeLength.undefined(),
96
+ ];
97
+ private aspectRatio_ = NaN;
98
+
99
+ direction(): Direction {
100
+ return this.direction_;
101
+ }
102
+ setDirection(value: Direction): void {
103
+ this.direction_ = value;
104
+ }
105
+
106
+ flexDirection(): FlexDirection {
107
+ return this.flexDirection_;
108
+ }
109
+ setFlexDirection(value: FlexDirection): void {
110
+ this.flexDirection_ = value;
111
+ }
112
+
113
+ justifyContent(): Justify {
114
+ return this.justifyContent_;
115
+ }
116
+ setJustifyContent(value: Justify): void {
117
+ this.justifyContent_ = value;
118
+ }
119
+
120
+ justifyItems(): Justify {
121
+ return this.justifyItems_;
122
+ }
123
+ setJustifyItems(value: Justify): void {
124
+ this.justifyItems_ = value;
125
+ }
126
+
127
+ justifySelf(): Justify {
128
+ return this.justifySelf_;
129
+ }
130
+ setJustifySelf(value: Justify): void {
131
+ this.justifySelf_ = value;
132
+ }
133
+
134
+ alignContent(): Align {
135
+ return this.alignContent_;
136
+ }
137
+ setAlignContent(value: Align): void {
138
+ this.alignContent_ = value;
139
+ }
140
+
141
+ alignItems(): Align {
142
+ return this.alignItems_;
143
+ }
144
+ setAlignItems(value: Align): void {
145
+ this.alignItems_ = value;
146
+ }
147
+
148
+ alignSelf(): Align {
149
+ return this.alignSelf_;
150
+ }
151
+ setAlignSelf(value: Align): void {
152
+ this.alignSelf_ = value;
153
+ }
154
+
155
+ positionType(): PositionType {
156
+ return this.positionType_;
157
+ }
158
+ setPositionType(value: PositionType): void {
159
+ this.positionType_ = value;
160
+ }
161
+
162
+ flexWrap(): Wrap {
163
+ return this.flexWrap_;
164
+ }
165
+ setFlexWrap(value: Wrap): void {
166
+ this.flexWrap_ = value;
167
+ }
168
+
169
+ overflow(): Overflow {
170
+ return this.overflow_;
171
+ }
172
+ setOverflow(value: Overflow): void {
173
+ this.overflow_ = value;
174
+ }
175
+
176
+ display(): Display {
177
+ return this.display_;
178
+ }
179
+ setDisplay(value: Display): void {
180
+ this.display_ = value;
181
+ }
182
+
183
+ flex(): number {
184
+ return this.flex_;
185
+ }
186
+ setFlex(value: number): void {
187
+ this.flex_ = value;
188
+ }
189
+
190
+ flexGrow(): number {
191
+ return this.flexGrow_;
192
+ }
193
+ setFlexGrow(value: number): void {
194
+ this.flexGrow_ = value;
195
+ }
196
+
197
+ flexShrink(): number {
198
+ return this.flexShrink_;
199
+ }
200
+ setFlexShrink(value: number): void {
201
+ this.flexShrink_ = value;
202
+ }
203
+
204
+ flexBasis(): StyleSizeLength {
205
+ return this.flexBasis_;
206
+ }
207
+ setFlexBasis(value: StyleSizeLength): void {
208
+ this.flexBasis_ = value;
209
+ }
210
+
211
+ margin(edge: Edge): StyleLength {
212
+ return this.margin_ !== null ? this.margin_[edge]! : StyleLength.undefined();
213
+ }
214
+ setMargin(edge: Edge, value: StyleLength): void {
215
+ (this.margin_ ??= undefinedLengths(EDGE_COUNT))[edge] = value;
216
+ this.marginResolved_ = null;
217
+ }
218
+
219
+ position(edge: Edge): StyleLength {
220
+ return this.position_ !== null ? this.position_[edge]! : StyleLength.undefined();
221
+ }
222
+ setPosition(edge: Edge, value: StyleLength): void {
223
+ (this.position_ ??= undefinedLengths(EDGE_COUNT))[edge] = value;
224
+ this.positionResolved_ = null;
225
+ }
226
+
227
+ padding(edge: Edge): StyleLength {
228
+ return this.padding_ !== null ? this.padding_[edge]! : StyleLength.undefined();
229
+ }
230
+ setPadding(edge: Edge, value: StyleLength): void {
231
+ (this.padding_ ??= undefinedLengths(EDGE_COUNT))[edge] = value;
232
+ this.paddingResolved_ = null;
233
+ }
234
+
235
+ border(edge: Edge): StyleLength {
236
+ return this.border_ !== null ? this.border_[edge]! : StyleLength.undefined();
237
+ }
238
+ setBorder(edge: Edge, value: StyleLength): void {
239
+ (this.border_ ??= undefinedLengths(EDGE_COUNT))[edge] = value;
240
+ this.borderResolved_ = null;
241
+ }
242
+
243
+ gap(gutter: Gutter): StyleLength {
244
+ return this.gap_ !== null ? this.gap_[gutter]! : StyleLength.undefined();
245
+ }
246
+ setGap(gutter: Gutter, value: StyleLength): void {
247
+ (this.gap_ ??= undefinedLengths(GUTTER_COUNT))[gutter] = value;
248
+ }
249
+
250
+ dimension(axis: Dimension): StyleSizeLength {
251
+ return this.dimensions_[axis]!;
252
+ }
253
+ setDimension(axis: Dimension, value: StyleSizeLength): void {
254
+ this.dimensions_[axis] = value;
255
+ }
256
+
257
+ minDimension(axis: Dimension): StyleSizeLength {
258
+ return this.dimensions_[2 + axis]!;
259
+ }
260
+ setMinDimension(axis: Dimension, value: StyleSizeLength): void {
261
+ this.dimensions_[2 + axis] = value;
262
+ }
263
+
264
+ maxDimension(axis: Dimension): StyleSizeLength {
265
+ return this.dimensions_[4 + axis]!;
266
+ }
267
+ setMaxDimension(axis: Dimension, value: StyleSizeLength): void {
268
+ this.dimensions_[4 + axis] = value;
269
+ }
270
+
271
+ resolvedMinDimension(
272
+ direction: Direction,
273
+ axis: Dimension,
274
+ referenceLength: number,
275
+ ownerWidth: number,
276
+ ): number {
277
+ const minDimension = this.dimensions_[2 + axis]!;
278
+ if (minDimension.isUndefined()) {
279
+ return NaN;
280
+ }
281
+ const value = minDimension.resolve(referenceLength);
282
+ if (this.boxSizing_ === BoxSizing.BorderBox || !isDefined(value)) {
283
+ return value;
284
+ }
285
+
286
+ const dimensionPaddingAndBorder = this.computePaddingAndBorderForDimension(
287
+ direction,
288
+ axis,
289
+ ownerWidth,
290
+ );
291
+
292
+ return value + (isDefined(dimensionPaddingAndBorder) ? dimensionPaddingAndBorder : 0);
293
+ }
294
+
295
+ resolvedMaxDimension(
296
+ direction: Direction,
297
+ axis: Dimension,
298
+ referenceLength: number,
299
+ ownerWidth: number,
300
+ ): number {
301
+ const maxDimension = this.dimensions_[4 + axis]!;
302
+ if (maxDimension.isUndefined()) {
303
+ return NaN;
304
+ }
305
+ const value = maxDimension.resolve(referenceLength);
306
+ if (this.boxSizing_ === BoxSizing.BorderBox || !isDefined(value)) {
307
+ return value;
308
+ }
309
+
310
+ const dimensionPaddingAndBorder = this.computePaddingAndBorderForDimension(
311
+ direction,
312
+ axis,
313
+ ownerWidth,
314
+ );
315
+
316
+ return value + (isDefined(dimensionPaddingAndBorder) ? dimensionPaddingAndBorder : 0);
317
+ }
318
+
319
+ aspectRatio(): number {
320
+ return this.aspectRatio_;
321
+ }
322
+ setAspectRatio(value: number): void {
323
+ // degenerate aspect ratios act as auto.
324
+ // see https://drafts.csswg.org/css-sizing-4/#valdef-aspect-ratio-ratio
325
+ this.aspectRatio_ = value === 0 || value === Infinity || value === -Infinity ? NaN : value;
326
+ }
327
+
328
+ boxSizing(): BoxSizing {
329
+ return this.boxSizing_;
330
+ }
331
+ setBoxSizing(value: BoxSizing): void {
332
+ this.boxSizing_ = value;
333
+ }
334
+
335
+ horizontalInsetsDefined(): boolean {
336
+ const position = this.position_;
337
+ return (
338
+ position !== null &&
339
+ (position[Edge.Left]!.isDefined() ||
340
+ position[Edge.Right]!.isDefined() ||
341
+ position[Edge.All]!.isDefined() ||
342
+ position[Edge.Horizontal]!.isDefined() ||
343
+ position[Edge.Start]!.isDefined() ||
344
+ position[Edge.End]!.isDefined())
345
+ );
346
+ }
347
+
348
+ verticalInsetsDefined(): boolean {
349
+ const position = this.position_;
350
+ return (
351
+ position !== null &&
352
+ (position[Edge.Top]!.isDefined() ||
353
+ position[Edge.Bottom]!.isDefined() ||
354
+ position[Edge.All]!.isDefined() ||
355
+ position[Edge.Vertical]!.isDefined())
356
+ );
357
+ }
358
+
359
+ hasPositionOrMargin(): boolean {
360
+ return this.position_ !== null || this.margin_ !== null;
361
+ }
362
+
363
+ hasPaddingOrBorder(): boolean {
364
+ return this.padding_ !== null || this.border_ !== null;
365
+ }
366
+
367
+ isFlexStartPositionDefined(axis: FlexDirection, direction: Direction): boolean {
368
+ if (this.position_ === null) return false;
369
+ return this.computePosition(flexStartEdge(axis), direction).isDefined();
370
+ }
371
+
372
+ isFlexStartPositionAuto(axis: FlexDirection, direction: Direction): boolean {
373
+ if (this.position_ === null) return false;
374
+ return this.computePosition(flexStartEdge(axis), direction).isAuto();
375
+ }
376
+
377
+ isInlineStartPositionDefined(axis: FlexDirection, direction: Direction): boolean {
378
+ if (this.position_ === null) return false;
379
+ return this.computePosition(inlineStartEdge(axis, direction), direction).isDefined();
380
+ }
381
+
382
+ isInlineStartPositionAuto(axis: FlexDirection, direction: Direction): boolean {
383
+ if (this.position_ === null) return false;
384
+ return this.computePosition(inlineStartEdge(axis, direction), direction).isAuto();
385
+ }
386
+
387
+ isFlexEndPositionDefined(axis: FlexDirection, direction: Direction): boolean {
388
+ if (this.position_ === null) return false;
389
+ return this.computePosition(flexEndEdge(axis), direction).isDefined();
390
+ }
391
+
392
+ isFlexEndPositionAuto(axis: FlexDirection, direction: Direction): boolean {
393
+ if (this.position_ === null) return false;
394
+ return this.computePosition(flexEndEdge(axis), direction).isAuto();
395
+ }
396
+
397
+ isInlineEndPositionDefined(axis: FlexDirection, direction: Direction): boolean {
398
+ if (this.position_ === null) return false;
399
+ return this.computePosition(inlineEndEdge(axis, direction), direction).isDefined();
400
+ }
401
+
402
+ isInlineEndPositionAuto(axis: FlexDirection, direction: Direction): boolean {
403
+ if (this.position_ === null) return false;
404
+ return this.computePosition(inlineEndEdge(axis, direction), direction).isAuto();
405
+ }
406
+
407
+ computeFlexStartPosition(axis: FlexDirection, direction: Direction, axisSize: number): number {
408
+ if (this.position_ === null) return 0;
409
+ return edgeValueOrZero(this.resolvedPosition(), direction * 4 + flexStartEdge(axis), axisSize);
410
+ }
411
+
412
+ computeInlineStartPosition(axis: FlexDirection, direction: Direction, axisSize: number): number {
413
+ if (this.position_ === null) return 0;
414
+ return edgeValueOrZero(
415
+ this.resolvedPosition(),
416
+ direction * 4 + inlineStartEdge(axis, direction),
417
+ axisSize,
418
+ );
419
+ }
420
+
421
+ computeFlexEndPosition(axis: FlexDirection, direction: Direction, axisSize: number): number {
422
+ if (this.position_ === null) return 0;
423
+ return edgeValueOrZero(this.resolvedPosition(), direction * 4 + flexEndEdge(axis), axisSize);
424
+ }
425
+
426
+ computeInlineEndPosition(axis: FlexDirection, direction: Direction, axisSize: number): number {
427
+ if (this.position_ === null) return 0;
428
+ return edgeValueOrZero(
429
+ this.resolvedPosition(),
430
+ direction * 4 + inlineEndEdge(axis, direction),
431
+ axisSize,
432
+ );
433
+ }
434
+
435
+ computeFlexStartMargin(axis: FlexDirection, direction: Direction, widthSize: number): number {
436
+ if (this.margin_ === null) return 0;
437
+ return edgeValueOrZero(this.resolvedMargin(), direction * 4 + flexStartEdge(axis), widthSize);
438
+ }
439
+
440
+ computeInlineStartMargin(axis: FlexDirection, direction: Direction, widthSize: number): number {
441
+ if (this.margin_ === null) return 0;
442
+ return edgeValueOrZero(
443
+ this.resolvedMargin(),
444
+ direction * 4 + inlineStartEdge(axis, direction),
445
+ widthSize,
446
+ );
447
+ }
448
+
449
+ computeFlexEndMargin(axis: FlexDirection, direction: Direction, widthSize: number): number {
450
+ if (this.margin_ === null) return 0;
451
+ return edgeValueOrZero(this.resolvedMargin(), direction * 4 + flexEndEdge(axis), widthSize);
452
+ }
453
+
454
+ computeInlineEndMargin(axis: FlexDirection, direction: Direction, widthSize: number): number {
455
+ if (this.margin_ === null) return 0;
456
+ return edgeValueOrZero(
457
+ this.resolvedMargin(),
458
+ direction * 4 + inlineEndEdge(axis, direction),
459
+ widthSize,
460
+ );
461
+ }
462
+
463
+ computeFlexStartBorder(axis: FlexDirection, direction: Direction): number {
464
+ if (this.border_ === null) return 0;
465
+ return edgeValueFloored(this.resolvedBorder(), direction * 4 + flexStartEdge(axis), 0);
466
+ }
467
+
468
+ computeInlineStartBorder(axis: FlexDirection, direction: Direction): number {
469
+ if (this.border_ === null) return 0;
470
+ return edgeValueFloored(
471
+ this.resolvedBorder(),
472
+ direction * 4 + inlineStartEdge(axis, direction),
473
+ 0,
474
+ );
475
+ }
476
+
477
+ computeFlexEndBorder(axis: FlexDirection, direction: Direction): number {
478
+ if (this.border_ === null) return 0;
479
+ return edgeValueFloored(this.resolvedBorder(), direction * 4 + flexEndEdge(axis), 0);
480
+ }
481
+
482
+ computeInlineEndBorder(axis: FlexDirection, direction: Direction): number {
483
+ if (this.border_ === null) return 0;
484
+ return edgeValueFloored(
485
+ this.resolvedBorder(),
486
+ direction * 4 + inlineEndEdge(axis, direction),
487
+ 0,
488
+ );
489
+ }
490
+
491
+ computeFlexStartPadding(axis: FlexDirection, direction: Direction, widthSize: number): number {
492
+ if (this.padding_ === null) return 0;
493
+ return edgeValueFloored(this.resolvedPadding(), direction * 4 + flexStartEdge(axis), widthSize);
494
+ }
495
+
496
+ computeInlineStartPadding(axis: FlexDirection, direction: Direction, widthSize: number): number {
497
+ if (this.padding_ === null) return 0;
498
+ return edgeValueFloored(
499
+ this.resolvedPadding(),
500
+ direction * 4 + inlineStartEdge(axis, direction),
501
+ widthSize,
502
+ );
503
+ }
504
+
505
+ computeFlexEndPadding(axis: FlexDirection, direction: Direction, widthSize: number): number {
506
+ if (this.padding_ === null) return 0;
507
+ return edgeValueFloored(this.resolvedPadding(), direction * 4 + flexEndEdge(axis), widthSize);
508
+ }
509
+
510
+ computeInlineEndPadding(axis: FlexDirection, direction: Direction, widthSize: number): number {
511
+ if (this.padding_ === null) return 0;
512
+ return edgeValueFloored(
513
+ this.resolvedPadding(),
514
+ direction * 4 + inlineEndEdge(axis, direction),
515
+ widthSize,
516
+ );
517
+ }
518
+
519
+ computeInlineStartPaddingAndBorder(
520
+ axis: FlexDirection,
521
+ direction: Direction,
522
+ widthSize: number,
523
+ ): number {
524
+ return (
525
+ this.computeInlineStartPadding(axis, direction, widthSize) +
526
+ this.computeInlineStartBorder(axis, direction)
527
+ );
528
+ }
529
+
530
+ computeFlexStartPaddingAndBorder(
531
+ axis: FlexDirection,
532
+ direction: Direction,
533
+ widthSize: number,
534
+ ): number {
535
+ return (
536
+ this.computeFlexStartPadding(axis, direction, widthSize) +
537
+ this.computeFlexStartBorder(axis, direction)
538
+ );
539
+ }
540
+
541
+ computeInlineEndPaddingAndBorder(
542
+ axis: FlexDirection,
543
+ direction: Direction,
544
+ widthSize: number,
545
+ ): number {
546
+ return (
547
+ this.computeInlineEndPadding(axis, direction, widthSize) +
548
+ this.computeInlineEndBorder(axis, direction)
549
+ );
550
+ }
551
+
552
+ computeFlexEndPaddingAndBorder(
553
+ axis: FlexDirection,
554
+ direction: Direction,
555
+ widthSize: number,
556
+ ): number {
557
+ return (
558
+ this.computeFlexEndPadding(axis, direction, widthSize) +
559
+ this.computeFlexEndBorder(axis, direction)
560
+ );
561
+ }
562
+
563
+ computePaddingAndBorderForDimension(
564
+ direction: Direction,
565
+ dimension: Dimension,
566
+ widthSize: number,
567
+ ): number {
568
+ const flexDirectionForDimension =
569
+ dimension === Dimension.Width ? FlexDirection.Row : FlexDirection.Column;
570
+
571
+ return (
572
+ this.computeFlexStartPaddingAndBorder(flexDirectionForDimension, direction, widthSize) +
573
+ this.computeFlexEndPaddingAndBorder(flexDirectionForDimension, direction, widthSize)
574
+ );
575
+ }
576
+
577
+ computeBorderForAxis(axis: FlexDirection): number {
578
+ const resolved = this.resolvedBorder();
579
+ if (resolved === null) {
580
+ return 0;
581
+ }
582
+ const startEdge = isRow(axis) ? PhysicalEdge.Left : PhysicalEdge.Top;
583
+ return (
584
+ edgeValueFloored(resolved, Direction.LTR * 4 + startEdge, 0) +
585
+ edgeValueFloored(resolved, Direction.LTR * 4 + startEdge + 2, 0)
586
+ );
587
+ }
588
+
589
+ computeMarginForAxis(axis: FlexDirection, widthSize: number): number {
590
+ // The total margin for a given axis does not depend on the direction
591
+ // so hardcoding LTR here to avoid piping direction to this function
592
+ const resolved = this.resolvedMargin();
593
+ if (resolved === null) {
594
+ return 0;
595
+ }
596
+ const startEdge = isRow(axis) ? PhysicalEdge.Left : PhysicalEdge.Top;
597
+ return (
598
+ edgeValueOrZero(resolved, Direction.LTR * 4 + startEdge, widthSize) +
599
+ edgeValueOrZero(resolved, Direction.LTR * 4 + startEdge + 2, widthSize)
600
+ );
601
+ }
602
+
603
+ computeGapForAxis(axis: FlexDirection, ownerSize: number): number {
604
+ if (this.gap_ === null) {
605
+ return 0;
606
+ }
607
+ const gap = isRow(axis) ? this.computeColumnGap() : this.computeRowGap();
608
+ return maxOrDefined(gap.resolve(ownerSize), 0);
609
+ }
610
+
611
+ computeGapForDimension(dimension: Dimension, ownerSize: number): number {
612
+ if (this.gap_ === null) {
613
+ return 0;
614
+ }
615
+ const gap = dimension === Dimension.Width ? this.computeColumnGap() : this.computeRowGap();
616
+ return maxOrDefined(gap.resolve(ownerSize), 0);
617
+ }
618
+
619
+ flexStartMarginIsAuto(axis: FlexDirection, direction: Direction): boolean {
620
+ if (this.margin_ === null) return false;
621
+ return this.computeMargin(flexStartEdge(axis), direction).isAuto();
622
+ }
623
+
624
+ flexEndMarginIsAuto(axis: FlexDirection, direction: Direction): boolean {
625
+ if (this.margin_ === null) return false;
626
+ return this.computeMargin(flexEndEdge(axis), direction).isAuto();
627
+ }
628
+
629
+ inlineStartMarginIsAuto(axis: FlexDirection, direction: Direction): boolean {
630
+ if (this.margin_ === null) return false;
631
+ return this.computeMargin(inlineStartEdge(axis, direction), direction).isAuto();
632
+ }
633
+
634
+ inlineEndMarginIsAuto(axis: FlexDirection, direction: Direction): boolean {
635
+ if (this.margin_ === null) return false;
636
+ return this.computeMargin(inlineEndEdge(axis, direction), direction).isAuto();
637
+ }
638
+
639
+ equals(other: Style): boolean {
640
+ // A null (never-set) edge array compares equal to one holding only
641
+ // undefined values.
642
+ const lengthsEqual = (a: StyleLength[] | null, b: StyleLength[] | null, count: number) => {
643
+ if (a === b) {
644
+ return true;
645
+ }
646
+ for (let i = 0; i < count; i++) {
647
+ const left = a !== null ? a[i]! : StyleLength.undefined();
648
+ const right = b !== null ? b[i]! : StyleLength.undefined();
649
+ if (!left.equals(right)) {
650
+ return false;
651
+ }
652
+ }
653
+ return true;
654
+ };
655
+ const numbersEqual = (a: number, b: number) => a === b || (Number.isNaN(a) && Number.isNaN(b));
656
+
657
+ return (
658
+ this.direction_ === other.direction_ &&
659
+ this.flexDirection_ === other.flexDirection_ &&
660
+ this.justifyContent_ === other.justifyContent_ &&
661
+ this.justifyItems_ === other.justifyItems_ &&
662
+ this.justifySelf_ === other.justifySelf_ &&
663
+ this.alignContent_ === other.alignContent_ &&
664
+ this.alignItems_ === other.alignItems_ &&
665
+ this.alignSelf_ === other.alignSelf_ &&
666
+ this.positionType_ === other.positionType_ &&
667
+ this.flexWrap_ === other.flexWrap_ &&
668
+ this.overflow_ === other.overflow_ &&
669
+ this.display_ === other.display_ &&
670
+ this.boxSizing_ === other.boxSizing_ &&
671
+ numbersEqual(this.flex_, other.flex_) &&
672
+ numbersEqual(this.flexGrow_, other.flexGrow_) &&
673
+ numbersEqual(this.flexShrink_, other.flexShrink_) &&
674
+ this.flexBasis_.equals(other.flexBasis_) &&
675
+ lengthsEqual(this.margin_, other.margin_, EDGE_COUNT) &&
676
+ lengthsEqual(this.position_, other.position_, EDGE_COUNT) &&
677
+ lengthsEqual(this.padding_, other.padding_, EDGE_COUNT) &&
678
+ lengthsEqual(this.border_, other.border_, EDGE_COUNT) &&
679
+ lengthsEqual(this.gap_, other.gap_, GUTTER_COUNT) &&
680
+ this.dimensions_.every((value, i) => value.equals(other.dimensions_[i]!)) &&
681
+ numbersEqual(this.aspectRatio_, other.aspectRatio_)
682
+ );
683
+ }
684
+
685
+ copyFrom(other: Style): void {
686
+ this.direction_ = other.direction_;
687
+ this.flexDirection_ = other.flexDirection_;
688
+ this.justifyContent_ = other.justifyContent_;
689
+ this.justifyItems_ = other.justifyItems_;
690
+ this.justifySelf_ = other.justifySelf_;
691
+ this.alignContent_ = other.alignContent_;
692
+ this.alignItems_ = other.alignItems_;
693
+ this.alignSelf_ = other.alignSelf_;
694
+ this.positionType_ = other.positionType_;
695
+ this.flexWrap_ = other.flexWrap_;
696
+ this.overflow_ = other.overflow_;
697
+ this.display_ = other.display_;
698
+ this.boxSizing_ = other.boxSizing_;
699
+ this.flex_ = other.flex_;
700
+ this.flexGrow_ = other.flexGrow_;
701
+ this.flexShrink_ = other.flexShrink_;
702
+ this.flexBasis_ = other.flexBasis_;
703
+ this.margin_ = other.margin_ !== null ? other.margin_.slice() : null;
704
+ this.position_ = other.position_ !== null ? other.position_.slice() : null;
705
+ this.padding_ = other.padding_ !== null ? other.padding_.slice() : null;
706
+ this.border_ = other.border_ !== null ? other.border_.slice() : null;
707
+ this.gap_ = other.gap_ !== null ? other.gap_.slice() : null;
708
+ this.marginResolved_ = null;
709
+ this.positionResolved_ = null;
710
+ this.paddingResolved_ = null;
711
+ this.borderResolved_ = null;
712
+ this.dimensions_ = other.dimensions_.slice();
713
+ this.aspectRatio_ = other.aspectRatio_;
714
+ }
715
+
716
+ private computeColumnGap(): StyleLength {
717
+ const gap = this.gap_;
718
+ if (gap === null) {
719
+ return StyleLength.undefined();
720
+ }
721
+ return gap[Gutter.Column]!.isDefined() ? gap[Gutter.Column]! : gap[Gutter.All]!;
722
+ }
723
+
724
+ private computeRowGap(): StyleLength {
725
+ const gap = this.gap_;
726
+ if (gap === null) {
727
+ return StyleLength.undefined();
728
+ }
729
+ return gap[Gutter.Row]!.isDefined() ? gap[Gutter.Row]! : gap[Gutter.All]!;
730
+ }
731
+
732
+ private computeLeftEdge(edges: StyleLength[], layoutDirection: Direction): StyleLength {
733
+ if (layoutDirection === Direction.LTR && edges[Edge.Start]!.isDefined()) {
734
+ return edges[Edge.Start]!;
735
+ } else if (layoutDirection === Direction.RTL && edges[Edge.End]!.isDefined()) {
736
+ return edges[Edge.End]!;
737
+ } else if (edges[Edge.Left]!.isDefined()) {
738
+ return edges[Edge.Left]!;
739
+ } else if (edges[Edge.Horizontal]!.isDefined()) {
740
+ return edges[Edge.Horizontal]!;
741
+ } else {
742
+ return edges[Edge.All]!;
743
+ }
744
+ }
745
+
746
+ private computeTopEdge(edges: StyleLength[]): StyleLength {
747
+ if (edges[Edge.Top]!.isDefined()) {
748
+ return edges[Edge.Top]!;
749
+ } else if (edges[Edge.Vertical]!.isDefined()) {
750
+ return edges[Edge.Vertical]!;
751
+ } else {
752
+ return edges[Edge.All]!;
753
+ }
754
+ }
755
+
756
+ private computeRightEdge(edges: StyleLength[], layoutDirection: Direction): StyleLength {
757
+ if (layoutDirection === Direction.LTR && edges[Edge.End]!.isDefined()) {
758
+ return edges[Edge.End]!;
759
+ } else if (layoutDirection === Direction.RTL && edges[Edge.Start]!.isDefined()) {
760
+ return edges[Edge.Start]!;
761
+ } else if (edges[Edge.Right]!.isDefined()) {
762
+ return edges[Edge.Right]!;
763
+ } else if (edges[Edge.Horizontal]!.isDefined()) {
764
+ return edges[Edge.Horizontal]!;
765
+ } else {
766
+ return edges[Edge.All]!;
767
+ }
768
+ }
769
+
770
+ private computeBottomEdge(edges: StyleLength[]): StyleLength {
771
+ if (edges[Edge.Bottom]!.isDefined()) {
772
+ return edges[Edge.Bottom]!;
773
+ } else if (edges[Edge.Vertical]!.isDefined()) {
774
+ return edges[Edge.Vertical]!;
775
+ } else {
776
+ return edges[Edge.All]!;
777
+ }
778
+ }
779
+
780
+ // Resolves all four physical edges for all three directions at once, so
781
+ // subsequent lookups are a single indexed read.
782
+ private buildResolvedEdges(edges: StyleLength[]): ResolvedEdges {
783
+ const lengths = Array.from<StyleLength>({ length: 12 });
784
+ const units = new Uint8Array(12);
785
+ const values = Array.from<number>({ length: 12 });
786
+ for (const direction of [Direction.Inherit, Direction.LTR, Direction.RTL]) {
787
+ lengths[direction * 4 + PhysicalEdge.Left] = this.computeLeftEdge(edges, direction);
788
+ lengths[direction * 4 + PhysicalEdge.Top] = this.computeTopEdge(edges);
789
+ lengths[direction * 4 + PhysicalEdge.Right] = this.computeRightEdge(edges, direction);
790
+ lengths[direction * 4 + PhysicalEdge.Bottom] = this.computeBottomEdge(edges);
791
+ }
792
+ for (let i = 0; i < 12; i++) {
793
+ units[i] = lengths[i]!.unit;
794
+ values[i] = lengths[i]!.value;
795
+ }
796
+ return { lengths, units, values };
797
+ }
798
+
799
+ private resolvedPosition(): ResolvedEdges | null {
800
+ return this.position_ === null
801
+ ? null
802
+ : (this.positionResolved_ ??= this.buildResolvedEdges(this.position_));
803
+ }
804
+
805
+ private resolvedMargin(): ResolvedEdges | null {
806
+ return this.margin_ === null
807
+ ? null
808
+ : (this.marginResolved_ ??= this.buildResolvedEdges(this.margin_));
809
+ }
810
+
811
+ private resolvedPadding(): ResolvedEdges | null {
812
+ return this.padding_ === null
813
+ ? null
814
+ : (this.paddingResolved_ ??= this.buildResolvedEdges(this.padding_));
815
+ }
816
+
817
+ private resolvedBorder(): ResolvedEdges | null {
818
+ return this.border_ === null
819
+ ? null
820
+ : (this.borderResolved_ ??= this.buildResolvedEdges(this.border_));
821
+ }
822
+
823
+ computePosition(edge: PhysicalEdge, direction: Direction): StyleLength {
824
+ const resolved = this.resolvedPosition();
825
+ return resolved === null ? StyleLength.undefined() : resolved.lengths[direction * 4 + edge]!;
826
+ }
827
+
828
+ computeMargin(edge: PhysicalEdge, direction: Direction): StyleLength {
829
+ const resolved = this.resolvedMargin();
830
+ return resolved === null ? StyleLength.undefined() : resolved.lengths[direction * 4 + edge]!;
831
+ }
832
+
833
+ computePadding(edge: PhysicalEdge, direction: Direction): StyleLength {
834
+ const resolved = this.resolvedPadding();
835
+ return resolved === null ? StyleLength.undefined() : resolved.lengths[direction * 4 + edge]!;
836
+ }
837
+
838
+ computeBorder(edge: PhysicalEdge, direction: Direction): StyleLength {
839
+ const resolved = this.resolvedBorder();
840
+ return resolved === null ? StyleLength.undefined() : resolved.lengths[direction * 4 + edge]!;
841
+ }
842
+ }
843
+
844
+ // Resolve a memoized edge to a number with undefined defaulting to 0
845
+ // (StyleLength.resolve + unwrapOrDefault(0)).
846
+ function edgeValueOrZero(
847
+ resolved: ResolvedEdges | null,
848
+ index: number,
849
+ referenceLength: number,
850
+ ): number {
851
+ if (resolved === null) {
852
+ return 0;
853
+ }
854
+ const unit = resolved.units[index]!;
855
+ if (unit === Unit.Point) {
856
+ return resolved.values[index]!;
857
+ }
858
+ if (unit === Unit.Percent) {
859
+ const value = resolved.values[index]! * referenceLength * 0.01;
860
+ // An undefined reference length resolves the percentage to undefined,
861
+ // which defaults to 0 here.
862
+ return Number.isNaN(value) ? 0 : value;
863
+ }
864
+ return 0;
865
+ }
866
+
867
+ // Resolve a memoized edge to a number floored at 0 (maxOrDefined(resolve, 0)),
868
+ // as used for padding and border.
869
+ function edgeValueFloored(
870
+ resolved: ResolvedEdges | null,
871
+ index: number,
872
+ referenceLength: number,
873
+ ): number {
874
+ if (resolved === null) {
875
+ return 0;
876
+ }
877
+ const unit = resolved.units[index]!;
878
+ if (unit === Unit.Point) {
879
+ const value = resolved.values[index]!;
880
+ return value > 0 ? value : 0;
881
+ }
882
+ if (unit === Unit.Percent) {
883
+ const value = resolved.values[index]! * referenceLength * 0.01;
884
+ return value > 0 ? value : 0;
885
+ }
886
+ return 0;
887
+ }