gesso-core 0.4.2 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as prepareInputSurface, $a as UiNodeType, $i as isTypographyRole, $n as offsetForVerticalMove, $r as isMinMaxTrack, $t as DEFAULT_FONT_FAMILY, A as accumulatedOffsetTo, Aa as writeDeclaredProperty, Ai as hasThemeExtension, An as linkOf, Ar as statesEqual, At as ELLIPSIS, B as parseFlexDirection, Ba as UiFocusEvent, Bi as defaultSpacing, Bn as isMultiline, Br as transform, Bt as drawText, C as describeLength, Ca as findEnvironmentKey, Ci as unknownContainerSize, Cn as isNodeInert, Cr as propertyValuesEqualByName, Ct as paragraphGeometry, D as formatNumber, Da as clearOverrideProperty, Di as withContrast, Dn as clearLinkHover, Dr as isUiRole, Dt as CharacterCountTextMeasurer, E as formatExplanation, Ea as DirtyNodeSet, Ei as themesEqual, En as resolveCursor, Er as UI_SEMANTIC_STATES, Et as wordRangeIn, F as constraintsEqual, Fa as visualState, Fi as contrastRatio, Fn as EDITOR_PROP, Fr as inputsEqual, Ft as isPrintable, G as MainAxisAlignment, Ga as UiPinchEvent, Gi as shadowsEqual, Gn as isVideoSurface, Gr as gradientsEqual, Gt as spanOf, H as sizeGridTracks, Ha as UiInputEvent, Hi as spacingEqual, Hn as nextCaretToggle, Hr as transformsEqual, Ht as layoutTextLines, I as tightenConstraints, Ia as visualStatesEqual, Ii as highContrastColors, In as caretVisibleAt, Ir as paintValuesEqual, It as EditableLayout, J as parseMainAxisAlignment, Ja as UiTextChangeEvent, Ji as boxShadowsEqual, Jn as lineIndexAtY, Jr as validateGradient, Jt as textRunDecorations, K as parseAlignContent, Ka as UiPointerEvent, Ki as boxShadow, Kn as videoFrameSize, Kr as linearGradient, Kt as textMeasureRequest, L as MAX_MEASURES_PER_CHILD, La as MOUSE_POINTER, Li as raiseContrast, Ln as editorFor, Lr as pathValuesEqual, Lt as applyCanvasTextStyle, M as LayoutRecord, Ma as UiVisualState, Mi as themeExtension, Mn as setLinkHover, Mr as validateStates, Mt as proportionalFontMetrics, N as Constraints, Na as defaultVisualState, Ni as themeExtensionsEqual, Nn as CARET_BLINK_MS, Nr as UI_SUBGRID_AXES, Nt as commandForKey, O as labelNode, Oa as overrideSources, Oi as withDensity, On as hasTextLinks, Or as isUiSemanticState, Ot as ParagraphTextMeasurer, P as clampSize, Pa as hasVisualState, Pi as withThemeExtension, Pn as CARET_WIDTH, Pr as validateSubgrid, Pt as detectEditingPlatform, Q as pointerDeviceOf, Qa as wheelDeltaYOf, Qi as defaultTypography, Qn as offsetAtX, Qr as isFrLength, Qt as registerFontStack, R as isLayoutProtocol, Ra as UiBeforeInputEvent, Ri as relativeLuminance, Rn as editorOf, Rr as UiTransforms, Rt as buildFontString, S as SCROLLBAR_LINGER_MS, Sa as createEnvironmentKey, Si as containerBands, Sn as isNodeHitTestable, Sr as propertyIsInherited, St as offsetAtPointIn, T as formatConstraints, Ta as UiNode, Ti as lightTheme, Tn as isNodeTabStop, Tr as UI_ROLES, Tt as selectionRectsIn, U as AlignContent, Ua as UiKeyboardEvent, Ui as spacingSteps, Un as syncEditorValue, Ur as MAX_GRADIENT_STOPS, Ut as runCanvasStyleInto, V as placeGridItems, Va as UiGestureEvent, Vi as scaleSpacing, Vn as isReadOnly, Vr as transformIsIdentity, Vt as fillTextRects, W as CrossAxisAlignment, Wa as UiPasteEvent, Wi as defaultShadows, Wn as resolveColorValue, Wr as gradientPaint, Wt as runFontString, X as UiPlatformAdapter, Xa as UiWheelEvent, Xi as isShapeName, Xn as lineLimit, Xr as fr, Xt as clearFontStacks, Y as CanvasPlatformSurface, Ya as UiWheelDeltaMode, Yi as defaultShapes, Yn as lineIndexForOffset, Yr as auto, Yt as bumpFontStack, Z as capturePointer, Za as noKeyModifiers, Zi as shapesEqual, Zn as offsetAtPoint, Zr as isAutoLength, Zt as fontStackFor, _ as LABEL_PADDING_X, _a as colorsEqual, _i as insetsEqual, _n as selectableTextNodes, _r as findPropertyDefinition, _t as scrollbarThumb, a as PaintPictureCache, aa as spanAtOffset, ai as UiBorderRadiuses, an as createPaintState, ar as nextGraphemeEnd, at as UiWheelController, b as LayoutEngine, ba as rgb8, bi as UiContainerSizeSource, bn as setSelectionRange, br as inheritedPropertyNames, bt as UiInputDispatcher, c as EMPTY_RECORDING, ca as textSpansEqual, ci as borderRadiusEqual, cn as normalizeVerticalAlign, cr as previousWordStart, ct as UiPointerController, d as tracePathData, da as darkColors, di as normalizeBorderRadius, dn as TEXT_MATCHES_PROP, dr as resolveNumber, dt as SCROLLBAR_HOVER_ZONE, ea as typographyEqual, ei as isPercentLength, en as DEFAULT_FONT_SIZE, eo as DirtyFlags, er as selectionRects, et as touchActionFor, f as ScaledImageCache, fa as lightColors, fi as uniformBorderRadius, fn as clearMatchRanges, fr as resolveProperty, ft as SCROLLBAR_INSET, g as paintsAfterChildren, ga as colorValuesEqual, gi as UiInsetRegistry, gn as clearSelectionRange, gr as closestPropertyName, gt as scrollRange, h as hasDecorationPhase, ha as colorToRgba, hi as UiEnvironmentKeys, hn as TEXT_SELECTION_PROP, hr as UiGraph, ht as scrollLeaderOf, i as traceRoundedRect, ia as resolvedSpansOf, ii as resolveLength, in as computeObjectFitRect, ir as lineStartAt, it as UiPinchRecognizer, j as contentOffset, ja as writeOverrideProperty, ji as noThemeExtensions, jn as linkRunAtPointIn, jr as validateRole, jt as layoutParagraph, k as withOverrideSource, ka as resetOverrideWarnings, ki as defineThemeExtension, kn as linkHoverOf, kr as normalizeStates, kt as spannedRunsFor, l as PaintRecorder, la as textStylesEqual, li as borderRadiusIsZero, ln as resolvePaintState, lr as wordRangeAt, lt as UiFocusManager, m as decorationRect, ma as colorToHex, mi as propertyValuesEqual, mn as setMatchRanges, mr as resolveString, mt as SCROLLBAR_THICKNESS, n as createCanvasSurface, na as editableSpansOf, ni as percent, nn as DEFAULT_TEXT_COLOR, nr as graphemeBoundaries, nt as UiTouchScroller, o as paintPictures, oa as spannedTextOf, oi as borderRadius, on as isPaintVisible, or as nextWordEnd, ot as isScrollContainer, p as decorationColor, pa as UiBasicColors, pi as defineProperty, pn as matchRangesOf, pr as resolvePropertyByName, pt as SCROLLBAR_MIN_THUMB, q as parseCrossAxisAlignment, qa as UiSelectionChangeEvent, qi as boxShadowArraysEqual, qn as caretRectFor, qr as radialGradient, qt as textRunBackgrounds, r as Canvas2DRenderer, ra as flattenTextSpans, ri as repeat, rn as colorToCss, rr as lineEndAt, rt as UiGestureRecognizer, s as PaintTarget, sa as textContentOf, si as borderRadiusCorners, sn as normalizeTextAlign, sr as previousGraphemeStart, st as UiKeyboardController, t as CanvasSurface, ta as defaultTextStyle, ti as minmax, tn as DEFAULT_FONT_WEIGHT, to as UiBinding, tr as EditableTextModel, tt as UiEditingController, u as replayPaint, ua as colorsEqualPalette, ui as borderRadiusValuesEqual, un as DEFAULT_LINE_HEIGHT_FACTOR, ur as resolveBoolean, ut as UiHitTester, v as drawOverlayShapes, va as normalizeColor, vi as noInsets, vn as selectableTextOf, vr as getPropertyNames, vt as scrollbarThumbs, w as describeOverrides, wa as UiEnvironment, wi as darkTheme, wn as isNodeSelectable, wr as UiProperties, wt as paragraphGeometryFrom, x as SCROLLBAR_FADE_MS, xa as rgba, xi as bandOf, xn as isNodeFocusable, xr as propertyEffects, xt as hasDrawnText, y as labelOrigin, ya as parseColor, yi as observeViewportInsets, yn as selectionRangeOf, yr as inheritedPropertyFlags, yt as scrollbarZoneAt, z as FlexDirection, za as UiEventType, zi as densityFactors, zn as isEditableNode, zr as parseTransform, zt as createCanvasTextStyle } from "./CanvasSurface-BMOmE_dD.js";
1
+ import { $ as pointerDeviceOf, $a as UiKeyboardEvent, $i as boxShadow, $n as caretRectFor, $r as radialGradient, $t as DEFAULT_FONT_SIZE, A as withOverrideSource, Aa as rgb8, Ai as darkTheme, An as linkRunAtPointIn, Ar as UiProperties, At as edgeField, B as FlexDirection, Ba as writeDeclaredProperty, Bi as withThemeExtension, Bn as isReadOnly, Br as validateSubgrid, Bt as fillTextRects, C as SCROLLBAR_LINGER_MS, Ca as UiBasicColors, Ci as insetsEqual, Cn as isNodeTabStop, Cr as findPropertyDefinition, Ct as offsetAtPointIn, D as formatExplanation, Da as colorsEqual, Di as bandOf, Dn as hasTextLinks, Dr as propertyEffects, Dt as wordRangeIn, E as formatConstraints, Ea as colorValuesEqual, Ei as UiContainerSizeSource, En as clearLinkHover, Er as inheritedPropertyNames, Et as selectionRectsIn, F as clampSize, Fa as UiNode, Fi as defineThemeExtension, Fn as caretVisibleAt, Fr as normalizeStates, Ft as EditableLayout, G as CrossAxisAlignment, Ga as visualState, Gi as densityFactors, Gn as videoFrameSize, Gr as parseTransform, Gt as textMeasureRequest, H as placeGridItems, Ha as UiVisualState, Hi as highContrastColors, Hn as syncEditorValue, Hr as paintValuesEqual, Ht as runCanvasStyleInto, I as constraintsEqual, Ia as DirtyNodeSet, Ii as hasThemeExtension, In as editorFor, Ir as statesEqual, It as applyCanvasTextStyle, J as parseCrossAxisAlignment, Ja as UiBeforeInputEvent, Ji as spacingEqual, Jn as spannedRunsFor, Jr as transformsEqual, Jt as bumpFontStack, K as MainAxisAlignment, Ka as visualStatesEqual, Ki as defaultSpacing, Kn as CharacterCountTextMeasurer, Kr as transform, Kt as textRunBackgrounds, L as tightenConstraints, La as clearOverrideProperty, Li as noThemeExtensions, Ln as editorOf, Lr as validateRole, Lt as buildFontString, M as contentOffset, Ma as createEnvironmentKey, Mi as themesEqual, Mn as CARET_BLINK_MS, Mr as UI_SEMANTIC_STATES, Mt as commandForKey, N as LayoutRecord, Na as findEnvironmentKey, Ni as withContrast, Nn as CARET_WIDTH, Nr as isUiRole, Nt as detectEditingPlatform, O as formatNumber, Oa as normalizeColor, Oi as containerBands, On as linkHoverOf, Or as propertyIsInherited, Ot as adjacentField, P as Constraints, Pa as UiEnvironment, Pi as withDensity, Pn as EDITOR_PROP, Pr as isUiSemanticState, Pt as isPrintable, Q as capturePointer, Qa as UiInputEvent, Qi as BOX_SHADOW_BLUR_REACH, Qn as DEFAULT_LINE_HEIGHT_FACTOR, Qr as linearGradient, Qt as DEFAULT_FONT_FAMILY, R as MAX_MEASURES_PER_CHILD, Ra as overrideSources, Ri as themeExtension, Rn as isEditableNode, Rr as validateStates, Rt as createCanvasTextStyle, S as SCROLLBAR_FADE_MS, Sa as lightColors, Si as UiInsetRegistry, Sn as isNodeSelectable, Sr as closestPropertyName, St as hasDrawnText, T as describeOverrides, Ta as colorToRgba, Ti as observeViewportInsets, Tn as resolveCursor, Tr as inheritedPropertyFlags, Tt as paragraphGeometryFrom, U as sizeGridTracks, Ua as defaultVisualState, Ui as raiseContrast, Un as resolveColorValue, Ur as pathValuesEqual, Ut as runFontString, V as parseFlexDirection, Va as writeOverrideProperty, Vi as contrastRatio, Vn as nextCaretToggle, Vr as inputsEqual, Vt as layoutTextLines, W as AlignContent, Wa as hasVisualState, Wi as relativeLuminance, Wn as isVideoSurface, Wr as UiTransforms, Wt as spanOf, X as CanvasPlatformSurface, Xa as UiFocusEvent, Xi as defaultShadows, Xn as layoutParagraph, Xr as gradientPaint, Xt as fontStackFor, Y as parseMainAxisAlignment, Ya as UiEventType, Yi as spacingSteps, Yn as ELLIPSIS, Yr as MAX_GRADIENT_STOPS, Yt as clearFontStacks, Z as UiPlatformAdapter, Za as UiGestureEvent, Zi as shadowsEqual, Zn as proportionalFontMetrics, Zr as gradientsEqual, Zt as registerFontStack, _ as LABEL_PADDING_X, _a as textContentOf, _i as normalizeBorderRadius, _n as selectionRangeOf, _r as resolveNumber, _t as scrollRange, a as PaintPictureCache, aa as isShapeName, ai as isMinMaxTrack, an as isPaintVisible, ao as UiWheelDeltaMode, ar as offsetForVerticalMove, at as UiPinchRecognizer, b as snapScroll, ba as colorsEqualPalette, bi as propertyValuesEqual, bn as isNodeHitTestable, br as resolveString, bt as scrollbarZoneAt, c as EMPTY_RECORDING, ca as isTypographyRole, ci as percent, cn as resolvePaintState, co as wheelDeltaYOf, cr as graphemeBoundaries, ct as UiKeyboardController, d as tracePathData, da as editableSpansOf, di as UiBorderRadiuses, dn as matchRangesOf, do as UiBinding, dr as nextGraphemeEnd, dt as UiHitTester, ea as boxShadowArraysEqual, ei as validateGradient, en as DEFAULT_FONT_WEIGHT, eo as UiPasteEvent, er as lineIndexAtY, et as prepareInputSurface, f as ScaledImageCache, fa as flattenTextSpans, fi as borderRadius, fn as setMatchRanges, fr as nextWordEnd, ft as SCROLLBAR_HOVER_ZONE, g as paintsAfterChildren, ga as spannedTextOf, gi as borderRadiusValuesEqual, gn as selectableTextOf, gr as resolveBoolean, gt as scrollLeaderOf, h as hasDecorationPhase, ha as spanAtOffset, hi as borderRadiusIsZero, hn as selectableTextNodes, hr as wordRangeAt, ht as SCROLLBAR_THICKNESS, i as traceRoundedRect, ia as defaultShapes, ii as isFrLength, in as createPaintState, io as UiTextChangeEvent, ir as offsetAtX, it as UiGestureRecognizer, j as accumulatedOffsetTo, ja as rgba, ji as lightTheme, jn as setLinkHover, jr as UI_ROLES, jt as editingGroupOf, k as labelNode, ka as parseColor, ki as unknownContainerSize, kn as linkOf, kr as propertyValuesEqualByName, kt as comparePositions, l as PaintRecorder, la as typographyEqual, li as repeat, ln as TEXT_MATCHES_PROP, lo as UiNodeType, lr as lineEndAt, lt as UiPointerController, m as decorationRect, ma as resolvedSpansOf, mi as borderRadiusEqual, mn as clearSelectionRange, mr as previousWordStart, mt as SCROLLBAR_MIN_THUMB, n as createCanvasSurface, na as boxShadowReach, ni as fr, nn as colorToCss, no as UiPointerEvent, nr as lineLimit, nt as UiEditingController, o as paintPictures, oa as shapesEqual, oi as isPercentLength, on as normalizeTextAlign, oo as UiWheelEvent, or as selectionRects, ot as UiWheelController, p as decorationColor, pa as hiddenRangesOf, pi as borderRadiusCorners, pn as TEXT_SELECTION_PROP, pr as previousGraphemeStart, pt as SCROLLBAR_INSET, q as parseAlignContent, qa as MOUSE_POINTER, qi as scaleSpacing, qn as ParagraphTextMeasurer, qr as transformIsIdentity, qt as textRunDecorations, r as Canvas2DRenderer, ra as boxShadowsEqual, ri as isAutoLength, rn as computeObjectFitRect, ro as UiSelectionChangeEvent, rr as offsetAtPoint, rt as UiTouchScroller, s as PaintTarget, sa as defaultTypography, si as minmax, sn as normalizeVerticalAlign, so as noKeyModifiers, sr as EditableTextModel, st as isScrollContainer, t as CanvasSurface, ta as boxShadowRadius, ti as auto, tn as DEFAULT_TEXT_COLOR, to as UiPinchEvent, tr as lineIndexForOffset, tt as touchActionFor, u as replayPaint, ua as defaultTextStyle, ui as resolveLength, un as clearMatchRanges, uo as DirtyFlags, ur as lineStartAt, ut as UiFocusManager, v as drawOverlayShapes, va as textSpansEqual, vi as uniformBorderRadius, vn as setSelectionRange, vr as resolveProperty, vt as scrollbarThumb, w as describeLength, wa as colorToHex, wi as noInsets, wn as isPressable, wr as getPropertyNames, wt as paragraphGeometry, x as LayoutEngine, xa as darkColors, xi as UiEnvironmentKeys, xn as isNodeInert, xr as UiGraph, xt as UiInputDispatcher, y as labelOrigin, ya as textStylesEqual, yi as defineProperty, yn as isNodeFocusable, yr as resolvePropertyByName, yt as scrollbarThumbs, z as isLayoutProtocol, za as resetOverrideWarnings, zi as themeExtensionsEqual, zn as isMultiline, zr as UI_SUBGRID_AXES, zt as drawText } from "./CanvasSurface-Dok8FuyX.js";
2
2
  import { BehaviorSubject, EMPTY, Subject, combineLatest, distinctUntilChanged, isObservable as isObservable$1, map, of } from "rxjs";
