gesso-core 0.6.30 → 0.7.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.
@@ -1685,6 +1685,18 @@ interface UiColors {
1685
1685
  readonly focusRing: UiColor;
1686
1686
  readonly selectionBackground: UiColor;
1687
1687
  readonly selectionForeground: UiColor;
1688
+ /**
1689
+ * A tooltip's box and its text.
1690
+ *
1691
+ * Their own pair rather than the control pair swapped round, which is
1692
+ * what a tooltip used to be: that is dark on a light page, but on a
1693
+ * dark one it turned the tooltip near-white, the brightest thing on
1694
+ * the screen for a label that should sit quietly over it. A tooltip
1695
+ * stays dark in both palettes, as the platforms draw theirs; in the
1696
+ * dark one a step lighter than the panels, so it lifts off them.
1697
+ */
1698
+ readonly tooltipBackground: UiColor;
1699
+ readonly tooltipForeground: UiColor;
1688
1700
  }
1689
1701
  /**
1690
1702
  * The stock palettes.
@@ -3111,6 +3123,22 @@ type UiPropValue = unknown | Observable<unknown>;
3111
3123
  type UiProps = Record<string, UiPropValue>;
3112
3124
  //#endregion
3113
3125
  //#region src/composition/UiElement.d.ts
3126
+ /**
3127
+ * Where an element was written: the location the JSX compiler passes
3128
+ * `jsxDEV` in development.
3129
+ *
3130
+ * Kept so a tool can go from a node on screen back to the line that
3131
+ * made it, which a canvas otherwise cannot do: there is no DOM for a
3132
+ * browser's own inspector to point at. A production build compiles to
3133
+ * `jsx`, which is given none, so it costs nothing there.
3134
+ */
3135
+ interface UiSourceLocation {
3136
+ readonly fileName: string;
3137
+ /** One-based, as the compiler gives it. */
3138
+ readonly lineNumber: number;
3139
+ /** One-based, as the compiler gives it. */
3140
+ readonly columnNumber: number;
3141
+ }
3114
3142
  /**
3115
3143
  * Opaque marker for component definitions.
3116
3144
  *
@@ -3126,6 +3154,8 @@ interface ComponentLikeElement {
3126
3154
  readonly component: Function;
3127
3155
  readonly props: Record<string, unknown>;
3128
3156
  readonly key?: string | number;
3157
+ /** Where the component was used, in development; see `UiSourceLocation`. */
3158
+ readonly source?: UiSourceLocation;
3129
3159
  }
3130
3160
  /**
3131
3161
  * A child definition may be a static element, a component definition,
@@ -3158,6 +3188,8 @@ interface UiElement {
3158
3188
  * definitions.
3159
3189
  */
3160
3190
  readonly children: readonly UiChild[];
3191
+ /** Where the element was written, in development; see `UiSourceLocation`. */
3192
+ readonly source?: UiSourceLocation;
3161
3193
  }
3162
3194
  /**
3163
3195
  * Returns true when the value is a component definition.
@@ -4086,10 +4118,20 @@ declare class UiContainerSizeSource implements UiContainerSize {
4086
4118
  */
4087
4119
  declare function bandOf(width: number, breakpoints: readonly number[]): number;
4088
4120
  /**
4089
- * The width bands of a container, one value per band entered.
4121
+ * The width bands of a container, one value per band entered, and once
4122
+ * more at the first size measured.
4090
4123
  *
4091
4124
  * What `Responsive` builds its children from, and what an author who
4092
4125
  * wants only a number rather than a subtree can subscribe to directly.
4126
+ *
4127
+ * The first value is the size before any layout, usually zeroes, and
4128
+ * the first measurement is the real one. Emitting only when the band
4129
+ * changed left a container whose real width fell in the same band as
4130
+ * the guess built from the guess for good, so a builder that reads the
4131
+ * width (`size.width < 600` inside the `[1024]` band) was handed zero
4132
+ * on a 768-wide tablet. One more value at the first measurement costs
4133
+ * one more build at most, once, and every build after it sees a size
4134
+ * that was measured.
4093
4135
  */
4094
4136
  declare function containerBands(size: UiContainerSize, breakpoints: readonly number[]): Observable<number>;
4095
4137
  //#endregion
