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/CHANGELOG.md +69 -0
- package/dist/{CanvasSurface-BMOmE_dD.js → CanvasSurface-Dok8FuyX.js} +4474 -2715
- package/dist/CanvasSurface-Dok8FuyX.js.map +1 -0
- package/dist/{index-BiN3WdTh.d.ts → index-B3zydgF2.d.ts} +1388 -480
- package/dist/index.d.ts +2 -2
- package/dist/index.js +720 -98
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +13 -1
- package/dist/testing.js +42 -2
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
- package/dist/CanvasSurface-BMOmE_dD.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
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.
|
|
840
|
-
*
|
|
841
|
-
*
|
|
842
|
-
*
|
|
843
|
-
*
|
|
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$
|
|
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$
|
|
1250
|
+
return kind$5(options);
|
|
1250
1251
|
}
|
|
1251
1252
|
/** Hover only. */
|
|
1252
1253
|
function hoverable() {
|
|
1253
|
-
return kind$
|
|
1254
|
+
return kind$5(HOVER_ONLY);
|
|
1254
1255
|
}
|
|
1255
1256
|
/** Press only. */
|
|
1256
1257
|
function pressable() {
|
|
1257
|
-
return kind$
|
|
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$
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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,
|
|
3222
|
-
* first frame
|
|
3223
|
-
*
|
|
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
|
-
*
|
|
4467
|
-
* focused node, its own `when` says no,
|
|
4468
|
-
* modifier at all
|
|
4469
|
-
*
|
|
4470
|
-
*
|
|
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
|
|
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
|
-
*
|
|
4601
|
-
*
|
|
4602
|
-
*
|
|
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
|
|
4606
|
-
return steps.map(
|
|
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
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
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
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
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$
|
|
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$
|
|
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$
|
|
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
|
-
*
|
|
5142
|
-
*
|
|
5143
|
-
*
|
|
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
|
|
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
|
-
})
|
|
5156
|
-
/**
|
|
5157
|
-
|
|
5158
|
-
|
|
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
|
|
6784
|
-
* frame
|
|
6785
|
-
*
|
|
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
|
|
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:
|
|
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
|
|
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 (
|
|
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
|
|
9327
|
-
|
|
9328
|
-
|
|
9329
|
-
|
|
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(
|
|
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 /
|
|
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 /
|
|
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.
|
|
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
|
-
|
|
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 /
|
|
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(
|
|
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
|
-
|
|
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:
|
|
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: "
|
|
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,
|
|
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
|
-
|
|
14602
|
-
|
|
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
|