3
3
  //#region src/animation/UiEasing.ts
4
4
  /** Progress equals time. What a spinner and a sweep want. */
@@ -836,11 +836,12 @@ var UiSharedElements = class {
836
836
  * But it must not disappear *yet*. A claim happens during
837
837
  * reconciliation, and the arriving node has no box until the frame
838
838
  * lays out — so yielding here leaves a window in which neither
839
- * element is drawn. For a transform morph that window is closed
840
- * within the same frame; for a geometry morph, which cannot write a
841
- * box after layout has run, it is a whole frame long, and a whole
842
- * frame with neither the old card nor the new one is a flash of the
843
- * page behind them. It was exactly that visible.
839
+ * element is drawn. The window closes within the frame now, for a
840
+ * geometry morph as for a transform one, but only because the
841
+ * arriving element takes its place in that frame's layout pass; when
842
+ * a geometry morph's box waited for the next frame, a whole frame
843
+ * with neither the old card nor the new one was a flash of the page
844
+ * behind them, and it was exactly that visible.
844
845
  *
845
846
  * So the caller yields the previous holder at the moment it actually
846
847
  * takes its place. Until then both are on screen, in the same
@@ -1199,7 +1200,7 @@ const PRESS_ONLY = Object.freeze({
1199
1200
  hover: false,
1200
1201
  press: true
1201
1202
  });
1202
- const kind$4 = defineModifier({
1203
+ const kind$5 = defineModifier({
1203
1204
  name: "interactive",
1204
1205
  attach(host, options) {
1205
1206
  let hovered = false;
@@ -1246,15 +1247,15 @@ const kind$4 = defineModifier({
1246
1247
  });
1247
1248
  /** Hover and press. */
1248
1249
  function interactive(options = BOTH) {
1249
- return kind$4(options);
1250
+ return kind$5(options);
1250
1251
  }
1251
1252
  /** Hover only. */
1252
1253
  function hoverable() {
1253
- return kind$4(HOVER_ONLY);
1254
+ return kind$5(HOVER_ONLY);
1254
1255
  }
1255
1256
  /** Press only. */
1256
1257
  function pressable() {
1257
- return kind$4(PRESS_ONLY);
1258
+ return kind$5(PRESS_ONLY);
1258
1259
  }
1259
1260
  /**
1260
1261
  * What every Button carries. One shared value, so `sameArgs` matches it
@@ -1263,7 +1264,7 @@ function pressable() {
1263
1264
  * that genuinely differ do detach and re-attach it, losing the hover and
1264
1265
  * press state with them, which is the reason this one is a constant.
1265
1266
  */
1266
- const BUTTON_INTERACTION = kind$4(BOTH);
1267
+ const BUTTON_INTERACTION = kind$5(BOTH);
1267
1268
  function sameStates(a, b) {
1268
1269
  if (a.size !== b.size) return false;
1269
1270
  for (const state of b) if (!a.has(state)) return false;
@@ -1756,26 +1757,26 @@ var Host = class {
1756
1757
  }
1757
1758
  this.own(layout.onLayout(this.node, listener));
1758
1759
  }
1759
- environment(key) {
1760
+ environment(key, of = this.node) {
1760
1761
  const environment = this.services.environment;
1761
1762
  if (environment === void 0) return key.defaultValue;
1762
- return environment.read(this.node, key);
1763
+ return environment.read(of, key);
1763
1764
  }
1764
- onEnvironment(listener) {
1765
+ onEnvironment(listener, of = this.node) {
1765
1766
  const environment = this.services.environment;
1766
1767
  if (environment === void 0) {
1767
1768
  warnMissing(this.name, "follow its environment", "environment");
1768
1769
  return;
1769
1770
  }
1770
- this.own(environment.onChange(this.node, listener));
1771
+ this.own(environment.onChange(of, listener));
1771
1772
  }
1772
- focus() {
1773
+ focus(options) {
1773
1774
  const focus = this.services.focus;
1774
1775
  if (focus === void 0) {
1775
1776
  warnMissing(this.name, "move focus", "focus");
1776
1777
  return;
1777
1778
  }
1778
- focus.focus(this.node);
1779
+ focus.focus(this.node, options);
1779
1780
  }
1780
1781
  isFocused() {
1781
1782
  return this.services.focus?.isFocused(this.node) ?? false;
@@ -2497,15 +2498,30 @@ var UiGraphBuilder = class {
2497
2498
  * instance is unchanged and torn down when a property stops
2498
2499
  * being reactive.
2499
2500
  */
2501
+ /**
2502
+ * The properties each node's element declared last time, so a render
2503
+ * that stops declaring one takes it off the node.
2504
+ *
2505
+ * Only bindings used to be torn down that way. A plain value stayed:
2506
+ * a conditional that swapped `<scrollview padding={20}>` for a
2507
+ * `<scrollview>` reused the node and kept the padding, and an editor
2508
+ * switching from its source view back to its document came back
2509
+ * twenty pixels narrower. Only what the builder declared is tracked,
2510
+ * so what modifiers and the runtime write on a node is left alone.
2511
+ */
2512
+ declaredProps = /* @__PURE__ */ new WeakMap();
2500
2513
  reconcileProps(node, props, parent) {
2501
2514
  this.reconcileTransitions(node, props[TRANSITION_PROP]);
2502
2515
  const present = /* @__PURE__ */ new Set();
2503
2516
  const presentEvents = /* @__PURE__ */ new Set();
2504
2517
  let declaredModifiers;
2518
+ let declaredRef;
2519
+ let hasRef = false;
2505
2520
  for (const [property, value] of Object.entries(props)) {
2506
2521
  if (property === KEY_PROP) continue;
2507
2522
  if (property === REF_PROP) {
2508
- this.reconcileRef(node, value);
2523
+ declaredRef = value;
2524
+ hasRef = true;
2509
2525
  continue;
2510
2526
  }
2511
2527
  if (property === MODIFIERS_PROP) {
@@ -2532,7 +2548,13 @@ var UiGraphBuilder = class {
2532
2548
  }
2533
2549
  for (const binding of this.graph.getBindingsForNode(node)) if (!present.has(binding.property)) this.graph.unbind(binding);
2534
2550
  for (const binding of this.graph.getEventBindingsForNode(node)) if (!presentEvents.has(binding.type)) this.graph.unbindEvent(node, binding);
2551
+ const previous = this.declaredProps.get(node);
2552
+ if (previous !== void 0) {
2553
+ for (const property of previous) if (!present.has(property)) this.graph.removeNodeProperty(node, property, propertyEffects(property));
2554
+ }
2555
+ this.declaredProps.set(node, present);
2535
2556
  if (node.environment === null && parent?.environment != null) node.environment = this.graph.buildNodeEnvironment(node, parent);
2557
+ if (hasRef) this.reconcileRef(node, declaredRef);
2536
2558
  this.reconcileModifiers(node, declaredModifiers);
2537
2559
  }
2538
2560
  /**
@@ -3183,6 +3205,9 @@ function lazyList(axis, props, renderItem, grid) {
3183
3205
  * padding, and a layout that switched arms at 600 px would otherwise
3184
3206
  * switch at 600 px of border box and lay itself out in 560.
3185
3207
  *
3208
+ * What a subtree builds from the size it reports is laid out on the
3209
+ * same frame, before anything paints; see `UiModifierHost.onLayout`.
3210
+ *
3186
3211
  * `Responsive` attaches this for you. Attach it by hand when the
3187
3212
  * source has to be reachable somewhere the helper's own children are
3188
3213
  * not, and put the same object on the node's `containerSize` prop.
@@ -3218,9 +3243,15 @@ const sizeContainer = defineModifier({
3218
3243
  * about it and the thing a media query cannot do: a card in a sidebar
3219
3244
  * asks how wide the card is, not how wide the window is.
3220
3245
  *
3221
- * Nothing is written until the node has been laid out once, so the
3222
- * first frame uses the element's own values. Give the element the
3223
- * narrowest band's values as its declared props if that matters.
3246
+ * Nothing is written until the node has been laid out once, but the
3247
+ * first frame is already right: the runtime lays out again before it
3248
+ * paints when a layout listener changes layout (see
3249
+ * `UiModifierHost.onLayout`), so the frame a node first appears on,
3250
+ * and the frame a resize crosses a width on, are drawn with the band's
3251
+ * values. The element's own values are what that first pass measures
3252
+ * with; give it the narrowest band's values as its declared props so a
3253
+ * layout nothing settles (a headless one, a spec driving layout by
3254
+ * hand) starts from the right band.
3224
3255
  */
3225
3256
  const breakpoint = defineModifier({
3226
3257
  name: "breakpoint",
@@ -3273,7 +3304,9 @@ const breakpoint = defineModifier({
3273
3304
  * The first build happens before any layout, when the size is zero, so
3274
3305
  * `build` must return something sensible for a container whose room is
3275
3306
  * not yet known. Zero picks the narrowest arm, which is the right
3276
- * guess and also what a phone gets.
3307
+ * guess and also what a phone gets. It is never what a wider container
3308
+ * paints: the first layout reports the real size, the arm for it is
3309
+ * built, and the runtime lays that out before the frame paints.
3277
3310
  */
3278
3311
  function Responsive(props, build) {
3279
3312
  const { at, as = "column", modifiers, ...rest } = props;
@@ -4375,6 +4408,12 @@ const MODIFIER_KEYS = /* @__PURE__ */ new Set([
4375
4408
  * Without that rule an application with a `n` for "new note" becomes an
4376
4409
  * application you cannot type the letter n into, which is the failure
4377
4410
  * every home-grown key handler eventually ships.
4411
+ *
4412
+ * ## Pressing is not a shortcut
4413
+ *
4414
+ * A bare Enter or Space is skipped while a button or link has focus,
4415
+ * unless the shortcut is that control's own: the control is focused, so
4416
+ * it has the key first, as it would in a browser.
4378
4417
  */
4379
4418
  var UiShortcutRegistry = class {
4380
4419
  bindings = [];
@@ -4390,10 +4429,11 @@ var UiShortcutRegistry = class {
4390
4429
  /** Adds a shortcut. The returned function removes it again. */
4391
4430
  register(shortcut) {
4392
4431
  const steps = parseShortcut(shortcut.keys);
4432
+ this.platform ??= detectEditingPlatform();
4393
4433
  const binding = {
4394
4434
  ...shortcut,
4395
4435
  steps,
4396
- display: formatShortcut(steps)
4436
+ display: formatShortcut(steps, this.platform)
4397
4437
  };
4398
4438
  this.bindings.push(binding);
4399
4439
  return () => {
@@ -4434,6 +4474,10 @@ var UiShortcutRegistry = class {
4434
4474
  */
4435
4475
  handleKey(key, modifiers, focused) {
4436
4476
  if (MODIFIER_KEYS.has(key)) return false;
4477
+ if (focused !== null && isTypingInto(focused) && this.isEditingKey(key, modifiers)) {
4478
+ this.pending = [];
4479
+ return false;
4480
+ }
4437
4481
  const step = stepFor(key, modifiers);
4438
4482
  const at = this.now();
4439
4483
  if (this.pending.length > 0 && at - this.pendingAt > this.chordTimeout) this.pending = [];
@@ -4456,6 +4500,13 @@ var UiShortcutRegistry = class {
4456
4500
  this.pending = [];
4457
4501
  return false;
4458
4502
  }
4503
+ platform = null;
4504
+ /** Whether a field would take this key as an edit of its own, rather than as text or as Enter. */
4505
+ isEditingKey(key, modifiers) {
4506
+ this.platform ??= detectEditingPlatform();
4507
+ const command = commandForKey(key, modifiers, this.platform, false);
4508
+ return command !== null && command.kind !== "newline" && command.kind !== "insert";
4509
+ }
4459
4510
  /** Forgets a half-typed chord, for a route change or a lost focus. */
4460
4511
  reset() {
4461
4512
  this.pending = [];
@@ -4463,17 +4514,20 @@ var UiShortcutRegistry = class {
4463
4514
  /**
4464
4515
  * Whether a binding would fire for a key going to `focused`.
4465
4516
  *
4466
- * Three things take a shortcut out: its scope does not contain the
4467
- * focused node, its own `when` says no, and, for a shortcut with no
4468
- * modifier at all, the focused node is somewhere text is being
4469
- * typed. The last is the rule that keeps a single-letter shortcut
4470
- * from making a text field unusable.
4517
+ * Four things take a shortcut out: its scope does not contain the
4518
+ * focused node, its own `when` says no, for a shortcut with no
4519
+ * modifier at all the focused node is somewhere text is being typed,
4520
+ * and for a bare Enter or Space the focused node is a button that
4521
+ * isn't the shortcut's own. The third keeps a single-letter shortcut
4522
+ * from making a text field unusable; the fourth keeps a list's Enter
4523
+ * from opening a row when the button focused inside it was pressed.
4471
4524
  */
4472
4525
  isLive(binding, focused) {
4473
4526
  const scope = binding.scope ?? null;
4474
4527
  if (scope !== null && (focused === null || !containsNode(scope, focused))) return false;
4475
4528
  if (binding.when !== void 0 && !binding.when()) return false;
4476
4529
  if (focused !== null && isTypingInto(focused) && binding.steps.every((step) => isBare(step))) return false;
4530
+ if (focused !== null && scope !== focused && isPressing(binding.steps) && isPressable(focused)) return false;
4477
4531
  return true;
4478
4532
  }
4479
4533
  };
@@ -4508,6 +4562,11 @@ function isTypingInto(node) {
4508
4562
  for (let current = node; current !== null; current = current.parent) if (current.type === "editable-text" && !isNodeInert(current)) return true;
4509
4563
  return false;
4510
4564
  }
4565
+ /** A bare Enter or Space on its own: what presses a focused button. */
4566
+ function isPressing(steps) {
4567
+ const [step] = steps;
4568
+ return steps.length === 1 && step !== void 0 && isBare(step) && !step.shift && (step.key === "Enter" || step.key === " ");
4569
+ }
4511
4570
  /** A press with no modifier at all: an ordinary character. */
4512
4571
  function isBare(step) {
4513
4572
  return !step.mod && !step.ctrl && !step.meta && !step.alt;
@@ -4569,20 +4628,47 @@ function parseStep(text) {
4569
4628
  * `'Mod+K'` and `'Mod+k'` are the same shortcut, and the browser
4570
4629
  * reports whichever the shift state produced. Anything longer than one
4571
4630
  * character is a named key (`'Enter'`, `'ArrowUp'`) and keeps its case.
4631
+ *
4632
+ * The space bar is the exception that has to be spelled out. The
4633
+ * platform reports it as `' '`, which a shortcut string cannot contain
4634
+ * because space separates the steps of a chord, so the name `Space`
4635
+ * stands for it. Before this, `'Space'` was kept as the literal name and
4636
+ * never matched a press: the board's keyboard drag in the issue tracker
4637
+ * was the first thing to need it.
4572
4638
  */
4573
4639
  function normalizeKey(key) {
4640
+ const named = NAMED_KEYS[key.toLowerCase()];
4641
+ if (named !== void 0) return named;
4574
4642
  return key.length === 1 ? key.toLowerCase() : key;
4575
4643
  }
4644
+ /** Key names a shortcut string uses for keys it cannot spell. */
4645
+ const NAMED_KEYS = {
4646
+ space: " ",
4647
+ spacebar: " "
4648
+ };
4576
4649
  /** Whether the presses so far could still complete this shortcut. */
4577
4650
  function matchesPrefix(steps, sequence) {
4578
4651
  if (sequence.length > steps.length) return false;
4579
4652
  return sequence.every((step, index) => sameStep(steps[index], step));
4580
4653
  }
4581
4654
  function sameStep(want, got) {
4582
- if (want.key !== got.key || want.shift !== got.shift || want.alt !== got.alt) return false;
4655
+ if (want.key !== got.key) return false;
4656
+ if (isSymbol(want.key)) {
4657
+ if (isBare(want) && got.alt && !got.meta) return true;
4658
+ } else if (want.shift !== got.shift) return false;
4659
+ if (want.alt !== got.alt) return false;
4583
4660
  if (want.mod) return got.ctrl || got.meta;
4584
4661
  return want.ctrl === got.ctrl && want.meta === got.meta;
4585
4662
  }
4663
+ /**
4664
+ * Whether a key is a character that isn't a letter: punctuation, a digit
4665
+ * or a symbol, which different layouts put under different keys and
4666
+ * reach with or without Shift. A letter keeps its Shift, which is what
4667
+ * tells `Shift+L` from `l`.
4668
+ */
4669
+ function isSymbol(key) {
4670
+ return key.length === 1 && key !== " " && key.toLowerCase() === key.toUpperCase();
4671
+ }
4586
4672
  /** The press the person actually made. */
4587
4673
  function stepFor(key, modifiers) {
4588
4674
  return {
@@ -4595,24 +4681,123 @@ function stepFor(key, modifiers) {
4595
4681
  };
4596
4682
  }
4597
4683
  /**
4598
- * The shortcut as a palette should print it.
4684
+ * The shortcut as a palette should print it, the way the platform
4685
+ * writes its own: `⇧⌘K` on a Mac, where `Mod` is Command, and
4686
+ * `Ctrl+Shift+K` elsewhere, where it is Control. The platform is the
4687
+ * one the editing keys follow (`detectEditingPlatform`, from the user
4688
+ * agent, which a worker can read too).
4689
+ */
4690
+ function formatShortcut(steps, platform = detectEditingPlatform()) {
4691
+ return shortcutKeyCaps(steps, platform).map((caps) => caps.join(platform === "mac" ? "" : "+")).join(" ");
4692
+ }
4693
+ /**
4694
+ * The keys of each press, one string per key, for a help sheet that
4695
+ * draws them as key caps: `[['⇧', '⌘', 'K']]` on a Mac and
4696
+ * `[['Ctrl', 'Shift', 'K']]` elsewhere, and a chord is one array per
4697
+ * press. They are the pieces `formatShortcut` joins, so a sheet and a
4698
+ * palette print the same keys.
4699
+ */
4700
+ function shortcutKeyCaps(steps, platform = detectEditingPlatform()) {
4701
+ return steps.map((step) => [...modifierNames(step, platform, MAC_CAPS, OTHER_CAPS), keyName(step.key)]);
4702
+ }
4703
+ /**
4704
+ * The shortcut as a screen reader should say it: `Command Shift K` on a
4705
+ * Mac and `Control Shift K` elsewhere, `Down arrow`, `Question mark`,
4706
+ * and `g then d` for a chord.
4599
4707
  *
4600
- * `Mod` is printed as `Ctrl`, not as a platform glyph: the render
4601
- * worker cannot see the platform, and a wrong symbol is worse than a
4602
- * plain word. An application that knows what it is running on can
4603
- * format the `steps` itself.
4708
+ * A key cap's `⌘` or `↓` is read out inconsistently or not at all, and
4709
+ * punctuation is skipped at a screen reader's default verbosity, so a
4710
+ * row that shows caps takes this as its name.
4604
4711
  */
4605
- function formatShortcut(steps) {
4606
- return steps.map(formatStep).join(" ");
4712
+ function describeShortcut(steps, platform = detectEditingPlatform()) {
4713
+ return steps.map((step) => {
4714
+ const modifiers = modifierNames(step, platform, MAC_WORDS, OTHER_WORDS);
4715
+ return [...modifiers, spokenKey(step.key, modifiers.length > 0)].join(" ");
4716
+ }).join(" then ");
4607
4717
  }
4608
- function formatStep(step) {
4609
- const parts = [];
4610
- if (step.mod || step.ctrl) parts.push("Ctrl");
4611
- if (step.meta) parts.push("Meta");
4612
- if (step.alt) parts.push("Alt");
4613
- if (step.shift) parts.push("Shift");
4614
- parts.push(step.key.length === 1 ? step.key.toUpperCase() : step.key);
4615
- return parts.join("+");
4718
+ /** In the order the Mac's menus print them: Control, Option, Shift, Command. */
4719
+ const MAC_CAPS = {
4720
+ ctrl: "⌃",
4721
+ alt: "⌥",
4722
+ shift: "⇧",
4723
+ meta: "⌘"
4724
+ };
4725
+ const MAC_WORDS = {
4726
+ ctrl: "Control",
4727
+ alt: "Option",
4728
+ shift: "Shift",
4729
+ meta: "Command"
4730
+ };
4731
+ const OTHER_CAPS = {
4732
+ ctrl: "Ctrl",
4733
+ meta: "Meta",
4734
+ alt: "Alt",
4735
+ shift: "Shift"
4736
+ };
4737
+ const OTHER_WORDS = {
4738
+ ctrl: "Control",
4739
+ meta: "Meta",
4740
+ alt: "Alt",
4741
+ shift: "Shift"
4742
+ };
4743
+ /**
4744
+ * A press's modifiers, in the platform's order: Control, Option, Shift,
4745
+ * Command on a Mac, where `Mod` is Command; Control, Meta, Alt, Shift
4746
+ * elsewhere, where it is Control.
4747
+ */
4748
+ function modifierNames(step, platform, mac, other) {
4749
+ const names = [];
4750
+ if (platform === "mac") {
4751
+ if (step.ctrl) names.push(mac.ctrl);
4752
+ if (step.alt) names.push(mac.alt);
4753
+ if (step.shift) names.push(mac.shift);
4754
+ if (step.mod || step.meta) names.push(mac.meta);
4755
+ } else {
4756
+ if (step.mod || step.ctrl) names.push(other.ctrl);
4757
+ if (step.meta) names.push(other.meta);
4758
+ if (step.alt) names.push(other.alt);
4759
+ if (step.shift) names.push(other.shift);
4760
+ }
4761
+ return names;
4762
+ }
4763
+ /** The arrows as arrows, which every keyboard prints them as. */
4764
+ const KEY_NAMES = {
4765
+ " ": "Space",
4766
+ ArrowUp: "↑",
4767
+ ArrowDown: "↓",
4768
+ ArrowLeft: "←",
4769
+ ArrowRight: "→"
4770
+ };
4771
+ function keyName(key) {
4772
+ return KEY_NAMES[key] ?? (key.length === 1 ? key.toUpperCase() : key);
4773
+ }
4774
+ /** What a screen reader should say for a key it would read as a symbol, or skip. */
4775
+ const SPOKEN_KEYS = {
4776
+ " ": "Space",
4777
+ ArrowUp: "Up arrow",
4778
+ ArrowDown: "Down arrow",
4779
+ ArrowLeft: "Left arrow",
4780
+ ArrowRight: "Right arrow",
4781
+ PageUp: "Page up",
4782
+ PageDown: "Page down",
4783
+ "?": "Question mark",
4784
+ "/": "Slash",
4785
+ "\\": "Backslash",
4786
+ ".": "Period",
4787
+ ",": "Comma",
4788
+ ";": "Semicolon",
4789
+ ":": "Colon",
4790
+ "'": "Apostrophe",
4791
+ "`": "Backtick",
4792
+ "[": "Left bracket",
4793
+ "]": "Right bracket",
4794
+ "-": "Minus",
4795
+ "=": "Equals",
4796
+ "+": "Plus"
4797
+ };
4798
+ /** A letter as typed when it's pressed alone (`j`), and as its cap after a modifier (`Command K`). */
4799
+ function spokenKey(key, modified) {
4800
+ return SPOKEN_KEYS[key] ?? (key.length === 1 && !modified ? key : keyName(key));
4616
4801
  }
4617
4802
  function defaultClock() {
4618
4803
  return typeof performance !== "undefined" ? performance.now() : Date.now();
@@ -4656,6 +4841,8 @@ var UiDragSession = class {
4656
4841
  zones = [];
4657
4842
  current = null;
4658
4843
  inside = null;
4844
+ /** Every zone the point is in that would take the payload, winner or not. */
4845
+ hovering = /* @__PURE__ */ new Set();
4659
4846
  /** Registers a drop target. The returned function unregisters it. */
4660
4847
  addZone(zone) {
4661
4848
  this.zones.push(zone);
@@ -4719,6 +4906,7 @@ var UiDragSession = class {
4719
4906
  }
4720
4907
  const effect = zone.drop(state);
4721
4908
  zone.leave();
4909
+ this.unhover();
4722
4910
  return {
4723
4911
  node: zone.node,
4724
4912
  effect
@@ -4729,6 +4917,12 @@ var UiDragSession = class {
4729
4917
  this.inside?.leave();
4730
4918
  this.inside = null;
4731
4919
  this.current = null;
4920
+ this.unhover();
4921
+ }
4922
+ /** Tells every zone the drag was hovering over that it no longer is. */
4923
+ unhover() {
4924
+ for (const zone of this.hovering) zone.hover?.(null);
4925
+ this.hovering.clear();
4732
4926
  }
4733
4927
  /**
4734
4928
  * Turns a shell's file-drop message into an ordinary drag.
@@ -4779,10 +4973,12 @@ var UiDragSession = class {
4779
4973
  if (state === null) return;
4780
4974
  let best = null;
4781
4975
  let bestDepth = -1;
4976
+ const containing = /* @__PURE__ */ new Set();
4782
4977
  for (const zone of this.zones) {
4783
4978
  if (!zone.accepts(state.payload)) continue;
4784
4979
  const box = zone.boxOf();
4785
4980
  if (box === null || !contains$1(box, state.x, state.y)) continue;
4981
+ containing.add(zone);
4786
4982
  const depth = depthOf(zone.node);
4787
4983
  if (depth > bestDepth) {
4788
4984
  best = zone;
@@ -4793,9 +4989,10 @@ var UiDragSession = class {
4793
4989
  this.inside?.leave();
4794
4990
  this.inside = best;
4795
4991
  best?.enter(state);
4796
- return;
4797
- }
4798
- best?.over(state);
4992
+ } else best?.over(state);
4993
+ for (const zone of this.hovering) if (!containing.has(zone)) zone.hover?.(null);
4994
+ for (const zone of containing) zone.hover?.(state);
4995
+ this.hovering = containing;
4799
4996
  }
4800
4997
  };
4801
4998
  function contains$1(box, x, y) {
@@ -5007,7 +5204,7 @@ function ringShapes(options) {
5007
5204
  * costs nothing here because the options of a focus ring do not
5008
5205
  * change while it is attached.
5009
5206
  */
5010
- const kind$3 = defineModifier({
5207
+ const kind$4 = defineModifier({
5011
5208
  name: "focusRing",
5012
5209
  attach(host, options) {
5013
5210
  const shapes = ringShapes(options);
@@ -5018,7 +5215,7 @@ const kind$3 = defineModifier({
5018
5215
  host.onFocusChange(sync);
5019
5216
  }
5020
5217
  });
5021
- const DEFAULT_RING = kind$3(Object.freeze({}));
5218
+ const DEFAULT_RING = kind$4(Object.freeze({}));
5022
5219
  /**
5023
5220
  * The ring, with the theme's own colour and spacing.
5024
5221
  *
@@ -5029,7 +5226,7 @@ const DEFAULT_RING = kind$3(Object.freeze({}));
5029
5226
  * attachment.
5030
5227
  */
5031
5228
  function focusRing(options) {
5032
- return options === void 0 ? DEFAULT_RING : kind$3(options);
5229
+ return options === void 0 ? DEFAULT_RING : kind$4(options);
5033
5230
  }
5034
5231
  /**
5035
5232
  * A border per edge, as paint rather than as layout.
@@ -5138,24 +5335,62 @@ function borderShapes(options) {
5138
5335
  //#endregion
5139
5336
  //#region src/modifiers/focus.ts
5140
5337
  /**
5141
- * One shared instance, so the arguments keep their identity across
5142
- * renders and the modifier is never detached and re-attached (which
5143
- * would autofocus a second time).
5338
+ * Takes focus the first time the node is laid out.
5339
+ *
5340
+ * The one a dialog needs: an overlay that opens with the caret already
5341
+ * in its first field, without the component that opened it reaching
5342
+ * for a `ref` and a focus store.
5343
+ *
5344
+ * **Why the first layout and not the attach.** A modifier attaches
5345
+ * while its node is still being built, before the builder inserts it
5346
+ * into its parent, so at attach time the node has no parent and is not
5347
+ * under the focus manager's traversal root. `UiFocusManager.focus`
5348
+ * would accept it anyway (it asks whether the node is focusable, not
5349
+ * where it is), and the result would be a focused node that Tab cannot
5350
+ * reach and that no ancestor sees the focus event from. The first
5351
+ * layout is the first moment the node is demonstrably on screen, and
5352
+ * it is the same frame in every case that matters, because a node
5353
+ * mounted into a live tree is laid out on the frame that mounted it.
5354
+ *
5355
+ * It fires once. A node that is autofocused, loses focus to something
5356
+ * the person clicked, and is then laid out again does not steal the
5357
+ * focus back; that would make an autofocus a focus trap.
5358
+ *
5359
+ * A node that cannot take focus is left alone and no error is raised:
5360
+ * `focus()` refuses a node that is inert, not focusable, or outside an
5361
+ * active focus scope, which is exactly the set of cases where an
5362
+ * application would not want the focus moved either.
5144
5363
  */
5145
- const AUTO_FOCUS = defineModifier({
5364
+ const kind$3 = defineModifier({
5146
5365
  name: "autoFocus",
5147
- attach(host) {
5366
+ attach(host, options) {
5148
5367
  let done = false;
5149
5368
  host.onLayout(() => {
5150
5369
  if (done) return;
5151
5370
  done = true;
5152
- host.focus();
5371
+ host.focus(options);
5153
5372
  });
5154
5373
  }
5155
- })(void 0);
5156
- /** Takes focus the first time the node is laid out. */
5157
- function autoFocus() {
5158
- return AUTO_FOCUS;
5374
+ });
5375
+ /**
5376
+ * One shared instance of each, so the arguments keep their identity
5377
+ * across renders and the modifier is never detached and re-attached
5378
+ * (which would autofocus a second time).
5379
+ */
5380
+ const AUTO_FOCUS = kind$3({});
5381
+ const AUTO_FOCUS_IN_PLACE = kind$3({ preventScroll: true });
5382
+ /**
5383
+ * Takes focus the first time the node is laid out.
5384
+ *
5385
+ * The node is scrolled into view, as focus from code always is, once
5386
+ * the frame's layout has settled. Pass `{ preventScroll: true }` to
5387
+ * leave the page where it is, as `element.focus({ preventScroll: true })`
5388
+ * does: for a region focused when a page opens so a screen reader reads
5389
+ * it, where revealing it would scroll a tall region to a few pixels
5390
+ * short of its own top instead of leaving the page at its start.
5391
+ */
5392
+ function autoFocus(options = {}) {
5393
+ return options.preventScroll === true ? AUTO_FOCUS_IN_PLACE : AUTO_FOCUS;
5159
5394
  }
5160
5395
  //#endregion
5161
5396
  //#region src/modifiers/clickOutside.ts
@@ -5485,13 +5720,20 @@ var DropTarget = class {
5485
5720
  x: state.x,
5486
5721
  y: state.y
5487
5722
  });
5488
- this.updateAutoScroll(state);
5489
5723
  }
5490
5724
  leave() {
5491
5725
  for (const property of Object.keys(this.options.over ?? {})) this.host.clear(property);
5492
- this.stopScrolling();
5493
5726
  this.options.onLeave?.();
5494
5727
  }
5728
+ /**
5729
+ * Auto-scroll follows the point being inside this zone, not this zone
5730
+ * winning the drop: a list covered in row zones is never the winner,
5731
+ * and still has to scroll when a card is held at its edge.
5732
+ */
5733
+ hover(state) {
5734
+ if (state === null) this.stopScrolling();
5735
+ else this.updateAutoScroll(state);
5736
+ }
5495
5737
  drop(state) {
5496
5738
  return this.options.onDrop(state.payload, {
5497
5739
  x: state.x,
@@ -6780,15 +7022,15 @@ var SharedElementController = class {
6780
7022
  *
6781
7023
  * Held rather than called on arrival: see `UiSharedElements.claim`.
6782
7024
  * Between claiming a name and taking the departing element's place
6783
- * there is at least one layout, and for a geometry morph a whole
6784
- * frame — and hiding it up front makes that a frame with neither
6785
- * element on screen, which reads as a flash of the page behind them.
7025
+ * there is at least one layout pass — and hiding it up front, on a
7026
+ * frame painted between the two, would leave neither element on
7027
+ * screen, which reads as a flash of the page behind them.
6786
7028
  */
6787
7029
  yieldPrevious = null;
6788
7030
  yielded = false;
6789
7031
  /** Whether a morph is running, so `onMorph` is never told twice. */
6790
7032
  morphing = false;
6791
- /** Set for the one frame a geometry morph spends being measured. */
7033
+ /** Set between a geometry morph writing its first box and that box being laid out. */
6792
7034
  geometryTarget = null;
6793
7035
  constructor(host, args) {
6794
7036
  this.host = host;
@@ -8294,6 +8536,40 @@ function onDeviceLost(listener) {
8294
8536
  onDeviceLostListeners.delete(listener);
8295
8537
  };
8296
8538
  }
8539
+ //#endregion
8540
+ //#region src/rendering/webgpu/WebGPUShader.ts
8541
+ /**
8542
+ * WGSL sources for the two WebGPU pipelines.
8543
+ *
8544
+ * Both draw one unit quad per instance. An instance carries the
8545
+ * rectangle it covers in absolute layout coordinates and the affine
8546
+ * transform that maps those coordinates to logical screen pixels, so
8547
+ * every instance under one node shares the node's transform and the
8548
+ * rectangle is honest — a scrollbar thumb sits where its geometry says.
8549
+ *
8550
+ * Clipping is two-layered. The rectangular part is a scissor set per
8551
+ * draw command. The rounded part is a **clip chain**: a storage buffer
8552
+ * of clipping boxes with corner radii, each holding its parent's index
8553
+ * and the inverse of its own transform. An instance names its
8554
+ * innermost rounded clip; the fragment shader carries the pixel back
8555
+ * into each clip's space up the chain and multiplies their coverages,
8556
+ * so every rounded ancestor applies.
8557
+ *
8558
+ * Edges are anti-aliased by coverage rather than cut by `discard`: a
8559
+ * pixel's alpha is scaled by how far its centre sits inside the shape,
8560
+ * in physical pixels. A box on integer coordinates is still crisp —
8561
+ * every pixel centre is half a pixel from its edge — and rounded
8562
+ * corners match the anti-aliased paths Canvas2D draws.
8563
+ *
8564
+ * A box shadow is a primitive too, drawn analytically: the coverage of
8565
+ * a Gaussian-blurred rounded rectangle is integrated in closed form
8566
+ * across one axis (an error function) and sampled along the other, as
8567
+ * in Evan Wallace's "Fast rounded rectangle shadows". It is exact for
8568
+ * square corners and within a fraction of a percent for round ones,
8569
+ * which is closer than browsers' own blur gets to a Gaussian.
8570
+ */
8571
+ /** Mirrors `BOX_SHADOW_BLUR_REACH`: a shadow's quad reaches this many blur radii past its shape. */
8572
+ const SHADOW_REACH = BOX_SHADOW_BLUR_REACH;
8297
8573
  const SHARED = `
8298
8574
  // x: logical width, y: logical height, z: device pixel ratio.
8299
8575
  @group(0) @binding(0) var<uniform> uView: vec4f;
@@ -8438,6 +8714,86 @@ fn gradientColor(index: u32, local: vec2f) -> vec4f {
8438
8714
  return unpremultiply(previousColor);
8439
8715
  }
8440
8716
 
8717
+ // PrimitiveKind: 0 fill, 1 border, 2 shadow, 3 inset shadow.
8718
+ const KIND_BORDER = 1u;
8719
+ const KIND_SHADOW = 2u;
8720
+ const SHADOW_REACH = ${SHADOW_REACH};
8721
+
8722
+ // Abramowitz and Stegun's approximation, to about 5e-4, for two values.
8723
+ fn erf2(x: vec2f) -> vec2f {
8724
+ let s = sign(x);
8725
+ let a = abs(x);
8726
+ var t = 1.0 + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a;
8727
+ t = t * t;
8728
+ return s - s / (t * t);
8729
+ }
8730
+
8731
+ fn gaussian(x: f32, sigma: f32) -> f32 {
8732
+ return exp(-(x * x) / (2.0 * sigma * sigma)) / (2.5066283 * sigma);
8733
+ }
8734
+
8735
+ // The blurred shape's coverage along x at one height y, both relative
8736
+ // to its centre: an error function across the row the rounded corner
8737
+ // leaves at that height.
8738
+ fn shadowRow(x: f32, y: f32, sigma: f32, corner: f32, halfSize: vec2f) -> f32 {
8739
+ let delta = min(halfSize.y - corner - abs(y), 0.0);
8740
+ let curved = halfSize.x - corner + sqrt(max(0.0, corner * corner - delta * delta));
8741
+ let integral = 0.5 + 0.5 * erf2((x + vec2f(-curved, curved)) * (0.70710678 / sigma));
8742
+ return integral.y - integral.x;
8743
+ }
8744
+
8745
+ // Coverage at a point of a rounded rectangle blurred by a Gaussian of
8746
+ // the given standard deviation. The row integral is weighted by the
8747
+ // Gaussian over the three deviations either side that it reaches.
8748
+ fn blurredRoundedRect(point: vec2f, origin: vec2f, size: vec2f, radius: f32, sigma: f32, dpr: f32) -> f32 {
8749
+ if (size.x <= 0.0 || size.y <= 0.0) {
8750
+ return 0.0;
8751
+ }
8752
+ if (sigma * dpr < 0.25) {
8753
+ // Under a quarter of a device pixel: the sharp shape, anti-aliased.
8754
+ return coverage(roundedRectDistance(point, origin, size, radius), dpr);
8755
+ }
8756
+ let halfSize = size * 0.5;
8757
+ let corner = min(radius, min(halfSize.x, halfSize.y));
8758
+ let p = point - (origin + halfSize);
8759
+ let low = p.y - halfSize.y;
8760
+ let high = p.y + halfSize.y;
8761
+ let first = clamp(-3.0 * sigma, low, high);
8762
+ let last = clamp(3.0 * sigma, low, high);
8763
+ let stride = (last - first) / 4.0;
8764
+ var y = first + stride * 0.5;
8765
+ var value = 0.0;
8766
+ for (var i = 0; i < 4; i = i + 1) {
8767
+ value = value + shadowRow(p.x, p.y - y, sigma, corner, halfSize) * gaussian(y, sigma) * stride;
8768
+ y = y + stride;
8769
+ }
8770
+ return clamp(value, 0.0, 1.0);
8771
+ }
8772
+
8773
+ // A shadow's alpha at a point of its quad; see the instance layout in
8774
+ // WebGPURenderData.ts for what each field holds.
8775
+ fn shadowAlpha(kind: u32, local: vec2f, size: vec2f, radius: f32, blur: f32, shadow: vec4f, dpr: f32) -> f32 {
8776
+ let sigma = blur * 0.5;
8777
+ let offset = shadow.xy;
8778
+ let spread = shadow.z;
8779
+ if (kind == KIND_SHADOW) {
8780
+ // The quad is the blurred shape grown by the blur's reach; the box
8781
+ // sits back by the offset and in by the spread, and hides it.
8782
+ let reach = blur * SHADOW_REACH;
8783
+ let shapeOrigin = vec2f(reach, reach);
8784
+ let shapeSize = size - vec2f(reach, reach) * 2.0;
8785
+ let boxOrigin = shapeOrigin - offset + vec2f(spread, spread);
8786
+ let boxSize = shapeSize - vec2f(spread, spread) * 2.0;
8787
+ let blurred = blurredRoundedRect(local, shapeOrigin, shapeSize, radius, sigma, dpr);
8788
+ return blurred * (1.0 - coverage(roundedRectDistance(local, boxOrigin, boxSize, shadow.w), dpr));
8789
+ }
8790
+ // Inset: the quad is the box; everything but the blurred hole is shadow.
8791
+ let holeOrigin = offset + vec2f(spread, spread);
8792
+ let holeSize = size - vec2f(spread, spread) * 2.0;
8793
+ let inside = coverage(roundedRectDistance(local, vec2f(0.0, 0.0), size, radius), dpr);
8794
+ return inside * (1.0 - blurredRoundedRect(local, holeOrigin, holeSize, shadow.w, sigma, dpr));
8795
+ }
8796
+
8441
8797
  struct VertexOutput {
8442
8798
  @builtin(position) position: vec4f,
8443
8799
  @location(0) localPos: vec2f,
@@ -8447,6 +8803,7 @@ struct VertexOutput {
8447
8803
  @location(4) @interpolate(flat) kind: u32,
8448
8804
  @location(5) @interpolate(flat) clipIndex: f32,
8449
8805
  @location(6) @interpolate(flat) gradientIndex: f32,
8806
+ @location(7) @interpolate(flat) shadow: vec4f,
8450
8807
  };
8451
8808
 
8452
8809
  @vertex
@@ -8456,12 +8813,13 @@ fn vs(
8456
8813
  @location(2) instanceSize: vec2f,
8457
8814
  @location(3) instanceColor: vec4f,
8458
8815
  @location(4) radiusOpacityBorder: vec3f,
8459
- @location(5) instanceKind: u32,
8816
+ @location(5) instanceKind: f32,
8460
8817
  @location(6) transformA: vec2f,
8461
8818
  @location(7) transformB: vec2f,
8462
8819
  @location(8) transformC: vec2f,
8463
8820
  @location(9) clipIndex: f32,
8464
8821
  @location(10) gradientIndex: f32,
8822
+ @location(11) shadow: vec4f,
8465
8823
  ) -> VertexOutput {
8466
8824
  var out: VertexOutput;
8467
8825
  // The quad is inflated by one physical pixel on every side so the
@@ -8480,9 +8838,10 @@ fn vs(
8480
8838
  out.size = instanceSize;
8481
8839
  out.color = instanceColor;
8482
8840
  out.radiusOpacityBorder = radiusOpacityBorder;
8483
- out.kind = instanceKind;
8841
+ out.kind = u32(instanceKind + 0.5);
8484
8842
  out.clipIndex = clipIndex;
8485
8843
  out.gradientIndex = gradientIndex;
8844
+ out.shadow = shadow;
8486
8845
  return out;
8487
8846
  }
8488
8847
 
@@ -8492,7 +8851,17 @@ fn fs(in: VertexOutput) -> @location(0) vec4f {
8492
8851
  let dist = roundedRectDistance(in.localPos, vec2f(0.0, 0.0), in.size, in.radiusOpacityBorder.x);
8493
8852
 
8494
8853
  var shape = coverage(dist, dpr);
8495
- if (in.kind != 0u) {
8854
+ if (in.kind >= KIND_SHADOW) {
8855
+ shape = shadowAlpha(
8856
+ in.kind,
8857
+ in.localPos,
8858
+ in.size,
8859
+ in.radiusOpacityBorder.x,
8860
+ in.radiusOpacityBorder.z,
8861
+ in.shadow,
8862
+ dpr
8863
+ );
8864
+ } else if (in.kind == KIND_BORDER) {
8496
8865
  // Border: the band between the outer edge and the inner edge inset
8497
8866
  // by borderWidth.
8498
8867
  let bw = max(in.radiusOpacityBorder.z, 0.0);
@@ -9319,14 +9688,25 @@ function createWebGPUSurface(host) {
9319
9688
  * 2 size.xy
9320
9689
  * 4 color.rgba
9321
9690
  * 8 radius, opacity, borderWidth
9322
- * 11 kind (u32: PrimitiveKind)
9691
+ * 11 kind (PrimitiveKind, as a float)
9323
9692
  * 12 transform 3x2 affine, absolute layout → logical screen
9324
9693
  * 18 clipIndex index into the clip chain, -1 for none
9325
9694
  * 19 gradientIndex index into the frame's gradients, -1 for none
9326
- * 20 (end)
9327
- */
9328
- const INSTANCE_STRIDE_FLOATS = 20;
9329
- const INSTANCE_STRIDE_BYTES = 80;
9695
+ * 20 shadow offsetX, offsetY, spread, the other shape's radius
9696
+ * 24 (end)
9697
+ *
9698
+ * A shadow is two rounded rectangles, the blurred one and the box it
9699
+ * is cut by, and an instance describes the first. For an outer shadow
9700
+ * the rectangle is the blurred shape grown by the blur's reach
9701
+ * (`BOX_SHADOW_BLUR_REACH` × blur), `radius` its corners, `borderWidth`
9702
+ * the blur, and the box it must not show under is recovered from the
9703
+ * offset and spread, with the box's own radius last. An inset shadow's
9704
+ * rectangle is the box, and the hole it is cast from is the box moved
9705
+ * by the offset and shrunk by the spread, with the hole's radius last.
9706
+ * Every other instance writes zeros there.
9707
+ */
9708
+ const INSTANCE_STRIDE_FLOATS = 24;
9709
+ const INSTANCE_STRIDE_BYTES = 96;
9330
9710
  /**
9331
9711
  * Textured instance layout (glyphs and images), in floats:
9332
9712
  *
@@ -9362,6 +9742,10 @@ const NO_CLIP_INDEX = -1;
9362
9742
  let PrimitiveKind = /* @__PURE__ */ function(PrimitiveKind) {
9363
9743
  PrimitiveKind[PrimitiveKind["Fill"] = 0] = "Fill";
9364
9744
  PrimitiveKind[PrimitiveKind["Border"] = 1] = "Border";
9745
+ /** A `boxShadows` entry outside the box; see the instance layout. */
9746
+ PrimitiveKind[PrimitiveKind["Shadow"] = 2] = "Shadow";
9747
+ /** A `boxShadows` entry marked `inset`. */
9748
+ PrimitiveKind[PrimitiveKind["InsetShadow"] = 3] = "InsetShadow";
9365
9749
  return PrimitiveKind;
9366
9750
  }({});
9367
9751
  let CommandKind = /* @__PURE__ */ function(CommandKind) {
@@ -9435,7 +9819,7 @@ var FloatBuffer = class {
9435
9819
  return this.data.slice(0, this.length);
9436
9820
  }
9437
9821
  };
9438
- const instanceScratch = new FloatBuffer(10240);
9822
+ const instanceScratch = new FloatBuffer(12288);
9439
9823
  const texturedScratch = new FloatBuffer(32768);
9440
9824
  const clipScratch = new FloatBuffer(1024);
9441
9825
  const gradientScratch = new FloatBuffer(768);
@@ -9488,7 +9872,7 @@ function buildRenderList(root, layout, measurer, logicalWidth, logicalHeight, dp
9488
9872
  /** The nodes asking for `lift`, met on the walk and drawn after it. */
9489
9873
  const liftedPass = [];
9490
9874
  function closePrimitives() {
9491
- const end = instanceData.length / 20;
9875
+ const end = instanceData.length / 24;
9492
9876
  if (end > openStart) commands.push({
9493
9877
  kind: 0,
9494
9878
  start: openStart,
@@ -9498,7 +9882,7 @@ function buildRenderList(root, layout, measurer, logicalWidth, logicalHeight, dp
9498
9882
  openStart = end;
9499
9883
  }
9500
9884
  function beginPrimitives(scissor) {
9501
- if (openStart === instanceData.length / 20) {
9885
+ if (openStart === instanceData.length / 24) {
9502
9886
  openScissor = scissor;
9503
9887
  return;
9504
9888
  }
@@ -9612,7 +9996,7 @@ function buildRenderList(root, layout, measurer, logicalWidth, logicalHeight, dp
9612
9996
  return;
9613
9997
  }
9614
9998
  const sticky = rec.stickyOffsetX !== 0 || rec.stickyOffsetY !== 0;
9615
- if (state.cull !== null && !intersectsCull(state.cull, rec.x + rec.stickyOffsetX, rec.y + rec.stickyOffsetY, rec.width, rec.height)) return;
9999
+ if (state.cull !== null && !intersectsCull(state.cull, rec.extentMinX + rec.stickyOffsetX, rec.extentMinY + rec.stickyOffsetY, rec.extentMaxX - rec.extentMinX, rec.extentMaxY - rec.extentMinY)) return;
9616
10000
  const paint = resolvePaintState(node, paintScratch);
9617
10001
  const effectiveOpacity = state.opacity * paint.opacity;
9618
10002
  const baseCtm = sticky ? translateTransform(state.ctm, rec.stickyOffsetX, rec.stickyOffsetY) : state.ctm;
@@ -9637,6 +10021,10 @@ function buildRenderList(root, layout, measurer, logicalWidth, logicalHeight, dp
9637
10021
  }
9638
10022
  const contentScissor = nextClip;
9639
10023
  const contentRounded = nextRounded;
10024
+ if (paint.boxShadows.length > 0) {
10025
+ beginPrimitives(ownScissor);
10026
+ pushShadows(instanceData, rec, paint, effectiveOpacity, nodeCtm, ownRounded, false);
10027
+ }
9640
10028
  if (paint.backgroundColor !== void 0) {
9641
10029
  const color = parseColor$1(paint.backgroundColor);
9642
10030
  if (color !== void 0) {
@@ -9652,6 +10040,10 @@ function buildRenderList(root, layout, measurer, logicalWidth, logicalHeight, dp
9652
10040
  pushInstance(instanceData, rec.x, rec.y, rec.width, rec.height, first, uniformBorderRadius(paint.borderRadius), effectiveOpacity, 0, 0, nodeCtm, ownRounded, index);
9653
10041
  }
9654
10042
  }
10043
+ if (paint.boxShadows.length > 0) {
10044
+ beginPrimitives(ownScissor);
10045
+ pushShadows(instanceData, rec, paint, effectiveOpacity, nodeCtm, ownRounded, true);
10046
+ }
9655
10047
  const textureSource = paint.video !== void 0 && paint.video.frame !== null ? paint.video : paint.image;
9656
10048
  if (textureSource !== void 0) {
9657
10049
  const sourceSize = paint.video !== void 0 && paint.video.frame !== null ? videoFrameSize(paint.video) : {
@@ -9766,7 +10158,7 @@ function buildRenderList(root, layout, measurer, logicalWidth, logicalHeight, dp
9766
10158
  state.rounded = nextRounded;
9767
10159
  if (rec.clips && state.cull !== null) state.cull = pushCull(state.cull, rec);
9768
10160
  if (paint.hasTransform || sticky) state.cull = null;
9769
- if (rec.scrollable) state.ctm = translateTransform(state.ctm, -rec.scrollX, -rec.scrollY);
10161
+ if (rec.scrollable) state.ctm = translateTransform(state.ctm, -snapScroll(rec.scrollX, dpr), -snapScroll(rec.scrollY, dpr));
9770
10162
  liftedFrom = liftedPass.length;
9771
10163
  visitChildren(node, rec.paintOrder);
9772
10164
  state.opacity = saved.opacity;
@@ -9821,9 +10213,10 @@ function buildRenderList(root, layout, measurer, logicalWidth, logicalHeight, dp
9821
10213
  const model = text.editor;
9822
10214
  const editable = new EditableLayout(model, contentBox, text, measurer);
9823
10215
  pushTextRects(textRunBackgrounds(editable.lines, text));
9824
- if (model.focused && !model.collapsed) {
10216
+ const spanned = text.textSelection;
10217
+ if (spanned !== void 0 || model.focused && !model.collapsed) {
9825
10218
  const selection = parseColor$1(text.selectionColor);
9826
- if (selection !== void 0) for (const box of editable.selectionBoxes()) pushContentRect(box, selection);
10219
+ if (selection !== void 0) for (const box of editable.selectionBoxes(spanned)) pushContentRect(box, selection);
9827
10220
  }
9828
10221
  if (editable.placeholderLines.length > 0) pushTextRun(editable.placeholderLines, colorToCss(text.placeholderColor));
9829
10222
  else {
@@ -9842,7 +10235,7 @@ function buildRenderList(root, layout, measurer, logicalWidth, logicalHeight, dp
9842
10235
  }, underline);
9843
10236
  }
9844
10237
  }
9845
- if (model.focused && model.collapsed && caretVisibleAt(model, now)) {
10238
+ if (spanned === void 0 && model.focused && model.collapsed && caretVisibleAt(model, now)) {
9846
10239
  const caretColor = parseColor$1(text.caretColor);
9847
10240
  if (caretColor !== void 0) {
9848
10241
  const caret = editable.caretRect();
@@ -9976,7 +10369,7 @@ function buildRenderList(root, layout, measurer, logicalWidth, logicalHeight, dp
9976
10369
  closePrimitives();
9977
10370
  return {
9978
10371
  instanceData: instanceData.take(),
9979
- instanceCount: instanceData.length / 20,
10372
+ instanceCount: instanceData.length / 24,
9980
10373
  texturedData: texturedData.take(),
9981
10374
  texturedCount: texturedData.length / 16,
9982
10375
  clipData: clipData.take(),
@@ -10024,8 +10417,8 @@ function pushScrollbars(out, rec, opacity, transform, rounded, now) {
10024
10417
  pushInstance(out, x, y, width, height, color, 3, opacity, 0, 0, transform, rounded);
10025
10418
  }
10026
10419
  }
10027
- function pushInstance(out, x, y, width, height, color, radius, opacity, borderWidth, kind, transform, clip, gradient = -1) {
10028
- out.ensure(20);
10420
+ function pushInstance(out, x, y, width, height, color, radius, opacity, borderWidth, kind, transform, clip, gradient = -1, shadowX = 0, shadowY = 0, shadowSpread = 0, shadowRadius = 0) {
10421
+ out.ensure(24);
10029
10422
  const data = out.data;
10030
10423
  const at = out.length;
10031
10424
  data[at] = x;
@@ -10048,7 +10441,38 @@ function pushInstance(out, x, y, width, height, color, radius, opacity, borderWi
10048
10441
  data[at + 17] = transform[5];
10049
10442
  data[at + 18] = clip;
10050
10443
  data[at + 19] = gradient;
10051
- out.length = at + 20;
10444
+ data[at + 20] = shadowX;
10445
+ data[at + 21] = shadowY;
10446
+ data[at + 22] = shadowSpread;
10447
+ data[at + 23] = shadowRadius;
10448
+ out.length = at + 24;
10449
+ }
10450
+ /**
10451
+ * One instance per outer shadow, or per inset one, in the order
10452
+ * Canvas2D draws them: the last declared first, since CSS paints the
10453
+ * first shadow on top. The shader evaluates the blurred shape exactly
10454
+ * rather than sampling a blurred texture, so a shadow costs a quad.
10455
+ */
10456
+ function pushShadows(out, rec, paint, opacity, transform, clip, inset) {
10457
+ const shadows = paint.boxShadows;
10458
+ const radius = borderRadiusIsZero(paint.borderRadius) ? 0 : uniformBorderRadius(paint.borderRadius);
10459
+ for (let i = shadows.length - 1; i >= 0; i--) {
10460
+ const shadow = shadows[i];
10461
+ if (shadow.inset === true !== inset || shadow.color.a <= 0) continue;
10462
+ const color = parseColor$1(shadow.color);
10463
+ if (color === void 0) continue;
10464
+ const blur = Math.max(0, shadow.blurRadius);
10465
+ const spread = shadow.spreadRadius;
10466
+ if (inset) {
10467
+ pushInstance(out, rec.x, rec.y, rec.width, rec.height, color, radius, opacity, blur, 3, transform, clip, -1, shadow.offsetX, shadow.offsetY, spread, boxShadowRadius(radius, spread, true));
10468
+ continue;
10469
+ }
10470
+ const width = rec.width + spread * 2;
10471
+ const height = rec.height + spread * 2;
10472
+ if (width <= 0 || height <= 0) continue;
10473
+ const reach = blur * BOX_SHADOW_BLUR_REACH;
10474
+ pushInstance(out, rec.x + shadow.offsetX - spread - reach, rec.y + shadow.offsetY - spread - reach, width + reach * 2, height + reach * 2, color, boxShadowRadius(radius, spread, false), opacity, blur, 2, transform, clip, -1, shadow.offsetX, shadow.offsetY, spread, radius);
10475
+ }
10052
10476
  }
10053
10477
  /**
10054
10478
  * Writes one gradient record for a rectangle of the given size and
@@ -10503,7 +10927,7 @@ function quadVertexLayout() {
10503
10927
  /** Mirrors the float layout documented on INSTANCE_STRIDE_FLOATS. */
10504
10928
  function primitiveInstanceLayout() {
10505
10929
  return {
10506
- arrayStride: 80,
10930
+ arrayStride: 96,
10507
10931
  stepMode: "instance",
10508
10932
  attributes: [
10509
10933
  {
@@ -10529,7 +10953,7 @@ function primitiveInstanceLayout() {
10529
10953
  {
10530
10954
  shaderLocation: 5,
10531
10955
  offset: 44,
10532
- format: "uint32"
10956
+ format: "float32"
10533
10957
  },
10534
10958
  {
10535
10959
  shaderLocation: 6,
@@ -10555,6 +10979,11 @@ function primitiveInstanceLayout() {
10555
10979
  shaderLocation: 10,
10556
10980
  offset: 76,
10557
10981
  format: "float32"
10982
+ },
10983
+ {
10984
+ shaderLocation: 11,
10985
+ offset: 80,
10986
+ format: "float32x4"
10558
10987
  }
10559
10988
  ]
10560
10989
  };
@@ -11022,7 +11451,7 @@ var WebGPURenderer = class {
11022
11451
  glyphPages.flush();
11023
11452
  const uploadStart = this.hooks.onUploadStart !== void 0 || this.hooks.onUploadEnd !== void 0 ? performance.now() : 0;
11024
11453
  if (list.instanceCount > 0) {
11025
- const buffer = this.ensureBuffer(this.instanceBuffer, list.instanceData.byteLength, 80);
11454
+ const buffer = this.ensureBuffer(this.instanceBuffer, list.instanceData.byteLength, 96);
11026
11455
  if (buffer !== this.instanceBuffer) {
11027
11456
  this.instanceBuffer = buffer;
11028
11457
  this.cachedInstanceData = null;
@@ -13470,7 +13899,7 @@ function markNow() {
13470
13899
  * frame is collected, so a node dirtied again while the frame
13471
13900
  * is being processed belongs to the next frame.
13472
13901
  */
13473
- var UiFrame = class {
13902
+ var UiFrame = class UiFrame {
13474
13903
  id;
13475
13904
  time;
13476
13905
  dirty;
@@ -13516,6 +13945,21 @@ var UiFrame = class {
13516
13945
  for (const value of this.dirty.values()) if ((value & flags) !== 0) return true;
13517
13946
  return false;
13518
13947
  }
13948
+ /**
13949
+ * This frame and `later` as one: every node in either, with the
13950
+ * flags it carried in both.
13951
+ *
13952
+ * What the phases after layout read when layout ran more than once
13953
+ * in a frame (see `UiScheduler.recollect`): a node dirtied by a
13954
+ * layout listener has to be re-meant and redrawn like any other
13955
+ * node the frame changed.
13956
+ */
13957
+ merged(later) {
13958
+ if (later.isEmpty()) return this;
13959
+ const dirty = new Map(this.dirty);
13960
+ for (const [node, flags] of later.entries()) dirty.set(node, (dirty.get(node) ?? 0) | flags);
13961
+ return new UiFrame(this.id, this.time, dirty);
13962
+ }
13519
13963
  get size() {
13520
13964
  return this.dirty.size;
13521
13965
  }
@@ -13652,6 +14096,32 @@ var UiScheduler = class {
13652
14096
  this.handleFrame(time);
13653
14097
  }
13654
14098
  /**
14099
+ * Takes what was dirtied since `frame` was collected into that same
14100
+ * frame, rather than leaving it for the next one.
14101
+ *
14102
+ * For a phase that has to finish inside the frame what the frame
14103
+ * started. A layout listener (a `breakpoint`, a `sizeContainer`)
14104
+ * that writes padding after the boxes are final has made those boxes
14105
+ * stale, and painting them would show the stale layout for one frame
14106
+ * before the next corrects it. The runtime lays the writes out again
14107
+ * from what this returns, before anything paints.
14108
+ *
14109
+ * The result holds only the newly dirtied nodes, with `frame`'s id
14110
+ * and time: it is more of the same frame, not a new one, so the
14111
+ * frame count does not move. Anything armed by those writes finds
14112
+ * nothing left to do.
14113
+ */
14114
+ recollect(frame) {
14115
+ const count = this.dirty.drainInto(this.drained);
14116
+ const dirty = /* @__PURE__ */ new Map();
14117
+ for (let i = 0; i < count; i++) {
14118
+ const node = this.drained[i];
14119
+ dirty.set(node, node.dirtyFlags);
14120
+ node.dirtyFlags = 0;
14121
+ }
14122
+ return new UiFrame(frame.id, frame.time, dirty);
14123
+ }
14124
+ /**
13655
14125
  * Runs one frame, and names its three parts for the browser's
13656
14126
  * profiler when anything is recording (`PerformanceMarks`).
13657
14127
  *
@@ -14565,8 +15035,14 @@ const PRESENTATIONAL_CHILDREN = /* @__PURE__ */ new Set([
14565
15035
  * is, carrying `disabled` — unavailable is a thing to announce,
14566
15036
  * hidden is not.
14567
15037
  */
14568
- function buildSemanticsTree(root) {
14569
- return walk(root, null, false);
15038
+ function buildSemanticsTree(root, memory) {
15039
+ return walk(root, null, false, memory);
15040
+ }
15041
+ function semanticsMemory() {
15042
+ return {
15043
+ described: /* @__PURE__ */ new WeakSet(),
15044
+ spans: /* @__PURE__ */ new WeakMap()
15045
+ };
14570
15046
  }
14571
15047
  /**
14572
15048
  * The records one subtree contributes, as if walked in place.
@@ -14588,8 +15064,8 @@ function buildSemanticsTree(root) {
14588
15064
  * `inert` is whether an ancestor above this subtree is disabled, which
14589
15065
  * only the caller can know.
14590
15066
  */
14591
- function buildSemanticsSubtree(node, parent, index, inert) {
14592
- const records = walk(node, parent, inert);
15067
+ function buildSemanticsSubtree(node, parent, index, inert, memory) {
15068
+ const records = walk(node, parent, inert, memory);
14593
15069
  const own = records.get(node.id);
14594
15070
  if (own === void 0) return null;
14595
15071
  records.set(node.id, {
@@ -14598,26 +15074,129 @@ function buildSemanticsSubtree(node, parent, index, inert) {
14598
15074
  });
14599
15075
  return records;
14600
15076
  }
14601
- function walk(root, rootParent, rootInert) {
14602
- const records = /* @__PURE__ */ new Map();
15077
+ /**
15078
+ * Walks a subtree again after the shape of the tree changed inside it,
15079
+ * describing only what changed.
15080
+ *
15081
+ * A full walk asks every node what it means, and moves every record
15082
+ * whose siblings moved. After a block is inserted in a long document
15083
+ * nearly every node means what it did. So a record `reuse.unchanged`
15084
+ * vouches for is taken back as it was, and an untouched transparent
15085
+ * subtree (one with no record of its own, like a block of the document)
15086
+ * is taken back as the run of its parent's children it contributed last
15087
+ * time, without being walked into. Nothing taken back is renumbered:
15088
+ * the caller learns where everything went from `children` and `placed`.
15089
+ *
15090
+ * `node` has to carry a record, as for `buildSemanticsSubtree`; null
15091
+ * otherwise.
15092
+ */
15093
+ function rewalkSemantics(node, parent, index, inert, reuse) {
15094
+ const result = {
15095
+ records: /* @__PURE__ */ new Map(),
15096
+ children: /* @__PURE__ */ new Map(),
15097
+ kept: /* @__PURE__ */ new Set(),
15098
+ placed: []
15099
+ };
15100
+ walk(node, parent, inert, reuse.memory, reuse, result);
15101
+ const own = result.records.get(node.id);
15102
+ if (own === void 0) return null;
15103
+ result.records.set(node.id, {
15104
+ ...own,
15105
+ index
15106
+ });
15107
+ result.placed[0] = {
15108
+ id: node.id,
15109
+ parent,
15110
+ index
15111
+ };
15112
+ return result;
15113
+ }
15114
+ function walk(root, rootParent, rootInert, memory, reuse, rewalk) {
15115
+ const records = rewalk?.records ?? /* @__PURE__ */ new Map();
14603
15116
  const childCounts = /* @__PURE__ */ new Map();
15117
+ /** Each parent's children so far, in order: for spans, and for a rewalk's result. */
15118
+ const given = rewalk?.children ?? /* @__PURE__ */ new Map();
15119
+ const placed = rewalk?.placed;
15120
+ const tracking = memory !== void 0 || rewalk !== void 0;
14604
15121
  const nextIndex = (parent) => {
14605
15122
  const index = childCounts.get(parent) ?? 0;
14606
15123
  childCounts.set(parent, index + 1);
14607
15124
  return index;
14608
15125
  };
15126
+ const note = (parent, id, index) => {
15127
+ if (!tracking) return;
15128
+ let list = given.get(parent);
15129
+ if (list === void 0) given.set(parent, list = []);
15130
+ list.push(id);
15131
+ placed?.push({
15132
+ id,
15133
+ parent,
15134
+ index
15135
+ });
15136
+ };
15137
+ /** Takes back a record nothing changed, subtree and all. */
15138
+ const keep = (id, parent) => {
15139
+ note(parent, id, nextIndex(parent));
15140
+ rewalk.kept.add(id);
15141
+ };
15142
+ /**
15143
+ * Takes back everything an untouched transparent node contributed, as
15144
+ * a run of its parent's old children, without walking into it. False
15145
+ * when its span can't be trusted, and it is walked.
15146
+ */
15147
+ const keepSpan = (node, parent) => {
15148
+ const span = memory.spans.get(node);
15149
+ if (span === void 0 || span.parent !== parent) return false;
15150
+ if (span.count === 0) return true;
15151
+ const at = span.first === null ? -1 : reuse.positionOf(parent, span.first);
15152
+ if (at < 0) return false;
15153
+ const ids = reuse.childrenOf(parent).slice(at, at + span.count);
15154
+ if (ids.length !== span.count) return false;
15155
+ for (const id of ids) keep(id, parent);
15156
+ return true;
15157
+ };
14609
15158
  const visit = (node, parent, inert) => {
14610
15159
  if (node.properties.get("visible") === false) return;
14611
15160
  const disabled = inert || node.properties.get("disabled") === true;
15161
+ if (reuse !== void 0 && node !== root && reuse.unchanged(node)) {
15162
+ if (memory.described.has(node) && reuse.previous.has(node.id)) {
15163
+ keep(node.id, parent);
15164
+ return;
15165
+ }
15166
+ if (keepSpan(node, parent)) return;
15167
+ }
14612
15168
  const record = describe(node, parent, disabled, nextIndex);
14613
15169
  if (record === null) {
15170
+ const start = childCounts.get(parent) ?? 0;
14614
15171
  for (let child = node.firstChild; child !== null; child = child.nextSibling) visit(child, parent, disabled);
15172
+ if (memory !== void 0) {
15173
+ const count = (childCounts.get(parent) ?? 0) - start;
15174
+ memory.spans.set(node, {
15175
+ parent,
15176
+ first: count === 0 ? null : given.get(parent)[start],
15177
+ count
15178
+ });
15179
+ }
14615
15180
  return;
14616
15181
  }
15182
+ memory?.described.add(node);
15183
+ if (node !== root) note(parent, record.id, record.index);
15184
+ else placed?.push({
15185
+ id: record.id,
15186
+ parent,
15187
+ index: record.index
15188
+ });
15189
+ if (rewalk !== void 0 && !given.has(record.id)) given.set(record.id, []);
14617
15190
  const runs = linkRunsOf(node);
14618
15191
  if (runs.length > 0) {
14619
15192
  records.set(record.id, paragraphOf(record));
14620
15193
  appendTextRuns(node, record.id, runs, records);
15194
+ if (tracking) for (let run = 0;; run++) {
15195
+ const id = `${record.id}${TEXT_RUN_ID_SEPARATOR}${run}`;
15196
+ const added = records.get(id);
15197
+ if (added === void 0) break;
15198
+ note(record.id, id, added.index);
15199
+ }
14621
15200
  } else records.set(record.id, record);
14622
15201
  for (let child = node.firstChild; child !== null; child = child.nextSibling) {
14623
15202
  if (claimedByName(node, child)) continue;
@@ -14664,7 +15243,10 @@ function describe(node, parent, disabled, nextIndex) {
14664
15243
  valueText: valueTextOf(node),
14665
15244
  posInSet: node.properties.get("posInSet"),
14666
15245
  setSize: node.properties.get("setSize"),
14667
- level: node.properties.get("level")
15246
+ level: node.properties.get("level"),
15247
+ activeDescendant: node.properties.get("activeDescendant")?.id,
15248
+ controls: node.properties.get("controls")?.id,
15249
+ autocomplete: node.properties.get("autocomplete")
14668
15250
  });
14669
15251
  }
14670
15252
  /**
@@ -14828,6 +15410,46 @@ function diffSemantics(previous, next) {
14828
15410
  }
14829
15411
  return patches;
14830
15412
  }
15413
+ /**
15414
+ * Drops the updates that only renumber a record whose siblings kept
15415
+ * their order.
15416
+ *
15417
+ * A record carries its index among its siblings, so inserting one near
15418
+ * the top of a list changes the index of every record after it, and
15419
+ * each of those used to go out as an update: 4,266 patches for one
15420
+ * paragraph inserted in a 5,000-line document, every one of them
15421
+ * crossing to the main thread and rewriting a mirror element. They say
15422
+ * nothing a mirror needs. It applies removals, then adds in document
15423
+ * order at their indices, so the elements that stayed are already in
15424
+ * the right order around the ones that came and went. Only when the
15425
+ * siblings that stayed changed their order among themselves (a move)
15426
+ * do the new indices matter, and then every update is kept.
15427
+ *
15428
+ * The records keep their new indices; this only thins the patches.
15429
+ */
15430
+ function dropIndexShifts(previous, next, patches) {
15431
+ const parents = /* @__PURE__ */ new Set();
15432
+ for (const patch of patches) if (patch.op === "update" && onlyIndexMoved(previous.get(patch.node.id), patch.node)) parents.add(patch.node.parent);
15433
+ if (parents.size === 0) return [...patches];
15434
+ const lastOld = /* @__PURE__ */ new Map();
15435
+ const reordered = /* @__PURE__ */ new Set();
15436
+ for (const record of next.values()) {
15437
+ if (!parents.has(record.parent) || reordered.has(record.parent)) continue;
15438
+ const before = previous.get(record.id);
15439
+ if (before === void 0 || before.parent !== record.parent) continue;
15440
+ if (before.index < (lastOld.get(record.parent) ?? -1)) reordered.add(record.parent);
15441
+ lastOld.set(record.parent, before.index);
15442
+ }
15443
+ return patches.filter((patch) => patch.op !== "update" || reordered.has(patch.node.parent) || !onlyIndexMoved(previous.get(patch.node.id), patch.node));
15444
+ }
15445
+ /** Whether two records differ in their index and in nothing else. */
15446
+ function onlyIndexMoved(before, after) {
15447
+ if (before === void 0 || before.parent !== after.parent || before.index === after.index) return false;
15448
+ return recordsEqual({
15449
+ ...before,
15450
+ index: after.index
15451
+ }, after);
15452
+ }
14831
15453
  /** Structural equality over the record's flat, pruned members. */
14832
15454
  function recordsEqual(a, b) {
14833
15455
  const aKeys = Object.keys(a);
@@ -14847,6 +15469,6 @@ function recordsEqual(a, b) {
14847
15469
  return true;
14848
15470
  }
14849
15471
  //#endregion
14850
- export { AlignContent, AnimationDriver, BUTTON_INTERACTION, Box, Button, CARET_BLINK_MS, CARET_WIDTH, CLIP_STRIDE_BYTES, CLIP_STRIDE_FLOATS, Canvas2DRenderer, CanvasPlatformSurface, CanvasSurface, CanvasTextMeasurer, CharacterCountTextMeasurer, Column, CommandKind, Constraints, CrossAxisAlignment, DEFAULT_BLOCK_SIZE, DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, DEFAULT_FONT_WEIGHT, DEFAULT_LINE_HEIGHT_FACTOR, DEFAULT_TEXT_COLOR, DefaultImageResolver, DefaultVideoResolver, DirtyFlags, DirtyNodeSet, EDITOR_PROP, ELLIPSIS, EMPTY_RECORDING, EXTERNAL_FILES, EditableLayout, EditableText, EditableTextModel, EnvironmentNotifier, FlexDirection, FocusNotifier, GLYPH_SUBPIXEL_PHASES, GlyphShaper, Grid, INSPECTOR_HEAT_MS, INSTANCE_STRIDE_BYTES, INSTANCE_STRIDE_FLOATS, IconRasterizer, LABEL_PADDING_X, LayoutEngine, LayoutInspector, LayoutNotifier, LayoutRecord, LazyColumn, LazyGrid, LazyRow, LazySheet, MARK_PREFIX, MAX_GRADIENT_STOPS, MAX_MEASURES_PER_CHILD, MOTION_CHANNELS, MOTION_REST, MOUSE_POINTER, MainAxisAlignment, Mp3Frames, NO_CLIP_INDEX, NodeTransitions, Paint, PaintPictureCache, PaintRecorder, PaintTarget, ParagraphTextMeasurer, PrimitiveKind, Responsive, Row, SCROLLBAR_FADE_MS, SCROLLBAR_HOVER_ZONE, SCROLLBAR_INSET, SCROLLBAR_LINGER_MS, SCROLLBAR_MIN_THUMB, SCROLLBAR_THICKNESS, ScrollView, Stack, TEXTURED_STRIDE_BYTES, TEXTURED_STRIDE_FLOATS, TEXT_MATCHES_PROP, TEXT_RUN_ID_SEPARATOR, TEXT_SELECTION_PROP, Text, UI_ROLES, UI_SEMANTIC_STATES, UI_SUBGRID_AXES, UiAnimation, UiAnimationFrameClock, UiBasicColors, UiBeforeInputEvent, UiBinding, UiBorderRadiuses, UiChildrenBinding, UiContainerSizeSource, UiDragSession, UiEditingController, UiEnvironment, UiEnvironmentKeys, UiEventBinding, UiEventType, UiFindController, UiFocusEvent, UiFocusManager, UiFrame, UiGestureEvent, UiGestureRecognizer, UiGraph, UiGraphBuilder, UiHitTester, UiHostFrameClock, UiInputDispatcher, UiInputEvent, UiInsetRegistry, UiKeyboardController, UiKeyboardEvent, UiManualFrameClock, UiModifierSet, UiNode, UiNodeType, UiPasteEvent, UiPinchEvent, UiPinchRecognizer, UiPlatformAdapter, UiPointerController, UiPointerEvent, UiProperties, UiScheduler, UiSelectionChangeEvent, UiSelectionController, UiSharedElements, UiShortcutRegistry, UiSpring, UiTextChangeEvent, UiTimerFrameClock, UiTouchScroller, UiTransforms, UiTween, UiUnknownModifierPropertyError, UiVirtualSheet, UiVirtualWindow, UiVisualState, UiWheelController, UiWheelDeltaMode, UiWheelEvent, VIRTUAL_INDEX_PROP, VIRTUAL_LEAD_PROP, VIRTUAL_SHEET_PROP, VIRTUAL_WINDOW_PROP, WebGPUError, WebGPUGlyphAtlas, WebGPUGlyphPages, WebGPURenderer, WebGPUSurface, WebGPUTextureCache, accumulatedOffsetTo, animateLayout, applyCanvasTextStyle, assertModifierList, assertTransitionMap, auto, autoFocus, bandOf, borderRadius, borderRadiusCorners, borderRadiusEqual, borderRadiusIsZero, borderRadiusValuesEqual, borderShapes, borders, boxShadow, boxShadowArraysEqual, boxShadowsEqual, breakpoint, bufferSource, buildFontString, buildRenderList, buildSemanticsSubtree, buildSemanticsTree, bumpFontStack, bundle, canDecodeVideo, capturePointer, caretRectFor, caretVisibleAt, clampSize, clearFontStacks, clearLinkHover, clearMatchRanges, clearOverrideProperty, clearSelectionRange, clickOutside, closestPropertyName, colorToCss, colorToHex, colorToRgba, colorValuesEqual, colorsEqual, colorsEqualPalette, commandForKey, computeObjectFitRect, constraintsEqual, containerBands, contentOffset, contextMenu, contrastRatio, createCanvasSurface, createCanvasTextStyle, createElement, createEnvironmentKey, createPaintState, createTextCache, createTween, createWebGPUSurface, cubicBezier, cueAt, darkColors, darkTheme, decorated, decorationColor, decorationRect, defaultMotion, defaultShadows, defaultShapes, defaultSpacing, defaultTextStyle, defaultTypography, defaultVisualState, defineModifier, defineProperty, defineThemeExtension, demuxMp4Audio, demuxMp4Video, densityFactors, describeLength, describeOverrides, detectEditingPlatform, diffSemantics, dragSessionFor, dragSource, draggable, drawOverlayShapes, drawText, dropTarget, easings, editableSpansOf, editorFor, editorOf, fade, fillTextRects, findEnvironmentKey, findMatchesIn, findPropertyDefinition, flattenTextSpans, focusRing, fontStackFor, formatConstraints, formatExplanation, formatShortcut, fr, getPropertyNames, glyphCount, gradientPaint, gradientsEqual, graphemeBoundaries, hasDecorationPhase, hasDrawnText, hasTextLinks, hasThemeExtension, hasVisualState, highContrastColors, hoverable, iconKey, iconSource, imageSource, inheritedPropertyFlags, inheritedPropertyNames, initializeWebGPU, inputsEqual, insetPadding, insetsEqual, interactive, interpolateColor, interpolateNumber, interpolateTransform, interpolatorFor, isAutoLength, isComponentLikeElement, isEditableNode, isFrLength, isLayoutProtocol, isMinMaxTrack, isMotionRest, isMultiline, isNodeFocusable, isNodeHitTestable, isNodeInert, isNodeSelectable, isNodeTabStop, isObservable, isPaintVisible, isPercentLength, isPrintable, isReadOnly, isScrollContainer, isShapeName, isTypographyRole, isUiChild, isUiElement, isUiModifier, isUiRole, isUiSemanticState, isVideoSurface, isWebGPUAvailable, labelNode, labelOrigin, layoutParagraph, layoutTextLines, lazySource, lightColors, lightTheme, lineEndAt, lineIndexAtY, lineIndexForOffset, lineLimit, lineStartAt, linear, linearGradient, linkHoverOf, linkOf, linkRunAtPointIn, markInstant, markNow, matchRangesOf, measure, measureSpan, minmax, motion, nextCaretToggle, nextGraphemeEnd, nextWordEnd, noInsets, noKeyModifiers, noModifiers, noThemeExtensions, normalizeBorderRadius, normalizeColor, normalizeStates, normalizeTextAlign, normalizeTransition, normalizeVerticalAlign, observeViewportInsets, offsetAtPoint, offsetAtPointIn, offsetAtX, offsetForVerticalMove, overrideSources, paintPictures, paintValuesEqual, paintsAfterChildren, paragraphGeometry, paragraphGeometryFrom, parseAlignContent, parseColor, parseCrossAxisAlignment, parseFlexDirection, parseMainAxisAlignment, parseShortcut, parseTransform, parseWebVtt, pathValuesEqual, percent, performanceMarksEnabled, pinchable, placeGridItems, pointerDeviceOf, pop, prepareInputSurface, pressable, previousGraphemeStart, previousWordStart, propertyEffects, propertyIsInherited, propertyValuesEqual, propertyValuesEqualByName, proportionalFontMetrics, provideEnvironment, publishInset, radialGradient, raiseContrast, rangeSource, readMp3Header, recordsEqual, registerFontStack, relativeLuminance, reorderable, repeat, replayPaint, resetOverrideWarnings, resetTransitionWarnings, resolveBoolean, resolveCursor, resolveLength, resolveMotionState, resolveNumber, resolvePaintState, resolveProperty, resolvePropertyByName, resolveString, resolvedSpansOf, rgb8, rgba, rotateFrom, runCanvasStyleInto, runFontString, sameArgs, scaleFrom, scaleSpacing, scrollLeaderOf, scrollPosition, scrollRange, scrollbarThumb, scrollbarThumbs, scrollbarZoneAt, selectableTextNodes, selectableTextOf, selectionRangeOf, selectionRects, selectionRectsIn, semanticsInertAbove, setLinkHover, setMatchRanges, setPerformanceMarks, setSelectionRange, shadowsEqual, shapesEqual, sharedElement, sheetSource, shortcut, shortcuts, sizeContainer, sizeGridTracks, slideDown, slideFrom, slideUp, spacingEqual, spacingSteps, spanAtOffset, spannedRunsFor, spannedTextOf, splitMp3Frames, spring, statesEqual, steps, syncEditorValue, textContentOf, textRunBackgrounds, textRunDecorations, textRunOfRecordId, textRuns, textSpansEqual, textStylesEqual, themeExtension, themeExtensionsEqual, themeTokens, themesEqual, tightenConstraints, touchActionFor, tracePathData, traceRoundedRect, transform, transformIsIdentity, transformsEqual, tween, typographyEqual, uniformBorderRadius, unknownContainerSize, validateGradient, validateRole, validateStates, validateSubgrid, videoFrameSize, videoSource, visualState, visualStatesEqual, wheelDeltaYOf, withContrast, withDensity, withOverrideSource, withThemeExtension, wordRangeAt, wordRangeIn, writeDeclaredProperty, writeOverrideProperty };
15472
+ export { AlignContent, AnimationDriver, BOX_SHADOW_BLUR_REACH, BUTTON_INTERACTION, Box, Button, CARET_BLINK_MS, CARET_WIDTH, CLIP_STRIDE_BYTES, CLIP_STRIDE_FLOATS, Canvas2DRenderer, CanvasPlatformSurface, CanvasSurface, CanvasTextMeasurer, CharacterCountTextMeasurer, Column, CommandKind, Constraints, CrossAxisAlignment, DEFAULT_BLOCK_SIZE, DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, DEFAULT_FONT_WEIGHT, DEFAULT_LINE_HEIGHT_FACTOR, DEFAULT_TEXT_COLOR, DefaultImageResolver, DefaultVideoResolver, DirtyFlags, DirtyNodeSet, EDITOR_PROP, ELLIPSIS, EMPTY_RECORDING, EXTERNAL_FILES, EditableLayout, EditableText, EditableTextModel, EnvironmentNotifier, FlexDirection, FocusNotifier, GLYPH_SUBPIXEL_PHASES, GlyphShaper, Grid, INSPECTOR_HEAT_MS, INSTANCE_STRIDE_BYTES, INSTANCE_STRIDE_FLOATS, IconRasterizer, LABEL_PADDING_X, LayoutEngine, LayoutInspector, LayoutNotifier, LayoutRecord, LazyColumn, LazyGrid, LazyRow, LazySheet, MARK_PREFIX, MAX_GRADIENT_STOPS, MAX_MEASURES_PER_CHILD, MOTION_CHANNELS, MOTION_REST, MOUSE_POINTER, MainAxisAlignment, Mp3Frames, NO_CLIP_INDEX, NodeTransitions, Paint, PaintPictureCache, PaintRecorder, PaintTarget, ParagraphTextMeasurer, PrimitiveKind, Responsive, Row, SCROLLBAR_FADE_MS, SCROLLBAR_HOVER_ZONE, SCROLLBAR_INSET, SCROLLBAR_LINGER_MS, SCROLLBAR_MIN_THUMB, SCROLLBAR_THICKNESS, ScrollView, Stack, TEXTURED_STRIDE_BYTES, TEXTURED_STRIDE_FLOATS, TEXT_MATCHES_PROP, TEXT_RUN_ID_SEPARATOR, TEXT_SELECTION_PROP, Text, UI_ROLES, UI_SEMANTIC_STATES, UI_SUBGRID_AXES, UiAnimation, UiAnimationFrameClock, UiBasicColors, UiBeforeInputEvent, UiBinding, UiBorderRadiuses, UiChildrenBinding, UiContainerSizeSource, UiDragSession, UiEditingController, UiEnvironment, UiEnvironmentKeys, UiEventBinding, UiEventType, UiFindController, UiFocusEvent, UiFocusManager, UiFrame, UiGestureEvent, UiGestureRecognizer, UiGraph, UiGraphBuilder, UiHitTester, UiHostFrameClock, UiInputDispatcher, UiInputEvent, UiInsetRegistry, UiKeyboardController, UiKeyboardEvent, UiManualFrameClock, UiModifierSet, UiNode, UiNodeType, UiPasteEvent, UiPinchEvent, UiPinchRecognizer, UiPlatformAdapter, UiPointerController, UiPointerEvent, UiProperties, UiScheduler, UiSelectionChangeEvent, UiSelectionController, UiSharedElements, UiShortcutRegistry, UiSpring, UiTextChangeEvent, UiTimerFrameClock, UiTouchScroller, UiTransforms, UiTween, UiUnknownModifierPropertyError, UiVirtualSheet, UiVirtualWindow, UiVisualState, UiWheelController, UiWheelDeltaMode, UiWheelEvent, VIRTUAL_INDEX_PROP, VIRTUAL_LEAD_PROP, VIRTUAL_SHEET_PROP, VIRTUAL_WINDOW_PROP, WebGPUError, WebGPUGlyphAtlas, WebGPUGlyphPages, WebGPURenderer, WebGPUSurface, WebGPUTextureCache, accumulatedOffsetTo, adjacentField, animateLayout, applyCanvasTextStyle, assertModifierList, assertTransitionMap, auto, autoFocus, bandOf, borderRadius, borderRadiusCorners, borderRadiusEqual, borderRadiusIsZero, borderRadiusValuesEqual, borderShapes, borders, boxShadow, boxShadowArraysEqual, boxShadowRadius, boxShadowReach, boxShadowsEqual, breakpoint, bufferSource, buildFontString, buildRenderList, buildSemanticsSubtree, buildSemanticsTree, bumpFontStack, bundle, canDecodeVideo, capturePointer, caretRectFor, caretVisibleAt, clampSize, clearFontStacks, clearLinkHover, clearMatchRanges, clearOverrideProperty, clearSelectionRange, clickOutside, closestPropertyName, colorToCss, colorToHex, colorToRgba, colorValuesEqual, colorsEqual, colorsEqualPalette, commandForKey, comparePositions, computeObjectFitRect, constraintsEqual, containerBands, contentOffset, contextMenu, contrastRatio, createCanvasSurface, createCanvasTextStyle, createElement, createEnvironmentKey, createPaintState, createTextCache, createTween, createWebGPUSurface, cubicBezier, cueAt, darkColors, darkTheme, decorated, decorationColor, decorationRect, defaultMotion, defaultShadows, defaultShapes, defaultSpacing, defaultTextStyle, defaultTypography, defaultVisualState, defineModifier, defineProperty, defineThemeExtension, demuxMp4Audio, demuxMp4Video, densityFactors, describeLength, describeOverrides, describeShortcut, detectEditingPlatform, diffSemantics, dragSessionFor, dragSource, draggable, drawOverlayShapes, drawText, dropIndexShifts, dropTarget, easings, edgeField, editableSpansOf, editingGroupOf, editorFor, editorOf, fade, fillTextRects, findEnvironmentKey, findMatchesIn, findPropertyDefinition, flattenTextSpans, focusRing, fontStackFor, formatConstraints, formatExplanation, formatShortcut, fr, getPropertyNames, glyphCount, gradientPaint, gradientsEqual, graphemeBoundaries, hasDecorationPhase, hasDrawnText, hasTextLinks, hasThemeExtension, hasVisualState, hiddenRangesOf, highContrastColors, hoverable, iconKey, iconSource, imageSource, inheritedPropertyFlags, inheritedPropertyNames, initializeWebGPU, inputsEqual, insetPadding, insetsEqual, interactive, interpolateColor, interpolateNumber, interpolateTransform, interpolatorFor, isAutoLength, isComponentLikeElement, isEditableNode, isFrLength, isLayoutProtocol, isMinMaxTrack, isMotionRest, isMultiline, isNodeFocusable, isNodeHitTestable, isNodeInert, isNodeSelectable, isNodeTabStop, isObservable, isPaintVisible, isPercentLength, isPrintable, isReadOnly, isScrollContainer, isShapeName, isTypographyRole, isUiChild, isUiElement, isUiModifier, isUiRole, isUiSemanticState, isVideoSurface, isWebGPUAvailable, labelNode, labelOrigin, layoutParagraph, layoutTextLines, lazySource, lightColors, lightTheme, lineEndAt, lineIndexAtY, lineIndexForOffset, lineLimit, lineStartAt, linear, linearGradient, linkHoverOf, linkOf, linkRunAtPointIn, markInstant, markNow, matchRangesOf, measure, measureSpan, minmax, motion, nextCaretToggle, nextGraphemeEnd, nextWordEnd, noInsets, noKeyModifiers, noModifiers, noThemeExtensions, normalizeBorderRadius, normalizeColor, normalizeStates, normalizeTextAlign, normalizeTransition, normalizeVerticalAlign, observeViewportInsets, offsetAtPoint, offsetAtPointIn, offsetAtX, offsetForVerticalMove, overrideSources, paintPictures, paintValuesEqual, paintsAfterChildren, paragraphGeometry, paragraphGeometryFrom, parseAlignContent, parseColor, parseCrossAxisAlignment, parseFlexDirection, parseMainAxisAlignment, parseShortcut, parseTransform, parseWebVtt, pathValuesEqual, percent, performanceMarksEnabled, pinchable, placeGridItems, pointerDeviceOf, pop, prepareInputSurface, pressable, previousGraphemeStart, previousWordStart, propertyEffects, propertyIsInherited, propertyValuesEqual, propertyValuesEqualByName, proportionalFontMetrics, provideEnvironment, publishInset, radialGradient, raiseContrast, rangeSource, readMp3Header, recordsEqual, registerFontStack, relativeLuminance, reorderable, repeat, replayPaint, resetOverrideWarnings, resetTransitionWarnings, resolveBoolean, resolveCursor, resolveLength, resolveMotionState, resolveNumber, resolvePaintState, resolveProperty, resolvePropertyByName, resolveString, resolvedSpansOf, rewalkSemantics, rgb8, rgba, rotateFrom, runCanvasStyleInto, runFontString, sameArgs, scaleFrom, scaleSpacing, scrollLeaderOf, scrollPosition, scrollRange, scrollbarThumb, scrollbarThumbs, scrollbarZoneAt, selectableTextNodes, selectableTextOf, selectionRangeOf, selectionRects, selectionRectsIn, semanticsInertAbove, semanticsMemory, setLinkHover, setMatchRanges, setPerformanceMarks, setSelectionRange, shadowsEqual, shapesEqual, sharedElement, sheetSource, shortcut, shortcutKeyCaps, shortcuts, sizeContainer, sizeGridTracks, slideDown, slideFrom, slideUp, spacingEqual, spacingSteps, spanAtOffset, spannedRunsFor, spannedTextOf, splitMp3Frames, spring, statesEqual, steps, syncEditorValue, textContentOf, textRunBackgrounds, textRunDecorations, textRunOfRecordId, textRuns, textSpansEqual, textStylesEqual, themeExtension, themeExtensionsEqual, themeTokens, themesEqual, tightenConstraints, touchActionFor, tracePathData, traceRoundedRect, transform, transformIsIdentity, transformsEqual, tween, typographyEqual, uniformBorderRadius, unknownContainerSize, validateGradient, validateRole, validateStates, validateSubgrid, videoFrameSize, videoSource, visualState, visualStatesEqual, wheelDeltaYOf, withContrast, withDensity, withOverrideSource, withThemeExtension, wordRangeAt, wordRangeIn, writeDeclaredProperty, writeOverrideProperty };
14851
15473
 
14852
15474
  //# sourceMappingURL=index.js.map