@@ -4186,1360 +4228,1511 @@ declare class UiInsetRegistry implements UiInsetSource {
4186
4228
  */
4187
4229
  declare function observeViewportInsets(onChange: (insets: UiInsets) => void): () => void;
4188
4230
  //#endregion
4189
- //#region src/properties/UiPropertyDefinition.d.ts
4231
+ //#region src/environment/UiSpacing.d.ts
4190
4232
  /**
4191
- * Metadata describing a single UI property.
4192
- *
4193
- * The runtime uses this definition to know:
4233
+ * A renderer-independent spacing scale.
4194
4234
  *
4195
- * - what the property is called
4196
- * - what value to use when none is specified
4197
- * - whether the value inherits from the scoped environment
4198
- * - what changing the value invalidates
4199
- * - how to compare two values for equality
4235
+ * Each value is a logical pixel gap. The names are the shape scale's
4236
+ * names on purpose: an application that has learned `borderRadius`
4237
+ * from `theme.shapes` already knows what `small` and `extraLarge`
4238
+ * mean, and one vocabulary across the theme is one thing to learn.
4200
4239
  *
4201
- * A property may optionally declare an environment key and a
4202
- * resolver that extracts the property value from that environment
4203
- * value. When `environmentKey` is absent, inherited properties look
4204
- * for an environment key whose name matches the property name.
4240
+ * Eight steps rather than the shape scale's seven, because spacing is
4241
+ * the token an application reaches for most often and a scale that
4242
+ * cannot say "two" sends the author back to a literal. The values are
4243
+ * a four pixel grid with a two pixel step at the bottom, which is what
4244
+ * the two applications' own numbers already cluster on.
4205
4245
  */
4206
- interface UiPropertyDefinition<T> {
4207
- readonly name: string;
4208
- readonly defaultValue: T;
4209
- readonly inherited: boolean;
4210
- readonly affects: DirtyFlags;
4211
- readonly compare?: (a: T, b: T) => boolean;
4212
- readonly environmentKey?: UiEnvironmentKey<unknown>;
4213
- readonly resolveFromEnvironment?: (value: unknown) => T;
4214
- /**
4215
- * Rejects a value the property cannot hold, returning the message
4216
- * for the error the builder throws. Declared only by properties with
4217
- * a closed set of values, such as `role`; the builder checks it when
4218
- * a plain value is written, so it costs nothing on the graph's own
4219
- * write path. A value arriving through an Observable is checked by
4220
- * whatever reads it, as a bound length is checked at layout.
4221
- */
4222
- readonly validate?: (value: T) => string | undefined;
4223
- /**
4224
- * Narrows `affects` for one particular change, when what changed
4225
- * shows that less is invalid than the property's worst case.
4226
- *
4227
- * `paint` is the reason it exists. A painter may declare an intrinsic
4228
- * size, so a new painter can change layout, and `affects` has to say
4229
- * so; but a new picture with the same declared size (usually none)
4230
- * cannot, and marking layout for it laid the tree out again up to the
4231
- * nearest relayout boundary on every repaint, which for a painted
4232
- * node sized by its parent was the root, every frame of a scroll.
4233
- * Given the old and new values and the flags `affects` gives, it
4234
- * returns the flags this change actually needs.
4235
- */
4236
- readonly narrowEffects?: (previous: T, next: T, flags: DirtyFlags) => DirtyFlags;
4246
+ interface UiSpacing {
4247
+ readonly none: number;
4248
+ readonly hairline: number;
4249
+ readonly extraSmall: number;
4250
+ readonly small: number;
4251
+ readonly medium: number;
4252
+ readonly large: number;
4253
+ readonly extraLarge: number;
4254
+ readonly huge: number;
4237
4255
  }
4256
+ declare const defaultSpacing: UiSpacing;
4257
+ /** The steps, in order, for a scale that is derived rather than written out. */
4258
+ declare const spacingSteps: readonly (keyof UiSpacing)[];
4238
4259
  /**
4239
- * Creates a property definition with the supplied metadata.
4260
+ * The same scale at a different density.
4240
4261
  *
4241
- * The default compare function is reference equality (`Object.is`).
4262
+ * Rounded to whole pixels, because a padding that lands on a half
4263
+ * pixel puts every box inside it on one too, and the renderers snap
4264
+ * differently at that point. `none` stays zero at every density: a gap
4265
+ * an application asked not to have is not a gap to shrink.
4242
4266
  */
4243
- declare function defineProperty<T>(options: Omit<UiPropertyDefinition<T>, 'name'> & {
4244
- name: string;
4245
- }): UiPropertyDefinition<T>;
4267
+ declare function scaleSpacing(spacing: UiSpacing, factor: number): UiSpacing;
4246
4268
  /**
4247
- * Compares two property values using the definition's comparison
4248
- * function, falling back to `Object.is` when none is provided.
4269
+ * Compares two spacing scales for equality.
4249
4270
  */
4250
- declare function propertyValuesEqual<T>(definition: UiPropertyDefinition<T>, a: T, b: T): boolean;
4271
+ declare function spacingEqual(a: UiSpacing, b: UiSpacing): boolean;
4251
4272
  //#endregion
4252
- //#region src/properties/UiBoxShadow.d.ts
4273
+ //#region src/properties/UiTextStyle.d.ts
4253
4274
  /**
4254
- * Renderer-independent box shadow description, with CSS `box-shadow`
4255
- * semantics.
4275
+ * A coherent typography value.
4256
4276
  *
4257
- * An outer shadow is the node's (rounded) box, grown by `spreadRadius`
4258
- * on every side, moved by the offset, blurred by `blurRadius` (a
4259
- * Gaussian whose standard deviation is half of it), and seen only
4260
- * outside the box. An inset one is the same shape inverted and seen
4261
- * only inside the box. `color` may be a palette name, resolved against
4262
- * the node's theme as `backgroundColor` is.
4277
+ * TextStyle is the unit of inheritance: a parent can provide a
4278
+ * TextStyle and descendants can override individual fields while
4279
+ * keeping the rest.
4280
+ *
4281
+ * The four fields below `textDirection` are optional because the
4282
+ * environment's typography roles were written before they existed and
4283
+ * a role that says nothing about them means "normal", which is what
4284
+ * their property defaults already say.
4263
4285
  */
4264
- interface UiBoxShadow {
4265
- readonly offsetX: number;
4266
- readonly offsetY: number;
4267
- readonly blurRadius: number;
4268
- readonly spreadRadius: number;
4269
- readonly color: UiColorValue;
4270
- readonly inset?: boolean;
4286
+ interface UiTextStyle {
4287
+ readonly fontFamily: string;
4288
+ readonly fontSize: number;
4289
+ readonly fontWeight: UiFontWeight;
4290
+ readonly lineHeight: number;
4291
+ readonly letterSpacing: number;
4292
+ readonly color: UiColor;
4293
+ readonly textAlign: UiTextAlign;
4294
+ readonly textDirection: UiTextDirection;
4295
+ readonly fontStyle?: UiFontStyle;
4296
+ readonly fontStretch?: UiFontStretch;
4297
+ readonly fontVariant?: UiFontVariant;
4298
+ readonly fontKerning?: UiFontKerning;
4299
+ readonly textDecoration?: UiTextDecoration;
4271
4300
  }
4301
+ /** Upright or sloped. `oblique` is a synthesised slant where no italic face exists. */
4302
+ type UiFontStyle = 'normal' | 'italic' | 'oblique';
4272
4303
  /**
4273
- * Creates a box shadow with the supplied parameters.
4274
- */
4275
- declare function boxShadow(offsetX: number, offsetY: number, blurRadius: number, spreadRadius: number, color: UiColorValue, inset?: boolean): UiBoxShadow;
4276
- /**
4277
- * Compares two box shadows for equality.
4304
+ * The width axis, as CSS names it.
4305
+ *
4306
+ * A variable font's `wdth` is reached through these keywords and
4307
+ * nowhere else: the Canvas2D context takes `fontStretch` as a
4308
+ * property, and a font string cannot carry an axis tuple.
4278
4309
  */
4279
- declare function boxShadowsEqual(a: UiBoxShadow, b: UiBoxShadow): boolean;
4310
+ type UiFontStretch = 'ultra-condensed' | 'extra-condensed' | 'condensed' | 'semi-condensed' | 'normal' | 'semi-expanded' | 'expanded' | 'extra-expanded' | 'ultra-expanded';
4280
4311
  /**
4281
- * Compares two shadow arrays for equality.
4312
+ * The one font-variant value the CSS font shorthand carries, and so
4313
+ * the one a canvas font string carries. `font-feature-settings` is not
4314
+ * part of the shorthand and the context has no property for it, which
4315
+ * is why `tnum` and `liga` are not here.
4282
4316
  */
4283
- declare function boxShadowArraysEqual(a: readonly UiBoxShadow[], b: readonly UiBoxShadow[]): boolean;
4317
+ type UiFontVariant = 'normal' | 'small-caps';
4318
+ /** Whether the shaper applies the font's kerning pairs. */
4319
+ type UiFontKerning = 'auto' | 'normal' | 'none';
4320
+ /** Lines drawn with the text. Both may be asked for at once. */
4321
+ type UiTextDecoration = 'none' | 'underline' | 'line-through' | 'underline line-through';
4284
4322
  /**
4285
- * How far a shadow's blur reaches past the edge of its shape, as a
4286
- * multiple of `blurRadius`.
4323
+ * The fields of a style that change how wide its text measures.
4287
4324
  *
4288
- * The blur is a Gaussian with a standard deviation of half the radius,
4289
- * so this is three standard deviations: what is left beyond it is
4290
- * under a quarter of a percent of the shadow's colour, and both
4291
- * renderers stop drawing there.
4292
- */
4293
- declare const BOX_SHADOW_BLUR_REACH = 1.5;
4294
- /**
4295
- * The corner radius of a shadow's shape, from the box's and the
4296
- * spread: an outer shadow's corner grows with its spread, an inset
4297
- * one's hole shrinks with it. A square corner stays square, as CSS
4298
- * keeps it.
4325
+ * The split matters: only these reach the measure request, so a run
4326
+ * that changes colour, background or underline is repainted from the
4327
+ * paragraph the cache already holds, and only a run that changes font
4328
+ * makes the paragraph new. See `TextMeasurer.ts`.
4299
4329
  */
4300
- declare function boxShadowRadius(boxRadius: number, spreadRadius: number, inset: boolean): number;
4330
+ interface UiTextMetrics {
4331
+ readonly fontFamily?: string;
4332
+ readonly fontSize?: number;
4333
+ readonly fontWeight?: UiFontWeight;
4334
+ readonly fontStyle?: UiFontStyle;
4335
+ readonly fontStretch?: UiFontStretch;
4336
+ readonly fontVariant?: UiFontVariant;
4337
+ readonly fontKerning?: UiFontKerning;
4338
+ readonly letterSpacing?: number;
4339
+ /**
4340
+ * Kept in the text but not drawn: the run takes no room, paints
4341
+ * nothing, and a caret steps over it as one unit.
4342
+ *
4343
+ * It is a metric field because it changes a width, to nothing. Its
4344
+ * characters stay where they were, so every offset still means what
4345
+ * it meant, a copy of the text still copies them, and the semantics
4346
+ * mirror still reads them. It is how an editor that styles markup
4347
+ * as it is typed (`**bold**` drawn as a bold word) puts the markers
4348
+ * out of sight without taking them out of the string.
4349
+ */
4350
+ readonly hidden?: boolean;
4351
+ }
4301
4352
  /**
4302
- * How far past each side of the box a node's outer shadows may paint,
4303
- * written into `out`; all zero for a node with none. Inset shadows
4304
- * paint inside the box and add nothing.
4353
+ * A run that is activated rather than only read.
4354
+ *
4355
+ * `onClick` runs on a press that neither moved nor selected, and on
4356
+ * Enter or Space while the run is focused. `label` names the run in
4357
+ * the semantics mirror when the text itself would not ("here" is a
4358
+ * link a screen reader cannot use); `href` is carried for the
4359
+ * application's own use and the runtime never navigates to it.
4305
4360
  */
4306
- declare function boxShadowReach(shadows: readonly UiBoxShadow[], out: {
4307
- left: number;
4308
- top: number;
4309
- right: number;
4310
- bottom: number;
4311
- }): void;
4312
- //#endregion
4313
- //#region src/layout/UiLength.d.ts
4361
+ interface UiTextLink {
4362
+ readonly onClick?: () => void;
4363
+ readonly label?: string;
4364
+ readonly href?: string;
4365
+ }
4314
4366
  /**
4315
- * Length values accepted by size and offset properties.
4367
+ * One run of a paragraph, with the style fields it overrides.
4316
4368
  *
4317
- * A plain number is logical pixels. Anything else is a small tagged
4318
- * object built by the helpers below — never a string to parse — so a
4319
- * typo is a type error, and a malformed value reaching the engine at
4320
- * runtime throws at layout rather than silently becoming zero.
4369
+ * A `Text` node takes either a `text` string or a `spans` array, and
4370
+ * the array is the whole of the paragraph: its texts concatenated in
4371
+ * order are the text, so every offset the rest of the runtime
4372
+ * works in — a line's `start`, a selection range, a find match, a
4373
+ * caret — means the same thing whether the paragraph has runs or not.
4374
+ * That is the property the whole feature rests on, and it is why runs
4375
+ * are a shape of one paragraph rather than a tree of nodes.
4321
4376
  *
4322
- * width: 200 // pixels
4323
- * width: percent(50) // half of the containing size, when it is
4324
- * // definite; behaves as `auto` otherwise
4325
- * margin: auto // main-axis auto margins absorb free space;
4326
- * // cross-axis ones centre the item
4327
- * minWidth: auto // the default: a flex item's automatic
4328
- * // minimum, its min-content size
4377
+ * Anything a span does not set it inherits from the node, and the
4378
+ * node from its environment, exactly as a node inherits today.
4329
4379
  */
4330
- interface PercentLength {
4331
- readonly unit: 'percent';
4332
- readonly value: number;
4333
- }
4334
- interface AutoLength {
4335
- readonly unit: 'auto';
4380
+ interface UiTextSpan extends UiTextMetrics {
4381
+ readonly text: string;
4382
+ readonly color?: UiColorValue;
4383
+ readonly backgroundColor?: UiColorValue;
4384
+ readonly textDecoration?: UiTextDecoration;
4385
+ readonly link?: UiTextLink;
4336
4386
  }
4337
- type UiLength = number | PercentLength | AutoLength;
4338
- /** A grid track that takes a share of free space, `fr(1)`. */
4339
- interface FrLength {
4340
- readonly unit: 'fr';
4341
- readonly value: number;
4387
+ /** A span placed in the flattened text: the same fields, plus where it is. */
4388
+ interface UiResolvedTextSpan extends UiTextMetrics {
4389
+ readonly start: number;
4390
+ readonly end: number;
4391
+ readonly color?: UiColorValue;
4392
+ readonly backgroundColor?: UiColorValue;
4393
+ readonly textDecoration?: UiTextDecoration;
4394
+ readonly link?: UiTextLink;
4342
4395
  }
4343
- /** A grid track bounded below and above, `minmax(100, fr(1))`. */
4344
- interface MinMaxTrack {
4345
- readonly unit: 'minmax';
4346
- readonly min: number | PercentLength | AutoLength;
4347
- readonly max: number | PercentLength | AutoLength | FrLength;
4396
+ /** A paragraph's text and the runs inside it. */
4397
+ interface UiSpannedText {
4398
+ readonly text: string;
4399
+ readonly spans: readonly UiResolvedTextSpan[];
4348
4400
  }
4349
- /** What a grid's `columns` / `rows` arrays hold. */
4350
- type UiTrackSize = number | PercentLength | AutoLength | FrLength | MinMaxTrack;
4351
- declare function fr(value: number): FrLength;
4352
- declare function minmax(min: MinMaxTrack['min'], max: MinMaxTrack['max']): MinMaxTrack;
4353
- /** `repeat(3, fr(1))` → three `fr(1)` tracks; several sizes repeat as a pattern. */
4354
- declare function repeat(count: number, ...sizes: UiTrackSize[]): UiTrackSize[];
4355
- declare function isFrLength(value: unknown): value is FrLength;
4356
- declare function isMinMaxTrack(value: unknown): value is MinMaxTrack;
4357
- declare function percent(value: number): PercentLength;
4358
- declare const auto: AutoLength;
4359
- declare function isAutoLength(value: unknown): value is AutoLength | 'auto';
4360
- declare function isPercentLength(value: unknown): value is PercentLength;
4361
4401
  /**
4362
- * Resolves a property value to pixels.
4363
- *
4364
- * Returns `undefined` when the property is unset, `null`, `auto`, or a
4365
- * percentage of an indefinite size — every case the caller treats as
4366
- * "no value". Returns `'auto'` only when `keepAuto` is set, for the
4367
- * properties where auto means something (margins, minimum sizes).
4402
+ * What text is set in when nothing says otherwise.
4368
4403
  *
4369
- * Anything else that is not a finite number or a tagged length throws,
4370
- * naming the property: `width: '100%'` must fail loudly, not lay out
4371
- * as if the property were absent.
4404
+ * `system-ui` is the platform's own interface face (San Francisco,
4405
+ * Segoe UI, Roboto), which is what an application on that platform is
4406
+ * expected to look like; `sans-serif` is there for an engine that does
4407
+ * not know the generic. The line is 20 on 14, about 1.43, because the
4408
+ * 1.2 that a browser's `normal` comes to sets lines too tight to read
4409
+ * in a paragraph. The ink is the stock palette's `text`, not black.
4372
4410
  */
4373
- declare function resolveLength(value: unknown, base: number | undefined, property: string, keepAuto?: boolean): number | undefined | 'auto';
4374
- //#endregion
4375
- //#region src/properties/UiGradient.d.ts
4411
+ declare const defaultTextStyle: UiTextStyle;
4412
+ /** The text of a span array, with each run's offsets into it. */
4413
+ declare function flattenTextSpans(spans: readonly UiTextSpan[]): UiSpannedText;
4376
4414
  /**
4377
- * Renderer-independent gradient descriptions.
4378
- *
4379
- * A gradient is a paint, not a colour: it is what a box's background
4380
- * is filled with instead of one flat value, and both backends have to
4381
- * arrive at the same pixels from it. So the description here is
4382
- * geometry plus stops, with nothing renderer-shaped in it, and the two
4383
- * renderers share the arithmetic in `gradientPaint` below rather than
4384
- * each deriving a gradient line of its own.
4415
+ * A node's paragraph as text and runs, or undefined when it has no
4416
+ * runs.
4385
4417
  *
4386
- * Lengths follow the rest of the framework: a plain number is logical
4387
- * pixels and `percent(n)` is a fraction of whatever the value is a
4388
- * fraction of, never a string to parse. For a stop that is the length
4389
- * of the gradient itself, so `percent(50)` is halfway along it whatever
4390
- * the box measures, and `24` is 24 pixels from its start.
4418
+ * `spans` wins over `text` when both are set, because a node that was
4419
+ * given runs meant them; the `text` prop is then ignored rather than
4420
+ * appended, so there is exactly one source of offsets.
4391
4421
  */
4392
- /** How far along a gradient a stop sits. */
4393
- type UiGradientOffset = number | PercentLength;
4394
- interface UiGradientStop {
4395
- /**
4396
- * Omitted on every stop of a gradient means "spread them evenly",
4397
- * which is what almost every gradient wants. Omitted on only some of
4398
- * them is an error rather than a guess: CSS's rule for filling the
4399
- * gaps is subtle enough that a reader could not predict the result.
4400
- *
4401
- * A number is a pixel length along the ramp, never a fraction of it:
4402
- * `{ offset: 0.45 }` is under half a pixel in, and a gradient whose
4403
- * stops all sit within the first pixel paints a one-pixel ramp that
4404
- * reads as nothing at all. A fraction is `percent(45)`. So
4405
- * `validateGradient` refuses a gradient whose numeric offsets all lie
4406
- * within 0 to 1 when there are two or more of them; one stop at a
4407
- * pixel or less among larger pixel offsets is a real position and is
4408
- * left alone.
4409
- */
4410
- readonly offset?: UiGradientOffset;
4411
- /**
4412
- * A palette name resolves against the theme the node inherits, so a
4413
- * themed gradient follows a theme change exactly as `backgroundColor`
4414
- * does.
4415
- */
4416
- readonly color: UiColorValue;
4417
- }
4418
- interface UiLinearGradient {
4419
- readonly kind: 'linear';
4420
- /**
4421
- * Direction in radians, on CSS's compass: 0 points at the top of the
4422
- * box and the angle turns clockwise, so `Math.PI / 2` runs left to
4423
- * right and `Math.PI` runs top to bottom.
4424
- */
4425
- readonly angle: number;
4426
- readonly stops: readonly UiGradientStop[];
4427
- }
4428
- interface UiRadialGradient {
4429
- readonly kind: 'radial';
4430
- /** The centre, from the box's top-left. Defaults to `percent(50)` on both axes. */
4431
- readonly centerX?: UiGradientOffset;
4432
- readonly centerY?: UiGradientOffset;
4433
- /**
4434
- * The radius of the outermost stop. `percent(100)`, the default, is
4435
- * the distance from the centre to the box's farthest corner, which is
4436
- * CSS's `farthest-corner`.
4437
- */
4438
- readonly radius?: UiGradientOffset;
4439
- readonly stops: readonly UiGradientStop[];
4440
- }
4441
- type UiGradient = UiLinearGradient | UiRadialGradient;
4422
+ declare function spannedTextOf(node: UiNode): UiSpannedText | undefined;
4442
4423
  /**
4443
- * The most stops one gradient may carry.
4424
+ * The text a node draws: its runs' text if it has runs, its `text`
4425
+ * property otherwise.
4444
4426
  *
4445
- * The WebGPU side stores a gradient as a fixed-size slab in a storage
4446
- * buffer, because a variable-length record would need a second buffer
4447
- * of stops and an index into it for what is, in every real interface, a
4448
- * handful of colours. Eight keeps a record at twelve `vec4`s, and a
4449
- * ninth stop is a loud error rather than a stop that quietly vanishes:
4450
- * see `validateGradient`.
4427
+ * Every reader of a node's paragraph goes through this — layout,
4428
+ * paint, selection, find and the semantics mirror — so a spanned
4429
+ * paragraph is selectable, findable and readable without any of them
4430
+ * knowing what a span is.
4451
4431
  */
4452
- declare const MAX_GRADIENT_STOPS = 8;
4432
+ declare function textContentOf(node: UiNode): string;
4433
+ /** The runs of a node's paragraph; empty when it has none. */
4434
+ declare function resolvedSpansOf(node: UiNode): readonly UiResolvedTextSpan[];
4453
4435
  /**
4454
- * A linear gradient at `angle` radians, clockwise from the top.
4436
+ * The runs an *editable* node styles its own text with.
4455
4437
  *
4456
- * linearGradient(Math.PI, [{ color: '#0ea5e9' }, { color: '#1e293b' }])
4457
- */
4458
- declare function linearGradient(angle: number, stops: readonly UiGradientStop[]): UiLinearGradient;
4459
- /** A radial gradient, centred and sized as `UiRadialGradient` describes. */
4460
- declare function radialGradient(stops: readonly UiGradientStop[], options?: Omit<UiRadialGradient, 'kind' | 'stops'>): UiRadialGradient;
4461
- /**
4462
- * Rejects a gradient the renderers cannot draw, returning the message
4463
- * for the error the caller raises.
4438
+ * An editable's paragraph is the user's, held by its model rather
4439
+ * than by a property — so unlike a `Text`, its runs do not supply the
4440
+ * text, they only describe it. `spans` on an editable is presentation
4441
+ * over a string somebody is typing.
4464
4442
  *
4465
- * The property registry calls this when a plain value is written, so a
4466
- * bad gradient fails where it was authored. A gradient arriving through
4467
- * an Observable is checked by `resolveGradient` instead, at paint,
4468
- * which is where a bound length is checked too.
4443
+ * Which is why this checks. Every offset the editor works in — the
4444
+ * caret, the selection, the hit test that turns a click into a text
4445
+ * position — is an offset into the model's string. Runs describing a
4446
+ * *different* string would put the glyphs somewhere the caret does
4447
+ * not agree with, and the field would look subtly, unfixably wrong.
4448
+ * When they disagree the text is drawn unstyled, which is a frame of
4449
+ * plain colour rather than a frame of nonsense, and corrects itself
4450
+ * as soon as the application catches up.
4469
4451
  */
4470
- declare function validateGradient(value: unknown): string | undefined;
4471
- /** Whether two gradient property values would paint the same, for the registry. */
4472
- declare function gradientsEqual(a: UiGradient | undefined, b: UiGradient | undefined): boolean;
4473
- interface ResolvedGradientStop {
4474
- readonly offset: UiGradientOffset | undefined;
4475
- readonly color: UiColor;
4452
+ declare function editableSpansOf(node: UiNode, text: string, composition?: UiTextRange | null): readonly UiResolvedTextSpan[];
4453
+ /** A stretch of a paragraph, as offsets into its text. */
4454
+ interface UiTextRange {
4455
+ readonly start: number;
4456
+ readonly end: number;
4476
4457
  }
4458
+ /** The part of a run `hiddenRangesOf` reads; a paint span has it as well as a resolved one. */
4459
+ type HiddenSpan = Pick<UiResolvedTextSpan, 'start' | 'end' | 'hidden'>;
4477
4460
  /**
4478
- * A gradient with its palette names resolved against the node's theme,
4479
- * and nothing else changed.
4461
+ * The stretches of a paragraph its runs hide, in order, with runs that
4462
+ * touch merged into one: `**` hidden next to a hidden `_` is one
4463
+ * stretch of three characters, which a caret steps over at once.
4464
+ * Remembered by the identity of the array, as the flattening is.
4465
+ */
4466
+ declare function hiddenRangesOf(spans: readonly HiddenSpan[]): readonly UiTextRange[];
4467
+ /** The span covering an offset, or undefined where no run does. */
4468
+ declare function spanAtOffset(spans: readonly UiResolvedTextSpan[], offset: number): UiResolvedTextSpan | undefined;
4469
+ /**
4470
+ * Compares two span arrays for equality.
4480
4471
  *
4481
- * Geometry stays as it was authored because it needs the node's box,
4482
- * which `resolvePaintState` does not have: the renderer turns this into
4483
- * a `GradientPaint` once it knows the record. Splitting it that way
4484
- * also means the theme is read once per node per frame rather than once
4485
- * per stop per pixel.
4472
+ * A link is compared by identity, as every function-valued prop in
4473
+ * the registry is: an application that rebuilds its handler each
4474
+ * render says the run changed, which costs a paint and no layout,
4475
+ * since a handler is not a metric field.
4486
4476
  */
4487
- type ResolvedGradient = {
4488
- readonly kind: 'linear';
4489
- readonly angle: number;
4490
- readonly stops: readonly ResolvedGradientStop[];
4491
- } | {
4492
- readonly kind: 'radial';
4493
- readonly centerX: UiGradientOffset | undefined;
4494
- readonly centerY: UiGradientOffset | undefined;
4495
- readonly radius: UiGradientOffset | undefined;
4496
- readonly stops: readonly ResolvedGradientStop[];
4497
- };
4477
+ declare function textSpansEqual(a: readonly UiTextSpan[] | undefined, b: readonly UiTextSpan[] | undefined): boolean;
4498
4478
  /**
4499
- * Note that the resolution itself, `resolveGradient`, lives in
4500
- * `UiThemeColor.ts` rather than here. The registry imports this file
4501
- * for `gradientsEqual` and `validateGradient`, and the theme lookup
4502
- * reads properties, so a gradient that resolved its own stops would
4503
- * close a cycle through the registry. It is the same split that keeps
4504
- * `colorValuesEqual` in `UiColor.ts`.
4479
+ * Whether two lists of runs are the same text, set the same way, and
4480
+ * differ at most in colour, background and decoration, which are drawn
4481
+ * rather than measured.
4505
4482
  */
4483
+ declare function spansDifferOnlyInPaint(a: readonly UiTextSpan[] | undefined, b: readonly UiTextSpan[] | undefined): boolean;
4506
4484
  /**
4507
- * A gradient placed in a box: geometry in the box's own coordinates,
4508
- * with the origin at its top-left, and stop offsets as fractions of the
4509
- * gradient's length.
4510
- *
4511
- * This is the shared form both renderers draw from. Canvas2D adds the
4512
- * box's origin and hands the numbers to `createLinearGradient`; the
4513
- * WebGPU builder writes them into the frame's gradient buffer and the
4514
- * fragment shader evaluates the same ramp per pixel.
4485
+ * Compares two text styles for equality.
4515
4486
  */
4516
- interface GradientPaint {
4517
- readonly kind: 'linear' | 'radial';
4518
- /** Linear: the start of the gradient line. Radial: the centre. */
4519
- readonly x0: number;
4520
- readonly y0: number;
4521
- /** Linear: the end of the gradient line. Radial: the centre again. */
4522
- readonly x1: number;
4523
- readonly y1: number;
4524
- /** Radial only; zero for a linear gradient. */
4525
- readonly radius: number;
4526
- readonly stops: readonly {
4527
- readonly offset: number;
4528
- readonly color: UiColor;
4529
- }[];
4530
- }
4487
+ declare function textStylesEqual(a: UiTextStyle, b: UiTextStyle): boolean;
4488
+ //#endregion
4489
+ //#region src/environment/UiTypography.d.ts
4531
4490
  /**
4532
- * Places a resolved gradient in a box of the given size.
4491
+ * A typography scale.
4533
4492
  *
4534
- * The linear case is CSS's: the gradient line runs through the centre
4535
- * of the box in the direction of the angle, and it is long enough that
4536
- * the two corners nearest its ends sit exactly on its endpoints, which
4537
- * is `|w·sin| + |h·cos|`. The radial case is a circle, centred where
4538
- * the gradient says and reaching the farthest corner at `percent(100)`.
4493
+ * Each named style is a complete TextStyle so that it can be
4494
+ * inherited as a unit. Components can override individual fields
4495
+ * while falling back to the scale for the rest.
4496
+ */
4497
+ interface UiTypography {
4498
+ readonly body: UiTextStyle;
4499
+ readonly bodyLarge: UiTextStyle;
4500
+ readonly bodySmall: UiTextStyle;
4501
+ readonly headline: UiTextStyle;
4502
+ readonly title: UiTextStyle;
4503
+ readonly label: UiTextStyle;
4504
+ }
4505
+ /**
4506
+ * Roles an application adds to the scale, declared by merging.
4539
4507
  *
4540
- * Offsets are clamped into `[0, 1]` and forced to not go backwards, as
4541
- * CSS forces them, so the two backends receive one already-sorted list
4542
- * and neither has to decide what a stop behind its predecessor means.
4508
+ * A scale of six covers a document and not an application: the two
4509
+ * applications here use fourteen and eleven distinct sizes. Rather
4510
+ * than grow `UiTypography` for everyone, or send an application back
4511
+ * to writing numbers on elements, a theme's typography may carry names
4512
+ * of its own, and an application declares them so they type:
4513
+ *
4514
+ * declare module 'gesso-core' {
4515
+ * interface UiTypographyExtensions {
4516
+ * readonly cardTitle: unknown;
4517
+ * readonly display: unknown;
4518
+ * }
4519
+ * }
4520
+ *
4521
+ * The value type is not used, only the key, because what the theme
4522
+ * carries is always a `UiTextStyle`. Declaring one makes
4523
+ * `textStyle="cardTitle"` legal and `textStyle="cardTtile"` a compile
4524
+ * error, which is the whole point.
4543
4525
  */
4544
- declare function gradientPaint(gradient: ResolvedGradient, width: number, height: number): GradientPaint;
4526
+ interface UiTypographyExtensions {}
4527
+ /**
4528
+ * A role in the scale, as an element names it: `textStyle="title"`.
4529
+ *
4530
+ * The idiom the documentation teaches. A size, a weight and a line
4531
+ * height written out on an element are three numbers to keep in step
4532
+ * across a screen and six to keep in step across an application, and
4533
+ * none of them follows a theme; a role is one word that does.
4534
+ */
4535
+ type UiTypographyRole = keyof UiTypography | (keyof UiTypographyExtensions & string);
4536
+ /**
4537
+ * Whether a value names a role of the supplied scale.
4538
+ *
4539
+ * Asked of the scale rather than of a written-out list, so a role an
4540
+ * application added is a role. A name the scale does not carry is not
4541
+ * one, and the element keeps whatever type it inherited rather than
4542
+ * drawing at a default size, which is the quieter of the two failures.
4543
+ */
4544
+ declare function isTypographyRole(value: unknown, scale: UiTypography): value is UiTypographyRole;
4545
+ /**
4546
+ * The stock scale: one face, and line heights on a 4-point grid rather
4547
+ * than 1.2 of the size, so a paragraph has room and a stack of text
4548
+ * lines up with the spacing scale around it.
4549
+ */
4550
+ declare const defaultTypography: UiTypography;
4551
+ /**
4552
+ * Compares two typography scales for equality.
4553
+ *
4554
+ * Over the keys rather than a written-out list, as `colorsEqualPalette`
4555
+ * is and for the same reason: a scale that carries roles of its own
4556
+ * has to invalidate on a change to one of them. Written out, the six
4557
+ * shipped roles were compared and an application's own were not, so a
4558
+ * scale differing only in a role it had added compared equal and the
4559
+ * change never reached the nodes that would have read it.
4560
+ */
4561
+ declare function typographyEqual(a: UiTypography, b: UiTypography): boolean;
4545
4562
  //#endregion
4546
- //#region src/properties/UiImage.d.ts
4563
+ //#region src/properties/UiBoxShadow.d.ts
4547
4564
  /**
4548
- * Renderer-facing image type.
4565
+ * Renderer-independent box shadow description, with CSS `box-shadow`
4566
+ * semantics.
4549
4567
  *
4550
- * ImageBitmap is available on the main thread and in Workers
4551
- * (createImageBitmap), so the rendering core never depends on
4552
- * HTMLImageElement and an image decoded in a worker can be drawn there.
4568
+ * An outer shadow is the node's (rounded) box, grown by `spreadRadius`
4569
+ * on every side, moved by the offset, blurred by `blurRadius` (a
4570
+ * Gaussian whose standard deviation is half of it), and seen only
4571
+ * outside the box. An inset one is the same shape inverted and seen
4572
+ * only inside the box. `color` may be a palette name, resolved against
4573
+ * the node's theme as `backgroundColor` is.
4553
4574
  */
4554
- type UiImage = ImageBitmap;
4575
+ interface UiBoxShadow {
4576
+ readonly offsetX: number;
4577
+ readonly offsetY: number;
4578
+ readonly blurRadius: number;
4579
+ readonly spreadRadius: number;
4580
+ readonly color: UiColorValue;
4581
+ readonly inset?: boolean;
4582
+ }
4583
+ /** A size on the theme's shadow scale (`UiTheme.shadows`), which `boxShadows` takes as a name. */
4584
+ type UiShadowName = 'none' | 'extraSmall' | 'small' | 'medium' | 'large' | 'extraLarge';
4585
+ /**
4586
+ * What `boxShadows` holds: the shadows themselves, or a size on the
4587
+ * theme's scale, `boxShadows="medium"`, as `borderRadius` takes a shape.
4588
+ * A name follows the theme, so a rebrand's shadows reach every card.
4589
+ */
4590
+ type UiBoxShadows = readonly UiBoxShadow[] | UiShadowName;
4591
+ /**
4592
+ * The shadows a `boxShadows` value stands for: itself, or the named
4593
+ * size from `scale`, the node's theme's shadows. A name the scale lacks,
4594
+ * or no scale, is no shadow.
4595
+ */
4596
+ declare function shadowsOf(value: unknown, scale: {
4597
+ readonly [name: string]: readonly UiBoxShadow[];
4598
+ } | undefined): readonly UiBoxShadow[];
4599
+ /**
4600
+ * Compares two `boxShadows` values: two names by name, two lists entry by entry.
4601
+ */
4602
+ declare function boxShadowValuesEqual(a: UiBoxShadows, b: UiBoxShadows): boolean;
4603
+ /**
4604
+ * Creates a box shadow with the supplied parameters.
4605
+ */
4606
+ declare function boxShadow(offsetX: number, offsetY: number, blurRadius: number, spreadRadius: number, color: UiColorValue, inset?: boolean): UiBoxShadow;
4607
+ /**
4608
+ * Compares two box shadows for equality.
4609
+ */
4610
+ declare function boxShadowsEqual(a: UiBoxShadow, b: UiBoxShadow): boolean;
4611
+ /**
4612
+ * Compares two shadow arrays for equality.
4613
+ */
4614
+ declare function boxShadowArraysEqual(a: readonly UiBoxShadow[], b: readonly UiBoxShadow[]): boolean;
4615
+ /**
4616
+ * How far a shadow's blur reaches past the edge of its shape, as a
4617
+ * multiple of `blurRadius`.
4618
+ *
4619
+ * The blur is a Gaussian with a standard deviation of half the radius,
4620
+ * so this is three standard deviations: what is left beyond it is
4621
+ * under a quarter of a percent of the shadow's colour, and both
4622
+ * renderers stop drawing there.
4623
+ */
4624
+ declare const BOX_SHADOW_BLUR_REACH = 1.5;
4625
+ /**
4626
+ * The corner radius of a shadow's shape, from the box's and the
4627
+ * spread: an outer shadow's corner grows with its spread, an inset
4628
+ * one's hole shrinks with it. A square corner stays square, as CSS
4629
+ * keeps it.
4630
+ */
4631
+ declare function boxShadowRadius(boxRadius: number, spreadRadius: number, inset: boolean): number;
4632
+ /**
4633
+ * How far past each side of the box a node's outer shadows may paint,
4634
+ * written into `out`; all zero for a node with none. Inset shadows
4635
+ * paint inside the box and add nothing.
4636
+ */
4637
+ declare function boxShadowReach(shadows: readonly UiBoxShadow[], out: {
4638
+ left: number;
4639
+ top: number;
4640
+ right: number;
4641
+ bottom: number;
4642
+ }): void;
4555
4643
  //#endregion
4556
- //#region src/rendering/PaintSurface.d.ts
4644
+ //#region src/environment/UiShadows.d.ts
4557
4645
  /**
4558
- * The drawing vocabulary an application gets when it wants to draw
4559
- * something the property set has no name for: a sparkline, a gauge, a
4560
- * waveform, a chart axis.
4646
+ * A renderer-independent shadow scale.
4561
4647
  *
4562
- * It sits beside `UiRenderer` on purpose argues
4563
- * the placement at length. The short version is the risk it exists to
4564
- * avoid: a paint hook handed a `CanvasRenderingContext2D` would be a
4565
- * Canvas2D-only capability with a WebGPU backend that could never
4566
- * catch up, which is how a second-class renderer is made. Nothing here
4567
- * names a canvas, a device or a texture, so neither backend can be the
4568
- * one the vocabulary was written for.
4648
+ * Each value is an array of shadows so layered shadows can be
4649
+ * expressed. Renderers translate these into native shadow drawing
4650
+ * operations.
4651
+ */
4652
+ interface UiShadows {
4653
+ readonly none: readonly UiBoxShadow[];
4654
+ readonly extraSmall: readonly UiBoxShadow[];
4655
+ readonly small: readonly UiBoxShadow[];
4656
+ readonly medium: readonly UiBoxShadow[];
4657
+ readonly large: readonly UiBoxShadow[];
4658
+ readonly extraLarge: readonly UiBoxShadow[];
4659
+ }
4660
+ declare const defaultShadows: UiShadows;
4661
+ /**
4662
+ * Compares two shadow scales for equality.
4663
+ */
4664
+ declare function shadowsEqual(a: UiShadows, b: UiShadows): boolean;
4665
+ //#endregion
4666
+ //#region src/environment/UiDensity.d.ts
4667
+ /**
4668
+ * How tightly a theme packs.
4569
4669
  *
4570
- * **Coordinates are the node's own.** `(0, 0)` is the top-left of the
4571
- * resolved box and the box's width and height are the extent, so a
4572
- * painter never reads a layout record and never learns where on the
4573
- * screen it ended up. The device scale arrives separately, for the one
4574
- * thing that genuinely needs it: choosing a hairline that is one
4575
- * physical pixel rather than one logical one.
4670
+ * An axis rather than a second theme: an application that wants a
4671
+ * compact table and a comfortable settings sheet provides the same
4672
+ * theme twice with one field changed, and nothing else about its
4673
+ * colours or type is duplicated.
4576
4674
  *
4577
- * **Every call is recorded, not executed.** The object a painter is
4578
- * handed is a `PaintRecorder`, and what it produces is a
4579
- * `PaintRecording`: plain data, comparable, replayable, and cheap
4580
- * enough to keep. See `PaintRecording.ts` for why that indirection is
4581
- * what makes the two backends agree.
4675
+ * `comfortable` is the scale as written. `compact` is three quarters
4676
+ * of it, `spacious` a quarter more. Only the spacing scale moves; type
4677
+ * and shape do not, because a smaller gap between two rows is a
4678
+ * density choice and a smaller word is a typography one.
4582
4679
  */
4583
- interface PaintSurface {
4584
- /** Pushes the transform, the clip and every style value. */
4585
- save(): void;
4586
- restore(): void;
4587
- translate(x: number, y: number): void;
4588
- scale(x: number, y: number): void;
4589
- /** Radians, clockwise, about the current origin. */
4590
- rotate(angle: number): void;
4591
- /** Multiplies the current transform by the 3x2 affine `a b c d e f`. */
4592
- transform(a: number, b: number, c: number, d: number, e: number, f: number): void;
4593
- beginPath(): void;
4594
- moveTo(x: number, y: number): void;
4595
- lineTo(x: number, y: number): void;
4596
- quadraticCurveTo(cx: number, cy: number, x: number, y: number): void;
4597
- bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): void;
4598
- /** Radians; `counterclockwise` defaults to false. */
4599
- arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
4600
- rect(x: number, y: number, width: number, height: number): void;
4601
- /** One radius for all four corners, clamped to half the smaller side. */
4602
- roundRect(x: number, y: number, width: number, height: number, radius: number): void;
4603
- closePath(): void;
4604
- /**
4605
- * Appends SVG path data to the current path, in the surface's own
4606
- * coordinates.
4607
- *
4608
- * The whole grammar an icon set uses is understood, `A` included:
4609
- * `PaintPathData.ts` turns it into the calls above, so a `d` string
4610
- * costs exactly what writing those calls by hand would and works
4611
- * wherever the rest of this does. That last part is the reason it is
4612
- * parsed here rather than handed to `Path2D`, which exists in a
4613
- * browser and not in the suite.
4614
- */
4615
- path(d: string): void;
4616
- /**
4617
- * A `UiColor`, a hex or named CSS colour, or a palette name.
4618
- *
4619
- * A palette name is the reason a painted node follows the light and
4620
- * dark toggle without the painter knowing there was a toggle: the
4621
- * name is resolved against whatever theme the node inherits, at the
4622
- * moment the picture is made, exactly as a `backgroundColor` prop is.
4623
- */
4624
- fillColor(color: UiColorValue): void;
4625
- /**
4626
- * A gradient for the fills that follow, placed in the rectangle
4627
- * given here rather than in the node's box, so a painter can ramp
4628
- * one bar of a chart without arithmetic of its own.
4629
- */
4630
- fillGradient(gradient: UiGradient, x: number, y: number, width: number, height: number): void;
4631
- strokeColor(color: UiColorValue): void;
4632
- lineWidth(width: number): void;
4633
- lineCap(cap: PaintLineCap): void;
4634
- lineJoin(join: PaintLineJoin): void;
4635
- miterLimit(limit: number): void;
4636
- /**
4637
- * A dash pattern in logical pixels, and how far into it the first
4638
- * dash starts. An empty pattern draws solid.
4639
- */
4640
- lineDash(segments: readonly number[], offset?: number): void;
4641
- /** Multiplies into the opacity already in force, as a node's does. */
4642
- alpha(value: number): void;
4643
- /**
4644
- * Blurs everything drawn after it, by a radius in logical pixels.
4645
- *
4646
- * Scoped by `save` and `restore` like every other style value, so a
4647
- * frosted panel is `save`, `blur`, draw, `restore`. Zero clears it.
4648
- */
4649
- blur(radius: number): void;
4650
- /** Fills the current path. The default rule is `nonzero`. */
4651
- fill(rule?: PaintFillRule): void;
4652
- stroke(): void;
4653
- /** Intersects the clip with the current path, until the next `restore`. */
4654
- clip(rule?: PaintFillRule): void;
4680
+ type UiDensity = 'compact' | 'comfortable' | 'spacious';
4681
+ /** The multiplier each density applies to the spacing scale. */
4682
+ declare const densityFactors: Readonly<Record<UiDensity, number>>;
4683
+ //#endregion
4684
+ //#region src/environment/UiContrast.d.ts
4685
+ /**
4686
+ * How much separation a theme keeps between what is drawn and what it
4687
+ * is drawn on.
4688
+ *
4689
+ * `standard` is the palette as the designer wrote it. `high` is the
4690
+ * same palette with every foreground pushed away from the surface
4691
+ * behind it until it clears a contrast ratio, which is what a person
4692
+ * who has turned the operating system's high-contrast setting on is
4693
+ * asking for. It is an axis of the theme rather than a second palette
4694
+ * so that an application which has already chosen its colours does not
4695
+ * have to choose them twice, and so that the accessibility audit has
4696
+ * one place to look.
4697
+ */
4698
+ type UiContrast = 'standard' | 'high';
4699
+ /**
4700
+ * Relative luminance, as WCAG defines it.
4701
+ *
4702
+ * Alpha is ignored: a token is compared against the surface it sits
4703
+ * on, and what a translucent foreground actually looks like depends on
4704
+ * a composite this cannot see. Raising a translucent token toward the
4705
+ * extreme is still the right direction.
4706
+ */
4707
+ declare function relativeLuminance(color: UiColor): number;
4708
+ /**
4709
+ * The WCAG contrast ratio between two colours, from 1 to 21.
4710
+ */
4711
+ declare function contrastRatio(a: UiColor, b: UiColor): number;
4712
+ /**
4713
+ * The same colour, moved toward black or white until it clears
4714
+ * `ratio` against `against`.
4715
+ *
4716
+ * Toward whichever extreme is already the further from the surface, so
4717
+ * text on a dark ground gets lighter and text on a light ground gets
4718
+ * darker: pushing the other way would cross the surface's own
4719
+ * luminance and come out worse before it came out better. A colour
4720
+ * that cannot reach the ratio even at the extreme is returned at the
4721
+ * extreme, which is the best the palette can do and is still an
4722
+ * improvement.
4723
+ *
4724
+ * Mixed in linear steps of the stored channels rather than by solving
4725
+ * for the luminance, because the search is sixteen steps and this runs
4726
+ * when a theme is built, not when a frame is drawn.
4727
+ */
4728
+ declare function raiseContrast(color: UiColor, against: UiColor, ratio: number): UiColor;
4729
+ /** What a high-contrast palette needs to know of an application's own names. */
4730
+ interface HighContrastOptions {
4655
4731
  /**
4656
- * One line of text at a baseline, in the current fill colour.
4657
- *
4658
- * Deliberately one line and not a paragraph: wrapping, bidi and
4659
- * selection belong to the text node, which does them properly, and a
4660
- * painter that needs them should draw a text node instead. This is
4661
- * for the labels a chart puts on its own axes.
4732
+ * Names a custom palette added that are grounds, not marks, and are
4733
+ * left alone as the stock grounds are: a code editor's selection, its
4734
+ * current line, a diff's filled lines. Raised as foregrounds, they
4735
+ * would turn bright enough against the page that what is drawn on them
4736
+ * could not be read.
4662
4737
  */
4663
- text(value: string, x: number, y: number, style?: PaintTextStyle): void;
4664
- /** Draws an image into a rectangle, stretched to fill it. */
4665
- image(image: UiImage, x: number, y: number, width: number, height: number): void;
4666
- }
4667
- type PaintFillRule = 'nonzero' | 'evenodd';
4668
- type PaintLineCap = 'butt' | 'round' | 'square';
4669
- type PaintLineJoin = 'miter' | 'round' | 'bevel';
4670
- type PaintTextAlign = 'left' | 'center' | 'right';
4671
- /** The little of a text style a single painted line can carry. */
4672
- interface PaintTextStyle {
4673
- readonly fontSize?: number;
4674
- readonly fontFamily?: string;
4675
- readonly fontWeight?: number | string;
4676
- /** Which end of the run `x` names. Defaults to `left`. */
4677
- readonly align?: PaintTextAlign;
4738
+ readonly surfaces?: Iterable<string>;
4678
4739
  }
4679
4740
  /**
4680
- * The box a painter is asked to fill, in its own coordinates.
4741
+ * A palette at high contrast.
4681
4742
  *
4682
- * The node's border box, not its content box: a painter that wants to
4683
- * respect padding is told what it is and decides, because a gauge
4684
- * drawn to the edge and a chart inset by its padding are both
4685
- * legitimate and the property set cannot tell which was meant.
4743
+ * Every extra name a custom palette added is raised too, against the
4744
+ * page background, because a palette that grew a token for its own
4745
+ * accent should not be the one thing that stays quiet when the setting
4746
+ * is turned on; unless it says it is a ground (`surfaces`). The named
4747
+ * foregrounds above override that default with the surface they are
4748
+ * really drawn on.
4686
4749
  */
4687
- interface PaintBox {
4688
- readonly width: number;
4689
- readonly height: number;
4690
- readonly paddingTop: number;
4691
- readonly paddingRight: number;
4692
- readonly paddingBottom: number;
4693
- readonly paddingLeft: number;
4750
+ declare function highContrastColors(colors: UiColors, options?: HighContrastOptions): UiColors;
4751
+ //#endregion
4752
+ //#region src/environment/UiThemeExtension.d.ts
4753
+ /**
4754
+ * Tokens an application adds to a theme, under its own name.
4755
+ *
4756
+ * `UiTheme` carries the vocabulary every application shares: colours,
4757
+ * type, shapes, shadows, spacing. An application always has more than
4758
+ * that, and the two in this repository each grew a module of module
4759
+ * level constants to hold it, which is a theme that no provider can
4760
+ * change and no appearance toggle can reach.
4761
+ *
4762
+ * An extension is that module turned into part of the theme:
4763
+ *
4764
+ * const brand = defineThemeExtension({
4765
+ * name: 'brand',
4766
+ * defaults: { linen: '#be9a6e', chalk: '#f7f3ea' }
4767
+ * });
4768
+ *
4769
+ * const theme = withThemeExtension(lightTheme, brand, { linen: …, chalk: … });
4770
+ * themeExtension(theme, brand).linen
4771
+ *
4772
+ * The read is a property access on the object the extension was
4773
+ * declared with, so an editor completes the token names and a
4774
+ * misspelling is a compile error. Nothing about `UiTheme` or
4775
+ * `themesEqual` changes to add one: the extensions ride in a map keyed
4776
+ * by the symbol `defineThemeExtension` minted, and `themesEqual`
4777
+ * compares them with each extension's own comparison.
4778
+ *
4779
+ * A component in a library may declare an extension too, which is how
4780
+ * a component that needs a token the shared vocabulary does not have
4781
+ * gets one without adding a prop for it.
4782
+ */
4783
+ interface UiThemeExtension<T extends object> {
4784
+ /** Identity, so two extensions cannot collide on a name. */
4785
+ readonly key: symbol;
4786
+ readonly name: string;
4787
+ /** What `themeExtension` returns for a theme that does not carry it. */
4788
+ readonly defaults: T;
4789
+ /** What it returns instead for such a theme turned for a finger; `defaults` when absent. See `UiPointer`. */
4790
+ readonly coarse?: T;
4791
+ readonly equals: (a: T, b: T) => boolean;
4792
+ }
4793
+ interface UiThemeExtensionOptions<T extends object> {
4794
+ readonly name: string;
4795
+ readonly defaults: T;
4694
4796
  /**
4695
- * Physical pixels per logical pixel the picture is being made at.
4797
+ * The group's values for a finger: what a theme turned for touch
4798
+ * (`withPointer(theme, 'coarse')`) reads when it does not carry the
4799
+ * group itself. A control library's touch sizes go here, so an
4800
+ * application gets them on a touch screen with nothing to provide.
4801
+ */
4802
+ readonly coarse?: T;
4803
+ /**
4804
+ * How two values of this extension are compared, for the environment
4805
+ * to decide whether a theme change has to invalidate the subtree.
4696
4806
  *
4697
- * The one thing a painter needs the device for: `1 / scale` is a
4698
- * hairline, and a grid line drawn at `1` on a retina display is two
4699
- * physical pixels wide and looks it.
4807
+ * The default compares the group's own keys, and compares each one
4808
+ * structurally when it is a plain object, so a group of `UiColor`
4809
+ * tokens built freshly on each appearance change is equal to the one
4810
+ * before it. It goes no deeper than that: an extension whose tokens
4811
+ * are themselves nested groups should pass its own comparison rather
4812
+ * than find out later that its theme never invalidates.
4700
4813
  */
4701
- readonly scale: number;
4814
+ readonly equals?: (a: T, b: T) => boolean;
4702
4815
  }
4816
+ /** The map a theme carries. Empty for every stock theme. */
4817
+ type UiThemeExtensions = ReadonlyMap<symbol, object>;
4818
+ declare const noThemeExtensions: UiThemeExtensions;
4703
4819
  /**
4704
- * What a node's `paint` prop holds: the drawing, and what it depends
4705
- * on.
4820
+ * Declares a group of tokens an application or a library adds to a
4821
+ * theme. Call it once, at module level, and export the result.
4822
+ */
4823
+ declare function defineThemeExtension<T extends object>(options: UiThemeExtensionOptions<T>): UiThemeExtension<T>;
4824
+ /** What the theme carries for this extension, or its declared defaults. */
4825
+ declare function themeExtension<T extends object>(theme: {
4826
+ readonly extensions?: UiThemeExtensions;
4827
+ readonly pointer?: 'fine' | 'coarse';
4828
+ }, extension: UiThemeExtension<T>): T;
4829
+ /** Whether the theme carries this extension at all, rather than falling back. */
4830
+ declare function hasThemeExtension<T extends object>(theme: {
4831
+ readonly extensions?: UiThemeExtensions;
4832
+ }, extension: UiThemeExtension<T>): boolean;
4833
+ /**
4834
+ * The same theme with one extension's tokens set.
4706
4835
  *
4707
- * `inputs` is the whole of the cost story. The picture is made when
4708
- * the inputs change and at no other time, so a painted node on a
4709
- * still frame costs one image draw and nothing else, and
4710
- * `PaintPicture.budget.spec.ts` asserts exactly that. Without it the
4711
- * only safe assumption would be that the closure captured something
4712
- * new, and every frame would repaint.
4836
+ * Returns a new theme; a theme is a value and is compared as one. The
4837
+ * extensions map is copied rather than mutated for the same reason,
4838
+ * since two themes derived from one base must not share it.
4839
+ */
4840
+ declare function withThemeExtension<Theme extends {
4841
+ readonly extensions?: UiThemeExtensions;
4842
+ }, T extends object>(theme: Theme, extension: UiThemeExtension<T>, value: T): Theme;
4843
+ /**
4844
+ * Compares the extension maps of two themes.
4713
4845
  *
4714
- * Values are compared with `Object.is`, one by one, so a list of
4715
- * numbers or of stable references works and an array literal rebuilt
4716
- * per render does not defeat it. Omitting `inputs` means the drawing
4717
- * never changes on its own, which is the right default for a static
4718
- * shape and the wrong one for a chart.
4846
+ * A key one carries and the other does not is a difference, and each
4847
+ * key is compared with the comparison its own extension declared. The
4848
+ * comparison lives on the value rather than in a registry so that an
4849
+ * extension declared in an application is compared as well as one
4850
+ * declared here, which is the whole point of the mechanism.
4719
4851
  */
4720
- interface UiPaint {
4721
- readonly draw: (surface: PaintSurface, box: PaintBox) => void;
4722
- readonly inputs?: readonly unknown[];
4723
- /**
4724
- * The size the node takes when the layout has none to give it: no
4725
- * width or height, no flex, nothing stretching it. Zero, like any
4726
- * other empty leaf, when it is absent.
4727
- */
4728
- readonly intrinsicWidth?: number;
4729
- readonly intrinsicHeight?: number;
4730
- }
4852
+ declare function themeExtensionsEqual(a: UiThemeExtensions | undefined, b: UiThemeExtensions | undefined): boolean;
4853
+ //#endregion
4854
+ //#region src/environment/UiUnits.d.ts
4731
4855
  /**
4732
- * A static vector shape, as a property rather than a function.
4856
+ * What a theme's lengths are measured against.
4733
4857
  *
4734
- * The declarative half of this workstream: an icon, a logo, a
4735
- * decorative rule, anything whose geometry is fixed and whose colours
4736
- * follow the theme. It is drawn through the same surface a painter
4737
- * writes to, so there is no second path to keep in step, and a node
4738
- * may carry both a `path` and a `paint` (the path is drawn first, and
4739
- * the painter draws over it).
4858
+ * Every length Gesso lays out or paints is a logical pixel, the CSS
4859
+ * pixel, and nothing in the layout pass knows another unit. A designer
4860
+ * thinks in more than one: type in points or rems, a print margin in
4861
+ * millimetres, a badge in inches. The two numbers here are what those
4862
+ * are worth in pixels, carried on the theme so a screen and the scales
4863
+ * it is written from agree on them.
4864
+ *
4865
+ * They are resolved when a value is written, not when it is laid out:
4866
+ * `lengths(theme.units).rem(1.5)` is the number 24, and the element
4867
+ * that receives it never knows it was a rem. That keeps the layout
4868
+ * engine's per-node cache honest, since a resolved number cannot change
4869
+ * under it when a parent's units do, and it is why changing a theme's
4870
+ * units moves what is written with them the next time it is written,
4871
+ * not the screen already drawn.
4740
4872
  */
4741
- interface UiPath {
4742
- /** SVG path data, in `viewBox` units. */
4743
- readonly d: string;
4873
+ interface UiUnits {
4744
4874
  /**
4745
- * The square the path is authored in, scaled to fit the node's box
4746
- * as `object-fit: contain` would, and centred in it. Omitted means
4747
- * the path is already in the node's own logical pixels.
4875
+ * How many logical pixels make an inch, and from it a point (1/72 in)
4876
+ * and a millimetre (1/25.4 in). 96, as in CSS, so a theme that never
4877
+ * sets it measures as the browser does.
4748
4878
  */
4749
- readonly viewBox?: number;
4750
- readonly fill?: UiColorValue;
4751
- readonly fillRule?: PaintFillRule;
4752
- readonly stroke?: UiColorValue;
4753
- readonly strokeWidth?: number;
4754
- readonly lineCap?: PaintLineCap;
4755
- readonly lineJoin?: PaintLineJoin;
4756
- readonly miterLimit?: number;
4757
- readonly dash?: readonly number[];
4758
- readonly dashOffset?: number;
4879
+ readonly pixelsPerInch: number;
4880
+ /** What one `rem` is, in logical pixels: 16, as a browser's default root font. */
4881
+ readonly rootFontSize: number;
4759
4882
  }
4883
+ declare const defaultUnits: UiUnits;
4760
4884
  /**
4761
- * Whether two `paint` values would draw the same picture.
4885
+ * Conversions from a designer's units to logical pixels, for one set
4886
+ * of units.
4762
4887
  *
4763
- * Identity on `draw` plus item-by-item identity on `inputs`, which is
4764
- * the comparison the property registry runs on every write. A painter
4765
- * rebuilt by a render body has a new `draw`, so a component that wants
4766
- * the caching has to hoist the function and vary the inputs, which is
4767
- * the same rule a modifier's arguments follow.
4888
+ * Unrounded, because a size in points is often meant to be a fraction
4889
+ * of a pixel (`pt(10.5)` is 14): rounding is the author's choice, made
4890
+ * where a half pixel would put every box inside on one too.
4768
4891
  */
4769
- declare function paintValuesEqual(a: UiPaint | undefined, b: UiPaint | undefined): boolean;
4770
- /** Item-by-item identity, with absent and empty treated alike. */
4771
- declare function inputsEqual(a: readonly unknown[] | undefined, b: readonly unknown[] | undefined): boolean;
4772
- /** Whether two `path` values describe the same shape in the same style. */
4773
- declare function pathValuesEqual(a: UiPath | undefined, b: UiPath | undefined): boolean;
4774
- //#endregion
4775
- //#region src/properties/UiTextStyle.d.ts
4892
+ interface UiLengths {
4893
+ /** The units these convert with. */
4894
+ readonly units: UiUnits;
4895
+ /** Multiples of the root font size: `rem(1.5)` is 24 at the default 16. */
4896
+ rem(value: number): number;
4897
+ /** Inches: `inch(1)` is the pixels per inch. */
4898
+ inch(value: number): number;
4899
+ /** Points, 72 to the inch: `pt(12)` is 16 at 96 pixels per inch. */
4900
+ pt(value: number): number;
4901
+ /** Millimetres, 25.4 to the inch. */
4902
+ mm(value: number): number;
4903
+ }
4776
4904
  /**
4777
- * A coherent typography value.
4905
+ * The conversions for a set of units, usually a theme's.
4778
4906
  *
4779
- * TextStyle is the unit of inheritance: a parent can provide a
4780
- * TextStyle and descendants can override individual fields while
4781
- * keeping the rest.
4907
+ * const { rem, pt } = lengths(theme.units);
4908
+ * <box padding={rem(1)}><text fontSize={pt(12)} /></box>
4782
4909
  *
4783
- * The four fields below `textDirection` are optional because the
4784
- * environment's typography roles were written before they existed and
4785
- * a role that says nothing about them means "normal", which is what
4786
- * their property defaults already say.
4787
- */
4788
- interface UiTextStyle {
4789
- readonly fontFamily: string;
4790
- readonly fontSize: number;
4791
- readonly fontWeight: UiFontWeight;
4792
- readonly lineHeight: number;
4793
- readonly letterSpacing: number;
4794
- readonly color: UiColor;
4795
- readonly textAlign: UiTextAlign;
4796
- readonly textDirection: UiTextDirection;
4797
- readonly fontStyle?: UiFontStyle;
4798
- readonly fontStretch?: UiFontStretch;
4799
- readonly fontVariant?: UiFontVariant;
4800
- readonly fontKerning?: UiFontKerning;
4801
- readonly textDecoration?: UiTextDecoration;
4802
- }
4803
- /** Upright or sloped. `oblique` is a synthesised slant where no italic face exists. */
4804
- type UiFontStyle = 'normal' | 'italic' | 'oblique';
4805
- /**
4806
- * The width axis, as CSS names it.
4910
+ * A theme writes its own scales the same way, from the units it is
4911
+ * about to carry, so the scales follow them:
4807
4912
  *
4808
- * A variable font's `wdth` is reached through these keywords and
4809
- * nowhere else: the Canvas2D context takes `fontStretch` as a
4810
- * property, and a font string cannot carry an axis tuple.
4913
+ * const units = { pixelsPerInch: 96, rootFontSize: 16 };
4914
+ * const { rem } = lengths(units);
4915
+ * export const theme = { ...lightTheme, units, spacing: { ...lightTheme.spacing, large: rem(1) } };
4916
+ *
4917
+ * Throws on units that cannot measure anything, a zero or negative or
4918
+ * non-finite number, since every length written from them would be.
4811
4919
  */
4812
- type UiFontStretch = 'ultra-condensed' | 'extra-condensed' | 'condensed' | 'semi-condensed' | 'normal' | 'semi-expanded' | 'expanded' | 'extra-expanded' | 'ultra-expanded';
4920
+ declare function lengths(units?: UiUnits): UiLengths;
4813
4921
  /**
4814
- * The one font-variant value the CSS font shorthand carries, and so
4815
- * the one a canvas font string carries. `font-feature-settings` is not
4816
- * part of the shorthand and the context has no property for it, which
4817
- * is why `tnum` and `liga` are not here.
4922
+ * Compares two sets of units for equality.
4818
4923
  */
4819
- type UiFontVariant = 'normal' | 'small-caps';
4820
- /** Whether the shaper applies the font's kerning pairs. */
4821
- type UiFontKerning = 'auto' | 'normal' | 'none';
4822
- /** Lines drawn with the text. Both may be asked for at once. */
4823
- type UiTextDecoration = 'none' | 'underline' | 'line-through' | 'underline line-through';
4924
+ declare function unitsEqual(a: UiUnits, b: UiUnits): boolean;
4925
+ //#endregion
4926
+ //#region src/environment/UiTheme.d.ts
4824
4927
  /**
4825
- * The fields of a style that change how wide its text measures.
4928
+ * A renderer-independent theme.
4826
4929
  *
4827
- * The split matters: only these reach the measure request, so a run
4828
- * that changes colour, background or underline is repainted from the
4829
- * paragraph the cache already holds, and only a run that changes font
4830
- * makes the paragraph new. See `TextMeasurer.ts`.
4930
+ * A theme bundles colors, typography, shapes, shadows and spacing into
4931
+ * a single environment value. It can be provided at any node and is
4932
+ * inherited by descendants until another provider overrides it.
4933
+ *
4934
+ * `density` and `contrast` are axes rather than scales: they record
4935
+ * which way this theme was already turned, so a component can branch
4936
+ * on the answer and `withDensity` and `withContrast` can turn it
4937
+ * again from the base. `units` is what an inch and a rem are worth in
4938
+ * pixels, for lengths written in them; see `UiUnits.ts`. `extensions`
4939
+ * is where an application's own token groups live; see
4940
+ * `UiThemeExtension.ts`.
4831
4941
  */
4832
- interface UiTextMetrics {
4833
- readonly fontFamily?: string;
4834
- readonly fontSize?: number;
4835
- readonly fontWeight?: UiFontWeight;
4836
- readonly fontStyle?: UiFontStyle;
4837
- readonly fontStretch?: UiFontStretch;
4838
- readonly fontVariant?: UiFontVariant;
4839
- readonly fontKerning?: UiFontKerning;
4840
- readonly letterSpacing?: number;
4942
+ interface UiTheme {
4943
+ readonly colors: UiColors;
4944
+ readonly typography: UiTypography;
4945
+ readonly shapes: UiShapes;
4946
+ readonly shadows: UiShadows;
4947
+ readonly spacing: UiSpacing;
4948
+ readonly density: UiDensity;
4949
+ readonly contrast: UiContrast;
4950
+ readonly units: UiUnits;
4951
+ readonly extensions?: UiThemeExtensions;
4841
4952
  /**
4842
- * Kept in the text but not drawn: the run takes no room, paints
4843
- * nothing, and a caret steps over it as one unit.
4844
- *
4845
- * It is a metric field because it changes a width, to nothing. Its
4846
- * characters stay where they were, so every offset still means what
4847
- * it meant, a copy of the text still copies them, and the semantics
4848
- * mirror still reads them. It is how an editor that styles markup
4849
- * as it is typed (`**bold**` drawn as a bold word) puts the markers
4850
- * out of sight without taking them out of the string.
4953
+ * What the person points with, which way this theme was turned (see
4954
+ * `UiPointer`); absent is `fine`. Set by `withPointer`, which every
4955
+ * subtree under a `pointer="coarse"` (or a touch device) is drawn in.
4851
4956
  */
4852
- readonly hidden?: boolean;
4957
+ readonly pointer?: UiPointer;
4958
+ /** What the theme changes for a finger; see `UiThemeTouch`. */
4959
+ readonly touch?: UiThemeTouch;
4853
4960
  }
4961
+ declare const lightTheme: UiTheme;
4962
+ declare const darkTheme: UiTheme;
4854
4963
  /**
4855
- * A run that is activated rather than only read.
4964
+ * Compares two themes for equality.
4856
4965
  *
4857
- * `onClick` runs on a press that neither moved nor selected, and on
4858
- * Enter or Space while the run is focused. `label` names the run in
4859
- * the semantics mirror when the text itself would not ("here" is a
4860
- * link a screen reader cannot use); `href` is carried for the
4861
- * application's own use and the runtime never navigates to it.
4966
+ * The extensions are compared with each extension's own comparison, so
4967
+ * an application that adds a token group gets invalidation on a change
4968
+ * to it without editing this function. That was the point of the
4969
+ * mechanism: a theme layer
4970
+ * added without extending `themesEqual` is a theme change that does
4971
+ * not repaint, and it is easy to forget.
4862
4972
  */
4863
- interface UiTextLink {
4864
- readonly onClick?: () => void;
4865
- readonly label?: string;
4866
- readonly href?: string;
4867
- }
4973
+ declare function themesEqual(a: UiTheme, b: UiTheme): boolean;
4868
4974
  /**
4869
- * One run of a paragraph, with the style fields it overrides.
4975
+ * The same theme at another density.
4870
4976
  *
4871
- * A `Text` node takes either a `text` string or a `spans` array, and
4872
- * the array is the whole of the paragraph: its texts concatenated in
4873
- * order are the text, so every offset the rest of the runtime
4874
- * works in — a line's `start`, a selection range, a find match, a
4875
- * caret — means the same thing whether the paragraph has runs or not.
4876
- * That is the property the whole feature rests on, and it is why runs
4877
- * are a shape of one paragraph rather than a tree of nodes.
4977
+ * Derived from the theme it is given rather than from a base, so
4978
+ * asking twice for `compact` does not shrink the scale twice: a theme
4979
+ * already at that density is returned unchanged.
4980
+ */
4981
+ declare function withDensity(theme: UiTheme, density: UiDensity): UiTheme;
4982
+ /**
4983
+ * The same theme at another contrast.
4878
4984
  *
4879
- * Anything a span does not set it inherits from the node, and the
4880
- * node from its environment, exactly as a node inherits today.
4985
+ * There is no way back from `high`: raising a palette loses what it
4986
+ * was, and a theme that has to be able to return keeps its standard
4987
+ * self and derives the high-contrast one from it. That is what an
4988
+ * application does anyway, since the setting it follows is a cell and
4989
+ * both themes exist for the life of the application.
4881
4990
  */
4882
- interface UiTextSpan extends UiTextMetrics {
4883
- readonly text: string;
4884
- readonly color?: UiColorValue;
4885
- readonly backgroundColor?: UiColorValue;
4886
- readonly textDecoration?: UiTextDecoration;
4887
- readonly link?: UiTextLink;
4888
- }
4889
- /** A span placed in the flattened text: the same fields, plus where it is. */
4890
- interface UiResolvedTextSpan extends UiTextMetrics {
4891
- readonly start: number;
4892
- readonly end: number;
4893
- readonly color?: UiColorValue;
4894
- readonly backgroundColor?: UiColorValue;
4895
- readonly textDecoration?: UiTextDecoration;
4896
- readonly link?: UiTextLink;
4897
- }
4898
- /** A paragraph's text and the runs inside it. */
4899
- interface UiSpannedText {
4900
- readonly text: string;
4901
- readonly spans: readonly UiResolvedTextSpan[];
4902
- }
4991
+ declare function withContrast(theme: UiTheme, contrast: UiContrast, options?: HighContrastOptions): UiTheme;
4992
+ //#endregion
4993
+ //#region src/environment/UiPointer.d.ts
4903
4994
  /**
4904
- * What text is set in when nothing says otherwise.
4995
+ * What the person points with: a mouse or a trackpad (`fine`), or a
4996
+ * finger (`coarse`), as CSS's `pointer` media feature says it.
4905
4997
  *
4906
- * `system-ui` is the platform's own interface face (San Francisco,
4907
- * Segoe UI, Roboto), which is what an application on that platform is
4908
- * expected to look like; `sans-serif` is there for an engine that does
4909
- * not know the generic. The line is 20 on 14, about 1.43, because the
4910
- * 1.2 that a browser's `normal` comes to sets lines too tight to read
4911
- * in a paragraph. The ink is the stock palette's `text`, not black.
4998
+ * Separate from how big the screen is, because the two do not go
4999
+ * together: a tablet with a trackpad is fine, a laptop with a touch
5000
+ * screen is coarse. A layout follows the width (`Responsive`,
5001
+ * `breakpoint`); a control follows this, growing to a target a finger
5002
+ * can hit.
4912
5003
  */
4913
- declare const defaultTextStyle: UiTextStyle;
4914
- /** The text of a span array, with each run's offsets into it. */
4915
- declare function flattenTextSpans(spans: readonly UiTextSpan[]): UiSpannedText;
5004
+ type UiPointer = 'fine' | 'coarse';
4916
5005
  /**
4917
- * A node's paragraph as text and runs, or undefined when it has no
4918
- * runs.
4919
- *
4920
- * `spans` wins over `text` when both are set, because a node that was
4921
- * given runs meant them; the `text` prop is then ignored rather than
4922
- * appended, so there is exactly one source of offsets.
5006
+ * What a theme changes for a finger, laid over itself by
5007
+ * `withPointer(theme, 'coarse')`: type a size larger (an input at 16
5008
+ * pixels, which a phone does not zoom into), more room, and token
5009
+ * groups of its own for touch. Any part left out stays as it is, and a
5010
+ * token group the theme does not carry falls back to the group's own
5011
+ * touch values (`UiThemeExtensionOptions.coarse`).
4923
5012
  */
4924
- declare function spannedTextOf(node: UiNode): UiSpannedText | undefined;
5013
+ interface UiThemeTouch {
5014
+ readonly typography?: Partial<UiTypography>;
5015
+ readonly spacing?: Partial<UiSpacing>;
5016
+ readonly extensions?: UiThemeExtensions;
5017
+ }
5018
+ /** The smallest target a finger can be asked to hit, in pixels: WCAG's 2.5.5, Apple's and Android's 44 to 48. */
5019
+ declare const TOUCH_TARGET = 44;
4925
5020
  /**
4926
- * The text a node draws: its runs' text if it has runs, its `text`
4927
- * property otherwise.
5021
+ * The same theme for another pointer.
4928
5022
  *
4929
- * Every reader of a node's paragraph goes through this — layout,
4930
- * paint, selection, find and the semantics mirror — so a spanned
4931
- * paragraph is selectable, findable and readable without any of them
4932
- * knowing what a span is.
5023
+ * Turned to `coarse`, it is the theme with its `touch` laid over it and
5024
+ * `pointer` saying so; turned back, it is the theme it was turned from,
5025
+ * kept for the purpose, so a subtree that goes from touch to mouse and
5026
+ * back gets the identical theme each time. A theme already for that
5027
+ * pointer is returned as it is.
4933
5028
  */
4934
- declare function textContentOf(node: UiNode): string;
4935
- /** The runs of a node's paragraph; empty when it has none. */
4936
- declare function resolvedSpansOf(node: UiNode): readonly UiResolvedTextSpan[];
5029
+ declare function withPointer(theme: UiTheme, pointer: UiPointer): UiTheme;
5030
+ //#endregion
5031
+ //#region src/properties/UiPropertyDefinition.d.ts
4937
5032
  /**
4938
- * The runs an *editable* node styles its own text with.
5033
+ * Metadata describing a single UI property.
4939
5034
  *
4940
- * An editable's paragraph is the user's, held by its model rather
4941
- * than by a property — so unlike a `Text`, its runs do not supply the
4942
- * text, they only describe it. `spans` on an editable is presentation
4943
- * over a string somebody is typing.
5035
+ * The runtime uses this definition to know:
4944
5036
  *
4945
- * Which is why this checks. Every offset the editor works in — the
4946
- * caret, the selection, the hit test that turns a click into a text
4947
- * position — is an offset into the model's string. Runs describing a
4948
- * *different* string would put the glyphs somewhere the caret does
4949
- * not agree with, and the field would look subtly, unfixably wrong.
4950
- * When they disagree the text is drawn unstyled, which is a frame of
4951
- * plain colour rather than a frame of nonsense, and corrects itself
4952
- * as soon as the application catches up.
5037
+ * - what the property is called
5038
+ * - what value to use when none is specified
5039
+ * - whether the value inherits from the scoped environment
5040
+ * - what changing the value invalidates
5041
+ * - how to compare two values for equality
5042
+ *
5043
+ * A property may optionally declare an environment key and a
5044
+ * resolver that extracts the property value from that environment
5045
+ * value. When `environmentKey` is absent, inherited properties look
5046
+ * for an environment key whose name matches the property name.
4953
5047
  */
4954
- declare function editableSpansOf(node: UiNode, text: string, composition?: UiTextRange | null): readonly UiResolvedTextSpan[];
4955
- /** A stretch of a paragraph, as offsets into its text. */
4956
- interface UiTextRange {
4957
- readonly start: number;
4958
- readonly end: number;
5048
+ interface UiPropertyDefinition<T> {
5049
+ readonly name: string;
5050
+ readonly defaultValue: T;
5051
+ readonly inherited: boolean;
5052
+ readonly affects: DirtyFlags;
5053
+ readonly compare?: (a: T, b: T) => boolean;
5054
+ readonly environmentKey?: UiEnvironmentKey<unknown>;
5055
+ readonly resolveFromEnvironment?: (value: unknown) => T;
5056
+ /**
5057
+ * Rejects a value the property cannot hold, returning the message
5058
+ * for the error the builder throws. Declared only by properties with
5059
+ * a closed set of values, such as `role`; the builder checks it when
5060
+ * a plain value is written, so it costs nothing on the graph's own
5061
+ * write path. A value arriving through an Observable is checked by
5062
+ * whatever reads it, as a bound length is checked at layout.
5063
+ */
5064
+ readonly validate?: (value: T) => string | undefined;
5065
+ /**
5066
+ * Narrows `affects` for one particular change, when what changed
5067
+ * shows that less is invalid than the property's worst case.
5068
+ *
5069
+ * `paint` is the reason it exists. A painter may declare an intrinsic
5070
+ * size, so a new painter can change layout, and `affects` has to say
5071
+ * so; but a new picture with the same declared size (usually none)
5072
+ * cannot, and marking layout for it laid the tree out again up to the
5073
+ * nearest relayout boundary on every repaint, which for a painted
5074
+ * node sized by its parent was the root, every frame of a scroll.
5075
+ * Given the old and new values and the flags `affects` gives, it
5076
+ * returns the flags this change actually needs.
5077
+ */
5078
+ readonly narrowEffects?: (previous: T, next: T, flags: DirtyFlags) => DirtyFlags;
4959
5079
  }
4960
- /** The part of a run `hiddenRangesOf` reads; a paint span has it as well as a resolved one. */
4961
- type HiddenSpan = Pick<UiResolvedTextSpan, 'start' | 'end' | 'hidden'>;
4962
5080
  /**
4963
- * The stretches of a paragraph its runs hide, in order, with runs that
4964
- * touch merged into one: `**` hidden next to a hidden `_` is one
4965
- * stretch of three characters, which a caret steps over at once.
4966
- * Remembered by the identity of the array, as the flattening is.
5081
+ * Creates a property definition with the supplied metadata.
5082
+ *
5083
+ * The default compare function is reference equality (`Object.is`).
4967
5084
  */
4968
- declare function hiddenRangesOf(spans: readonly HiddenSpan[]): readonly UiTextRange[];
4969
- /** The span covering an offset, or undefined where no run does. */
4970
- declare function spanAtOffset(spans: readonly UiResolvedTextSpan[], offset: number): UiResolvedTextSpan | undefined;
5085
+ declare function defineProperty<T>(options: Omit<UiPropertyDefinition<T>, 'name'> & {
5086
+ name: string;
5087
+ }): UiPropertyDefinition<T>;
4971
5088
  /**
4972
- * Compares two span arrays for equality.
4973
- *
4974
- * A link is compared by identity, as every function-valued prop in
4975
- * the registry is: an application that rebuilds its handler each
4976
- * render says the run changed, which costs a paint and no layout,
4977
- * since a handler is not a metric field.
5089
+ * Compares two property values using the definition's comparison
5090
+ * function, falling back to `Object.is` when none is provided.
4978
5091
  */
4979
- declare function textSpansEqual(a: readonly UiTextSpan[] | undefined, b: readonly UiTextSpan[] | undefined): boolean;
5092
+ declare function propertyValuesEqual<T>(definition: UiPropertyDefinition<T>, a: T, b: T): boolean;
5093
+ //#endregion
5094
+ //#region src/layout/UiLength.d.ts
4980
5095
  /**
4981
- * Whether two lists of runs are the same text, set the same way, and
4982
- * differ at most in colour, background and decoration, which are drawn
4983
- * rather than measured.
5096
+ * Length values accepted by size and offset properties.
5097
+ *
5098
+ * A plain number is logical pixels. Anything else is a small tagged
5099
+ * object built by the helpers below — never a string to parse — so a
5100
+ * typo is a type error, and a malformed value reaching the engine at
5101
+ * runtime throws at layout rather than silently becoming zero.
5102
+ *
5103
+ * width: 200 // pixels
5104
+ * width: percent(50) // half of the containing size, when it is
5105
+ * // definite; behaves as `auto` otherwise
5106
+ * margin: auto // main-axis auto margins absorb free space;
5107
+ * // cross-axis ones centre the item
5108
+ * minWidth: auto // the default: a flex item's automatic
5109
+ * // minimum, its min-content size
4984
5110
  */
4985
- declare function spansDifferOnlyInPaint(a: readonly UiTextSpan[] | undefined, b: readonly UiTextSpan[] | undefined): boolean;
5111
+ interface PercentLength {
5112
+ readonly unit: 'percent';
5113
+ readonly value: number;
5114
+ }
5115
+ interface AutoLength {
5116
+ readonly unit: 'auto';
5117
+ }
5118
+ type UiLength = number | PercentLength | AutoLength;
5119
+ /** A grid track that takes a share of free space, `fr(1)`. */
5120
+ interface FrLength {
5121
+ readonly unit: 'fr';
5122
+ readonly value: number;
5123
+ }
5124
+ /** A grid track bounded below and above, `minmax(100, fr(1))`. */
5125
+ interface MinMaxTrack {
5126
+ readonly unit: 'minmax';
5127
+ readonly min: number | PercentLength | AutoLength;
5128
+ readonly max: number | PercentLength | AutoLength | FrLength;
5129
+ }
5130
+ /** What a grid's `columns` / `rows` arrays hold. */
5131
+ type UiTrackSize = number | PercentLength | AutoLength | FrLength | MinMaxTrack;
5132
+ declare function fr(value: number): FrLength;
5133
+ declare function minmax(min: MinMaxTrack['min'], max: MinMaxTrack['max']): MinMaxTrack;
5134
+ /** `repeat(3, fr(1))` → three `fr(1)` tracks; several sizes repeat as a pattern. */
5135
+ declare function repeat(count: number, ...sizes: UiTrackSize[]): UiTrackSize[];
5136
+ declare function isFrLength(value: unknown): value is FrLength;
5137
+ declare function isMinMaxTrack(value: unknown): value is MinMaxTrack;
5138
+ declare function percent(value: number): PercentLength;
5139
+ declare const auto: AutoLength;
5140
+ declare function isAutoLength(value: unknown): value is AutoLength | 'auto';
5141
+ declare function isPercentLength(value: unknown): value is PercentLength;
4986
5142
  /**
4987
- * Compares two text styles for equality.
5143
+ * Resolves a property value to pixels.
5144
+ *
5145
+ * Returns `undefined` when the property is unset, `null`, `auto`, or a
5146
+ * percentage of an indefinite size — every case the caller treats as
5147
+ * "no value". Returns `'auto'` only when `keepAuto` is set, for the
5148
+ * properties where auto means something (margins, minimum sizes).
5149
+ *
5150
+ * Anything else that is not a finite number or a tagged length throws,
5151
+ * naming the property: `width: '100%'` must fail loudly, not lay out
5152
+ * as if the property were absent.
4988
5153
  */
4989
- declare function textStylesEqual(a: UiTextStyle, b: UiTextStyle): boolean;
5154
+ declare function resolveLength(value: unknown, base: number | undefined, property: string, keepAuto?: boolean): number | undefined | 'auto';
4990
5155
  //#endregion
4991
- //#region src/properties/UiVisualState.d.ts
5156
+ //#region src/properties/UiGradient.d.ts
4992
5157
  /**
4993
- * A small, explicit set of interactive visual states.
5158
+ * Renderer-independent gradient descriptions.
4994
5159
  *
4995
- * This is intentionally not a CSS pseudo-class system. Components
4996
- * can resolve properties against the current state set, and the
4997
- * reactive pipeline can drive state changes through Observables.
5160
+ * A gradient is a paint, not a colour: it is what a box's background
5161
+ * is filled with instead of one flat value, and both backends have to
5162
+ * arrive at the same pixels from it. So the description here is
5163
+ * geometry plus stops, with nothing renderer-shaped in it, and the two
5164
+ * renderers share the arithmetic in `gradientPaint` below rather than
5165
+ * each deriving a gradient line of its own.
5166
+ *
5167
+ * Lengths follow the rest of the framework: a plain number is logical
5168
+ * pixels and `percent(n)` is a fraction of whatever the value is a
5169
+ * fraction of, never a string to parse. For a stop that is the length
5170
+ * of the gradient itself, so `percent(50)` is halfway along it whatever
5171
+ * the box measures, and `24` is 24 pixels from its start.
4998
5172
  */
4999
- declare enum UiVisualState {
5000
- Normal = "normal",
5001
- Hovered = "hovered",
5002
- Pressed = "pressed",
5003
- Focused = "focused",
5004
- Disabled = "disabled",
5005
- Selected = "selected",
5006
- Dragged = "dragged"
5173
+ /** How far along a gradient a stop sits. */
5174
+ type UiGradientOffset = number | PercentLength;
5175
+ interface UiGradientStop {
5176
+ /**
5177
+ * Omitted on every stop of a gradient means "spread them evenly",
5178
+ * which is what almost every gradient wants. Omitted on only some of
5179
+ * them is an error rather than a guess: CSS's rule for filling the
5180
+ * gaps is subtle enough that a reader could not predict the result.
5181
+ *
5182
+ * A number is a pixel length along the ramp, never a fraction of it:
5183
+ * `{ offset: 0.45 }` is under half a pixel in, and a gradient whose
5184
+ * stops all sit within the first pixel paints a one-pixel ramp that
5185
+ * reads as nothing at all. A fraction is `percent(45)`. So
5186
+ * `validateGradient` refuses a gradient whose numeric offsets all lie
5187
+ * within 0 to 1 when there are two or more of them; one stop at a
5188
+ * pixel or less among larger pixel offsets is a real position and is
5189
+ * left alone.
5190
+ */
5191
+ readonly offset?: UiGradientOffset;
5192
+ /**
5193
+ * A palette name resolves against the theme the node inherits, so a
5194
+ * themed gradient follows a theme change exactly as `backgroundColor`
5195
+ * does.
5196
+ */
5197
+ readonly color: UiColorValue;
5198
+ }
5199
+ interface UiLinearGradient {
5200
+ readonly kind: 'linear';
5201
+ /**
5202
+ * Direction in radians, on CSS's compass: 0 points at the top of the
5203
+ * box and the angle turns clockwise, so `Math.PI / 2` runs left to
5204
+ * right and `Math.PI` runs top to bottom.
5205
+ */
5206
+ readonly angle: number;
5207
+ readonly stops: readonly UiGradientStop[];
5208
+ }
5209
+ interface UiRadialGradient {
5210
+ readonly kind: 'radial';
5211
+ /** The centre, from the box's top-left. Defaults to `percent(50)` on both axes. */
5212
+ readonly centerX?: UiGradientOffset;
5213
+ readonly centerY?: UiGradientOffset;
5214
+ /**
5215
+ * The radius of the outermost stop. `percent(100)`, the default, is
5216
+ * the distance from the centre to the box's farthest corner, which is
5217
+ * CSS's `farthest-corner`.
5218
+ */
5219
+ readonly radius?: UiGradientOffset;
5220
+ readonly stops: readonly UiGradientStop[];
5007
5221
  }
5222
+ type UiGradient = UiLinearGradient | UiRadialGradient;
5008
5223
  /**
5009
- * A set of active visual states.
5224
+ * The most stops one gradient may carry.
5225
+ *
5226
+ * The WebGPU side stores a gradient as a fixed-size slab in a storage
5227
+ * buffer, because a variable-length record would need a second buffer
5228
+ * of stops and an index into it for what is, in every real interface, a
5229
+ * handful of colours. Eight keeps a record at twelve `vec4`s, and a
5230
+ * ninth stop is a loud error rather than a stop that quietly vanishes:
5231
+ * see `validateGradient`.
5010
5232
  */
5011
- type UiVisualStateSet = ReadonlySet<UiVisualState>;
5233
+ declare const MAX_GRADIENT_STOPS = 8;
5012
5234
  /**
5013
- * Creates a state set from zero or more states.
5235
+ * A linear gradient at `angle` radians, clockwise from the top.
5236
+ *
5237
+ * linearGradient(Math.PI, [{ color: '#0ea5e9' }, { color: '#1e293b' }])
5014
5238
  */
5015
- declare function visualState(...states: UiVisualState[]): UiVisualStateSet;
5239
+ declare function linearGradient(angle: number, stops: readonly UiGradientStop[]): UiLinearGradient;
5240
+ /** A radial gradient, centred and sized as `UiRadialGradient` describes. */
5241
+ declare function radialGradient(stops: readonly UiGradientStop[], options?: Omit<UiRadialGradient, 'kind' | 'stops'>): UiRadialGradient;
5016
5242
  /**
5017
- * The default visual state set containing only Normal.
5243
+ * Rejects a gradient the renderers cannot draw, returning the message
5244
+ * for the error the caller raises.
5245
+ *
5246
+ * The property registry calls this when a plain value is written, so a
5247
+ * bad gradient fails where it was authored. A gradient arriving through
5248
+ * an Observable is checked by `resolveGradient` instead, at paint,
5249
+ * which is where a bound length is checked too.
5018
5250
  */
5019
- declare const defaultVisualState: UiVisualStateSet;
5251
+ declare function validateGradient(value: unknown): string | undefined;
5252
+ /** Whether two gradient property values would paint the same, for the registry. */
5253
+ declare function gradientsEqual(a: UiGradient | undefined, b: UiGradient | undefined): boolean;
5254
+ interface ResolvedGradientStop {
5255
+ readonly offset: UiGradientOffset | undefined;
5256
+ readonly color: UiColor;
5257
+ }
5020
5258
  /**
5021
- * Returns true when the supplied state is active in the set.
5259
+ * A gradient with its palette names resolved against the node's theme,
5260
+ * and nothing else changed.
5261
+ *
5262
+ * Geometry stays as it was authored because it needs the node's box,
5263
+ * which `resolvePaintState` does not have: the renderer turns this into
5264
+ * a `GradientPaint` once it knows the record. Splitting it that way
5265
+ * also means the theme is read once per node per frame rather than once
5266
+ * per stop per pixel.
5022
5267
  */
5023
- declare function hasVisualState(states: UiVisualStateSet, state: UiVisualState): boolean;
5268
+ type ResolvedGradient = {
5269
+ readonly kind: 'linear';
5270
+ readonly angle: number;
5271
+ readonly stops: readonly ResolvedGradientStop[];
5272
+ } | {
5273
+ readonly kind: 'radial';
5274
+ readonly centerX: UiGradientOffset | undefined;
5275
+ readonly centerY: UiGradientOffset | undefined;
5276
+ readonly radius: UiGradientOffset | undefined;
5277
+ readonly stops: readonly ResolvedGradientStop[];
5278
+ };
5024
5279
  /**
5025
- * Compares two visual state sets for equality.
5280
+ * Note that the resolution itself, `resolveGradient`, lives in
5281
+ * `UiThemeColor.ts` rather than here. The registry imports this file
5282
+ * for `gradientsEqual` and `validateGradient`, and the theme lookup
5283
+ * reads properties, so a gradient that resolved its own stops would
5284
+ * close a cycle through the registry. It is the same split that keeps
5285
+ * `colorValuesEqual` in `UiColor.ts`.
5026
5286
  */
5027
- declare function visualStatesEqual(a: UiVisualStateSet, b: UiVisualStateSet): boolean;
5028
- //#endregion
5029
- //#region src/layout/CustomLayout.d.ts
5030
5287
  /**
5031
- * How many times one child may be measured in a single call to a
5032
- * protocol's `layout`.
5033
- *
5034
- * Two, because two is what the engine's own flex algorithm needs: a
5035
- * base measurement at the item's content size, and a second one once
5036
- * the main axis is resolved so a cross size that depends on it comes
5037
- * out right. A protocol that needs a third measurement of the same
5038
- * child is almost always measuring inside a loop over its siblings,
5039
- * which is the shape that turns a linear pass into a quadratic one, so
5040
- * the third throws rather than running.
5288
+ * A gradient placed in a box: geometry in the box's own coordinates,
5289
+ * with the origin at its top-left, and stop offsets as fractions of the
5290
+ * gradient's length.
5041
5291
  *
5042
- * The cap is per child, so the total across a call can never exceed
5043
- * twice the number of children however the protocol distributes them.
5292
+ * This is the shared form both renderers draw from. Canvas2D adds the
5293
+ * box's origin and hands the numbers to `createLinearGradient`; the
5294
+ * WebGPU builder writes them into the frame's gradient buffer and the
5295
+ * fragment shader evaluates the same ramp per pixel.
5044
5296
  */
5045
- declare const MAX_MEASURES_PER_CHILD = 2;
5297
+ interface GradientPaint {
5298
+ readonly kind: 'linear' | 'radial';
5299
+ /** Linear: the start of the gradient line. Radial: the centre. */
5300
+ readonly x0: number;
5301
+ readonly y0: number;
5302
+ /** Linear: the end of the gradient line. Radial: the centre again. */
5303
+ readonly x1: number;
5304
+ readonly y1: number;
5305
+ /** Radial only; zero for a linear gradient. */
5306
+ readonly radius: number;
5307
+ readonly stops: readonly {
5308
+ readonly offset: number;
5309
+ readonly color: UiColor;
5310
+ }[];
5311
+ }
5046
5312
  /**
5047
- * One child of a custom layout, as its protocol sees it.
5313
+ * Places a resolved gradient in a box of the given size.
5048
5314
  *
5049
- * Deliberately not a `UiNode`. A protocol is application code running
5050
- * inside the layout pass, and the four things here are the whole
5051
- * budget: it can ask a child how big it is at a given size, read what
5052
- * it last answered, read the value the element declared as
5053
- * `layoutData`, and say where it goes. It cannot reach the node, its
5054
- * record, its siblings' records or the engine, so there is no way for
5055
- * it to move a box the pass is not expecting to move, and no way for
5056
- * it to read geometry that this pass has not computed yet.
5315
+ * The linear case is CSS's: the gradient line runs through the centre
5316
+ * of the box in the direction of the angle, and it is long enough that
5317
+ * the two corners nearest its ends sit exactly on its endpoints, which
5318
+ * is `|w·sin| + |h·cos|`. The radial case is a circle, centred where
5319
+ * the gradient says and reaching the farthest corner at `percent(100)`.
5057
5320
  *
5058
- * A handle lives for exactly one call. Holding one and using it later
5059
- * throws, because a `place` that landed after the pass had ended would
5060
- * write a box nothing invalidated.
5321
+ * Offsets are clamped into `[0, 1]` and forced to not go backwards, as
5322
+ * CSS forces them, so the two backends receive one already-sorted list
5323
+ * and neither has to decide what a stop behind its predecessor means.
5061
5324
  */
5062
- interface UiLayoutChild {
5063
- /** Its position among the container's in-flow children, from zero. */
5064
- readonly index: number;
5065
- /**
5066
- * Whatever the element declared as `layoutData`: a weight, a lane, a
5067
- * timestamp. The protocol decides what the value means; the engine
5068
- * only carries it.
5069
- */
5070
- readonly data: unknown;
5071
- /**
5072
- * Measures the child under `constraints` and returns the size it
5073
- * takes, margins excluded.
5074
- *
5075
- * At most `MAX_MEASURES_PER_CHILD` times per call. A child that is
5076
- * never measured is measured once by the engine, under the same
5077
- * constraints the container was given, so a protocol that only
5078
- * arranges fixed-size children need not measure at all.
5079
- */
5080
- measure(constraints: Constraints): Size;
5081
- /** What the last `measure` returned, or a zero size before the first. */
5082
- readonly size: Size;
5083
- /**
5084
- * Puts the child's border box at a point in the container's content
5085
- * box, `start` running from the edge the reading starts at.
5086
- *
5087
- * Under `textDirection="rtl"` that edge is the right one and the
5088
- * engine mirrors the coordinate, so a layout written once is laid out
5089
- * both ways round. A protocol that needs to know which way it is
5090
- * being mirrored reads `UiLayoutContext.direction`.
5091
- *
5092
- * `margin` on a child is not applied: only the protocol knows what
5093
- * the space between two of its own children means, and a margin the
5094
- * engine added behind its back would move boxes it had placed.
5095
- */
5096
- place(start: number, top: number): void;
5097
- /**
5098
- * Where `place` last put the child, in the same coordinates, or null
5099
- * when this pass has not placed it. Read by `explain`.
5100
- */
5101
- readonly position: {
5102
- readonly start: number;
5103
- readonly top: number;
5104
- } | null;
5105
- }
5106
- /** What a protocol is told about the container it is laying out. */
5107
- interface UiLayoutContext {
5108
- /** Which way the container reads, so a protocol can be asymmetric on purpose. */
5109
- readonly direction: 'ltr' | 'rtl';
5110
- /** The container's content box, padding excluded, when the axis is definite. */
5111
- readonly definiteWidth: number | undefined;
5112
- readonly definiteHeight: number | undefined;
5113
- }
5325
+ declare function gradientPaint(gradient: ResolvedGradient, width: number, height: number): GradientPaint;
5326
+ //#endregion
5327
+ //#region src/properties/UiImage.d.ts
5114
5328
  /**
5115
- * A layout an application writes itself: the analogue of SwiftUI's
5116
- * `Layout` and Compose's `Layout {}`.
5329
+ * Renderer-facing image type.
5117
5330
  *
5118
- * A masonry, a radial arrangement, a timeline and a tag cloud are all
5119
- * one function over the children's sizes, and none of them is
5120
- * expressible in flex or in grid. Before this they were written with
5121
- * `position: 'absolute'` and a `ctx.bounds()` subscription, which put
5122
- * the arrangement one frame behind the sizes it was arranged from and
5123
- * made every such component measure its own children twice.
5331
+ * ImageBitmap is available on the main thread and in Workers
5332
+ * (createImageBitmap), so the rendering core never depends on
5333
+ * HTMLImageElement and an image decoded in a worker can be drawn there.
5334
+ */
5335
+ type UiImage = ImageBitmap;
5336
+ //#endregion
5337
+ //#region src/rendering/PaintSurface.d.ts
5338
+ /**
5339
+ * The drawing vocabulary an application gets when it wants to draw
5340
+ * something the property set has no name for: a sparkline, a gauge, a
5341
+ * waveform, a chart axis.
5124
5342
  *
5125
- * The protocol speaks the engine's own vocabulary. `Constraints` is
5126
- * the same class the engine hands down, `Size` is what a measurement
5127
- * returns, and the size the protocol returns is clamped by the node's
5128
- * own `width`, `minWidth` and the rest exactly as a Row's content size
5129
- * is. That is the point of the shape: a custom layout is another
5130
- * container, not a hole in the pass.
5343
+ * It sits beside `UiRenderer` on purpose argues
5344
+ * the placement at length. The short version is the risk it exists to
5345
+ * avoid: a paint hook handed a `CanvasRenderingContext2D` would be a
5346
+ * Canvas2D-only capability with a WebGPU backend that could never
5347
+ * catch up, which is how a second-class renderer is made. Nothing here
5348
+ * names a canvas, a device or a texture, so neither backend can be the
5349
+ * one the vocabulary was written for.
5131
5350
  *
5132
- * Hold the protocol object still. It is a property value, compared with
5133
- * `Object.is` like every other, so a fresh object per render marks the
5134
- * node dirty on every frame. Build it once at module scope, or
5135
- * memoise it on the parameters it closes over.
5351
+ * **Coordinates are the node's own.** `(0, 0)` is the top-left of the
5352
+ * resolved box and the box's width and height are the extent, so a
5353
+ * painter never reads a layout record and never learns where on the
5354
+ * screen it ended up. The device scale arrives separately, for the one
5355
+ * thing that genuinely needs it: choosing a hairline that is one
5356
+ * physical pixel rather than one logical one.
5136
5357
  *
5137
- * See `layout/conformance` for what the engine is graded against, and
5138
- * `apps/playground/src/examples/MasonryApp.tsx` for a masonry written
5139
- * against these exports alone.
5358
+ * **Every call is recorded, not executed.** The object a painter is
5359
+ * handed is a `PaintRecorder`, and what it produces is a
5360
+ * `PaintRecording`: plain data, comparable, replayable, and cheap
5361
+ * enough to keep. See `PaintRecording.ts` for why that indirection is
5362
+ * what makes the two backends agree.
5140
5363
  */
5141
- interface UiLayoutProtocol {
5142
- /** Names the arrangement in `explain` and in an error. */
5143
- readonly name: string;
5364
+ interface PaintSurface {
5365
+ /** Pushes the transform, the clip and every style value. */
5366
+ save(): void;
5367
+ restore(): void;
5368
+ translate(x: number, y: number): void;
5369
+ scale(x: number, y: number): void;
5370
+ /** Radians, clockwise, about the current origin. */
5371
+ rotate(angle: number): void;
5372
+ /** Multiplies the current transform by the 3x2 affine `a b c d e f`. */
5373
+ transform(a: number, b: number, c: number, d: number, e: number, f: number): void;
5374
+ beginPath(): void;
5375
+ moveTo(x: number, y: number): void;
5376
+ lineTo(x: number, y: number): void;
5377
+ quadraticCurveTo(cx: number, cy: number, x: number, y: number): void;
5378
+ bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): void;
5379
+ /** Radians; `counterclockwise` defaults to false. */
5380
+ arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
5381
+ rect(x: number, y: number, width: number, height: number): void;
5382
+ /** One radius for all four corners, clamped to half the smaller side. */
5383
+ roundRect(x: number, y: number, width: number, height: number, radius: number): void;
5384
+ closePath(): void;
5385
+ /**
5386
+ * Appends SVG path data to the current path, in the surface's own
5387
+ * coordinates.
5388
+ *
5389
+ * The whole grammar an icon set uses is understood, `A` included:
5390
+ * `PaintPathData.ts` turns it into the calls above, so a `d` string
5391
+ * costs exactly what writing those calls by hand would and works
5392
+ * wherever the rest of this does. That last part is the reason it is
5393
+ * parsed here rather than handed to `Path2D`, which exists in a
5394
+ * browser and not in the suite.
5395
+ */
5396
+ path(d: string): void;
5144
5397
  /**
5145
- * Measures the children, places them, and returns the size the
5146
- * content needs.
5398
+ * A `UiColor`, a hex or named CSS colour, or a palette name.
5147
5399
  *
5148
- * Called twice per pass over a node whose layout is not memoised:
5149
- * once while measuring, when the returned size is what the container
5150
- * reports to its parent and `place` does nothing, and once while
5151
- * placing, when the constraints are the resolved content box and the
5152
- * `place` calls are what assign the boxes. Both calls see the same
5153
- * children in the same order, so a protocol that is a function of its
5154
- * arguments needs no state between them, and one that keeps state
5155
- * anyway will be wrong the first time a memo hit skips a measurement.
5400
+ * A palette name is the reason a painted node follows the light and
5401
+ * dark toggle without the painter knowing there was a toggle: the
5402
+ * name is resolved against whatever theme the node inherits, at the
5403
+ * moment the picture is made, exactly as a `backgroundColor` prop is.
5156
5404
  */
5157
- layout(children: readonly UiLayoutChild[], constraints: Constraints, context: UiLayoutContext): Size;
5405
+ fillColor(color: UiColorValue): void;
5158
5406
  /**
5159
- * Sentences describing the arrangement, for `LayoutEngine.explain`.
5407
+ * A gradient for the fills that follow, placed in the rectangle
5408
+ * given here rather than in the node's box, so a painter can ramp
5409
+ * one bar of a chart without arithmetic of its own.
5410
+ */
5411
+ fillGradient(gradient: UiGradient, x: number, y: number, width: number, height: number): void;
5412
+ strokeColor(color: UiColorValue): void;
5413
+ lineWidth(width: number): void;
5414
+ lineCap(cap: PaintLineCap): void;
5415
+ lineJoin(join: PaintLineJoin): void;
5416
+ miterLimit(limit: number): void;
5417
+ /**
5418
+ * A dash pattern in logical pixels, and how far into it the first
5419
+ * dash starts. An empty pattern draws solid.
5420
+ */
5421
+ lineDash(segments: readonly number[], offset?: number): void;
5422
+ /** Multiplies into the opacity already in force, as a node's does. */
5423
+ alpha(value: number): void;
5424
+ /**
5425
+ * Blurs everything drawn after it, by a radius in logical pixels.
5160
5426
  *
5161
- * Called after a pass, never during one, and given handles that can
5162
- * be read but neither measured nor placed. Say the things the boxes
5163
- * do not: how many columns there are, which one a child landed in,
5164
- * what was left over. `formatExplanation` prints them under the
5165
- * node's own reasons.
5427
+ * Scoped by `save` and `restore` like every other style value, so a
5428
+ * frosted panel is `save`, `blur`, draw, `restore`. Zero clears it.
5166
5429
  */
5167
- explain?(children: readonly UiLayoutChild[], size: Size, context: UiLayoutContext): readonly string[];
5430
+ blur(radius: number): void;
5431
+ /** Fills the current path. The default rule is `nonzero`. */
5432
+ fill(rule?: PaintFillRule): void;
5433
+ stroke(): void;
5434
+ /** Intersects the clip with the current path, until the next `restore`. */
5435
+ clip(rule?: PaintFillRule): void;
5436
+ /**
5437
+ * One line of text at a baseline, in the current fill colour.
5438
+ *
5439
+ * Deliberately one line and not a paragraph: wrapping, bidi and
5440
+ * selection belong to the text node, which does them properly, and a
5441
+ * painter that needs them should draw a text node instead. This is
5442
+ * for the labels a chart puts on its own axes.
5443
+ */
5444
+ text(value: string, x: number, y: number, style?: PaintTextStyle): void;
5445
+ /** Draws an image into a rectangle, stretched to fill it. */
5446
+ image(image: UiImage, x: number, y: number, width: number, height: number): void;
5168
5447
  }
5169
- /** Whether a property value is a usable layout protocol. */
5170
- declare function isLayoutProtocol(value: unknown): value is UiLayoutProtocol;
5171
- //#endregion
5172
- //#region src/environment/UiTypography.d.ts
5173
- /**
5174
- * A typography scale.
5175
- *
5176
- * Each named style is a complete TextStyle so that it can be
5177
- * inherited as a unit. Components can override individual fields
5178
- * while falling back to the scale for the rest.
5179
- */
5180
- interface UiTypography {
5181
- readonly body: UiTextStyle;
5182
- readonly bodyLarge: UiTextStyle;
5183
- readonly bodySmall: UiTextStyle;
5184
- readonly headline: UiTextStyle;
5185
- readonly title: UiTextStyle;
5186
- readonly label: UiTextStyle;
5448
+ type PaintFillRule = 'nonzero' | 'evenodd';
5449
+ type PaintLineCap = 'butt' | 'round' | 'square';
5450
+ type PaintLineJoin = 'miter' | 'round' | 'bevel';
5451
+ type PaintTextAlign = 'left' | 'center' | 'right';
5452
+ /** The little of a text style a single painted line can carry. */
5453
+ interface PaintTextStyle {
5454
+ readonly fontSize?: number;
5455
+ readonly fontFamily?: string;
5456
+ readonly fontWeight?: number | string;
5457
+ /** Which end of the run `x` names. Defaults to `left`. */
5458
+ readonly align?: PaintTextAlign;
5187
5459
  }
5188
5460
  /**
5189
- * Roles an application adds to the scale, declared by merging.
5190
- *
5191
- * A scale of six covers a document and not an application: the two
5192
- * applications here use fourteen and eleven distinct sizes. Rather
5193
- * than grow `UiTypography` for everyone, or send an application back
5194
- * to writing numbers on elements, a theme's typography may carry names
5195
- * of its own, and an application declares them so they type:
5196
- *
5197
- * declare module 'gesso-core' {
5198
- * interface UiTypographyExtensions {
5199
- * readonly cardTitle: unknown;
5200
- * readonly display: unknown;
5201
- * }
5202
- * }
5203
- *
5204
- * The value type is not used, only the key, because what the theme
5205
- * carries is always a `UiTextStyle`. Declaring one makes
5206
- * `textStyle="cardTitle"` legal and `textStyle="cardTtile"` a compile
5207
- * error, which is the whole point.
5208
- */
5209
- interface UiTypographyExtensions {}
5210
- /**
5211
- * A role in the scale, as an element names it: `textStyle="title"`.
5212
- *
5213
- * The idiom the documentation teaches. A size, a weight and a line
5214
- * height written out on an element are three numbers to keep in step
5215
- * across a screen and six to keep in step across an application, and
5216
- * none of them follows a theme; a role is one word that does.
5217
- */
5218
- type UiTypographyRole = keyof UiTypography | (keyof UiTypographyExtensions & string);
5219
- /**
5220
- * Whether a value names a role of the supplied scale.
5461
+ * The box a painter is asked to fill, in its own coordinates.
5221
5462
  *
5222
- * Asked of the scale rather than of a written-out list, so a role an
5223
- * application added is a role. A name the scale does not carry is not
5224
- * one, and the element keeps whatever type it inherited rather than
5225
- * drawing at a default size, which is the quieter of the two failures.
5226
- */
5227
- declare function isTypographyRole(value: unknown, scale: UiTypography): value is UiTypographyRole;
5228
- /**
5229
- * The stock scale: one face, and line heights on a 4-point grid rather
5230
- * than 1.2 of the size, so a paragraph has room and a stack of text
5231
- * lines up with the spacing scale around it.
5463
+ * The node's border box, not its content box: a painter that wants to
5464
+ * respect padding is told what it is and decides, because a gauge
5465
+ * drawn to the edge and a chart inset by its padding are both
5466
+ * legitimate and the property set cannot tell which was meant.
5232
5467
  */
5233
- declare const defaultTypography: UiTypography;
5468
+ interface PaintBox {
5469
+ readonly width: number;
5470
+ readonly height: number;
5471
+ readonly paddingTop: number;
5472
+ readonly paddingRight: number;
5473
+ readonly paddingBottom: number;
5474
+ readonly paddingLeft: number;
5475
+ /**
5476
+ * Physical pixels per logical pixel the picture is being made at.
5477
+ *
5478
+ * The one thing a painter needs the device for: `1 / scale` is a
5479
+ * hairline, and a grid line drawn at `1` on a retina display is two
5480
+ * physical pixels wide and looks it.
5481
+ */
5482
+ readonly scale: number;
5483
+ }
5234
5484
  /**
5235
- * Compares two typography scales for equality.
5485
+ * What a node's `paint` prop holds: the drawing, and what it depends
5486
+ * on.
5236
5487
  *
5237
- * Over the keys rather than a written-out list, as `colorsEqualPalette`
5238
- * is and for the same reason: a scale that carries roles of its own
5239
- * has to invalidate on a change to one of them. Written out, the six
5240
- * shipped roles were compared and an application's own were not, so a
5241
- * scale differing only in a role it had added compared equal and the
5242
- * change never reached the nodes that would have read it.
5243
- */
5244
- declare function typographyEqual(a: UiTypography, b: UiTypography): boolean;
5245
- //#endregion
5246
- //#region src/environment/UiShadows.d.ts
5247
- /**
5248
- * A renderer-independent shadow scale.
5488
+ * `inputs` is the whole of the cost story. The picture is made when
5489
+ * the inputs change and at no other time, so a painted node on a
5490
+ * still frame costs one image draw and nothing else, and
5491
+ * `PaintPicture.budget.spec.ts` asserts exactly that. Without it the
5492
+ * only safe assumption would be that the closure captured something
5493
+ * new, and every frame would repaint.
5249
5494
  *
5250
- * Each value is an array of shadows so layered shadows can be
5251
- * expressed. Renderers translate these into native shadow drawing
5252
- * operations.
5495
+ * Values are compared with `Object.is`, one by one, so a list of
5496
+ * numbers or of stable references works and an array literal rebuilt
5497
+ * per render does not defeat it. Omitting `inputs` means the drawing
5498
+ * never changes on its own, which is the right default for a static
5499
+ * shape and the wrong one for a chart.
5253
5500
  */
5254
- interface UiShadows {
5255
- readonly none: readonly UiBoxShadow[];
5256
- readonly extraSmall: readonly UiBoxShadow[];
5257
- readonly small: readonly UiBoxShadow[];
5258
- readonly medium: readonly UiBoxShadow[];
5259
- readonly large: readonly UiBoxShadow[];
5260
- readonly extraLarge: readonly UiBoxShadow[];
5501
+ interface UiPaint {
5502
+ readonly draw: (surface: PaintSurface, box: PaintBox) => void;
5503
+ readonly inputs?: readonly unknown[];
5504
+ /**
5505
+ * The size the node takes when the layout has none to give it: no
5506
+ * width or height, no flex, nothing stretching it. Zero, like any
5507
+ * other empty leaf, when it is absent.
5508
+ */
5509
+ readonly intrinsicWidth?: number;
5510
+ readonly intrinsicHeight?: number;
5261
5511
  }
5262
- declare const defaultShadows: UiShadows;
5263
- /**
5264
- * Compares two shadow scales for equality.
5265
- */
5266
- declare function shadowsEqual(a: UiShadows, b: UiShadows): boolean;
5267
- //#endregion
5268
- //#region src/environment/UiSpacing.d.ts
5269
5512
  /**
5270
- * A renderer-independent spacing scale.
5271
- *
5272
- * Each value is a logical pixel gap. The names are the shape scale's
5273
- * names on purpose: an application that has learned `borderRadius`
5274
- * from `theme.shapes` already knows what `small` and `extraLarge`
5275
- * mean, and one vocabulary across the theme is one thing to learn.
5513
+ * A static vector shape, as a property rather than a function.
5276
5514
  *
5277
- * Eight steps rather than the shape scale's seven, because spacing is
5278
- * the token an application reaches for most often and a scale that
5279
- * cannot say "two" sends the author back to a literal. The values are
5280
- * a four pixel grid with a two pixel step at the bottom, which is what
5281
- * the two applications' own numbers already cluster on.
5515
+ * The declarative half of this workstream: an icon, a logo, a
5516
+ * decorative rule, anything whose geometry is fixed and whose colours
5517
+ * follow the theme. It is drawn through the same surface a painter
5518
+ * writes to, so there is no second path to keep in step, and a node
5519
+ * may carry both a `path` and a `paint` (the path is drawn first, and
5520
+ * the painter draws over it).
5282
5521
  */
5283
- interface UiSpacing {
5284
- readonly none: number;
5285
- readonly hairline: number;
5286
- readonly extraSmall: number;
5287
- readonly small: number;
5288
- readonly medium: number;
5289
- readonly large: number;
5290
- readonly extraLarge: number;
5291
- readonly huge: number;
5522
+ interface UiPath {
5523
+ /** SVG path data, in `viewBox` units. */
5524
+ readonly d: string;
5525
+ /**
5526
+ * The square the path is authored in, scaled to fit the node's box
5527
+ * as `object-fit: contain` would, and centred in it. Omitted means
5528
+ * the path is already in the node's own logical pixels.
5529
+ */
5530
+ readonly viewBox?: number;
5531
+ readonly fill?: UiColorValue;
5532
+ readonly fillRule?: PaintFillRule;
5533
+ readonly stroke?: UiColorValue;
5534
+ readonly strokeWidth?: number;
5535
+ readonly lineCap?: PaintLineCap;
5536
+ readonly lineJoin?: PaintLineJoin;
5537
+ readonly miterLimit?: number;
5538
+ readonly dash?: readonly number[];
5539
+ readonly dashOffset?: number;
5292
5540
  }
5293
- declare const defaultSpacing: UiSpacing;
5294
- /** The steps, in order, for a scale that is derived rather than written out. */
5295
- declare const spacingSteps: readonly (keyof UiSpacing)[];
5296
5541
  /**
5297
- * The same scale at a different density.
5542
+ * Whether two `paint` values would draw the same picture.
5298
5543
  *
5299
- * Rounded to whole pixels, because a padding that lands on a half
5300
- * pixel puts every box inside it on one too, and the renderers snap
5301
- * differently at that point. `none` stays zero at every density: a gap
5302
- * an application asked not to have is not a gap to shrink.
5303
- */
5304
- declare function scaleSpacing(spacing: UiSpacing, factor: number): UiSpacing;
5305
- /**
5306
- * Compares two spacing scales for equality.
5544
+ * Identity on `draw` plus item-by-item identity on `inputs`, which is
5545
+ * the comparison the property registry runs on every write. A painter
5546
+ * rebuilt by a render body has a new `draw`, so a component that wants
5547
+ * the caching has to hoist the function and vary the inputs, which is
5548
+ * the same rule a modifier's arguments follow.
5307
5549
  */
5308
- declare function spacingEqual(a: UiSpacing, b: UiSpacing): boolean;
5550
+ declare function paintValuesEqual(a: UiPaint | undefined, b: UiPaint | undefined): boolean;
5551
+ /** Item-by-item identity, with absent and empty treated alike. */
5552
+ declare function inputsEqual(a: readonly unknown[] | undefined, b: readonly unknown[] | undefined): boolean;
5553
+ /** Whether two `path` values describe the same shape in the same style. */
5554
+ declare function pathValuesEqual(a: UiPath | undefined, b: UiPath | undefined): boolean;
5309
5555
  //#endregion
5310
- //#region src/environment/UiDensity.d.ts
5556
+ //#region src/properties/UiVisualState.d.ts
5311
5557
  /**
5312
- * How tightly a theme packs.
5313
- *
5314
- * An axis rather than a second theme: an application that wants a
5315
- * compact table and a comfortable settings sheet provides the same
5316
- * theme twice with one field changed, and nothing else about its
5317
- * colours or type is duplicated.
5558
+ * A small, explicit set of interactive visual states.
5318
5559
  *
5319
- * `comfortable` is the scale as written. `compact` is three quarters
5320
- * of it, `spacious` a quarter more. Only the spacing scale moves; type
5321
- * and shape do not, because a smaller gap between two rows is a
5322
- * density choice and a smaller word is a typography one.
5560
+ * This is intentionally not a CSS pseudo-class system. Components
5561
+ * can resolve properties against the current state set, and the
5562
+ * reactive pipeline can drive state changes through Observables.
5323
5563
  */
5324
- type UiDensity = 'compact' | 'comfortable' | 'spacious';
5325
- /** The multiplier each density applies to the spacing scale. */
5326
- declare const densityFactors: Readonly<Record<UiDensity, number>>;
5327
- //#endregion
5328
- //#region src/environment/UiContrast.d.ts
5564
+ declare enum UiVisualState {
5565
+ Normal = "normal",
5566
+ Hovered = "hovered",
5567
+ Pressed = "pressed",
5568
+ Focused = "focused",
5569
+ Disabled = "disabled",
5570
+ Selected = "selected",
5571
+ Dragged = "dragged"
5572
+ }
5329
5573
  /**
5330
- * How much separation a theme keeps between what is drawn and what it
5331
- * is drawn on.
5332
- *
5333
- * `standard` is the palette as the designer wrote it. `high` is the
5334
- * same palette with every foreground pushed away from the surface
5335
- * behind it until it clears a contrast ratio, which is what a person
5336
- * who has turned the operating system's high-contrast setting on is
5337
- * asking for. It is an axis of the theme rather than a second palette
5338
- * so that an application which has already chosen its colours does not
5339
- * have to choose them twice, and so that the accessibility audit has
5340
- * one place to look.
5574
+ * A set of active visual states.
5341
5575
  */
5342
- type UiContrast = 'standard' | 'high';
5576
+ type UiVisualStateSet = ReadonlySet<UiVisualState>;
5343
5577
  /**
5344
- * Relative luminance, as WCAG defines it.
5345
- *
5346
- * Alpha is ignored: a token is compared against the surface it sits
5347
- * on, and what a translucent foreground actually looks like depends on
5348
- * a composite this cannot see. Raising a translucent token toward the
5349
- * extreme is still the right direction.
5578
+ * Creates a state set from zero or more states.
5350
5579
  */
5351
- declare function relativeLuminance(color: UiColor): number;
5580
+ declare function visualState(...states: UiVisualState[]): UiVisualStateSet;
5352
5581
  /**
5353
- * The WCAG contrast ratio between two colours, from 1 to 21.
5582
+ * The default visual state set containing only Normal.
5354
5583
  */
5355
- declare function contrastRatio(a: UiColor, b: UiColor): number;
5584
+ declare const defaultVisualState: UiVisualStateSet;
5356
5585
  /**
5357
- * The same colour, moved toward black or white until it clears
5358
- * `ratio` against `against`.
5359
- *
5360
- * Toward whichever extreme is already the further from the surface, so
5361
- * text on a dark ground gets lighter and text on a light ground gets
5362
- * darker: pushing the other way would cross the surface's own
5363
- * luminance and come out worse before it came out better. A colour
5364
- * that cannot reach the ratio even at the extreme is returned at the
5365
- * extreme, which is the best the palette can do and is still an
5366
- * improvement.
5367
- *
5368
- * Mixed in linear steps of the stored channels rather than by solving
5369
- * for the luminance, because the search is sixteen steps and this runs
5370
- * when a theme is built, not when a frame is drawn.
5586
+ * Returns true when the supplied state is active in the set.
5371
5587
  */
5372
- declare function raiseContrast(color: UiColor, against: UiColor, ratio: number): UiColor;
5373
- /** What a high-contrast palette needs to know of an application's own names. */
5374
- interface HighContrastOptions {
5375
- /**
5376
- * Names a custom palette added that are grounds, not marks, and are
5377
- * left alone as the stock grounds are: a code editor's selection, its
5378
- * current line, a diff's filled lines. Raised as foregrounds, they
5379
- * would turn bright enough against the page that what is drawn on them
5380
- * could not be read.
5381
- */
5382
- readonly surfaces?: Iterable<string>;
5383
- }
5588
+ declare function hasVisualState(states: UiVisualStateSet, state: UiVisualState): boolean;
5384
5589
  /**
5385
- * A palette at high contrast.
5386
- *
5387
- * Every extra name a custom palette added is raised too, against the
5388
- * page background, because a palette that grew a token for its own
5389
- * accent should not be the one thing that stays quiet when the setting
5390
- * is turned on; unless it says it is a ground (`surfaces`). The named
5391
- * foregrounds above override that default with the surface they are
5392
- * really drawn on.
5590
+ * Compares two visual state sets for equality.
5393
5591
  */
5394
- declare function highContrastColors(colors: UiColors, options?: HighContrastOptions): UiColors;
5592
+ declare function visualStatesEqual(a: UiVisualStateSet, b: UiVisualStateSet): boolean;
5395
5593
  //#endregion
5396
- //#region src/environment/UiThemeExtension.d.ts
5594
+ //#region src/layout/CustomLayout.d.ts
5397
5595
  /**
5398
- * Tokens an application adds to a theme, under its own name.
5399
- *
5400
- * `UiTheme` carries the vocabulary every application shares: colours,
5401
- * type, shapes, shadows, spacing. An application always has more than
5402
- * that, and the two in this repository each grew a module of module
5403
- * level constants to hold it, which is a theme that no provider can
5404
- * change and no appearance toggle can reach.
5405
- *
5406
- * An extension is that module turned into part of the theme:
5596
+ * How many times one child may be measured in a single call to a
5597
+ * protocol's `layout`.
5407
5598
  *
5408
- * const brand = defineThemeExtension({
5409
- * name: 'brand',
5410
- * defaults: { linen: '#be9a6e', chalk: '#f7f3ea' }
5411
- * });
5599
+ * Two, because two is what the engine's own flex algorithm needs: a
5600
+ * base measurement at the item's content size, and a second one once
5601
+ * the main axis is resolved so a cross size that depends on it comes
5602
+ * out right. A protocol that needs a third measurement of the same
5603
+ * child is almost always measuring inside a loop over its siblings,
5604
+ * which is the shape that turns a linear pass into a quadratic one, so
5605
+ * the third throws rather than running.
5412
5606
  *
5413
- * const theme = withThemeExtension(lightTheme, brand, { linen: …, chalk: … });
5414
- * themeExtension(theme, brand).linen
5607
+ * The cap is per child, so the total across a call can never exceed
5608
+ * twice the number of children however the protocol distributes them.
5609
+ */
5610
+ declare const MAX_MEASURES_PER_CHILD = 2;
5611
+ /**
5612
+ * One child of a custom layout, as its protocol sees it.
5415
5613
  *
5416
- * The read is a property access on the object the extension was
5417
- * declared with, so an editor completes the token names and a
5418
- * misspelling is a compile error. Nothing about `UiTheme` or
5419
- * `themesEqual` changes to add one: the extensions ride in a map keyed
5420
- * by the symbol `defineThemeExtension` minted, and `themesEqual`
5421
- * compares them with each extension's own comparison.
5614
+ * Deliberately not a `UiNode`. A protocol is application code running
5615
+ * inside the layout pass, and the four things here are the whole
5616
+ * budget: it can ask a child how big it is at a given size, read what
5617
+ * it last answered, read the value the element declared as
5618
+ * `layoutData`, and say where it goes. It cannot reach the node, its
5619
+ * record, its siblings' records or the engine, so there is no way for
5620
+ * it to move a box the pass is not expecting to move, and no way for
5621
+ * it to read geometry that this pass has not computed yet.
5422
5622
  *
5423
- * A component in a library may declare an extension too, which is how
5424
- * a component that needs a token the shared vocabulary does not have
5425
- * gets one without adding a prop for it.
5623
+ * A handle lives for exactly one call. Holding one and using it later
5624
+ * throws, because a `place` that landed after the pass had ended would
5625
+ * write a box nothing invalidated.
5426
5626
  */
5427
- interface UiThemeExtension<T extends object> {
5428
- /** Identity, so two extensions cannot collide on a name. */
5429
- readonly key: symbol;
5430
- readonly name: string;
5431
- /** What `themeExtension` returns for a theme that does not carry it. */
5432
- readonly defaults: T;
5433
- readonly equals: (a: T, b: T) => boolean;
5434
- }
5435
- interface UiThemeExtensionOptions<T extends object> {
5436
- readonly name: string;
5437
- readonly defaults: T;
5627
+ interface UiLayoutChild {
5628
+ /** Its position among the container's in-flow children, from zero. */
5629
+ readonly index: number;
5438
5630
  /**
5439
- * How two values of this extension are compared, for the environment
5440
- * to decide whether a theme change has to invalidate the subtree.
5631
+ * Whatever the element declared as `layoutData`: a weight, a lane, a
5632
+ * timestamp. The protocol decides what the value means; the engine
5633
+ * only carries it.
5634
+ */
5635
+ readonly data: unknown;
5636
+ /**
5637
+ * Measures the child under `constraints` and returns the size it
5638
+ * takes, margins excluded.
5441
5639
  *
5442
- * The default compares the group's own keys, and compares each one
5443
- * structurally when it is a plain object, so a group of `UiColor`
5444
- * tokens built freshly on each appearance change is equal to the one
5445
- * before it. It goes no deeper than that: an extension whose tokens
5446
- * are themselves nested groups should pass its own comparison rather
5447
- * than find out later that its theme never invalidates.
5640
+ * At most `MAX_MEASURES_PER_CHILD` times per call. A child that is
5641
+ * never measured is measured once by the engine, under the same
5642
+ * constraints the container was given, so a protocol that only
5643
+ * arranges fixed-size children need not measure at all.
5448
5644
  */
5449
- readonly equals?: (a: T, b: T) => boolean;
5450
- }
5451
- /** The map a theme carries. Empty for every stock theme. */
5452
- type UiThemeExtensions = ReadonlyMap<symbol, object>;
5453
- declare const noThemeExtensions: UiThemeExtensions;
5454
- /**
5455
- * Declares a group of tokens an application or a library adds to a
5456
- * theme. Call it once, at module level, and export the result.
5457
- */
5458
- declare function defineThemeExtension<T extends object>(options: UiThemeExtensionOptions<T>): UiThemeExtension<T>;
5459
- /** What the theme carries for this extension, or its declared defaults. */
5460
- declare function themeExtension<T extends object>(theme: {
5461
- readonly extensions?: UiThemeExtensions;
5462
- }, extension: UiThemeExtension<T>): T;
5463
- /** Whether the theme carries this extension at all, rather than falling back. */
5464
- declare function hasThemeExtension<T extends object>(theme: {
5465
- readonly extensions?: UiThemeExtensions;
5466
- }, extension: UiThemeExtension<T>): boolean;
5645
+ measure(constraints: Constraints): Size;
5646
+ /** What the last `measure` returned, or a zero size before the first. */
5647
+ readonly size: Size;
5648
+ /**
5649
+ * Puts the child's border box at a point in the container's content
5650
+ * box, `start` running from the edge the reading starts at.
5651
+ *
5652
+ * Under `textDirection="rtl"` that edge is the right one and the
5653
+ * engine mirrors the coordinate, so a layout written once is laid out
5654
+ * both ways round. A protocol that needs to know which way it is
5655
+ * being mirrored reads `UiLayoutContext.direction`.
5656
+ *
5657
+ * `margin` on a child is not applied: only the protocol knows what
5658
+ * the space between two of its own children means, and a margin the
5659
+ * engine added behind its back would move boxes it had placed.
5660
+ */
5661
+ place(start: number, top: number): void;
5662
+ /**
5663
+ * Where `place` last put the child, in the same coordinates, or null
5664
+ * when this pass has not placed it. Read by `explain`.
5665
+ */
5666
+ readonly position: {
5667
+ readonly start: number;
5668
+ readonly top: number;
5669
+ } | null;
5670
+ }
5671
+ /** What a protocol is told about the container it is laying out. */
5672
+ interface UiLayoutContext {
5673
+ /** Which way the container reads, so a protocol can be asymmetric on purpose. */
5674
+ readonly direction: 'ltr' | 'rtl';
5675
+ /** The container's content box, padding excluded, when the axis is definite. */
5676
+ readonly definiteWidth: number | undefined;
5677
+ readonly definiteHeight: number | undefined;
5678
+ }
5467
5679
  /**
5468
- * The same theme with one extension's tokens set.
5680
+ * A layout an application writes itself: the analogue of SwiftUI's
5681
+ * `Layout` and Compose's `Layout {}`.
5469
5682
  *
5470
- * Returns a new theme; a theme is a value and is compared as one. The
5471
- * extensions map is copied rather than mutated for the same reason,
5472
- * since two themes derived from one base must not share it.
5473
- */
5474
- declare function withThemeExtension<Theme extends {
5475
- readonly extensions?: UiThemeExtensions;
5476
- }, T extends object>(theme: Theme, extension: UiThemeExtension<T>, value: T): Theme;
5477
- /**
5478
- * Compares the extension maps of two themes.
5683
+ * A masonry, a radial arrangement, a timeline and a tag cloud are all
5684
+ * one function over the children's sizes, and none of them is
5685
+ * expressible in flex or in grid. Before this they were written with
5686
+ * `position: 'absolute'` and a `ctx.bounds()` subscription, which put
5687
+ * the arrangement one frame behind the sizes it was arranged from and
5688
+ * made every such component measure its own children twice.
5479
5689
  *
5480
- * A key one carries and the other does not is a difference, and each
5481
- * key is compared with the comparison its own extension declared. The
5482
- * comparison lives on the value rather than in a registry so that an
5483
- * extension declared in an application is compared as well as one
5484
- * declared here, which is the whole point of the mechanism.
5485
- */
5486
- declare function themeExtensionsEqual(a: UiThemeExtensions | undefined, b: UiThemeExtensions | undefined): boolean;
5487
- //#endregion
5488
- //#region src/environment/UiTheme.d.ts
5489
- /**
5490
- * A renderer-independent theme.
5690
+ * The protocol speaks the engine's own vocabulary. `Constraints` is
5691
+ * the same class the engine hands down, `Size` is what a measurement
5692
+ * returns, and the size the protocol returns is clamped by the node's
5693
+ * own `width`, `minWidth` and the rest exactly as a Row's content size
5694
+ * is. That is the point of the shape: a custom layout is another
5695
+ * container, not a hole in the pass.
5491
5696
  *
5492
- * A theme bundles colors, typography, shapes, shadows and spacing into
5493
- * a single environment value. It can be provided at any node and is
5494
- * inherited by descendants until another provider overrides it.
5697
+ * Hold the protocol object still. It is a property value, compared with
5698
+ * `Object.is` like every other, so a fresh object per render marks the
5699
+ * node dirty on every frame. Build it once at module scope, or
5700
+ * memoise it on the parameters it closes over.
5495
5701
  *
5496
- * `density` and `contrast` are axes rather than scales: they record
5497
- * which way this theme was already turned, so a component can branch
5498
- * on the answer and `withDensity` and `withContrast` can turn it
5499
- * again from the base. `extensions` is where an application's own
5500
- * token groups live; see `UiThemeExtension.ts`.
5702
+ * See `layout/conformance` for what the engine is graded against, and
5703
+ * `apps/playground/src/examples/MasonryApp.tsx` for a masonry written
5704
+ * against these exports alone.
5501
5705
  */
5502
- interface UiTheme {
5503
- readonly colors: UiColors;
5504
- readonly typography: UiTypography;
5505
- readonly shapes: UiShapes;
5506
- readonly shadows: UiShadows;
5507
- readonly spacing: UiSpacing;
5508
- readonly density: UiDensity;
5509
- readonly contrast: UiContrast;
5510
- readonly extensions?: UiThemeExtensions;
5706
+ interface UiLayoutProtocol {
5707
+ /** Names the arrangement in `explain` and in an error. */
5708
+ readonly name: string;
5709
+ /**
5710
+ * Measures the children, places them, and returns the size the
5711
+ * content needs.
5712
+ *
5713
+ * Called twice per pass over a node whose layout is not memoised:
5714
+ * once while measuring, when the returned size is what the container
5715
+ * reports to its parent and `place` does nothing, and once while
5716
+ * placing, when the constraints are the resolved content box and the
5717
+ * `place` calls are what assign the boxes. Both calls see the same
5718
+ * children in the same order, so a protocol that is a function of its
5719
+ * arguments needs no state between them, and one that keeps state
5720
+ * anyway will be wrong the first time a memo hit skips a measurement.
5721
+ */
5722
+ layout(children: readonly UiLayoutChild[], constraints: Constraints, context: UiLayoutContext): Size;
5723
+ /**
5724
+ * Sentences describing the arrangement, for `LayoutEngine.explain`.
5725
+ *
5726
+ * Called after a pass, never during one, and given handles that can
5727
+ * be read but neither measured nor placed. Say the things the boxes
5728
+ * do not: how many columns there are, which one a child landed in,
5729
+ * what was left over. `formatExplanation` prints them under the
5730
+ * node's own reasons.
5731
+ */
5732
+ explain?(children: readonly UiLayoutChild[], size: Size, context: UiLayoutContext): readonly string[];
5511
5733
  }
5512
- declare const lightTheme: UiTheme;
5513
- declare const darkTheme: UiTheme;
5514
- /**
5515
- * Compares two themes for equality.
5516
- *
5517
- * The extensions are compared with each extension's own comparison, so
5518
- * an application that adds a token group gets invalidation on a change
5519
- * to it without editing this function. That was the point of the
5520
- * mechanism: a theme layer
5521
- * added without extending `themesEqual` is a theme change that does
5522
- * not repaint, and it is easy to forget.
5523
- */
5524
- declare function themesEqual(a: UiTheme, b: UiTheme): boolean;
5525
- /**
5526
- * The same theme at another density.
5527
- *
5528
- * Derived from the theme it is given rather than from a base, so
5529
- * asking twice for `compact` does not shrink the scale twice: a theme
5530
- * already at that density is returned unchanged.
5531
- */
5532
- declare function withDensity(theme: UiTheme, density: UiDensity): UiTheme;
5533
- /**
5534
- * The same theme at another contrast.
5535
- *
5536
- * There is no way back from `high`: raising a palette loses what it
5537
- * was, and a theme that has to be able to return keeps its standard
5538
- * self and derives the high-contrast one from it. That is what an
5539
- * application does anyway, since the setting it follows is a cell and
5540
- * both themes exist for the life of the application.
5541
- */
5542
- declare function withContrast(theme: UiTheme, contrast: UiContrast, options?: HighContrastOptions): UiTheme;
5734
+ /** Whether a property value is a usable layout protocol. */
5735
+ declare function isLayoutProtocol(value: unknown): value is UiLayoutProtocol;
5543
5736
  //#endregion
5544
5737
  //#region src/properties/UiVideo.d.ts
5545
5738
  /**
@@ -7043,7 +7236,7 @@ declare const UiProperties: {
7043
7236
  */
7044
7237
  readonly borderRadius: UiPropertyDefinition<UiBorderRadiusValue>;
7045
7238
  readonly opacity: UiPropertyDefinition<number>;
7046
- readonly boxShadows: UiPropertyDefinition<readonly UiBoxShadow[]>;
7239
+ readonly boxShadows: UiPropertyDefinition<UiBoxShadows>;
7047
7240
  readonly visible: UiPropertyDefinition<boolean>;
7048
7241
  readonly fontFamily: UiPropertyDefinition<string>;
7049
7242
  readonly fontSize: UiPropertyDefinition<number>;
@@ -7153,6 +7346,15 @@ declare const UiProperties: {
7153
7346
  * container instead.
7154
7347
  */
7155
7348
  readonly pointerEvents: UiPropertyDefinition<UiPointerEvents | undefined>;
7349
+ /**
7350
+ * Takes a mouse over this subtree as a finger, as a browser's device
7351
+ * mode does: nothing is hovered without a press, a press hovers what
7352
+ * it lands on until it lifts, and the press has a finger's slop and
7353
+ * gestures. For a design tool playing a screen drawn for touch with a
7354
+ * mouse; read up the ancestor chain. A finger and a pen are
7355
+ * unchanged.
7356
+ */
7357
+ readonly touchEmulation: UiPropertyDefinition<boolean | undefined>;
7156
7358
  readonly focusable: UiPropertyDefinition<boolean | undefined>;
7157
7359
  readonly tabStop: UiPropertyDefinition<boolean | undefined>;
7158
7360
  readonly disabled: UiPropertyDefinition<boolean | undefined>;
@@ -7242,6 +7444,15 @@ declare const UiProperties: {
7242
7444
  readonly columnCount: UiPropertyDefinition<number | undefined>;
7243
7445
  /** Any subset of x, y, scaleX, scaleY, rotation; the rest is identity. */
7244
7446
  readonly transform: UiPropertyDefinition<Partial<UiTransform> | undefined>;
7447
+ /**
7448
+ * Keep what this subtree paints as pixels, and copy them while only
7449
+ * what is above it moves or scales: a design tool's frames under a
7450
+ * zooming camera, a map's tiles under a pan. Canvas2D only; see
7451
+ * `RasterCache.ts` for when it draws them again. A hint: a subtree
7452
+ * that changes on most frames, or one too large to hold at the scale
7453
+ * it is drawn at, is drawn directly.
7454
+ */
7455
+ readonly rasterize: UiPropertyDefinition<boolean>;
7245
7456
  readonly text: UiPropertyDefinition<string | undefined>;
7246
7457
  readonly image: UiPropertyDefinition<ImageBitmap | undefined>;
7247
7458
  /**
@@ -7253,6 +7464,16 @@ declare const UiProperties: {
7253
7464
  * why the value is a surface with a version rather than a frame.
7254
7465
  */
7255
7466
  readonly video: UiPropertyDefinition<UiVideoSurface | undefined>;
7467
+ /**
7468
+ * The URL the node's picture was loaded from, as `imageSource` last
7469
+ * resolved it: an image's or an SVG's.
7470
+ *
7471
+ * Nothing lays it out or paints it. It is there for what reads a tree
7472
+ * as a document, an inspector, a design tool writing the screen as
7473
+ * HTML, since the bitmap or the drawing on the node no longer says
7474
+ * where it came from.
7475
+ */
7476
+ readonly src: UiPropertyDefinition<string | undefined>;
7256
7477
  readonly objectFit: UiPropertyDefinition<UiObjectFit | undefined>;
7257
7478
  readonly scrollX: UiPropertyDefinition<number | undefined>;
7258
7479
  /**
@@ -7333,6 +7554,13 @@ declare const UiProperties: {
7333
7554
  /** Set by LazySheet on the scroll container: its UiVirtualSheet. */
7334
7555
  readonly virtualSheet: UiPropertyDefinition<UiVirtualSheet | undefined>;
7335
7556
  readonly theme: UiPropertyDefinition<UiTheme | undefined>;
7557
+ /**
7558
+ * What the person points with in this subtree, `fine` or `coarse`,
7559
+ * over the device's: a design tool's frame drawn as a phone says
7560
+ * `coarse`, and the controls in it grow to a finger's size. See
7561
+ * `UiPointer`.
7562
+ */
7563
+ readonly pointer: UiPropertyDefinition<UiPointer | undefined>;
7336
7564
  /**
7337
7565
  * The type this element and its subtree are written in: a role in
7338
7566
  * the theme's scale (`textStyle="title"`), or a style of its own.
@@ -7503,13 +7731,13 @@ type FlexItemProps = PropsOf<'flex' | 'flexGrow' | 'flexShrink' | 'flexBasis' |
7503
7731
  /** Where an element sits in a Grid. */
7504
7732
  type GridItemProps = PropsOf<'column' | 'columnSpan' | 'row' | 'rowSpan'>;
7505
7733
  type PositionProps = PropsOf<'position' | 'top' | 'right' | 'bottom' | 'left' | 'inset' | 'zIndex' | 'lift' | 'liftBoundary' | 'anchor' | 'anchorPoint' | 'anchorRect' | 'placement' | 'anchorOffset'>;
7506
- type PaintProps = PropsOf<'backgroundColor' | 'backgroundGradient' | 'borderColor' | 'borderWidth' | 'borderRadius' | 'opacity' | 'boxShadows' | 'visible' | 'transform'>;
7734
+ type PaintProps = PropsOf<'backgroundColor' | 'backgroundGradient' | 'borderColor' | 'borderWidth' | 'borderRadius' | 'opacity' | 'boxShadows' | 'visible' | 'transform' | 'rasterize'>;
7507
7735
  /**
7508
7736
  * Inherited text properties. Legal on any element: set on a container,
7509
7737
  * they cascade to the text below it.
7510
7738
  */
7511
7739
  type TypographyProps = PropsOf<'color' | 'fontFamily' | 'fontSize' | 'fontWeight' | 'lineHeight' | 'letterSpacing' | 'textAlign' | 'textDirection' | 'fontStyle' | 'fontStretch' | 'fontVariant' | 'fontKerning' | 'textDecoration'>;
7512
- type InteractionProps = PropsOf<'cursor' | 'pointerEvents' | 'focusable' | 'tabStop' | 'disabled' | 'hitTestable' | 'visualState' | 'selectable' | 'editingGroup' | 'textInput'>;
7740
+ type InteractionProps = PropsOf<'cursor' | 'pointerEvents' | 'touchEmulation' | 'focusable' | 'tabStop' | 'disabled' | 'hitTestable' | 'visualState' | 'selectable' | 'editingGroup' | 'textInput'>;
7513
7741
  /**
7514
7742
  * What the element means, for assistive technology. Legal on any
7515
7743
  * element; a component sets them on the node that *is* the control,
@@ -7517,7 +7745,7 @@ type InteractionProps = PropsOf<'cursor' | 'pointerEvents' | 'focusable' | 'tabS
7517
7745
  */
7518
7746
  type SemanticsProps = PropsOf<'role' | 'label' | 'description' | 'live' | 'states' | 'valueNow' | 'valueMin' | 'valueMax' | 'valueText' | 'posInSet' | 'setSize' | 'level' | 'rowIndex' | 'columnIndex' | 'rowCount' | 'columnCount' | 'activeDescendant' | 'controls' | 'autocomplete' | 'orientation'>;
7519
7747
  /** Environment values an element provides to its subtree. */
7520
- type EnvironmentProps = PropsOf<'theme' | 'textStyle' | 'contentColor' | 'containerSize' | 'insets'>;
7748
+ type EnvironmentProps = PropsOf<'theme' | 'pointer' | 'textStyle' | 'contentColor' | 'containerSize' | 'insets'>;
7521
7749
  /**
7522
7750
  * Behaviour attached to an element without wrapping it: hover and
7523
7751
  * press state, a focus ring, a tooltip, drag. See `packages/core/src/modifiers`.
@@ -7870,6 +8098,17 @@ declare class UiGraphBuilder {
7870
8098
  private warnMissingAnimations;
7871
8099
  /** The modifiers attached to a node, for the inspector and for tests. */
7872
8100
  modifiersFor(node: UiNode): UiModifierSet | undefined;
8101
+ /**
8102
+ * Where the element a node was last reconciled from was written, for
8103
+ * the inspector and for tools that edit the source. For a component's
8104
+ * anchor it is where the component was used, so walking up from a
8105
+ * node gives the line that made it and then each place it was used.
8106
+ *
8107
+ * Read off the definition the builder already keeps for each node
8108
+ * rather than stored on the node, so it costs a tree nothing when no
8109
+ * element carries one, which is every element in production.
8110
+ */
8111
+ sourceOf(node: UiNode): UiSourceLocation | undefined;
7873
8112
  /**
7874
8113
  * Rejects a prop nothing will ever read.
7875
8114
  *
@@ -9502,6 +9741,13 @@ declare const UiEnvironmentKeys: {
9502
9741
  * as it changes. Provided by `Responsive` and by the
9503
9742
  * `containerSize` property; see `UiContainerSize`.
9504
9743
  */
9744
+ /**
9745
+ * What the person points with here: the device's, as the runtime
9746
+ * reads it (CSS's `pointer` feature), or what an ancestor said with
9747
+ * `pointer`. A theme provided under `coarse` is turned for it
9748
+ * (`withPointer`). See `UiPointer`.
9749
+ */
9750
+ readonly pointer: UiEnvironmentKey<UiPointer>;
9505
9751
  readonly containerSize: UiEnvironmentKey<UiContainerSize>;
9506
9752
  /**
9507
9753
  * What is in the way of the content on each edge: the platform's
@@ -11059,6 +11305,11 @@ interface PointerControllerOptions {
11059
11305
  * same thing by holding, which the gesture recognizer answers.
11060
11306
  * - Touch hover: a finger's hover is dropped when it lifts, because
11061
11307
  * the finger is no longer anywhere. A mouse keeps its hover.
11308
+ * - Touch emulation: over a `touchEmulation` subtree a mouse is taken
11309
+ * as a finger, as a browser's device mode does. Its moves with
11310
+ * nothing pressed hover nothing there, and a press there is a
11311
+ * finger's from down to up: its slop, its gestures and its hover
11312
+ * dropped when it lifts.
11062
11313
  * - Scrollbars: a press on a scroll container's thumb starts a drag
11063
11314
  * that moves the content with the pointer; a press on the track
11064
11315
  * beside a visible thumb pages one viewport toward the pointer.
@@ -11116,6 +11367,8 @@ declare class UiPointerController {
11116
11367
  readonly y: number;
11117
11368
  } | null;
11118
11369
  private lastPosition;
11370
+ /** Whether the last hover hit was on a scrollbar; see `overScrollbar`. */
11371
+ private hoverOnScrollbar;
11119
11372
  /** The pressed node and its ancestors when the press began, deepest first. */
11120
11373
  private downPath;
11121
11374
  get hoveredNode(): UiNode | null;
@@ -11132,26 +11385,33 @@ declare class UiPointerController {
11132
11385
  private captured;
11133
11386
  /** The scroll container whose thumb is being dragged, or null. */
11134
11387
  get draggingScrollbarOf(): UiNode | null;
11388
+ /**
11389
+ * Whether the pointer is on a scrollbar, or dragging a thumb: the arrow
11390
+ * is shown there whatever the content under the bar asks for, as over a
11391
+ * native scrollbar. A hit on a bar is its scroll container's, so the
11392
+ * cursor set above that (an editor's I-beam) was shown over the thumb.
11393
+ */
11394
+ get overScrollbar(): boolean;
11135
11395
  /**
11136
11396
  * Pointer press. Hit-tests at the point, establishes hover, and
11137
11397
  * dispatches PointerDown to the pressed node. Subsequent moves and
11138
11398
  * the up are routed to that node until release.
11139
11399
  */
11140
- pointerDown(x: number, y: number, buttons?: number, modifiers?: UiKeyModifiers, pointer?: UiPointerDevice): UiPointerEvent;
11400
+ pointerDown(x: number, y: number, buttons?: number, modifiers?: UiKeyModifiers, device?: UiPointerDevice): UiPointerEvent;
11141
11401
  /**
11142
11402
  * Pointer movement. While a press is active the move is routed to
11143
11403
  * the pressed node (capture); otherwise it hit-tests, updates
11144
11404
  * hover enter/leave, and dispatches PointerMove to the hovered
11145
11405
  * node. Returns null when the move lands on empty space.
11146
11406
  */
11147
- pointerMove(x: number, y: number, buttons?: number, modifiers?: UiKeyModifiers, pointer?: UiPointerDevice): UiPointerEvent | null;
11407
+ pointerMove(x: number, y: number, buttons?: number, modifiers?: UiKeyModifiers, device?: UiPointerDevice): UiPointerEvent | null;
11148
11408
  /**
11149
11409
  * Pointer release. Dispatches PointerUp to the pressed node and,
11150
11410
  * when the press did not travel beyond the slop and was not
11151
11411
  * cancelled via preventDefault on the down, synthesizes a Click on
11152
11412
  * the same node. Returns null when nothing was pressed.
11153
11413
  */
11154
- pointerUp(x: number, y: number, buttons?: number, modifiers?: UiKeyModifiers, pointer?: UiPointerDevice): UiPointerEvent | null;
11414
+ pointerUp(x: number, y: number, buttons?: number, modifiers?: UiKeyModifiers, device?: UiPointerDevice): UiPointerEvent | null;
11155
11415
  /**
11156
11416
  * Pairs this Click with the one before it, and dispatches a
11157
11417
  * DoubleClick when they make a pair.
@@ -11168,7 +11428,7 @@ declare class UiPointerController {
11168
11428
  * Aborts the active press: dispatches PointerCancel to the pressed
11169
11429
  * node and clears press state so no Click is synthesized.
11170
11430
  */
11171
- pointerCancel(pointer?: UiPointerDevice): void;
11431
+ pointerCancel(device?: UiPointerDevice): void;
11172
11432
  /**
11173
11433
  * Whether an event from this contact should be acted on.
11174
11434
  *
@@ -11178,6 +11438,8 @@ declare class UiPointerController {
11178
11438
  * a mouse that never pressed anything.
11179
11439
  */
11180
11440
  private ownsPress;
11441
+ /** The contact an event is from: the press's own, which an emulated finger's mouse events are part of. */
11442
+ private contactOf;
11181
11443
  /**
11182
11444
  * A press on the thumb starts a drag that maps pointer travel to
11183
11445
  * scroll offset through the thumb's travel range. A press on the
@@ -11314,6 +11576,8 @@ interface UiShortcutStep {
11314
11576
  readonly meta: boolean;
11315
11577
  readonly shift: boolean;
11316
11578
  readonly alt: boolean;
11579
+ /** The physical key a press was made on, in the DOM's `code` vocabulary; only a press has one. */
11580
+ readonly code?: string;
11317
11581
  }
11318
11582
  /** What an application registers. */
11319
11583
  interface UiShortcut {
@@ -11442,8 +11706,11 @@ declare class UiShortcutRegistry {
11442
11706
  * `preventDefault()` so the keyboard controller's own defaults (Tab
11443
11707
  * navigation, Enter on a button, an editable's typing) do not also
11444
11708
  * act on a key that has already been spent.
11709
+ *
11710
+ * `code` is the physical key, which a digit written with Shift
11711
+ * matches on (see `sameStep`).
11445
11712
  */
11446
- handleKey(key: string, modifiers: UiKeyModifiers, focused: UiNode | null): boolean;
11713
+ handleKey(key: string, modifiers: UiKeyModifiers, focused: UiNode | null, code?: string): boolean;
11447
11714
  private platform;
11448
11715
  /** Whether a field would take this key as an edit of its own, rather than as text or as Enter. */
11449
11716
  private isEditingKey;
@@ -12500,7 +12767,6 @@ declare function isNodeInert(node: UiNode): boolean;
12500
12767
  * descendant can set 'auto'; the hit tester follows that itself.
12501
12768
  */
12502
12769
  declare function isSubtreeInert(node: UiNode): boolean;
12503
- /** `pointerEvents` as CSS inherits it: the nearest value set from the node up, 'auto' when none is. */
12504
12770
  declare function pointerEventsOf(node: UiNode | null): 'auto' | 'none';
12505
12771
  /** The node itself cannot be the target of a hit, but children can. */
12506
12772
  declare function isNodeHitTestable(node: UiNode): boolean;
@@ -12696,6 +12962,8 @@ declare class UiHostFrameClock implements UiFrameClock {
12696
12962
  /** Gaps between this thread's own refreshes while frames ran back to back. */
12697
12963
  private readonly localIntervals;
12698
12964
  private lastLocalTime;
12965
+ /** How long the frame drawn at `lastLocalTime` took, which says whether the gap after it was the refresh's or the frame's. */
12966
+ private lastLocalCost;
12699
12967
  /** The display's interval and the host's time origin, once the host has said. */
12700
12968
  private display;
12701
12969
  /**
@@ -12704,6 +12972,11 @@ declare class UiHostFrameClock implements UiFrameClock {
12704
12972
  * show (see \`displayInterval\`).
12705
12973
  */
12706
12974
  private locked;
12975
+ /** This thread's own `requestAnimationFrame` once given up, kept to see whether it keeps time after all. */
12976
+ private givenUp;
12977
+ /** When this thread's refreshes were last timed again, and their times while they are being. */
12978
+ private lastRetry;
12979
+ private retrying;
12707
12980
  /** The host's recent refresh times, which give the beat its phase. */
12708
12981
  private readonly refreshes;
12709
12982
  /** Host refreshes since the last frame drawn on the beat. */
@@ -12759,6 +13032,23 @@ declare class UiHostFrameClock implements UiFrameClock {
12759
13032
  * a faster screen), not a worker failing to keep up with it.
12760
13033
  */
12761
13034
  private compareLocal;
13035
+ /**
13036
+ * Times this thread's own refreshes again, now and then, once they were
13037
+ * given up, and takes them back if they keep the display's time.
13038
+ *
13039
+ * Given up for good, a worker's refreshes stayed given up whatever had
13040
+ * made them slow. A Chrome worker busy between its frames, opening a
13041
+ * large file or scrolling through lines it has never drawn, refreshes
13042
+ * late and unevenly, which no measure of the gaps alone told from
13043
+ * WebKit's timer: 5.5, 25.5, 10.9, 25 ms on a 165 Hz display one time,
13044
+ * 12.1, 6.1, 12.2, 24.2 the next. Its frames then went through the
13045
+ * host's ticks for as long as the page was open, a message and a hop
13046
+ * through the page's thread each. Timed again while frames are cheap,
13047
+ * they come a refresh apart and are taken back; WebKit's come 15 ms
13048
+ * apart on a 120 Hz display however idle the thread is, and stay given
13049
+ * up. Nine refreshes every two seconds or more, while frames come cheap.
13050
+ */
13051
+ private retryLocal;
12762
13052
  /** A time on the host's clock, on this thread's. */
12763
13053
  private toLocal;
12764
13054
  /**
@@ -13119,7 +13409,6 @@ declare function labelNode(node: UiNode): string;
13119
13409
  declare function formatExplanation(explanation: LayoutExplanation): string;
13120
13410
  //#endregion
13121
13411
  //#region src/layout/LayoutEngine.d.ts
13122
- /** How long overlay scrollbars stay after the last scroll change. */
13123
13412
  declare const SCROLLBAR_LINGER_MS = 1200;
13124
13413
  /** Portion of the linger during which the scrollbar fades out. */
13125
13414
  declare const SCROLLBAR_FADE_MS = 350;
@@ -13427,6 +13716,15 @@ declare class LayoutEngine {
13427
13716
  * with the node and sits twice as far into it.
13428
13717
  */
13429
13718
  screenBox(node: UiNode, part?: LayoutBox): LayoutBox;
13719
+ /**
13720
+ * Where everything under a node is drawn, through every transform
13721
+ * above it: its subtree's bounds, as `subtreeBoundsFor` left them,
13722
+ * projected as `screenBox` projects the node's own box. Null when the
13723
+ * subtree has no bounds to cull by (it draws past them, or has no
13724
+ * record). What a walk under a panned, zoomed parent passes a whole
13725
+ * subtree over by when none of it is on screen.
13726
+ */
13727
+ screenBounds(node: UiNode): LayoutBox | null;
13430
13728
  /**
13431
13729
  * The scroll offsets each scroll ancestor would need so that `node`
13432
13730
  * is inside its viewport, `padding` pixels from the nearest edge,
@@ -14190,6 +14488,16 @@ declare class LayoutEngine {
14190
14488
  */
14191
14489
  private lengthProp;
14192
14490
  private lengthPropOrAuto;
14491
+ /**
14492
+ * A length, or nothing when the value cannot be one. A plain value
14493
+ * that cannot is refused when it is written (each length property's
14494
+ * `validate`); one that arrives bound, from an Observable, is caught
14495
+ * here. Throwing here abandoned the frame, and with it every other
14496
+ * element: one mock's `width: '100%'` stopped a whole design editor
14497
+ * drawing. So it is said, once for the node and property, and the
14498
+ * element is laid out as if the property were not set.
14499
+ */
14500
+ private lengthOrNothing;
14193
14501
  /**
14194
14502
  * A margin side: the side's own value, else the logical side that
14195
14503
  * resolved to it, else its axis, else the shorthand; may be auto.
@@ -15268,11 +15576,9 @@ interface DefaultImageResolverOptions {
15268
15576
  *
15269
15577
  * **What it cannot decode.** `createImageBitmap` takes a `Blob`, and
15270
15578
  * Chrome refuses an SVG one — "The source image could not be decoded".
15271
- * So an `Image` pointed at an `.svg` fails on a browser where the same
15272
- * file in an `<img>` would work, and a vector glyph belongs in `Icon`,
15273
- * which draws a path rather than decoding a document. Found by
15274
- * pointing the playground's Media card at an SVG data URL and getting
15275
- * a placeholder.
15579
+ * Found by pointing the playground's Media card at an SVG data URL and
15580
+ * getting a placeholder. So an `Image` never sends one here: an SVG
15581
+ * source is read by `SvgResolver` and drawn as vectors (`svg/`).
15276
15582
  *
15277
15583
  * **Eviction.** Reference counting first, LRU second. A bitmap
15278
15584
  * something on screen is holding is never evicted, however long the
@@ -15298,6 +15604,131 @@ declare class DefaultImageResolver implements ImageResolver {
15298
15604
  dispose(): void;
15299
15605
  }
15300
15606
  //#endregion
15607
+ //#region src/rendering/svg/SvgXml.d.ts
15608
+ /**
15609
+ * Just enough XML to read an SVG file, in a worker.
15610
+ *
15611
+ * A render worker has no `DOMParser`, and an SVG file is XML, so the
15612
+ * file is read here: elements, their attributes and their nesting.
15613
+ * Text is kept only where SVG gives it meaning to a drawing, inside
15614
+ * `<style>`; everything else that is not an element (the declaration,
15615
+ * a doctype, comments, processing instructions) is skipped.
15616
+ *
15617
+ * Forgiving on purpose, in the way `tracePathData` is: a file a
15618
+ * design tool exported is well formed, and one that is not is better
15619
+ * drawn as far as it reads than refused, so an unclosed element is
15620
+ * closed at the end and a stray close tag is ignored.
15621
+ */
15622
+ interface SvgXmlElement {
15623
+ /** The element's name, with any namespace prefix: `svg`, `path`, `xlink:href` is an attribute. */
15624
+ readonly name: string;
15625
+ readonly attributes: Readonly<Record<string, string>>;
15626
+ readonly children: readonly SvgXmlElement[];
15627
+ /** The text directly inside it, joined; empty for an element with none. */
15628
+ readonly text: string;
15629
+ }
15630
+ //#endregion
15631
+ //#region src/rendering/svg/SvgDocument.d.ts
15632
+ /**
15633
+ * An SVG file, read and ready to draw.
15634
+ *
15635
+ * Gesso cannot hand an SVG file to the platform: `createImageBitmap`
15636
+ * refuses one in Chrome, and a render worker has no `<img>` to draw it
15637
+ * through. It does not need to. An SVG is shapes, paint and transforms,
15638
+ * and `PaintSurface` is exactly that vocabulary, so the file is read
15639
+ * here and drawn through it by `drawSvg`: as vectors, on either
15640
+ * renderer, at whatever size the node is laid out at, and with
15641
+ * `currentColor` following the theme.
15642
+ *
15643
+ * What a design tool exports is what is read: shapes and paths, groups
15644
+ * and `<use>`, transforms, solid fills and strokes with their
15645
+ * opacities, linear and radial gradients, clip paths, a `<style>` of
15646
+ * simple selectors, and nested `<svg>`. What is not drawn yet is named
15647
+ * in `unsupported`, so a file that leans on it can say so rather than
15648
+ * look subtly wrong.
15649
+ */
15650
+ interface SvgDocument {
15651
+ /** The `<svg>` element. */
15652
+ readonly root: SvgXmlElement;
15653
+ /** The size the file asks to be drawn at, in logical pixels: its `width` and `height`, else its viewBox's. */
15654
+ readonly width: number;
15655
+ readonly height: number;
15656
+ /** The region of the drawing's own coordinates that fills that size. */
15657
+ readonly viewBox: SvgRect;
15658
+ /** Every element with an `id`, for `<use>`, gradients and clip paths. */
15659
+ readonly ids: ReadonlyMap<string, SvgXmlElement>;
15660
+ /** The rules of its `<style>` elements, in document order. */
15661
+ readonly rules: readonly SvgStyleRule[];
15662
+ /** What the file uses that is not drawn: `text`, `filter`, `mask` and so on, once each. */
15663
+ readonly unsupported: readonly string[];
15664
+ }
15665
+ interface SvgRect {
15666
+ readonly x: number;
15667
+ readonly y: number;
15668
+ readonly width: number;
15669
+ readonly height: number;
15670
+ }
15671
+ /** One rule of a `<style>`: which elements, and what it declares for them. */
15672
+ interface SvgStyleRule {
15673
+ readonly selector: SvgSelector;
15674
+ readonly declarations: Readonly<Record<string, string>>;
15675
+ /** For the cascade: ids over classes over names. */
15676
+ readonly specificity: number;
15677
+ }
15678
+ /** A compound selector of the kind exporters write: `path`, `.st0`, `#logo`, `g.mark`. */
15679
+ interface SvgSelector {
15680
+ readonly name?: string;
15681
+ readonly id?: string;
15682
+ readonly classes: readonly string[];
15683
+ }
15684
+ /**
15685
+ * Reads an SVG file. Throws when it holds no `<svg>` element, since
15686
+ * there is then nothing to draw and the caller should fall back.
15687
+ */
15688
+ declare function parseSvg(source: string): SvgDocument;
15689
+ //#endregion
15690
+ //#region src/rendering/svg/SvgResolver.d.ts
15691
+ /**
15692
+ * Turns an SVG source into a read document, as `ImageResolver` turns a
15693
+ * picture's into a bitmap: fetched once, read once, shared by every
15694
+ * node that shows it.
15695
+ */
15696
+ interface SvgResolver {
15697
+ /** The read document, or a rejection when it will not fetch or is not SVG. */
15698
+ resolve(source: string): Promise<SvgDocument>;
15699
+ /** The document when it has already been read, so a node built in this frame draws it at once. */
15700
+ peek?(source: string): SvgDocument | null;
15701
+ }
15702
+ interface DefaultSvgResolverOptions {
15703
+ /** How many read files to keep. They are small: a tree of elements, no pixels. */
15704
+ capacity?: number;
15705
+ /** Injectable for specs, and for an app that fetches through its own stack. */
15706
+ fetch?: (source: string) => Promise<string>;
15707
+ }
15708
+ /**
15709
+ * Whether a source is an SVG file, from its name or its data URL's
15710
+ * type: what `Image` asks before it decodes, since the platform
15711
+ * decoder refuses SVG and this one draws it.
15712
+ */
15713
+ declare function isSvgSource(source: string): boolean;
15714
+ /**
15715
+ * Fetch, read, keep.
15716
+ *
15717
+ * Kept by recency and never closed, unlike a bitmap: a read file holds
15718
+ * no decoded pixels, so there is nothing to release promptly, and a
15719
+ * file a screen shows a hundred times (an icon in every row) is read
15720
+ * once. A failed fetch is not kept, so the next node tries again.
15721
+ */
15722
+ declare class DefaultSvgResolver implements SvgResolver {
15723
+ private readonly entries;
15724
+ private readonly settled;
15725
+ private readonly capacity;
15726
+ private readonly fetchText;
15727
+ constructor(options?: DefaultSvgResolverOptions);
15728
+ resolve(source: string): Promise<SvgDocument>;
15729
+ peek(source: string): SvgDocument | null;
15730
+ }
15731
+ //#endregion
15301
15732
  //#region src/rendering/IconRasterizer.d.ts
15302
15733
  /** What an icon is: a path in a square viewBox, at a size, in a colour. */
15303
15734
  interface IconSpec {
@@ -15385,6 +15816,16 @@ declare class IconRasterizer {
15385
15816
  }
15386
15817
  //#endregion
15387
15818
  //#region src/modifiers/media.d.ts
15819
+ /**
15820
+ * How many pictures the media modifiers in this thread are still
15821
+ * fetching or decoding: an `Image`'s bitmap or its SVG.
15822
+ *
15823
+ * A tree waiting on a picture asks for no frames while it waits, so a
15824
+ * caller that judges a tree finished by its quiet (`renderFrame`, which
15825
+ * draws a mock once, off screen) would draw it without the picture.
15826
+ * This is the other half of finished: nothing still on its way.
15827
+ */
15828
+ declare function mediaLoadsInFlight(): number;
15388
15829
  /** One url, or several to try in order until one resolves. */
15389
15830
  type ImageSources = string | readonly string[];
15390
15831
  interface ImageSourceArgs {
@@ -15395,6 +15836,13 @@ interface ImageSourceArgs {
15395
15836
  * new value replaces the last.
15396
15837
  */
15397
15838
  readonly source: Reactive<ImageSources>;
15839
+ /**
15840
+ * Where an SVG source is read, since the platform decoder refuses
15841
+ * one. Given, an `.svg` or `data:image/svg+xml` source is drawn as
15842
+ * vectors through the node's `paint`, fitted by its `objectFit`;
15843
+ * without it, an SVG source is decoded like any other and fails.
15844
+ */
15845
+ readonly vectors?: SvgResolver;
15398
15846
  readonly onState?: (state: 'loading' | 'loaded' | 'failed', error?: unknown) => void;
15399
15847
  }
15400
15848
  /**
@@ -16568,6 +17016,14 @@ interface UiRenderer {
16568
17016
  * emptied too and will not say so. The next frame redraws everything.
16569
17017
  */
16570
17018
  surfaceRestored?(): void;
17019
+ /**
17020
+ * When, on the \`performance.now\` clock, the renderer wants a frame
17021
+ * though nothing changes: Canvas2D's kept subtrees, drawn stretched
17022
+ * while a zoom moves, are drawn sharp once it settles, and nothing
17023
+ * else would ask for that frame. Undefined when nothing waits. Read
17024
+ * after each frame.
17025
+ */
17026
+ nextRepaint?(): number | undefined;
16571
17027
  dispose(): void;
16572
17028
  }
16573
17029
  //#endregion
@@ -16711,6 +17167,112 @@ declare class TextRasterCache {
16711
17167
  private drop;
16712
17168
  }
16713
17169
  //#endregion
17170
+ //#region src/rendering/canvas2d/RasterCache.d.ts
17171
+ /**
17172
+ * Subtrees kept as pixels, for a node marked `rasterize`, and copied
17173
+ * onto the frame while only what is above them moves or scales.
17174
+ *
17175
+ * **Why.** A design tool's board is a camera over a few dozen frames,
17176
+ * each a whole screen of photographs, vector logos and text. Zooming
17177
+ * it changes nothing inside any frame, yet a full traversal draws every
17178
+ * one of them again on every step: in Atelier, twenty frames cost 10 to
17179
+ * 50 ms a step, most of it resampling the photographs and filling the
17180
+ * logos' paths at a scale they had not been drawn at before. Copied, a
17181
+ * frame is one `drawImage`.
17182
+ *
17183
+ * **What is kept.** What the node and its subtree paint, drawn once into
17184
+ * a canvas of its own at the device scale it is drawn at, over the
17185
+ * area its subtree may paint (its record's extent), relative to its own
17186
+ * corner: a node that moves without changing is copied where it is.
17187
+ *
17188
+ * **When it is drawn again.**
17189
+ *
17190
+ * - At once, when what it shows may have changed: anything in the
17191
+ * subtree was dirtied, an ancestor changed what it passes down, the
17192
+ * node changed size, or the frame was not vouched for.
17193
+ * - Once a zoom has settled, when the scale it is drawn at is not the
17194
+ * one it was kept at. While the scale keeps changing the pixels it
17195
+ * has are stretched, which is blurred or soft for a moment and keeps
17196
+ * the frame rate; when the scale has held for `SETTLE_MS` it is
17197
+ * drawn again, sharp, a few a frame, and `nextRepaint` asks the
17198
+ * runtime for the frame that does it, since nothing else would.
17199
+ * - Mid-zoom, when the stretch is past what still reads as the picture
17200
+ * (`MAX_STRETCH`) and the frame has the time left for it, by what it
17201
+ * took the last time; one that would drop the frame waits to settle.
17202
+ *
17203
+ * **When it is drawn directly instead.** A context that rotates or
17204
+ * skews; a node with a transform or a sticky shift of its own; a
17205
+ * subtree that would not fit in `MAX_RASTER_PIXELS` at the scale it is
17206
+ * drawn at (zoomed far into it, where only a part is on screen and
17207
+ * culling draws just that part); one whose pixels change without its
17208
+ * changes saying so (a caret, a fading scrollbar, a video) or which lifts
17209
+ * something to the top layer; and one drawn again on most of its recent
17210
+ * frames, which a cache would only draw twice.
17211
+ */
17212
+ declare class RasterCache {
17213
+ private readonly createCanvas;
17214
+ private readonly settleMs;
17215
+ private readonly entries;
17216
+ private frame;
17217
+ private pixels;
17218
+ private open;
17219
+ /** Pixels drawn again this frame for a sharper scale. */
17220
+ private spent;
17221
+ /** The frame's own size in device pixels; nothing larger is kept. */
17222
+ private surfacePixels;
17223
+ private wanted;
17224
+ /** Copies, draws into the cache, and draws left to the frame, since the last reset. For budget specs. */
17225
+ readonly stats: {
17226
+ copied: number;
17227
+ drawn: number;
17228
+ direct: number;
17229
+ };
17230
+ constructor(createCanvas: LayerCanvasFactory, settleMs?: number);
17231
+ /**
17232
+ * Marks what the frame's changes leave out of date, before anything is
17233
+ * drawn. A frame the caller could not vouch for, or one after a frame
17234
+ * that never finished, leaves everything out of date.
17235
+ */
17236
+ beginFrame(changes: RenderChanges | undefined, surfacePixels?: number): void;
17237
+ /** Lets go of what was not drawn lately: removed, culled for a while, or hidden. */
17238
+ endFrame(): void;
17239
+ dropAll(): void;
17240
+ resetStats(): void;
17241
+ /**
17242
+ * When the frame just drawn would like another though nothing changes:
17243
+ * a zoom settling, whose kept pixels are then drawn again at the scale
17244
+ * it stopped at. Undefined when nothing waits.
17245
+ */
17246
+ get nextRepaint(): number | undefined;
17247
+ /**
17248
+ * Draws a node and its subtree from the cache, drawing them into it
17249
+ * first when what it holds is out of date. `paint` draws them into the
17250
+ * context it is handed, already placed, and answers whether what it
17251
+ * drew may be kept (see the class comment). False when the node should
17252
+ * be drawn directly.
17253
+ */
17254
+ draw(ctx: Canvas2DContext, node: UiNode, rec: LayoutRecord, now: number, paint: (target: Canvas2DContext, width: number, height: number) => boolean): boolean;
17255
+ /**
17256
+ * A subtree kept at another scale than it is drawn at: stretched while
17257
+ * the scale is moving, drawn again once it has settled or when it is
17258
+ * stretched too far, as the frame's budget allows.
17259
+ */
17260
+ private resharpen;
17261
+ private want;
17262
+ /**
17263
+ * Draws the subtree into the node's canvas at a scale, its area's
17264
+ * corner at (`cornerX`, `cornerY`) in layout pixels, with the
17265
+ * fraction of a device pixel its corner lands on, so a copy at that
17266
+ * scale is the direct draw's pixels. Null when no canvas could be had,
17267
+ * or when what `paint` drew may not be kept; the entry then draws
17268
+ * directly for a while, and this frame copies what was drawn.
17269
+ */
17270
+ private redraw;
17271
+ /** Makes room for `needed` more pixels, letting go of what was drawn least recently; false when it cannot. */
17272
+ private make;
17273
+ private drop;
17274
+ }
17275
+ //#endregion
16714
17276
  //#region src/rendering/canvas2d/Canvas2DRenderer.d.ts
16715
17277
  interface Canvas2DRendererOptions {
16716
17278
  /**
@@ -16733,8 +17295,10 @@ interface Canvas2DRendererOptions {
16733
17295
  */
16734
17296
  scrollLayers?: boolean;
16735
17297
  /**
16736
- * Makes the canvases scroll layers and kept text are held in. Defaults
16737
- * to an `OffscreenCanvas`; a spec passes a double.
17298
+ * Makes the canvases scroll layers, kept text and opacity groups are
17299
+ * held in. Defaults to an `OffscreenCanvas`; a spec passes a double.
17300
+ * Where none can be had, a group's opacity is multiplied into each of
17301
+ * its draws instead (see `GroupOpacity.ts`).
16738
17302
  */
16739
17303
  createLayerCanvas?: LayerCanvasFactory;
16740
17304
  /**
@@ -16749,6 +17313,16 @@ interface Canvas2DRendererOptions {
16749
17313
  * the layers themselves passes 1.
16750
17314
  */
16751
17315
  scrollLayerSettleFrames?: number;
17316
+ /**
17317
+ * Whether a node marked \`rasterize\` keeps its subtree as pixels.
17318
+ * Defaults to true; false draws it every frame. See \`RasterCache.ts\`.
17319
+ */
17320
+ rasterCache?: boolean;
17321
+ /**
17322
+ * How long a zoom's scale must hold before what was kept at another is
17323
+ * drawn again, sharp. Defaults to \`SETTLE_MS\`; a spec passes 0.
17324
+ */
17325
+ rasterSettleMs?: number;
16752
17326
  }
16753
17327
  /**
16754
17328
  * Canvas2D rendering backend.
@@ -16775,6 +17349,12 @@ interface Canvas2DRendererOptions {
16775
17349
  * containers clip to their viewport and translate by
16776
17350
  * (-scrollX, -scrollY); node transforms compose on the current CTM.
16777
17351
  *
17352
+ * Opacity groups: a node at `opacity < 1` whose subtree paints more
17353
+ * than one draw is drawn into an offscreen layer and blended onto the
17354
+ * frame once, as CSS composites it (`GroupOpacity.ts`). One that
17355
+ * paints a single draw multiplies `globalAlpha` instead, which is the
17356
+ * same picture for nothing.
17357
+ *
16778
17358
  * State isolation: save()/restore() are used exactly when a node
16779
17359
  * introduces opacity, a transform, or a scroll viewport. Flat style
16780
17360
  * fields (fillStyle, font, lineWidth, ...) are assigned before each
@@ -16852,7 +17432,30 @@ declare class Canvas2DRenderer implements UiRenderer {
16852
17432
  * not keep what it drew if it moved.
16853
17433
  */
16854
17434
  private volatileDraws;
17435
+ /**
17436
+ * The canvases opacity groups are drawn in, one per depth of nesting,
17437
+ * so a group inside a group never draws over what holds it. Each
17438
+ * group sizes the one at its depth to its region (`layerRegion`).
17439
+ */
17440
+ private readonly groups;
17441
+ /** How many groups the walk is inside. */
17442
+ private groupDepth;
16855
17443
  constructor(options: Canvas2DRendererOptions);
17444
+ /** Subtrees marked \`rasterize\` kept as pixels; see \`RasterCache.ts\`. */
17445
+ private readonly rasters;
17446
+ /** How deep inside a kept subtree's own walk the traversal is. One is not kept inside another. */
17447
+ private rasterDepth;
17448
+ /**
17449
+ * The device pixels the walk draws within: the surface's, or a kept
17450
+ * subtree's canvas while it is drawn into. An opacity group's region is
17451
+ * cut to them.
17452
+ */
17453
+ private boundsWidth;
17454
+ private boundsHeight;
17455
+ /** What the raster cache did since the last reset, or null with it off. For budget specs. */
17456
+ get rasterCacheStats(): RasterCache['stats'] | null;
17457
+ /** When a frame is wanted though nothing changes: a zoom settling, whose kept pixels are then drawn sharp. */
17458
+ nextRepaint(): number | undefined;
16856
17459
  /** Text kept as pixels; see `TextRasterCache.ts`. */
16857
17460
  private readonly textCache;
16858
17461
  /** What the text cache did since the last reset, or null with it off. For budget specs. */
@@ -16867,6 +17470,8 @@ declare class Canvas2DRenderer implements UiRenderer {
16867
17470
  resize(width: number, height: number, dpr: number): void;
16868
17471
  /** A restored scroll layer reads as healthy and holds nothing. */
16869
17472
  surfaceRestored(): void;
17473
+ /** Kept subtrees were drawn with the fallback face. */
17474
+ fontsChanged(): void;
16870
17475
  dispose(): void;
16871
17476
  render(root: UiNode, context: RenderContext): void;
16872
17477
  /**
@@ -16876,6 +17481,21 @@ declare class Canvas2DRenderer implements UiRenderer {
16876
17481
  private resolvePaint;
16877
17482
  private beginFrame;
16878
17483
  private renderNode;
17484
+ /**
17485
+ * Draws a node marked \`rasterize\` from its kept pixels, drawing it
17486
+ * into them first when they are out of date. False when it is to be
17487
+ * drawn directly: a transform of its own, which its extent does not
17488
+ * include, or anything \`RasterCache\` declines.
17489
+ */
17490
+ private drawKept;
17491
+ /**
17492
+ * The canvas an opacity group at the current depth is drawn in, made
17493
+ * the first time a group reaches that depth. Null where no canvas can
17494
+ * be had, or where the frame's context cannot say what transform the
17495
+ * layer should take on; the group then multiplies its opacity into
17496
+ * each draw, as before.
17497
+ */
17498
+ private groupLayer;
16879
17499
  private renderChildren;
16880
17500
  /**
16881
17501
  * The top layer: the nodes that asked for `lift`, drawn after the
@@ -17020,6 +17640,13 @@ declare class Canvas2DRenderer implements UiRenderer {
17020
17640
  /** One walk of a layer's children, clipped to `strips` and culled to what reaches them. */
17021
17641
  private walkLayer;
17022
17642
  private applyTransform;
17643
+ /**
17644
+ * Whether where a node's subtree may paint meets the visible region,
17645
+ * after its sticky shift and its own transform, which its extent does
17646
+ * not include: a node a transform moves on screen from off it is
17647
+ * drawn. One that turns is always drawn.
17648
+ */
17649
+ private extentVisible;
17023
17650
  private intersectsCull;
17024
17651
  /**
17025
17652
  * Intersects the visible region with a scroll viewport and shifts
@@ -17034,6 +17661,13 @@ declare class Canvas2DRenderer implements UiRenderer {
17034
17661
  */
17035
17662
  private paintScrollbars;
17036
17663
  private pushCull;
17664
+ /**
17665
+ * Takes the visible region back through a node's sticky shift and a
17666
+ * transform that only moves and scales, into the coordinates its
17667
+ * children are laid out in. False, with nothing pushed, for one that
17668
+ * turns or flips.
17669
+ */
17670
+ private pushMappedCull;
17037
17671
  private popCull;
17038
17672
  }
17039
17673
  /**
@@ -17195,6 +17829,35 @@ declare class LayoutInspector {
17195
17829
  private clippedVisibleBox;
17196
17830
  }
17197
17831
  //#endregion
17832
+ //#region src/rendering/svg/SvgDraw.d.ts
17833
+ /** How a drawing fills a box whose shape is not its own: `objectFit`'s values. */
17834
+ type SvgFit = 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
17835
+ interface SvgDrawOptions {
17836
+ /** How the drawing fills the box. `contain` by default, as an `<img>` of an SVG keeps its proportions. */
17837
+ readonly fit?: SvgFit;
17838
+ /**
17839
+ * What \`currentColor\` is: a palette name or a colour. By default the
17840
+ * node's own text colour, inherited, so an icon set authored in
17841
+ * \`currentColor\` takes the colour of the text around it and follows a
17842
+ * theme change.
17843
+ */
17844
+ readonly color?: UiColorValue;
17845
+ }
17846
+ /**
17847
+ * Draws a read SVG file into a box, through the surface every painted
17848
+ * node draws through, so it is vectors on either renderer and is drawn
17849
+ * again at whatever size the box is laid out at.
17850
+ */
17851
+ declare function drawSvg(document: SvgDocument, surface: PaintSurface, box: Pick<PaintBox, 'width' | 'height'>, options?: SvgDrawOptions): void;
17852
+ /**
17853
+ * A read SVG file as a node's `paint`: drawn to fill the node, and the
17854
+ * file's own size as the node's when the layout gives it none.
17855
+ *
17856
+ * The same object for the same file and options, so a node given it
17857
+ * again is not drawn again; see `paintValuesEqual`.
17858
+ */
17859
+ declare function svgPaint(document: SvgDocument, options?: SvgDrawOptions): UiPaint;
17860
+ //#endregion
17198
17861
  //#region src/rendering/PaintRecording.d.ts
17199
17862
  /**
17200
17863
  * One call a painter made, as data.
@@ -17861,6 +18524,12 @@ declare class WebGPURenderer implements UiRenderer {
17861
18524
  private frameLayout;
17862
18525
  private frameBindGroup;
17863
18526
  private cachedInstanceData;
18527
+ /**
18528
+ * The textures opacity groups are drawn in, one per depth of nesting,
18529
+ * so a group inside a group never clears what holds it. Made the first
18530
+ * time a frame reaches that depth and again when the surface resizes.
18531
+ */
18532
+ private groupLayers;
17864
18533
  /** Draw calls of the most recent frame. */
17865
18534
  readonly lastDraws: DrawStats;
17866
18535
  private pendingCapture;
@@ -17901,6 +18570,8 @@ declare class WebGPURenderer implements UiRenderer {
17901
18570
  * primitives under a scissor, one draw per text run or image.
17902
18571
  */
17903
18572
  render(root: UiNode, context: RenderContext): void;
18573
+ /** The layer for an opacity group at `depth`, made or remade at the surface's size. */
18574
+ private groupLayer;
17904
18575
  /**
17905
18576
  * When a capture is pending, encodes a copy of the frame into a
17906
18577
  * mappable buffer and returns the step that maps it after submit.
@@ -18042,6 +18713,12 @@ interface TexturedPipeline {
18042
18713
  textSampler: GPUSampler;
18043
18714
  /** Linear sampling: images are scaled by objectFit. */
18044
18715
  imageSampler: GPUSampler;
18716
+ /**
18717
+ * The same quads, blending a premultiplied opacity-group layer rather
18718
+ * than a straight-alpha texture; bound with `textSampler`, since a
18719
+ * layer is drawn one texel to a pixel.
18720
+ */
18721
+ layerPipeline: GPURenderPipeline;
18045
18722
  }
18046
18723
  //#endregion
18047
18724
  //#region src/rendering/webgpu/WebGPUTextureCache.d.ts
@@ -18419,7 +19096,14 @@ declare const enum CommandKind {
18419
19096
  /** A contiguous range of glyph instances sharing one atlas page. */
18420
19097
  Glyphs = 1,
18421
19098
  /** One textured instance drawn with an image. */
18422
- Image = 2
19099
+ Image = 2,
19100
+ /**
19101
+ * Everything until the matching `EndLayer` is drawn into a cleared
19102
+ * layer of its own, the start of an opacity group (`GroupOpacity.ts`).
19103
+ */
19104
+ BeginLayer = 3,
19105
+ /** The layer is done, and is blended onto what holds it at the group's opacity. */
19106
+ EndLayer = 4
18423
19107
  }
18424
19108
  type Affine = [number, number, number, number, number, number];
18425
19109
  interface ScissorRect {
@@ -18465,7 +19149,25 @@ interface ImageCommand {
18465
19149
  drawWidth: number;
18466
19150
  drawHeight: number;
18467
19151
  }
18468
- type RenderCommand = PrimitiveCommand | GlyphCommand | ImageCommand;
19152
+ interface BeginLayerCommand {
19153
+ kind: CommandKind.BeginLayer;
19154
+ /** Always null: opening a layer draws nothing. */
19155
+ scissor: null;
19156
+ }
19157
+ interface EndLayerCommand {
19158
+ kind: CommandKind.EndLayer;
19159
+ /**
19160
+ * The textured instance that blends the layer: a quad over the
19161
+ * group's region (`layerRegion`), one texel to a device pixel,
19162
+ * carrying the group's opacity and the rounded clip its ancestors
19163
+ * set. Null when the region is off the surface and there is nothing
19164
+ * to blend.
19165
+ */
19166
+ instance: number | null;
19167
+ /** The ancestors' clip, in physical pixels; null for none. */
19168
+ scissor: ScissorRect | null;
19169
+ }
19170
+ type RenderCommand = PrimitiveCommand | GlyphCommand | ImageCommand | BeginLayerCommand | EndLayerCommand;
18469
19171
  /**
18470
19172
  * One line of text the frame drew, as a whole.
18471
19173
  *
@@ -19720,5 +20422,5 @@ interface UiSemanticsAction {
19720
20422
  readonly value?: string;
19721
20423
  }
19722
20424
  //#endregion
19723
- export { Mp4AudioTrack as $, UiDroppedFile as $a, Row as $c, PaintLineJoin as $d, insetsEqual as $f, rgb8 as $g, TextMeasurer as $h, AxisExplanation as $i, normalizeStates as $l, paintsAfterChildren as $m, ScrollOffset as $n, scrollRange as $o, UiKeyModifiers as $p, clickOutside as $r, DEFAULT_TEXT_COLOR as $s, registerFontStack as $t, relativeLuminance as $u, offsetAtPointIn as A, resolveCursor as Aa, offsetForVerticalMove as Ac, UiFontVariant as Ad, fr as Af, UiMotion as Ag, borderRadiusValuesEqual as Ah, propertyValuesEqualByName as Ai, Reactive as Al, UiSharedElements as Am, LABEL_PADDING_X as An, overrideSources as Ao, FocusSource as Ap, ImageResolver as Ar, detectEditingPlatform as As, createTextCache as At, UiVideoSurface as Au, markNow as B, touchActionFor as Ba, Responsive as Bc, editableSpansOf as Bd, UiBoxShadow as Bf, UiTransforms as Bg, colorsEqualPalette as Bh, parseAlignContent as Bi, UiPropertyName as Bl, NodeId as Bm, resolvePropertyByName as Bn, HitTestResult as Bo, UiPropValue as Bp, ZoomState as Br, createCanvasTextStyle as Bs, isWebGPUAvailable as Bt, UiThemeExtensionOptions as Bu, hasTextLinks as C, isNodeFocusable as Ca, RunMeasure as Cc, defaultVisualState as Cd, AutoLength as Cf, UiSpring as Cg, validateSubgrid as Ch, findPropertyDefinition as Ci, GridProps as Cl, resolveMotionState as Cm, LayerCanvasFactory as Cn, UiGestureRecognizer as Co, UiModifier as Cp, IconContext as Cr, isMultiline as Cs, RenderList as Ct, VIRTUAL_INDEX_PROP as Cu, setLinkHover as D, isNodeTabStop as Da, lineLimit as Dc, UiFontKerning as Dd, UiLength as Df, createTween as Dg, borderRadiusCorners as Dh, propertyEffects as Di, PaintProps as Dl, slideFrom as Dm, LayoutReader as Dn, NodeTransitions as Do, UiModifierHost as Dp, iconKey as Dr, EditCommand as Ds, TEXTURED_STRIDE_FLOATS as Dt, VirtualUpdate as Du, linkRunAtPointIn as E, isNodeSelectable as Ea, lineIndexForOffset as Ec, visualStatesEqual as Ed, PercentLength as Ef, UiTweenOptions as Eg, borderRadius as Eh, inheritedPropertyNames as Ei, PaintElementProps as El, slideDown as Em, UiRenderer as En, FocusNotifier as Eo, isUiModifier as Ep, IconSpec as Er, syncEditorValue as Es, TEXTURED_STRIDE_BYTES as Et, VirtualItemMeasure as Eu, UiFrameCallback as F, UiPlatformAdapter as Fa, nextGraphemeEnd as Fc, UiTextMetrics as Fd, minmax as Ff, interpolateColor as Fg, UiShapes as Fh, placeGridItems as Fi, TextProps as Fl, Size as Fm, CanvasSurface as Fn, UiFindController as Fo, UiElement as Fp, ShortcutsOptions as Fr, SpanPaint as Fs, GlyphSlot as Ft, lightTheme as Fu, VttTrack as G, TouchScrollerOptions as Ga, LazyListProps as Gc, spannedTextOf as Gd, boxShadowsEqual as Gf, UiBasicColors as Gg, FixedMetricsOptions as Gh, ELLIPSIS as Gi, UiAutocomplete as Gl, UiPropertyOverrides as Gm, InsetPaddingArgs as Gn, SCROLLBAR_INSET as Go, UiListenerErrorReporter as Gp, ReorderableOptions as Gr, runFontString as Gs, WebGPURenderer as Gt, themeExtension as Gu, performanceMarksEnabled as H, EditingHost as Ha, LazyColumn as Hc, hiddenRangesOf as Hd, boxShadowArraysEqual as Hf, transform as Hg, lightColors as Hh, parseMainAxisAlignment as Hi, UiPropertyValues as Hl, UiNode as Hm, ThemeTokenTarget as Hn, UiHitTester as Ho, UiEventListener as Hp, AutoScrollOptions as Hr, fillTextRects as Hs, CapturedFrame as Ht, defineThemeExtension as Hu, UiScheduler as I, capturePointer as Ia, nextWordEnd as Ic, UiTextRange as Id, percent as If, interpolateNumber as Ig, defaultShapes as Ih, sizeGridTracks as Ii, TypographyProps as Il, TightenOptions as Im, createCanvasSurface as In, SelectionControllerOptions as Io, isComponentLikeElement as Ip, contextMenu as Ir, TextLinePlacement as Is, GlyphUpload as It, themesEqual as Iu, ByteSource as J, UiDragPayload as Ja, Button as Jc, textSpansEqual as Jd, propertyValuesEqual as Jf, colorToRgba as Jg, ParagraphTextMeasurer as Jh, LayoutNotifier as Ji, UiRole as Jl, DecorationShape as Jm, publishInset as Jn, ScrollBounds as Jo, UiCompositionEvent as Jp, reorderable as Jr, Canvas2DContext as Js, WebGPUSurface as Jt, HighContrastOptions as Ju, cueAt as K, UiTouchScroller as Ka, LazyRow as Kc, spansDifferOnlyInPaint as Kd, UiPropertyDefinition as Kf, UiColor as Kg, FontMetrics as Kh, layoutParagraph as Ki, UiLiveRegion as Kl, DecorationFill as Km, PublishInsetArgs as Kn, SCROLLBAR_MIN_THUMB as Ko, MOUSE_POINTER as Kp, dragSource as Kr, textRunBackgrounds as Ks, WebGPURendererOptions as Kt, themeExtensionsEqual as Ku, UiSchedulerOptions as L, isImeKey as La, previousGraphemeStart as Lc, UiTextSpan as Ld, repeat as Lf, interpolateTransform as Lg, isShapeName as Lh, AlignContent as Li, UiEventProps as Ll, clampSize as Lm, resolveBoolean as Ln, SelectionHost as Lo, isObservable$1 as Lp, shortcut as Lr, TextRunRect as Ls, WebGPUGlyphAtlas as Lt, withContrast as Lu, paragraphGeometryFrom as M, PlatformAdapterOptions as Ma, graphemeBoundaries as Mc, UiSpannedText as Md, isFrLength as Mf, UiSpringToken as Mg, uniformBorderRadius as Mh, GridItemRequest as Mi, ScrollViewProps as Ml, LayoutBox as Mm, drawOverlayShapes as Mn, writeDeclaredProperty as Mo, ComponentResolver as Mp, animateLayout as Mr, EditableLayout as Ms, textRuns as Mt, videoFrameSize as Mu, selectionRectsIn as N, PlatformEventTarget as Na, lineEndAt as Nc, UiTextDecoration as Nd, isMinMaxTrack as Nf, defaultMotion as Ng, UiShapeExtensions as Nh, GridPlacement as Ni, StackProps as Nl, LayoutResult as Nm, labelOrigin as Nn, writeOverrideProperty as No, ComponentLikeElement as Np, ContextMenuOptions as Nr, CanvasTextStyle as Ns, GlyphShaper as Nt, UiTheme as Nu, ParagraphGeometry as O, isSubtreeInert as Oa, offsetAtPoint as Oc, UiFontStretch as Od, UiTrackSize as Of, UiDurationToken as Og, borderRadiusEqual as Oh, propertyIsInherited as Oi, PositionProps as Ol, slideUp as Om, RenderChanges as On, resetTransitionWarnings as Oo, UiModifierTeardown as Op, DefaultImageResolver as Or, EditingPlatform as Os, TextRunDraw as Ot, VirtualViewport as Ou, wordRangeIn as P, PlatformSurface as Pa, lineStartAt as Pc, UiTextLink as Pd, isPercentLength as Pf, UiInterpolator as Pg, UiShapeName as Ph, GridTrack as Pi, TextContentProps as Pl, LayoutStats as Pm, CanvasHost as Pn, FindHost as Po, UiChild as Pp, ShortcutOptions as Pr, PlacedTextRun as Ps, GLYPH_SUBPIXEL_PHASES as Pt, darkTheme as Pu, rangeSource as Q, UiDropZone as Qa, Paint as Qc, PaintLineCap as Qd, UiInsets as Qf, parseColor as Qg, TextMeasureRequest as Qh, ScrollAdjustment as Qi, isUiSemanticState as Ql, hasDecorationPhase as Qm, sizeContainer as Qn, scrollLeaderOf as Qo, UiInputEvent as Qp, ClickOutsideOptions as Qr, DEFAULT_FONT_WEIGHT as Qs, fontStackFor as Qt, raiseContrast as Qu, MARK_PREFIX as R, pointerDeviceOf as Ra, previousWordStart as Rc, UiTextStyle as Rd, resolveLength as Rf, interpolatorFor as Rg, shapesEqual as Rh, CrossAxisAlignment as Ri, UiNodeRef as Rl, constraintsEqual as Rm, resolveNumber as Rn, UiSelectionController as Ro, isUiChild as Rp, shortcuts as Rr, applyCanvasTextStyle as Rs, WebGPUTextureCache as Rt, withDensity as Ru, clearLinkHover as S, UiTimerFrameClockOptions as Sa, PlacedLine as Sc, UiVisualStateSet as Sd, validateGradient as Sf, UiReducedMotionPolicy as Sg, UiVerticalAlign as Sh, closestPropertyName as Si, GridItemProps as Sl, pop as Sm, traceRoundedRect as Sn, GestureRecognizerOptions as So, assertModifierList as Sp, IconCanvas as Sr, isEditableNode as Ss, RenderCommand as St, UiVirtualWindow as Su, linkOf as T, isNodeInert as Ta, lineIndexAtY as Tc, visualState as Td, MinMaxTrack as Tf, UiTween as Tg, UiBorderRadiuses as Th, inheritedPropertyFlags as Ti, InteractionProps as Tl, scaleFrom as Tm, RendererBackend as Tn, UiPinchRecognizer as To, defineModifier as Tp, IconRasterizerOptions as Tr, nextCaretToggle as Ts, ScissorRect as Tt, VIRTUAL_WINDOW_PROP as Tu, setPerformanceMarks as U, EditingState as Ua, LazyGrid as Uc, resolvedSpansOf as Ud, boxShadowRadius as Uf, transformIsIdentity as Ug, LayoutRecord as Uh, FlexDirection as Ui, UI_ROLES as Ul, UiNodeTransitions as Um, themeTokens as Un, UiPoint as Uo, UiEventListenerOptions as Up, DragSourceOptions as Ur, layoutTextLines as Us, DrawStats as Ut, hasThemeExtension as Uu, measureSpan as V, EditingControllerOptions as Va, ResponsiveProps as Vc, flattenTextSpans as Vd, boxShadow as Vf, parseTransform as Vg, darkColors as Vh, parseCrossAxisAlignment as Vi, UiPropertyValueOf as Vl, NodeProperty as Vm, resolveString as Vn, HitTester as Vo, UiProps as Vp, pinchable as Vr, drawText as Vs, WebGPUError as Vt, UiThemeExtensions as Vu, VttCue as W, UiEditingController as Wa, LazyGridProps as Wc, spanAtOffset as Wd, boxShadowReach as Wf, transformsEqual as Wg, CharacterCountTextMeasurer as Wh, parseFlexDirection as Wi, UI_SEMANTIC_STATES as Wl, UiPropertyOverride as Wm, sameArgs as Wn, SCROLLBAR_HOVER_ZONE as Wo, UiInputDispatcher as Wp, DropTargetOptions as Wr, runCanvasStyleInto as Ws, RenderHooks as Wt, noThemeExtensions as Wu, RangeSourceOptions as X, UiDragState as Xa, EditableText as Xc, PaintBox as Xd, UiInsetRegistry as Xf, colorsEqual as Xg, TextLine as Xh, SCROLLBAR_FADE_MS as Xi, UiSemanticStates as Xl, decorationColor as Xm, SizeContainerArgs as Xn, ScrollbarThumb as Xo, UiFocusEvent as Xp, DraggableOptions as Xr, DEFAULT_FONT_FAMILY as Xs, bumpFontStack as Xt, contrastRatio as Xu, DEFAULT_BLOCK_SIZE as Y, UiDragSession as Ya, Column as Yc, textStylesEqual as Yd, UiInsetEdge as Yf, colorValuesEqual as Yg, SpannedRuns as Yh, LayoutEngine as Yi, UiSemanticState as Yl, DecorationStroke as Ym, BreakpointArgs as Yn, ScrollbarAxis as Yo, UiEventType as Yp, DragOffset as Yr, Canvas2DGradient as Ys, createWebGPUSurface as Yt, UiContrast as Yu, bufferSource as Z, UiDropEffect as Za, Grid as Zc, PaintFillRule as Zd, UiInsetSource as Zf, normalizeColor as Zg, TextLineRun as Zh, SCROLLBAR_LINGER_MS as Zi, isUiRole as Zl, decorationRect as Zm, breakpoint as Zn, scrollBounds as Zo, UiGestureEvent as Zp, draggable as Zr, DEFAULT_FONT_SIZE as Zs, clearFontStacks as Zt, highContrastColors as Zu, buildSemanticsTree as _, UiFrameTime as _a, selectableTextNodes as _c, UiLayoutChild as _d, UiRadialGradient as _f, spring as _g, UiTextAlign as _h, bundle as _i, ContainerProps as _l, MotionStateInput as _m, LayoutInspector as _n, UiScrollBehavior as _o, UiModifierEnvironment as _p, IconSourceArgs as _r, CARET_WIDTH as _s, INSTANCE_STRIDE_FLOATS as _t, LazyAxis as _u, diffSemantics as a, steps as a_, RelayoutExplanation as aa, VerticalAlign as ac, spacingEqual as ad, inputsEqual as af, spannedRunsFor as ag, UiCursor as ah, borderShapes as ai, BindingId as al, UiPointerKind as am, PaintContext2D as an, UiShortcutRegistry as ao, containerBands as ap, VideoTransport as ar, TEXT_MATCHES_PROP as as, Mp3Frame as at, EditableTextModel as au, semanticsMemory as b, UiManualFrameClock as ba, setSelectionRange as bc, isLayoutProtocol as bd, linearGradient as bf, UiAnimation as bg, UiTextWrapValue as bh, accumulatedOffsetTo as bi, FlexContainerProps as bl, fade as bm, Canvas2DRenderer as bn, isScrollContainer as bo, UiModifierSet as bp, iconSource as br, editorFor as bs, PrimitiveCommand as bt, LazyListOptions as bu, SemanticsMemory as c, describeOverrides as ca, createPaintState as cc, defaultShadows as cd, UiImage as cf, createEnvironmentKey as cg, UiFontWeight as ch, focusRing as ci, UiEventBinding as cl, UiWheelDeltaMode as cm, PaintTarget as cn, formatShortcut as co, UiTextInputState as cp, DefaultVideoResolverOptions as cr, setMatchRanges as cs, readMp3Header as ct, SheetHeaderRenderer as cu, SemanticsRewalk as d, labelNode as da, normalizeVerticalAlign as dc, UiTypographyExtensions as dd, ResolvedGradient as df, DirtyFlags as dg, UiOverflow as dh, hoverable as di, UiGraphBuilder as dl, wheelDeltaYOf as dm, PaintOp as dn, KeyboardControllerOptions as do, UiGroupEdit as dp, VideoResolver as dr, findMatchesIn as ds, Affine as dt, SheetSourceArgs as du, rgba as e_, CustomLayoutExplanation as ea, ObjectFit as ec, UiDensity as ed, PaintSurface as ef, TextOverflow as eg, UI_SUBGRID_AXES as eh, autoFocus as ei, ScrollView as el, UiKeyboardEvent as em, PaintCanvas as en, UiFileDropMessage as eo, noInsets as ep, ScrollPositionArgs as er, scrollbarThumb as es, Mp4Sample as et, statesEqual as eu, SemanticsSpan as f, withOverrideSource as fa, resolvePaintState as fc, UiTypographyRole as fd, ResolvedGradientStop as ff, AnimationDriver as fg, UiPlacement as fh, interactive as fi, BoxModelProps as fl, DirtyNodeSet as fm, PaintRecorder as fn, UiKeyboardController as fo, UiTextPosition as fp, canDecodeVideo as fr, UiEnvironmentProvider as fs, CLIP_STRIDE_BYTES as ft, SheetViewport as fu, buildSemanticsSubtree as g, UiFrameClockFactory as ga, clearSelectionRange as gc, MAX_MEASURES_PER_CHILD as gd, UiLinearGradient as gf, normalizeTransition as gg, UiSubgridAxis as gh, UiModifierBundle as gi, CommonProps as gl, MotionState as gm, InspectorOverlay as gn, ScrollSink as go, editingGroupOf as gp, sharedElement as gr, CARET_BLINK_MS as gs, INSTANCE_STRIDE_BYTES as gt, sheetSource as gu, UiSemanticsRecord as h, UiFrameClock as ha, TextRange as hc, typographyEqual as hd, UiGradientStop as hf, assertTransitionMap as hg, UiSelfAlignment as hh, pressable as hi, ColumnProps as hl, MotionChannel as hm, INSPECTOR_HEAT_MS as hn, ScrollContainerState as ho, edgeField as hp, motion as hr, EnvironmentNotifier as hs, GlyphCommand as ht, VIRTUAL_SHEET_PROP as hu, UiSemanticsPatch as i, linear as i_, OverrideSources as ia, TextAlign as ic, scaleSpacing as id, UiPath as if, TextWrap as ig, UiContentDistribution as ih, FocusRingOptions as ii, UiDefinition as il, UiPointerEvent as im, paintPictures as in, UiShortcutBinding as io, bandOf as ip, VideoState as ir, SubtreeBounds as is, Mp3Format as it, EditUnit as iu, paragraphGeometry as j, CanvasPlatformSurface as ja, selectionRects as jc, UiResolvedTextSpan as jd, isAutoLength as jf, UiSpringSpec as jg, normalizeBorderRadius as jh, GridContribution as ji, RowProps as jl, Constraints as jm, OverlayShape as jn, resetOverrideWarnings as jo, UiFocusManager as jp, AnimateLayoutOptions as jr, isPrintable as js, glyphCount as jt, isVideoSurface as ju, hasDrawnText as k, pointerEventsOf as ka, offsetAtX as kc, UiFontStyle as kd, auto as kf, UiEasingToken as kg, borderRadiusIsZero as kh, propertyNarrowers as ki, PropsOf as kl, SharedClaim as km, RenderContext as kn, clearOverrideProperty as ko, FocusOptions as kp, DefaultImageResolverOptions as kr, commandForKey as ks, buildRenderList as kt, lazySource as ku, SemanticsPlacement as l, formatConstraints as la, isPaintVisible as lc, shadowsEqual as ld, GradientPaint as lf, findEnvironmentKey as lg, UiGridAutoFlow as lh, BUTTON_INTERACTION as li, ChildrenBindingId as ll, UiWheelEvent as lm, tracePathData as ln, parseShortcut as lo, textInputOf as lp, RangeResponse as lr, FindMatch as ls, splitMp3Frames as lt, SheetRange as lu, UiSemanticsMap as m, UiAnimationFrameClock as ma, TEXT_SELECTION_PROP as mc, isTypographyRole as md, UiGradientOffset as mf, UiTransitionValue as mg, UiPosition as mh, measureFlow as mi, ButtonProps as ml, MOTION_REST as mm, replayPaint as mn, UiPointerController as mo, comparePositions as mp, SharedElementArgs as mr, UiEnvironmentKeys as ms, CommandKind as mt, UiVirtualSheetOptions as mu, UiSemanticsBox as n, cubicBezier as n_, LayoutExplanation as na, PaintState as nc, UiSpacing as nd, PaintTextStyle as nf, TextRunSpan as ng, UiBorderRadiusValue as nh, BordersOptions as ni, Text as nl, UiPinchEvent as nm, PaintPictureCache as nn, ShortcutRegistryOptions as no, UiContainerSize as np, VideoClock as nr, scrollbarZoneAt as ns, demuxMp4Audio as nt, validateStates as nu, dropIndexShifts as o, SizeDecision as oa, colorToCss as oc, spacingSteps as od, paintValuesEqual as of, UiEnvironment as og, UiDirection as oh, borders as oi, UiBinding as ol, UiSelectionChangeEvent as om, PaintGradient as on, UiShortcutStep as oo, unknownContainerSize as op, videoSource as or, clearMatchRanges as os, Mp3Frames as ot, LazySheet as ou, TEXT_RUN_ID_SEPARATOR as p, UiFrame as pa, DEFAULT_LINE_HEIGHT_FACTOR as pc, defaultTypography as pd, UiGradient as pf, UiTransitionSpec as pg, UiPointerEvents as ph, measure as pi, BoxProps as pl, MOTION_CHANNELS as pm, PaintRecording as pn, PointerControllerOptions as po, adjacentField as pp, MotionArgs as pr, provideEnvironment as ps, CLIP_STRIDE_FLOATS as pt, UiVirtualSheet as pu, parseWebVtt as q, EXTERNAL_FILES as qa, Box as qc, textContentOf as qd, defineProperty as qf, colorToHex as qg, ParagraphLayout as qh, proportionalFontMetrics as qi, UiOrientation as ql, DecorationRect as qm, insetPadding as qn, SCROLLBAR_THICKNESS as qo, UiBeforeInputEvent as qp, dropTarget as qr, textRunDecorations as qs, WebGPUCanvasHost as qt, withThemeExtension as qu, UiSemanticsUpdate as r, easings as r_, LayoutStateExplanation as ra, PaintTextSpan as rc, defaultSpacing as rd, UiPaint as rf, TextRunStyle as rg, UiColorValue as rh, Decorations as ri, createElement as rl, UiPointerDevice as rm, PaintStats as rn, UiShortcut as ro, UiContainerSizeSource as rp, VideoSourceArgs as rr, scrollsFromRight as rs, demuxMp4Video as rt, CompositionRange as ru, recordsEqual as s, describeLength as sa, computeObjectFitRect as sc, UiShadows as sd, pathValuesEqual as sf, UiEnvironmentKey as sg, UiFlexWrap as sh, decorated as si, UiGraph as sl, UiTextChangeEvent as sm, PaintResolver as sn, describeShortcut as so, UiTextInput as sp, DefaultVideoResolver as sr, matchRangesOf as ss, Mp3Header as st, LazySheetProps as su, UiSemanticsAction as t, UiEasing as t_, Edges as ta, PaintBoxShadow as tc, densityFactors as td, PaintTextAlign as tf, TextRunMeasurer as tg, UiAlignment as th, BorderEdge as ti, Stack as tl, UiPasteEvent as tm, PaintCanvasFactory as tn, dragSessionFor as to, observeViewportInsets as tp, scrollPosition as tr, scrollbarThumbs as ts, Mp4VideoTrack as tt, validateRole as tu, SemanticsReuse as u, formatExplanation as ua, normalizeTextAlign as uc, UiTypography as ud, MAX_GRADIENT_STOPS as uf, UiNodeType as ug, UiObjectFit as uh, InteractiveOptions as ui, UiChildrenBinding as ul, noKeyModifiers as um, EMPTY_RECORDING as un, shortcutKeyCaps as uo, UiEditingGroup as up, VideoPlayback as ur, FindOptions as us, WebGPUGlyphPages as ut, SheetRowRenderer as uu, rewalkSemantics as v, UiHostFrameClock as va, selectableTextOf as vc, UiLayoutContext as vd, gradientPaint as vf, tween as vg, UiTextDirection as vh, noModifiers as vi, EditableTextProps as vl, MotionTiming as vm, LayoutInspectorOptions as vn, UiScrollability as vo, UiModifierFocus as vp, ImageSourceArgs as vr, EDITOR_PROP as vs, ImageCommand as vt, LazyGridOptions as vu, linkHoverOf as w, isNodeHitTestable as wa, caretRectFor as wc, hasVisualState as wd, FrLength as wf, UiSpringOptions as wg, UiBorderRadius as wh, getPropertyNames as wi, IdentityProps as wl, rotateFrom as wm, ScrollLayerStats as wn, PinchRecognizerOptions as wo, UiModifierKind as wp, IconRasterizer as wr, isReadOnly as ws, RenderTextCache as wt, VIRTUAL_LEAD_PROP as wu, textRunOfRecordId as x, UiTimerFrameClock as xa, CaretRect as xc, UiVisualState as xd, radialGradient as xf, UiAnimationOptions as xg, UiThemeColorName as xh, contentOffset as xi, FlexItemProps as xl, isMotionRest as xm, Canvas2DRendererOptions as xn, GestureInput as xo, UiUnknownModifierPropertyError as xp, imageSource as xr, editorOf as xs, PrimitiveKind as xt, LazySourceArgs as xu, semanticsInertAbove as y, UiHostFrameClockOptions as ya, selectionRangeOf as yc, UiLayoutProtocol as yd, gradientsEqual as yf, AnimatedCell as yg, UiTextOverflowValue as yh, Transform as yi, EnvironmentProps as yl, ResolvedMotionState as ym, CanvasTextMeasurer as yn, UiWheelController as yo, UiModifierLayout as yp, ImageSources as yr, caretVisibleAt as ys, NO_CLIP_INDEX as yt, LazyItemRenderer as yu, markInstant as z, prepareInputSurface as za, wordRangeAt as zc, defaultTextStyle as zd, BOX_SHADOW_BLUR_REACH as zf, UiTransform as zg, UiColors as zh, MainAxisAlignment as zi, UiProperties as zl, tightenConstraints as zm, resolveProperty as zn, HitTestLayoutReader as zo, isUiElement as zp, PinchableOptions as zr, buildFontString as zs, initializeWebGPU as zt, UiThemeExtension as zu };
19724
- //# sourceMappingURL=index-CLCtv12G.d.ts.map
20425
+ export { Mp4AudioTrack as $, EditingControllerOptions as $a, ResponsiveProps as $c, darkTheme as $d, UiTextLink as $f, createTween as $g, borderRadiusCorners as $h, parseCrossAxisAlignment as $i, UiPropertyValueOf as $l, slideFrom as $m, BreakpointArgs as $n, HitTester as $o, UiModifierTeardown as $p, pinchable as $r, drawText as $s, registerFontStack as $t, hasVisualState as $u, offsetAtPointIn as A, linear as A_, UiHostFrameClock as Aa, selectableTextOf as Ac, FrLength as Ad, UiBoxShadow as Af, TextWrap as Ag, UiContentDistribution as Ah, noModifiers as Ai, EditableTextProps as Al, UiPointerEvent as Am, UiRenderer as An, UiScrollability as Ao, containerBands as Ap, IconRasterizerOptions as Ar, EDITOR_PROP as As, createTextCache as At, LazyGridOptions as Au, markNow as B, isSubtreeInert as Ba, offsetAtPoint as Bc, isPercentLength as Bd, UiTypography as Bf, UiTransitionValue as Bg, UiPosition as Bh, propertyIsInherited as Bi, PositionProps as Bl, MOTION_REST as Bm, createCanvasSurface as Bn, resetTransitionWarnings as Bo, edgeField as Bp, DefaultImageResolver as Br, EditingPlatform as Bs, isWebGPUAvailable as Bt, VirtualViewport as Bu, hasTextLinks as C, normalizeColor as C_, labelNode as Ca, normalizeVerticalAlign as Cc, UiRadialGradient as Cd, relativeLuminance as Cf, TextLineRun as Cg, decorationRect as Ch, hoverable as Ci, UiGraphBuilder as Cl, UiGestureEvent as Cm, CanvasTextMeasurer as Cn, KeyboardControllerOptions as Co, UiInsets as Cp, ImageSources as Cr, findMatchesIn as Cs, RenderList as Ct, SheetSourceArgs as Cu, setLinkHover as D, UiEasing as D_, UiFrameClock as Da, TextRange as Dc, radialGradient as Dd, defaultShadows as Df, TextRunMeasurer as Dg, UiAlignment as Dh, pressable as Di, ColumnProps as Dl, UiPasteEvent as Dm, LayerCanvasFactory as Dn, ScrollContainerState as Do, UiContainerSize as Dp, IconCanvas as Dr, EnvironmentNotifier as Ds, TEXTURED_STRIDE_FLOATS as Dt, VIRTUAL_SHEET_PROP as Du, linkRunAtPointIn as E, rgba as E_, UiAnimationFrameClock as Ea, TEXT_SELECTION_PROP as Ec, linearGradient as Ed, UiShadows as Ef, TextOverflow as Eg, UI_SUBGRID_AXES as Eh, measureFlow as Ei, ButtonProps as El, UiKeyboardEvent as Em, traceRoundedRect as En, UiPointerController as Eo, observeViewportInsets as Ep, mediaLoadsInFlight as Er, UiEnvironmentKeys as Es, TEXTURED_STRIDE_BYTES as Et, UiVirtualSheetOptions as Eu, UiFrameCallback as F, isNodeFocusable as Fa, RunMeasure as Fc, auto as Fd, boxShadowRadius as Ff, findEnvironmentKey as Fg, UiGridAutoFlow as Fh, findPropertyDefinition as Fi, GridProps as Fl, UiWheelEvent as Fm, OverlayShape as Fn, UiGestureRecognizer as Fo, UiEditingGroup as Fp, SvgResolver as Fr, isMultiline as Fs, GlyphSlot as Ft, VIRTUAL_INDEX_PROP as Fu, VttTrack as G, PlatformEventTarget as Ga, lineEndAt as Gc, UiPropertyDefinition as Gd, typographyEqual as Gf, AnimatedCell as Gg, UiTextOverflowValue as Gh, GridPlacement as Gi, StackProps as Gl, ResolvedMotionState as Gm, resolveString as Gn, writeOverrideProperty as Go, UiModifierSet as Gp, ContextMenuOptions as Gr, CanvasTextStyle as Gs, WebGPURenderer as Gt, MAX_MEASURES_PER_CHILD as Gu, performanceMarksEnabled as H, resolveCursor as Ha, offsetForVerticalMove as Hc, percent as Hd, UiTypographyRole as Hf, normalizeTransition as Hg, UiSubgridAxis as Hh, propertyValuesEqualByName as Hi, Reactive as Hl, MotionState as Hm, resolveNumber as Hn, overrideSources as Ho, UiModifierEnvironment as Hp, ImageResolver as Hr, detectEditingPlatform as Hs, CapturedFrame as Ht, UiVideoSurface as Hu, UiScheduler as I, isNodeHitTestable as Ia, caretRectFor as Ic, fr as Id, boxShadowReach as If, UiNodeType as Ig, UiObjectFit as Ih, getPropertyNames as Ii, IdentityProps as Il, noKeyModifiers as Im, drawOverlayShapes as In, PinchRecognizerOptions as Io, UiGroupEdit as Ip, isSvgSource as Ir, isReadOnly as Is, GlyphUpload as It, VIRTUAL_LEAD_PROP as Iu, ByteSource as J, capturePointer as Ja, nextWordEnd as Jc, TOUCH_TARGET as Jd, UiFontStyle as Jf, UiReducedMotionPolicy as Jg, UiVerticalAlign as Jh, sizeGridTracks as Ji, TypographyProps as Jl, pop as Jm, sameArgs as Jn, SelectionControllerOptions as Jo, UiModifier as Jp, contextMenu as Jr, TextLinePlacement as Js, WebGPUSurface as Jt, UiLayoutProtocol as Ju, cueAt as K, PlatformSurface as Ka, lineStartAt as Kc, defineProperty as Kd, UiFontKerning as Kf, UiAnimation as Kg, UiTextWrapValue as Kh, GridTrack as Ki, TextContentProps as Kl, fade as Km, ThemeTokenTarget as Kn, FindHost as Ko, UiUnknownModifierPropertyError as Kp, ShortcutOptions as Kr, PlacedTextRun as Ks, WebGPURendererOptions as Kt, UiLayoutChild as Ku, UiSchedulerOptions as L, isNodeInert as La, lineIndexAtY as Lc, isAutoLength as Ld, boxShadowValuesEqual as Lf, DirtyFlags as Lg, UiOverflow as Lh, inheritedPropertyFlags as Li, InteractionProps as Ll, wheelDeltaYOf as Lm, labelOrigin as Ln, UiPinchRecognizer as Lo, UiTextPosition as Lp, SvgDocument as Lr, nextCaretToggle as Ls, WebGPUGlyphAtlas as Lt, VIRTUAL_WINDOW_PROP as Lu, paragraphGeometryFrom as M, UiManualFrameClock as Ma, setSelectionRange as Mc, PercentLength as Md, UiShadowName as Mf, UiEnvironment as Mg, UiDirection as Mh, accumulatedOffsetTo as Mi, FlexContainerProps as Ml, UiSelectionChangeEvent as Mm, RenderChanges as Mn, isScrollContainer as Mo, UiTextInput as Mp, iconKey as Mr, editorFor as Ms, textRuns as Mt, LazyListOptions as Mu, selectionRectsIn as N, UiTimerFrameClock as Na, CaretRect as Nc, UiLength as Nd, boxShadow as Nf, UiEnvironmentKey as Ng, UiFlexWrap as Nh, contentOffset as Ni, FlexItemProps as Nl, UiTextChangeEvent as Nm, RenderContext as Nn, GestureInput as No, UiTextInputState as Np, DefaultSvgResolver as Nr, editorOf as Ns, GlyphShaper as Nt, LazySourceArgs as Nu, ParagraphGeometry as O, cubicBezier as O_, UiFrameClockFactory as Oa, clearSelectionRange as Oc, validateGradient as Od, shadowsEqual as Of, TextRunSpan as Og, UiBorderRadiusValue as Oh, UiModifierBundle as Oi, CommonProps as Ol, UiPinchEvent as Om, ScrollLayerStats as On, ScrollSink as Oo, UiContainerSizeSource as Op, IconContext as Or, CARET_BLINK_MS as Os, TextRunDraw as Ot, sheetSource as Ou, wordRangeIn as P, UiTimerFrameClockOptions as Pa, PlacedLine as Pc, UiTrackSize as Pd, boxShadowArraysEqual as Pf, createEnvironmentKey as Pg, UiFontWeight as Ph, closestPropertyName as Pi, GridItemProps as Pl, UiWheelDeltaMode as Pm, LABEL_PADDING_X as Pn, GestureRecognizerOptions as Po, textInputOf as Pp, DefaultSvgResolverOptions as Pr, isEditableNode as Ps, GLYPH_SUBPIXEL_PHASES as Pt, UiVirtualWindow as Pu, rangeSource as Q, touchActionFor as Qa, Responsive as Qc, UiTheme as Qd, UiTextDecoration as Qf, UiTweenOptions as Qg, borderRadius as Qh, parseAlignContent as Qi, UiPropertyName as Ql, slideDown as Qm, publishInset as Qn, HitTestResult as Qo, UiModifierHost as Qp, ZoomState as Qr, createCanvasTextStyle as Qs, fontStackFor as Qt, defaultVisualState as Qu, MARK_PREFIX as R, isNodeSelectable as Ra, lineIndexForOffset as Rc, isFrLength as Rd, boxShadowsEqual as Rf, AnimationDriver as Rg, UiPlacement as Rh, inheritedPropertyNames as Ri, PaintElementProps as Rl, DirtyNodeSet as Rm, CanvasHost as Rn, FocusNotifier as Ro, adjacentField as Rp, SvgRect as Rr, syncEditorValue as Rs, WebGPUTextureCache as Rt, VirtualItemMeasure as Ru, clearLinkHover as S, colorsEqual as S_, formatExplanation as Sa, normalizeTextAlign as Sc, UiLinearGradient as Sd, raiseContrast as Sf, TextLine as Sg, decorationColor as Sh, InteractiveOptions as Si, UiChildrenBinding as Sl, UiFocusEvent as Sm, LayoutInspectorOptions as Sn, shortcutKeyCaps as So, UiInsetSource as Sp, ImageSourceArgs as Sr, FindOptions as Ss, RenderCommand as St, SheetRowRenderer as Su, linkOf as T, rgb8 as T_, UiFrame as Ta, DEFAULT_LINE_HEIGHT_FACTOR as Tc, gradientsEqual as Td, densityFactors as Tf, TextMeasurer as Tg, paintsAfterChildren as Th, measure as Ti, BoxProps as Tl, UiKeyModifiers as Tm, Canvas2DRendererOptions as Tn, PointerControllerOptions as To, noInsets as Tp, imageSource as Tr, provideEnvironment as Ts, ScissorRect as Tt, UiVirtualSheet as Tu, setPerformanceMarks as U, CanvasPlatformSurface as Ua, selectionRects as Uc, repeat as Ud, defaultTypography as Uf, spring as Ug, UiTextAlign as Uh, GridContribution as Ui, RowProps as Ul, MotionStateInput as Um, resolveProperty as Un, resetOverrideWarnings as Uo, UiModifierFocus as Up, AnimateLayoutOptions as Ur, isPrintable as Us, DrawStats as Ut, isVideoSurface as Uu, measureSpan as V, pointerEventsOf as Va, offsetAtX as Vc, minmax as Vd, UiTypographyExtensions as Vf, assertTransitionMap as Vg, UiSelfAlignment as Vh, propertyNarrowers as Vi, PropsOf as Vl, MotionChannel as Vm, resolveBoolean as Vn, clearOverrideProperty as Vo, editingGroupOf as Vp, DefaultImageResolverOptions as Vr, commandForKey as Vs, WebGPUError as Vt, lazySource as Vu, VttCue as W, PlatformAdapterOptions as Wa, graphemeBoundaries as Wc, resolveLength as Wd, isTypographyRole as Wf, tween as Wg, UiTextDirection as Wh, GridItemRequest as Wi, ScrollViewProps as Wl, MotionTiming as Wm, resolvePropertyByName as Wn, writeDeclaredProperty as Wo, UiModifierLayout as Wp, animateLayout as Wr, EditableLayout as Ws, RenderHooks as Wt, videoFrameSize as Wu, RangeSourceOptions as X, pointerDeviceOf as Xa, previousWordStart as Xc, UiThemeTouch as Xd, UiResolvedTextSpan as Xf, UiSpringOptions as Xg, UiBorderRadius as Xh, CrossAxisAlignment as Xi, UiNodeRef as Xl, rotateFrom as Xm, PublishInsetArgs as Xn, UiSelectionController as Xo, defineModifier as Xp, shortcuts as Xr, applyCanvasTextStyle as Xs, bumpFontStack as Xt, UiVisualState as Xu, DEFAULT_BLOCK_SIZE as Y, isImeKey as Ya, previousGraphemeStart as Yc, UiPointer as Yd, UiFontVariant as Yf, UiSpring as Yg, validateSubgrid as Yh, AlignContent as Yi, UiEventProps as Yl, resolveMotionState as Ym, InsetPaddingArgs as Yn, SelectionHost as Yo, UiModifierKind as Yp, shortcut as Yr, TextRunRect as Ys, createWebGPUSurface as Yt, isLayoutProtocol as Yu, bufferSource as Z, prepareInputSurface as Za, wordRangeAt as Zc, withPointer as Zd, UiSpannedText as Zf, UiTween as Zg, UiBorderRadiuses as Zh, MainAxisAlignment as Zi, UiProperties as Zl, scaleFrom as Zm, insetPadding as Zn, HitTestLayoutReader as Zo, isUiModifier as Zp, PinchableOptions as Zr, buildFontString as Zs, clearFontStacks as Zt, UiVisualStateSet as Zu, buildSemanticsTree as _, UiBasicColors as __, RelayoutExplanation as _a, VerticalAlign as _c, ResolvedGradient as _d, withThemeExtension as _f, FixedMetricsOptions as _g, UiPropertyOverrides as _h, borderShapes as _i, BindingId as _l, UiListenerErrorReporter as _m, drawSvg as _n, UiShortcutRegistry as _o, scaleSpacing as _p, MotionArgs as _r, TEXT_MATCHES_PROP as _s, INSTANCE_STRIDE_FLOATS as _t, EditableTextModel as _u, diffSemantics as a, defaultMotion as a_, proportionalFontMetrics as aa, textRunDecorations as ac, PaintLineJoin as ad, UiUnits as af, UiShapeExtensions as ag, LayoutResult as ah, dropTarget as ai, Box as al, UiChild as am, PaintContext2D as an, EXTERNAL_FILES as ao, editableSpansOf as ap, scrollPosition as ar, SCROLLBAR_THICKNESS as as, Mp3Frame as at, UiOrientation as au, semanticsMemory as b, colorToRgba as b_, describeOverrides as ba, createPaintState as bc, UiGradientOffset as bd, contrastRatio as bf, ParagraphTextMeasurer as bg, DecorationShape as bh, focusRing as bi, UiEventBinding as bl, UiCompositionEvent as bm, InspectorOverlay as bn, formatShortcut as bo, UiInsetEdge as bp, sharedElement as br, setMatchRanges as bs, PrimitiveCommand as bt, SheetHeaderRenderer as bu, SemanticsMemory as c, interpolateNumber as c_, SCROLLBAR_FADE_MS as ca, DEFAULT_FONT_FAMILY as cc, PaintTextStyle as cd, unitsEqual as cf, defaultShapes as cg, TightenOptions as ch, DraggableOptions as ci, EditableText as cl, isComponentLikeElement as cm, PaintTarget as cn, UiDragState as co, resolvedSpansOf as cp, VideoState as cr, ScrollbarThumb as cs, readMp3Header as ct, UiSemanticStates as cu, SemanticsRewalk as d, UiTransform as d_, AxisExplanation as da, DEFAULT_TEXT_COLOR as dc, inputsEqual as dd, UiThemeExtensions as df, UiColors as dg, tightenConstraints as dh, clickOutside as di, Row as dl, isUiElement as dm, PaintOp as dn, UiDroppedFile as do, spansDifferOnlyInPaint as dp, DefaultVideoResolver as dr, scrollRange as ds, Affine as dt, normalizeStates as du, UiDurationToken as e_, parseMainAxisAlignment as ea, fillTextRects as ec, visualState as ed, lightTheme as ef, borderRadiusEqual as eg, slideUp as eh, AutoScrollOptions as ei, LazyColumn as el, FocusOptions as em, PaintCanvas as en, EditingHost as eo, UiTextMetrics as ep, SizeContainerArgs as er, UiHitTester as es, Mp4Sample as et, UiPropertyValues as eu, SemanticsSpan as f, UiTransforms as f_, CustomLayoutExplanation as fa, ObjectFit as fc, paintValuesEqual as fd, defineThemeExtension as ff, colorsEqualPalette as fg, NodeId as fh, autoFocus as fi, ScrollView as fl, UiPropValue as fm, PaintRecorder as fn, UiFileDropMessage as fo, textContentOf as fp, DefaultVideoResolverOptions as fr, scrollbarThumb as fs, CLIP_STRIDE_BYTES as ft, statesEqual as fu, buildSemanticsSubtree as g, transformsEqual as g_, OverrideSources as ga, TextAlign as gc, MAX_GRADIENT_STOPS as gd, themeExtensionsEqual as gf, CharacterCountTextMeasurer as gg, UiPropertyOverride as gh, FocusRingOptions as gi, UiDefinition as gl, UiInputDispatcher as gm, SvgFit as gn, UiShortcutBinding as go, defaultSpacing as gp, canDecodeVideo as gr, SubtreeBounds as gs, INSTANCE_STRIDE_BYTES as gt, EditUnit as gu, UiSemanticsRecord as h, transformIsIdentity as h_, LayoutStateExplanation as ha, PaintTextSpan as hc, GradientPaint as hd, themeExtension as hf, LayoutRecord as hg, UiNodeTransitions as hh, Decorations as hi, createElement as hl, UiEventListenerOptions as hm, SvgDrawOptions as hn, UiShortcut as ho, UiSpacing as hp, VideoResolver as hr, scrollsFromRight as hs, GlyphCommand as ht, CompositionRange as hu, UiSemanticsPatch as i, UiSpringToken as i_, layoutParagraph as ia, textRunBackgrounds as ic, PaintLineCap as id, UiLengths as if, uniformBorderRadius as ig, LayoutBox as ih, dragSource as ii, LazyRow as il, ComponentLikeElement as im, paintPictures as in, UiTouchScroller as io, defaultTextStyle as ip, ScrollPositionArgs as ir, SCROLLBAR_MIN_THUMB as is, Mp3Format as it, UiLiveRegion as iu, paragraphGeometry as j, steps as j_, UiHostFrameClockOptions as ja, selectionRangeOf as jc, MinMaxTrack as jd, UiBoxShadows as jf, spannedRunsFor as jg, UiCursor as jh, Transform as ji, EnvironmentProps as jl, UiPointerKind as jm, LayoutReader as jn, UiWheelController as jo, unknownContainerSize as jp, IconSpec as jr, caretVisibleAt as js, glyphCount as jt, LazyItemRenderer as ju, hasDrawnText as k, easings as k_, UiFrameTime as ka, selectableTextNodes as kc, AutoLength as kd, BOX_SHADOW_BLUR_REACH as kf, TextRunStyle as kg, UiColorValue as kh, bundle as ki, ContainerProps as kl, UiPointerDevice as km, RendererBackend as kn, UiScrollBehavior as ko, bandOf as kp, IconRasterizer as kr, CARET_WIDTH as ks, buildRenderList as kt, LazyAxis as ku, SemanticsPlacement as l, interpolateTransform as l_, SCROLLBAR_LINGER_MS as la, DEFAULT_FONT_SIZE as lc, UiPaint as ld, UiThemeExtension as lf, isShapeName as lg, clampSize as lh, draggable as li, Grid as ll, isObservable$1 as lm, tracePathData as ln, UiDropEffect as lo, spanAtOffset as lp, VideoTransport as lr, scrollBounds as ls, splitMp3Frames as lt, isUiRole as lu, UiSemanticsMap as m, transform as m_, LayoutExplanation as ma, PaintState as mc, UiImage as md, noThemeExtensions as mf, lightColors as mg, UiNode as mh, BordersOptions as mi, Text as ml, UiEventListener as mm, replayPaint as mn, ShortcutRegistryOptions as mo, textStylesEqual as mp, VideoPlayback as mr, scrollbarZoneAt as ms, CommandKind as mt, validateStates as mu, UiSemanticsBox as n, UiMotion as n_, parseFlexDirection as na, runCanvasStyleInto as nc, PaintBox as nd, withContrast as nf, borderRadiusValuesEqual as ng, UiSharedElements as nh, DropTargetOptions as ni, LazyGridProps as nl, UiFocusManager as nm, PaintPictureCache as nn, UiEditingController as no, UiTextSpan as np, sizeContainer as nr, SCROLLBAR_HOVER_ZONE as ns, demuxMp4Audio as nt, UI_SEMANTIC_STATES as nu, dropIndexShifts as o, UiInterpolator as o_, LayoutNotifier as oa, Canvas2DContext as oc, PaintSurface as od, defaultUnits as of, UiShapeName as og, LayoutStats as oh, reorderable as oi, Button as ol, UiElement as om, PaintGradient as on, UiDragPayload as oo, flattenTextSpans as op, VideoClock as or, ScrollBounds as os, Mp3Frames as ot, UiRole as ou, TEXT_RUN_ID_SEPARATOR as p, parseTransform as p_, Edges as pa, PaintBoxShadow as pc, pathValuesEqual as pd, hasThemeExtension as pf, darkColors as pg, NodeProperty as ph, BorderEdge as pi, Stack as pl, UiProps as pm, PaintRecording as pn, dragSessionFor as po, textSpansEqual as pp, RangeResponse as pr, scrollbarThumbs as ps, CLIP_STRIDE_FLOATS as pt, validateRole as pu, parseWebVtt as q, UiPlatformAdapter as qa, nextGraphemeEnd as qc, propertyValuesEqual as qd, UiFontStretch as qf, UiAnimationOptions as qg, UiThemeColorName as qh, placeGridItems as qi, TextProps as ql, isMotionRest as qm, themeTokens as qn, UiFindController as qo, assertModifierList as qp, ShortcutsOptions as qr, SpanPaint as qs, WebGPUCanvasHost as qt, UiLayoutContext as qu, UiSemanticsUpdate as r, UiSpringSpec as r_, ELLIPSIS as ra, runFontString as rc, PaintFillRule as rd, withDensity as rf, normalizeBorderRadius as rg, Constraints as rh, ReorderableOptions as ri, LazyListProps as rl, ComponentResolver as rm, PaintStats as rn, TouchScrollerOptions as ro, UiTextStyle as rp, ScrollOffset as rr, SCROLLBAR_INSET as rs, demuxMp4Video as rt, UiAutocomplete as ru, recordsEqual as s, interpolateColor as s_, LayoutEngine as sa, Canvas2DGradient as sc, PaintTextAlign as sd, lengths as sf, UiShapes as sg, Size as sh, DragOffset as si, Column as sl, UiSourceLocation as sm, PaintResolver as sn, UiDragSession as so, hiddenRangesOf as sp, VideoSourceArgs as sr, ScrollbarAxis as ss, Mp3Header as st, UiSemanticState as su, UiSemanticsAction as t, UiEasingToken as t_, FlexDirection as ta, layoutTextLines as tc, visualStatesEqual as td, themesEqual as tf, borderRadiusIsZero as tg, SharedClaim as th, DragSourceOptions as ti, LazyGrid as tl, FocusSource as tm, PaintCanvasFactory as tn, EditingState as to, UiTextRange as tp, breakpoint as tr, UiPoint as ts, Mp4VideoTrack as tt, UI_ROLES as tu, SemanticsReuse as u, interpolatorFor as u_, ScrollAdjustment as ua, DEFAULT_FONT_WEIGHT as uc, UiPath as ud, UiThemeExtensionOptions as uf, shapesEqual as ug, constraintsEqual as uh, ClickOutsideOptions as ui, Paint as ul, isUiChild as um, EMPTY_RECORDING as un, UiDropZone as uo, spannedTextOf as up, videoSource as ur, scrollLeaderOf as us, WebGPUGlyphPages as ut, isUiSemanticState as uu, rewalkSemantics as v, UiColor as v_, SizeDecision as va, colorToCss as vc, ResolvedGradientStop as vd, HighContrastOptions as vf, FontMetrics as vg, DecorationFill as vh, borders as vi, UiBinding as vl, MOUSE_POINTER as vm, svgPaint as vn, UiShortcutStep as vo, spacingEqual as vp, SharedElementArgs as vr, clearMatchRanges as vs, ImageCommand as vt, LazySheet as vu, linkHoverOf as w, parseColor as w_, withOverrideSource as wa, resolvePaintState as wc, gradientPaint as wd, UiDensity as wf, TextMeasureRequest as wg, hasDecorationPhase as wh, interactive as wi, BoxModelProps as wl, UiInputEvent as wm, Canvas2DRenderer as wn, UiKeyboardController as wo, insetsEqual as wp, iconSource as wr, UiEnvironmentProvider as ws, RenderTextCache as wt, SheetViewport as wu, textRunOfRecordId as x, colorValuesEqual as x_, formatConstraints as xa, isPaintVisible as xc, UiGradientStop as xd, highContrastColors as xf, SpannedRuns as xg, DecorationStroke as xh, BUTTON_INTERACTION as xi, ChildrenBindingId as xl, UiEventType as xm, LayoutInspector as xn, parseShortcut as xo, UiInsetRegistry as xp, IconSourceArgs as xr, FindMatch as xs, PrimitiveKind as xt, SheetRange as xu, semanticsInertAbove as y, colorToHex as y_, describeLength as ya, computeObjectFitRect as yc, UiGradient as yd, UiContrast as yf, ParagraphLayout as yg, DecorationRect as yh, decorated as yi, UiGraph as yl, UiBeforeInputEvent as ym, INSPECTOR_HEAT_MS as yn, describeShortcut as yo, spacingSteps as yp, motion as yr, matchRangesOf as ys, NO_CLIP_INDEX as yt, LazySheetProps as yu, markInstant as z, isNodeTabStop as za, lineLimit as zc, isMinMaxTrack as zd, shadowsOf as zf, UiTransitionSpec as zg, UiPointerEvents as zh, propertyEffects as zi, PaintProps as zl, MOTION_CHANNELS as zm, CanvasSurface as zn, NodeTransitions as zo, comparePositions as zp, parseSvg as zr, EditCommand as zs, initializeWebGPU as zt, VirtualUpdate as zu };
20426
+ //# sourceMappingURL=index-B5r1ETCh.d.ts.map