@blotch/angular-lynx 22.2.4 → 22.2.5
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/fesm2022/{blotch-angular-lynx-web-glass-ciDHw7Bw.mjs → blotch-angular-lynx-web-glass-zlVeee5K.mjs} +95 -30
- package/fesm2022/blotch-angular-lynx-web-glass-zlVeee5K.mjs.map +1 -0
- package/fesm2022/blotch-angular-lynx.mjs +186 -7
- package/fesm2022/blotch-angular-lynx.mjs.map +1 -1
- package/package.json +1 -1
- package/types/blotch-angular-lynx.d.ts +178 -56
- package/fesm2022/blotch-angular-lynx-web-glass-ciDHw7Bw.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -110,6 +110,60 @@ export declare class LynxAccessibilitySettings {
|
|
|
110
110
|
static ɵfac: i0.ɵɵFactoryDeclaration<LynxAccessibilitySettings, never>;
|
|
111
111
|
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
112
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* One trait of `accessibility-traits`, each of which iOS turns into a
|
|
115
|
+
* UIAccessibilityTraits flag (`LynxConverter+UI.m`).
|
|
116
|
+
*/
|
|
117
|
+
type AccessibilityTrait = 'text' | 'image' | 'button' | 'link' | 'header' | 'search' | 'selected' | 'playable' | 'keyboard' | 'summary' | 'disabled' | 'updating' | 'adjustable' | 'tabbar' | 'none';
|
|
118
|
+
/**
|
|
119
|
+
* Which traits LynxAccessibilityTraits adds, by name. `none` isn't one: it
|
|
120
|
+
* says the element has no traits, so there's nothing to add.
|
|
121
|
+
*/
|
|
122
|
+
type AccessibilityTraitStates = Partial<Record<Exclude<AccessibilityTrait, 'none'>, boolean>>;
|
|
123
|
+
/**
|
|
124
|
+
* Adds accessibility traits to an element's own `accessibility-traits` while
|
|
125
|
+
* a binding says so, such as `selected` on the chosen one of several options,
|
|
126
|
+
* or `disabled` on an item that can't be used now.
|
|
127
|
+
*
|
|
128
|
+
* Writing the state into the attribute instead,
|
|
129
|
+
* `accessibility-traits="button,selected"`, works only on iOS. Android reads
|
|
130
|
+
* the attribute as a single trait, so a list stops being a button there. The
|
|
131
|
+
* element merges these traits into its own instead (see
|
|
132
|
+
* LynxElement.setAccessibilityTrait): `button` reads `button,selected` on iOS,
|
|
133
|
+
* and stays `button` on Android, which has no selected trait to add. The
|
|
134
|
+
* element can still set its own traits at any time, and neither undoes the
|
|
135
|
+
* other.
|
|
136
|
+
*
|
|
137
|
+
* A trait that turns false, or that the map leaves out, is taken away again.
|
|
138
|
+
* Only the traits this directive added are: the element's own stay.
|
|
139
|
+
*
|
|
140
|
+
* It's part of LYNX_ELEMENTS, so a component that imports LYNX_ELEMENTS can
|
|
141
|
+
* bind it on any element.
|
|
142
|
+
*
|
|
143
|
+
* @usageNotes
|
|
144
|
+
* ```html
|
|
145
|
+
* <view
|
|
146
|
+
* [accessibility-element]="true"
|
|
147
|
+
* accessibility-traits="button"
|
|
148
|
+
* [accessibility-label]="label()"
|
|
149
|
+
* [lynxAccessibilityTraits]="{ selected: selected() }"
|
|
150
|
+
* (bindtap)="chosen.emit()"
|
|
151
|
+
* >
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export declare class LynxAccessibilityTraits {
|
|
155
|
+
#private;
|
|
156
|
+
readonly lynxAccessibilityTraits: import("@angular/core").InputSignal<Partial<Record<"text" | "search" | "link" | "image" | "button" | "header" | "selected" | "playable" | "keyboard" | "summary" | "disabled" | "updating" | "adjustable" | "tabbar", boolean>> | null | undefined>;
|
|
157
|
+
constructor();
|
|
158
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<LynxAccessibilityTraits, never>;
|
|
159
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<LynxAccessibilityTraits, "[lynxAccessibilityTraits]", never, {
|
|
160
|
+
"lynxAccessibilityTraits": {
|
|
161
|
+
"alias": "lynxAccessibilityTraits";
|
|
162
|
+
"required": false;
|
|
163
|
+
"isSignal": true;
|
|
164
|
+
};
|
|
165
|
+
}, {}, never, never, true, never>;
|
|
166
|
+
}
|
|
113
167
|
/**
|
|
114
168
|
* Phantom brand symbol — makes each ElementRef variant nominally distinct at
|
|
115
169
|
* the type level even though Lynx PAPI handles have no runtime structure.
|
|
@@ -1172,11 +1226,6 @@ export declare class TapGesture extends BaseGesture<TapGestureEvent, TapGesture>
|
|
|
1172
1226
|
* Lynx reads the margins as strings, so a bare number has no effect.
|
|
1173
1227
|
*/
|
|
1174
1228
|
type ExposureMargin = `${number}px` | `${number}rpx`;
|
|
1175
|
-
/**
|
|
1176
|
-
* One trait of `accessibility-traits`, each of which iOS turns into a
|
|
1177
|
-
* UIAccessibilityTraits flag (`LynxConverter+UI.m`).
|
|
1178
|
-
*/
|
|
1179
|
-
type AccessibilityTrait = 'text' | 'image' | 'button' | 'link' | 'header' | 'search' | 'selected' | 'playable' | 'keyboard' | 'summary' | 'disabled' | 'updating' | 'adjustable' | 'tabbar' | 'none';
|
|
1180
1229
|
/**
|
|
1181
1230
|
* @Directive() is required so that ng-packagr's Angular partial compiler
|
|
1182
1231
|
* recognizes this base class as an Angular artifact. The selector is left
|
|
@@ -1225,8 +1274,8 @@ declare class LynxElementBase implements OnChanges {
|
|
|
1225
1274
|
* The kind of element a screen reader announces. Plural, as Lynx reads it:
|
|
1226
1275
|
* iOS, Android and Harmony ignore `accessibility-trait`. iOS also reads a
|
|
1227
1276
|
* comma-separated list with no spaces, such as `button,selected`, which
|
|
1228
|
-
* is what LynxRouterLinkActive
|
|
1229
|
-
* trait. @default 'none'
|
|
1277
|
+
* is what LynxRouterLinkActive and LynxAccessibilityTraits write; Android
|
|
1278
|
+
* and Harmony read a single trait. @default 'none'
|
|
1230
1279
|
*/
|
|
1231
1280
|
'accessibility-traits'?: AccessibilityTrait | `${AccessibilityTrait},${string}`;
|
|
1232
1281
|
/**
|
|
@@ -1551,6 +1600,16 @@ export declare class LynxBlurView extends LynxElementBase {
|
|
|
1551
1600
|
* gets a tint that approximates it. @default 'light'
|
|
1552
1601
|
*/
|
|
1553
1602
|
'blur-effect'?: 'light' | 'extra-light' | 'dark' | 'glass' | 'glass-container';
|
|
1603
|
+
/**
|
|
1604
|
+
* One of UIKit's adaptive blur materials, which follow
|
|
1605
|
+
* `ios-user-interface-style` (iOS 13+, in apps built with
|
|
1606
|
+
* `ng build --platform ios`): `systemUltraThinMaterial` to
|
|
1607
|
+
* `systemThickMaterial`, or `systemChromeMaterial`, the bars'. While it's
|
|
1608
|
+
* set it replaces `blur-effect` and `blur-radius`. Lynx's own blur-view
|
|
1609
|
+
* doesn't have it, so Lynx Explorer and other hosts ignore it and draw the
|
|
1610
|
+
* `blur-effect`.
|
|
1611
|
+
*/
|
|
1612
|
+
'blur-material'?: 'ultra-thin' | 'thin' | 'regular' | 'thick' | 'chrome';
|
|
1554
1613
|
/**
|
|
1555
1614
|
* Distance at which glass elements inside a `glass-container` start to merge (iOS). @default 0
|
|
1556
1615
|
*/
|
|
@@ -1597,6 +1656,10 @@ export declare class LynxBlurView extends LynxElementBase {
|
|
|
1597
1656
|
"alias": "blur-effect";
|
|
1598
1657
|
"required": false;
|
|
1599
1658
|
};
|
|
1659
|
+
"blur-material": {
|
|
1660
|
+
"alias": "blur-material";
|
|
1661
|
+
"required": false;
|
|
1662
|
+
};
|
|
1600
1663
|
"spacing": {
|
|
1601
1664
|
"alias": "spacing";
|
|
1602
1665
|
"required": false;
|
|
@@ -3111,7 +3174,66 @@ export declare class LynxRouterLinkActive {
|
|
|
3111
3174
|
* All Lynx native element directives as a single importable array.
|
|
3112
3175
|
* Add to the `imports` of any component whose template uses Lynx elements.
|
|
3113
3176
|
*/
|
|
3114
|
-
export declare const LYNX_ELEMENTS: readonly [typeof LynxView, typeof LynxText, typeof LynxInlineTruncation, typeof LynxImage, typeof LynxScrollView, typeof LynxList, typeof LynxListItem, typeof LynxBlock, typeof LynxIf, typeof LynxFor, typeof LynxFrame, typeof LynxInput, typeof LynxTextarea, typeof LynxInputValueAccessor, typeof LynxTextareaValueAccessor, typeof LynxOverlay, typeof LynxRefresh, typeof LynxRefreshHeader, typeof LynxScrollCoordinator, typeof LynxScrollCoordinatorHeader, typeof LynxScrollCoordinatorSlot, typeof LynxScrollCoordinatorSlotDrag, typeof LynxScrollCoordinatorToolbar, typeof LynxSvg, typeof LynxViewPager, typeof LynxViewPagerItem, typeof LynxBlurView, typeof LynxVideo, typeof LynxWebView, typeof LynxCoverView, typeof LynxTitleBarView, typeof LynxRouterLinkActive];
|
|
3177
|
+
export declare const LYNX_ELEMENTS: readonly [typeof LynxView, typeof LynxText, typeof LynxInlineTruncation, typeof LynxImage, typeof LynxScrollView, typeof LynxList, typeof LynxListItem, typeof LynxBlock, typeof LynxIf, typeof LynxFor, typeof LynxFrame, typeof LynxInput, typeof LynxTextarea, typeof LynxInputValueAccessor, typeof LynxTextareaValueAccessor, typeof LynxOverlay, typeof LynxRefresh, typeof LynxRefreshHeader, typeof LynxScrollCoordinator, typeof LynxScrollCoordinatorHeader, typeof LynxScrollCoordinatorSlot, typeof LynxScrollCoordinatorSlotDrag, typeof LynxScrollCoordinatorToolbar, typeof LynxSvg, typeof LynxViewPager, typeof LynxViewPagerItem, typeof LynxBlurView, typeof LynxVideo, typeof LynxWebView, typeof LynxCoverView, typeof LynxTitleBarView, typeof LynxRouterLinkActive, typeof LynxAccessibilityTraits];
|
|
3178
|
+
type LynxEventType = 'bindEvent' | 'catchEvent' | 'capture-bindEvent' | 'capture-catchEvent' | 'global-bindEvent';
|
|
3179
|
+
declare const EVENT_PREFIXES: [string, LynxEventType][];
|
|
3180
|
+
/**
|
|
3181
|
+
* DOM event names whose Lynx event has another name. A listener for one of
|
|
3182
|
+
* them hears the Lynx event, bubbling, as if it were bound with `bind`: a
|
|
3183
|
+
* `(click)` listener runs on a tap. This is the mapping Lynx for Web makes
|
|
3184
|
+
* between the two (web-core's `W3cEventNameToLynx` turns a DOM `click` into
|
|
3185
|
+
* `tap`), and it's what lets Angular's own directives that listen for
|
|
3186
|
+
* `click`, such as `RouterLink`, work on Lynx elements.
|
|
3187
|
+
*/
|
|
3188
|
+
declare const DOM_EVENT_ALIASES: ReadonlyMap<string, string>;
|
|
3189
|
+
/**
|
|
3190
|
+
* The `nativeElement` of a Lynx element's `ElementRef`: AngularLynx's
|
|
3191
|
+
* wrapper around the native element, not a DOM element. Type an
|
|
3192
|
+
* `ElementRef` with it to call its methods, such as `animate()`, `invoke()`
|
|
3193
|
+
* or `setAccessibilityTrait()`.
|
|
3194
|
+
*
|
|
3195
|
+
* @usageNotes
|
|
3196
|
+
* ```ts
|
|
3197
|
+
* readonly option = viewChild.required<ElementRef<BaseLynxElement>>('option');
|
|
3198
|
+
* ```
|
|
3199
|
+
*/
|
|
3200
|
+
type BaseLynxElement = Pick<Element$1, 'setAttribute'> & {
|
|
3201
|
+
tagName: string;
|
|
3202
|
+
setProperty(name: string, value: any): void;
|
|
3203
|
+
getAttribute(name: string): string | null;
|
|
3204
|
+
removeAttribute(name: string): void;
|
|
3205
|
+
setStyle(key: string, value: unknown): void;
|
|
3206
|
+
removeStyle(key: string): void;
|
|
3207
|
+
setInlineStyles(inlineStyle: string): void;
|
|
3208
|
+
insertBefore(newChild: BaseLynxElement, refChild: BaseLynxElement | null): void;
|
|
3209
|
+
appendChild(newChild: BaseLynxElement): void;
|
|
3210
|
+
addClass(name: string): void;
|
|
3211
|
+
/**
|
|
3212
|
+
* Adds a class that stays when the whole class list is replaced, for
|
|
3213
|
+
* ViewEncapsulation.Emulated's scope classes (see EmulatedLynxRenderer).
|
|
3214
|
+
*/
|
|
3215
|
+
addScopeClass(name: string): void;
|
|
3216
|
+
removeClass(name: string): void;
|
|
3217
|
+
/**
|
|
3218
|
+
* Adds a trait to the element's own `accessibility-traits`, or takes it
|
|
3219
|
+
* away, keeping the traits the app sets. For state that changes, such as
|
|
3220
|
+
* `selected` on an active router link (see LynxRouterLinkActive). In a
|
|
3221
|
+
* template, LynxAccessibilityTraits does it from a binding.
|
|
3222
|
+
*/
|
|
3223
|
+
setAccessibilityTrait(trait: string, on: boolean): void;
|
|
3224
|
+
remove(): void;
|
|
3225
|
+
parentNode(): BaseLynxElement | null;
|
|
3226
|
+
nextSibling(): BaseLynxElement | null;
|
|
3227
|
+
querySelector(selector: string): BaseLynxElement | null;
|
|
3228
|
+
querySelectorAll(selector: string): BaseLynxElement[];
|
|
3229
|
+
addEventListener(name: string, cb: (event: any) => any): () => void;
|
|
3230
|
+
animate(keyframes: Record<string, string | number>[], options?: number | LynxAnimationOptions): BaseLynxAnimation;
|
|
3231
|
+
/**
|
|
3232
|
+
* Invokes a native UI method on this element (e.g. setValue, scrollTo).
|
|
3233
|
+
* LynxElement implements it via __InvokeUIMethod.
|
|
3234
|
+
*/
|
|
3235
|
+
invoke(methodName: string, params?: Record<string, unknown>): void;
|
|
3236
|
+
};
|
|
3115
3237
|
export declare class LynxLogger {
|
|
3116
3238
|
#private;
|
|
3117
3239
|
log(...args: unknown[]): void;
|
|
@@ -3264,53 +3386,6 @@ export declare class LynxNativeModule {
|
|
|
3264
3386
|
static ɵfac: i0.ɵɵFactoryDeclaration<LynxNativeModule, never>;
|
|
3265
3387
|
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
3266
3388
|
}
|
|
3267
|
-
type LynxEventType = 'bindEvent' | 'catchEvent' | 'capture-bindEvent' | 'capture-catchEvent' | 'global-bindEvent';
|
|
3268
|
-
declare const EVENT_PREFIXES: [string, LynxEventType][];
|
|
3269
|
-
/**
|
|
3270
|
-
* DOM event names whose Lynx event has another name. A listener for one of
|
|
3271
|
-
* them hears the Lynx event, bubbling, as if it were bound with `bind`: a
|
|
3272
|
-
* `(click)` listener runs on a tap. This is the mapping Lynx for Web makes
|
|
3273
|
-
* between the two (web-core's `W3cEventNameToLynx` turns a DOM `click` into
|
|
3274
|
-
* `tap`), and it's what lets Angular's own directives that listen for
|
|
3275
|
-
* `click`, such as `RouterLink`, work on Lynx elements.
|
|
3276
|
-
*/
|
|
3277
|
-
declare const DOM_EVENT_ALIASES: ReadonlyMap<string, string>;
|
|
3278
|
-
type BaseLynxElement = Pick<Element$1, 'setAttribute'> & {
|
|
3279
|
-
tagName: string;
|
|
3280
|
-
setProperty(name: string, value: any): void;
|
|
3281
|
-
getAttribute(name: string): string | null;
|
|
3282
|
-
removeAttribute(name: string): void;
|
|
3283
|
-
setStyle(key: string, value: unknown): void;
|
|
3284
|
-
removeStyle(key: string): void;
|
|
3285
|
-
setInlineStyles(inlineStyle: string): void;
|
|
3286
|
-
insertBefore(newChild: BaseLynxElement, refChild: BaseLynxElement | null): void;
|
|
3287
|
-
appendChild(newChild: BaseLynxElement): void;
|
|
3288
|
-
addClass(name: string): void;
|
|
3289
|
-
/**
|
|
3290
|
-
* Adds a class that stays when the whole class list is replaced, for
|
|
3291
|
-
* ViewEncapsulation.Emulated's scope classes (see EmulatedLynxRenderer).
|
|
3292
|
-
*/
|
|
3293
|
-
addScopeClass(name: string): void;
|
|
3294
|
-
removeClass(name: string): void;
|
|
3295
|
-
/**
|
|
3296
|
-
* Adds a trait to the element's own `accessibility-traits`, or takes it
|
|
3297
|
-
* away, keeping the traits the app sets. For state the runtime tracks, such
|
|
3298
|
-
* as `selected` on an active router link (see LynxRouterLinkActive).
|
|
3299
|
-
*/
|
|
3300
|
-
setAccessibilityTrait(trait: string, on: boolean): void;
|
|
3301
|
-
remove(): void;
|
|
3302
|
-
parentNode(): BaseLynxElement | null;
|
|
3303
|
-
nextSibling(): BaseLynxElement | null;
|
|
3304
|
-
querySelector(selector: string): BaseLynxElement | null;
|
|
3305
|
-
querySelectorAll(selector: string): BaseLynxElement[];
|
|
3306
|
-
addEventListener(name: string, cb: (event: any) => any): () => void;
|
|
3307
|
-
animate(keyframes: Record<string, string | number>[], options?: number | LynxAnimationOptions): BaseLynxAnimation;
|
|
3308
|
-
/**
|
|
3309
|
-
* Invokes a native UI method on this element (e.g. setValue, scrollTo).
|
|
3310
|
-
* LynxElement implements it via __InvokeUIMethod.
|
|
3311
|
-
*/
|
|
3312
|
-
invoke(methodName: string, params?: Record<string, unknown>): void;
|
|
3313
|
-
};
|
|
3314
3389
|
declare class LynxElement implements BaseLynxElement {
|
|
3315
3390
|
#private;
|
|
3316
3391
|
get element(): ElementRef;
|
|
@@ -3397,6 +3472,13 @@ declare class LynxElement implements BaseLynxElement {
|
|
|
3397
3472
|
* itself from the set via #cancelPendingRemoval, so only genuine destroys
|
|
3398
3473
|
* remain.
|
|
3399
3474
|
*/
|
|
3475
|
+
/**
|
|
3476
|
+
* Sends Lynx the attribute removals that weren't taken back this cycle
|
|
3477
|
+
* (see #removedAttributes). Called by `LynxRendererFactory2.end()` and the
|
|
3478
|
+
* settle flush, after removals and before `__FlushElementTree()`, so the
|
|
3479
|
+
* removals land in the same flush as the cycle's other mutations.
|
|
3480
|
+
*/
|
|
3481
|
+
static commitPendingAttributeRemovals(): void;
|
|
3400
3482
|
static commitPendingRemovals(): void;
|
|
3401
3483
|
/**
|
|
3402
3484
|
* Re-derives displayed whitespace for every text touched this cycle. Each dirty
|
|
@@ -3468,6 +3550,14 @@ declare class LynxElement implements BaseLynxElement {
|
|
|
3468
3550
|
* keeping removals in the same flush as the cycle's other mutations.
|
|
3469
3551
|
*/
|
|
3470
3552
|
declare const processPendingRemovals: () => void;
|
|
3553
|
+
/**
|
|
3554
|
+
* Commits this cycle's attribute removals (see LynxElement's
|
|
3555
|
+
* `#removedAttributes`). A free-function wrapper over
|
|
3556
|
+
* `LynxElement.commitPendingAttributeRemovals()` so
|
|
3557
|
+
* `LynxRendererFactory2.end()` can drain them (via the lynx-element barrel)
|
|
3558
|
+
* right after element removals and before `__FlushElementTree()`.
|
|
3559
|
+
*/
|
|
3560
|
+
declare const processPendingAttributeRemovals: () => void;
|
|
3471
3561
|
/**
|
|
3472
3562
|
* Re-derives positional edge whitespace for every text touched this cycle — a
|
|
3473
3563
|
* free-function wrapper over `LynxElement.commitPendingTextNormalization()` so
|
|
@@ -4338,6 +4428,22 @@ export declare class LynxTextMeasure {
|
|
|
4338
4428
|
static ɵfac: i0.ɵɵFactoryDeclaration<LynxTextMeasure, never>;
|
|
4339
4429
|
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
4340
4430
|
}
|
|
4431
|
+
/**
|
|
4432
|
+
* The Material 3 color roles that dynamic color gives, by Material's names.
|
|
4433
|
+
* The error roles aren't here: Material keeps them red whatever the
|
|
4434
|
+
* wallpaper.
|
|
4435
|
+
*/
|
|
4436
|
+
export declare const DYNAMIC_COLOR_ROLES: readonly ["primary", "onPrimary", "primaryContainer", "onPrimaryContainer", "inversePrimary", "secondary", "onSecondary", "secondaryContainer", "onSecondaryContainer", "tertiary", "onTertiary", "tertiaryContainer", "onTertiaryContainer", "background", "onBackground", "surface", "onSurface", "surfaceVariant", "onSurfaceVariant", "surfaceDim", "surfaceBright", "surfaceContainerLowest", "surfaceContainerLow", "surfaceContainer", "surfaceContainerHigh", "surfaceContainerHighest", "inverseSurface", "inverseOnSurface", "outline", "outlineVariant"];
|
|
4437
|
+
type DynamicColorRole = (typeof DYNAMIC_COLOR_ROLES)[number];
|
|
4438
|
+
/**
|
|
4439
|
+
* Each role's color, as a hex color such as `#6750a4`.
|
|
4440
|
+
*/
|
|
4441
|
+
type DynamicColorScheme = { readonly [R in DynamicColorRole]: string; };
|
|
4442
|
+
/** The color scheme for each appearance: the app can be in either. */
|
|
4443
|
+
type DynamicColors = {
|
|
4444
|
+
readonly light: DynamicColorScheme;
|
|
4445
|
+
readonly dark: DynamicColorScheme;
|
|
4446
|
+
};
|
|
4341
4447
|
/**
|
|
4342
4448
|
* Provides reactive access to the current Lynx theme ('Dark' or 'Light').
|
|
4343
4449
|
*
|
|
@@ -4365,6 +4471,22 @@ export declare class LynxTheme {
|
|
|
4365
4471
|
* Whether the current theme is dark mode. Reactive.
|
|
4366
4472
|
*/
|
|
4367
4473
|
readonly isDarkMode: import("@angular/core").Signal<boolean>;
|
|
4474
|
+
/**
|
|
4475
|
+
* The colors Android 12 and later take from the user's wallpaper (Material
|
|
4476
|
+
* You's dynamic color), as Material 3's color roles in light and dark, or
|
|
4477
|
+
* `null` where the host sends none.
|
|
4478
|
+
*
|
|
4479
|
+
* Lynx has no API for them, so they come from the host app, in its
|
|
4480
|
+
* `dynamicColors` global prop: `{ light, dark }`, each with a hex color,
|
|
4481
|
+
* such as `#6750a4`, for every role in {@link DYNAMIC_COLOR_ROLES}. The
|
|
4482
|
+
* Android app `ng build --platform android` makes sends them, and new ones
|
|
4483
|
+
* when the user changes their wallpaper or colors. iOS, the web preview and
|
|
4484
|
+
* Lynx Explorer have none.
|
|
4485
|
+
*
|
|
4486
|
+
* Both schemes come at once, so an app with a dark mode of its own can
|
|
4487
|
+
* follow it rather than the phone's.
|
|
4488
|
+
*/
|
|
4489
|
+
readonly dynamicColors: import("@angular/core").Signal<DynamicColors | null>;
|
|
4368
4490
|
static ɵfac: i0.ɵɵFactoryDeclaration<LynxTheme, never>;
|
|
4369
4491
|
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
4370
4492
|
}
|
|
@@ -4946,4 +5068,4 @@ declare global {
|
|
|
4946
5068
|
catchmouseleave: MouseEvent;
|
|
4947
5069
|
}
|
|
4948
5070
|
}
|
|
4949
|
-
export type { BackgroundFnHandle, BaseLynxAnimation, DataProcessorDefinition, DevToolsStats, ExposureEventDetail, FlingGestureEvent, GestureCallback, GestureCallbackWithState, GestureEvent, GlobalData, GlobalExposureEvent, InitData, InitDataRaw, LongPressGestureEvent, LynxAnimationOptions, LynxFontEntry, LynxFontFaceConfig, LynxFontStatus, LynxTraceOptions, MainThread, MainThreadFnHandle, NativeModuleMap, NativeModuleProxy, ObserverFrameRateOptions, PanGestureEvent, PinchGestureEvent, PortalConfig, PrefetchCacheTarget, PrefetchPriority, PrefetchRequest, PrefetchResultDetail, ResourcePrefetchData, ResourcePrefetchResult, RotationGestureEvent, SessionStorageSubscription, TapGestureEvent };
|
|
5071
|
+
export type { AccessibilityTrait, AccessibilityTraitStates, BackgroundFnHandle, BaseLynxAnimation, BaseLynxElement, DataProcessorDefinition, DevToolsStats, DynamicColorRole, DynamicColorScheme, DynamicColors, ExposureEventDetail, FlingGestureEvent, GestureCallback, GestureCallbackWithState, GestureEvent, GlobalData, GlobalExposureEvent, InitData, InitDataRaw, LongPressGestureEvent, LynxAnimationOptions, LynxFontEntry, LynxFontFaceConfig, LynxFontStatus, LynxTraceOptions, MainThread, MainThreadFnHandle, NativeModuleMap, NativeModuleProxy, ObserverFrameRateOptions, PanGestureEvent, PinchGestureEvent, PortalConfig, PrefetchCacheTarget, PrefetchPriority, PrefetchRequest, PrefetchResultDetail, ResourcePrefetchData, ResourcePrefetchResult, RotationGestureEvent, SessionStorageSubscription, TapGestureEvent };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"blotch-angular-lynx-web-glass-ciDHw7Bw.mjs","names":[],"sources":["../../src/lib/web-glass/blur-view-layout.ts","../../src/lib/web-glass/backdrop-observer.ts","../../src/lib/web-glass/css-color.ts","../../src/lib/web-glass/drawn-scale.ts","../../src/lib/web-glass/backdrop-clone.ts","../../src/lib/web-glass/backdrop-snapshot.ts","../../src/lib/web-glass/glass-shaders.ts","../../src/lib/web-glass/glass-gl.ts","../../src/lib/web-glass/glass-renderer.ts","../../src/lib/web-glass/glass-press.ts","../../src/lib/web-glass/glass-shapes.ts","../../src/lib/web-glass/glass-group.ts","../../src/lib/web-glass/glass-host-style.ts","../../src/lib/web-glass/glass-manager.ts","../../src/lib/web-glass/web-glass.ts"],"sourcesContent":["/**\n * web-elements' container layout rules for `<x-view>` (`linear.css`), as\n * `:host` rules for `<x-blur-view>`.\n *\n * On iOS a blur view lays its children out like any view: `flex-col`,\n * `flex-row` and the default linear layout all apply. web-elements gives\n * `<x-blur-view>` `display: flex` but leaves it out of the rules that turn\n * Lynx's layout variables (the display toggle, the linear orientation,\n * `--flex-direction`) into CSS; those list only `<x-view>` and the other\n * containers. So on web a blur view ignored `flex-col` and set its children\n * out in a row: the element-blur-view example's label sat centered across the\n * top of its panel instead of vertically centered at the left.\n *\n * A `:host` rule loses to every style from outside the shadow root, so a class\n * such as `flex` (which sets `--lynx-display-toggle`) or an inline style still\n * wins, exactly as it does over web-elements' own `x-view` rules.\n *\n * Its children need one more rule to lay out as flex items. web-elements\n * sizes an item (`flex-1`, a linear weight) by container style queries on its\n * parent's `--lynx-display` and `--lynx-linear-orientation`. A blur view's\n * children sit in its shadow root's `<slot>`, which is the parent those\n * queries see, and the variables don't inherit, so `flex-1` did nothing in a\n * blur view: a glass capsule beside a button in a glass group stayed as\n * narrow as its content. The slot takes them from the host.\n */\nexport const BLUR_VIEW_LAYOUT_CSS =\n ':host{' +\n '--lynx-display-toggle:var(--lynx-display-linear);' +\n '--lynx-display-linear:var(--lynx-display-toggle,);' +\n '--lynx-display-flex:var(--lynx-display-toggle,);' +\n '--lynx-linear-orientation-toggle:var(--lynx-linear-orientation-vertical);' +\n '--lynx-linear-orientation-horizontal:var(--lynx-linear-orientation-toggle,);' +\n '--lynx-linear-orientation-vertical:var(--lynx-linear-orientation-toggle,);' +\n '--lynx-linear-orientation-horizontal-reverse:var(--lynx-linear-orientation-toggle,);' +\n '--lynx-linear-orientation-vertical-reverse:var(--lynx-linear-orientation-toggle,);' +\n '--linear-flex-direction:var(--lynx-linear-orientation-horizontal,row) ' +\n 'var(--lynx-linear-orientation-vertical,column) ' +\n 'var(--lynx-linear-orientation-horizontal-reverse,row-reverse) ' +\n 'var(--lynx-linear-orientation-vertical-reverse,column-reverse);' +\n '--linear-justify-content:var(--lynx-linear-orientation-horizontal,var(--justify-content-row)) ' +\n 'var(--lynx-linear-orientation-vertical,var(--justify-content-column)) ' +\n 'var(--lynx-linear-orientation-horizontal-reverse,var(--justify-content-row-reverse)) ' +\n 'var(--lynx-linear-orientation-vertical-reverse,var(--justify-content-column-reverse));' +\n 'flex-wrap:var(--lynx-display-linear,nowrap) var(--lynx-display-flex,var(--flex-wrap));' +\n 'flex-direction:var(--lynx-display-linear,var(--linear-flex-direction)) ' +\n 'var(--lynx-display-flex,var(--flex-direction));' +\n 'justify-content:var(--lynx-display-linear,var(--linear-justify-content))' +\n '}' +\n 'slot{--lynx-display:inherit;--lynx-linear-orientation:inherit;' +\n '--lynx-linear-weight-sum:inherit}';\n\n/**\n * Gives a `<blur-view>` on Lynx for Web the layout of a `<view>` (see\n * {@link BLUR_VIEW_LAYOUT_CSS}), through a `<style>` in its own shadow root.\n * Like the glass styles, it stays inside the element: Lynx owns its `class`\n * and `style` attributes.\n */\nexport const applyBlurViewLayout = (element: HTMLElement): void => {\n const root = element.shadowRoot;\n if (!root) return;\n const style = element.ownerDocument.createElement('style');\n style.textContent = BLUR_VIEW_LAYOUT_CSS;\n root.appendChild(style);\n};\n","/**\n * Calls `onChange` whenever what's behind the glass may look different:\n * something in `backdrop` mutates, resizes, scrolls or loads, web fonts\n * finish loading, or the color scheme flips. Changes inside `glass` itself (a\n * blob dragged by its left/top) don't count, since they don't change what's\n * behind it. Returns a function that stops observing.\n */\nexport const observeBackdrop = (\n backdrop: HTMLElement,\n glass: Element,\n onChange: () => void,\n): (() => void) => {\n const win = backdrop.ownerDocument.defaultView!;\n const mutations = new win.MutationObserver((records) => {\n if (records.some((record) => !glass.contains(record.target))) onChange();\n });\n mutations.observe(backdrop, {\n subtree: true,\n childList: true,\n attributes: true,\n characterData: true,\n });\n const resizes = new win.ResizeObserver(onChange);\n resizes.observe(backdrop);\n // Scroll and image load events don't bubble, but they do reach a capturing\n // listener on an ancestor.\n backdrop.addEventListener('scroll', onChange, true);\n backdrop.addEventListener('load', onChange, true);\n const scheme = win.matchMedia('(prefers-color-scheme: dark)');\n scheme.addEventListener('change', onChange);\n // Text reflows once web fonts load, moving what's behind the glass.\n void backdrop.ownerDocument.fonts.ready.then(onChange);\n return () => {\n mutations.disconnect();\n resizes.disconnect();\n backdrop.removeEventListener('scroll', onChange, true);\n backdrop.removeEventListener('load', onChange, true);\n scheme.removeEventListener('change', onChange);\n };\n};\n","/** A color as red, green, blue and alpha channels, each from 0 to 1. */\nexport type Rgba = readonly [number, number, number, number];\n\nexport const TRANSPARENT: Rgba = [0, 0, 0, 0];\n\nconst RGB_FUNCTION = /^rgba?\\(([^)]*)\\)$/;\nconst HEX = /^#([0-9a-f]{6})$/i;\n\n/**\n * Parses the two forms a browser hands back for a color it has normalized:\n * six-digit hex (an opaque canvas `fillStyle`) and `rgb()`/`rgba()` (computed\n * styles, a translucent `fillStyle`). Anything else is transparent, so a value\n * the browser couldn't parse draws nothing rather than black.\n */\nexport const parseNormalizedColor = (value: string): Rgba => {\n const hex = HEX.exec(value);\n if (hex) {\n const n = parseInt(hex[1]!, 16);\n return [(n >> 16) / 255, ((n >> 8) & 255) / 255, (n & 255) / 255, 1];\n }\n const fn = RGB_FUNCTION.exec(value.trim());\n if (!fn) return TRANSPARENT;\n const parts = fn[1]!\n .split(/[\\s,/]+/)\n .filter(Boolean)\n .map(Number);\n if (parts.length < 3 || parts.some(Number.isNaN)) return TRANSPARENT;\n const [r, g, b, a = 1] = parts as [number, number, number, number?];\n return [r / 255, g / 255, b / 255, a];\n};\n\nconst cache = new Map<string, Rgba>();\nlet context: CanvasRenderingContext2D | null | undefined;\n\n/**\n * Resolves any CSS color an author can write (`red`, `#3b82f6`, `rgba(…)`)\n * into channels. A canvas `fillStyle` normalizes the value without touching the\n * DOM or forcing a style recalculation. An invalid value leaves `fillStyle` unchanged,\n * so a sentinel set first tells the two apart.\n */\nexport const resolveCssColor = (doc: Document, value: string | null): Rgba => {\n if (!value) return TRANSPARENT;\n const cached = cache.get(value);\n if (cached) return cached;\n context ??= doc.createElement('canvas').getContext('2d');\n if (!context) return TRANSPARENT;\n const sentinel = 'rgba(1, 2, 3, 0.5)';\n context.fillStyle = sentinel;\n context.fillStyle = value;\n const normalized = String(context.fillStyle);\n const color =\n normalized === sentinel ? TRANSPARENT : parseNormalizedColor(normalized);\n cache.set(value, color);\n return color;\n};\n\n/** Relative luminance, used to pick the light or dark glass material. */\nexport const luminance = ([r, g, b]: Rgba): number =>\n 0.2126 * r + 0.7152 * g + 0.0722 * b;\n","/**\n * Screen pixels per CSS pixel that `element` is drawn at: below 1 when a\n * transform on it or an ancestor scales it down, as the docs' previews do to\n * fit a phone-sized page in their pane. getBoundingClientRect() measures in\n * screen pixels, but layout and every CSS length are in CSS pixels, so the\n * glass code divides boxes by this to keep to CSS pixels.\n */\nexport const drawnScale = (element: HTMLElement): number => {\n const drawn = element.getBoundingClientRect().width;\n // A transform doesn't change offsetWidth.\n const laidOut = element.offsetWidth;\n // offsetWidth is rounded to a whole pixel, so a difference of less than one\n // is rounding, not scale.\n if (!laidOut || Math.abs(drawn - laidOut) < 1) return 1;\n return drawn / laidOut;\n};\n","import { parseNormalizedColor, type Rgba } from './css-color';\nimport { drawnScale } from './drawn-scale';\n\n/** A rectangle in viewport (client) coordinates. */\nexport type Region = {\n left: number;\n top: number;\n right: number;\n bottom: number;\n};\n\nexport type CloneOptions = {\n /** Leaves an element, and everything inside it, out of the copy. */\n exclude: (element: Element) => boolean;\n /**\n * The part of the page the glass can show. A clipping element wholly\n * outside it is copied empty, which keeps long lists cheap to capture.\n */\n region: Region;\n};\n\ntype Context = {\n doc: Document;\n win: Window;\n defaults: Map<string, string>;\n} & CloneOptions;\n\n// Properties that can't change a still image, or that would start animating\n// inside it. Custom properties are already resolved into the real ones.\nconst SKIPPED_PROPERTY =\n /^(--|transition|animation|will-change|cursor|pointer-events|user-select|-webkit-user-)/;\n// Widths whose computed value matches a plain div's only because that div has\n// no border or outline: `0px` comes from `border-style: none`. Lynx for Web\n// gives every element `border-style: solid`, so leaving the width out would\n// draw a 3px (`medium`) black border in the copy.\nconst ALWAYS_INLINED =\n /^(border-(top|right|bottom|left)-width|outline-width|column-rule-width)$/;\nconst SKIPPED_TAGS = new Set(['style', 'script', 'template', 'link', 'meta']);\n\n// Node types, spelled out: on Lynx for Web the main thread runs in an iframe's\n// realm while the elements belong to the page, so `instanceof` checks against\n// this realm's DOM classes would always fail.\nconst ELEMENT_NODE = 1;\nconst TEXT_NODE = 3;\n\nconst defaultsByDocument = new WeakMap<Document, Map<string, string>>();\n\n/**\n * A plain div's computed style: anything matching it needn't be inlined.\n */\nconst defaultStyle = (doc: Document, win: Window): Map<string, string> => {\n let defaults = defaultsByDocument.get(doc);\n if (!defaults) {\n const probe = doc.createElement('div');\n doc.documentElement.appendChild(probe);\n const style = win.getComputedStyle(probe);\n defaults = new Map(\n Array.from(style, (name) => [name, style.getPropertyValue(name)]),\n );\n probe.remove();\n defaultsByDocument.set(doc, defaults);\n }\n return defaults;\n};\n\n/**\n * Inlines a computed style, keeping each property that differs from a plain\n * div or from the parent. The parent check matters for inherited properties:\n * a black heading inside white text matches the default but would inherit\n * white in the copy if it were left out.\n */\nconst inlineStyle = (\n style: CSSStyleDeclaration,\n parent: CSSStyleDeclaration | null,\n defaults: Map<string, string>,\n): string => {\n let css = '';\n for (const name of Array.from(style)) {\n if (SKIPPED_PROPERTY.test(name)) continue;\n const value = style.getPropertyValue(name);\n if (\n ALWAYS_INLINED.test(name) ||\n value !== defaults.get(name) ||\n (parent && value !== parent.getPropertyValue(name))\n ) {\n css += `${name}:${value};`;\n }\n }\n return css;\n};\n\n/**\n * Children as they render: a shadow root's children instead of the light\n * ones, with each `<slot>` replaced by what's assigned to it. Every Lynx for\n * Web element is a custom element that draws its children through a slot.\n */\nconst renderedChildren = (element: Element): Node[] =>\n Array.from(element.shadowRoot?.childNodes ?? element.childNodes).flatMap(\n (child) =>\n (child as Element).localName === 'slot'\n ? (child as HTMLSlotElement).assignedNodes({ flatten: true })\n : [child],\n );\n\n/**\n * Moves a child of a scrolled element by the scroll offset, so the copy shows\n * what's scrolled into view rather than the top of the content.\n */\nconst scrollShift = (\n style: CSSStyleDeclaration,\n [x, y]: readonly [number, number],\n): string => {\n if (!x && !y) return '';\n if (style.position === 'fixed' || style.position === 'sticky') return '';\n if (style.position === 'static') {\n return `position:relative;left:${-x}px;top:${-y}px;`;\n }\n const left = (parseFloat(style.left) || 0) - x;\n const top = (parseFloat(style.top) || 0) - y;\n return `left:${left}px;top:${top}px;`;\n};\n\n/**\n * Inlines an image as a data URL: an SVG image can't load anything external.\n * A cross-origin image without CORS taints the canvas and is left blank.\n */\nconst mediaSource = (element: Element, doc: Document): string => {\n try {\n if (element.localName === 'canvas') {\n return (element as HTMLCanvasElement).toDataURL();\n }\n const image = element as HTMLImageElement;\n if (!image.complete || !image.naturalWidth) return '';\n const canvas = doc.createElement('canvas');\n canvas.width = image.naturalWidth;\n canvas.height = image.naturalHeight;\n canvas.getContext('2d')!.drawImage(image, 0, 0);\n return canvas.toDataURL();\n } catch {\n return '';\n }\n};\n\nconst outside = (rect: DOMRect, region: Region): boolean =>\n rect.right <= region.left ||\n rect.left >= region.right ||\n rect.bottom <= region.top ||\n rect.top >= region.bottom;\n\nconst cloneNode = (\n node: Node,\n context: Context,\n parent: CSSStyleDeclaration | null,\n scroll: readonly [number, number],\n): Node | null => {\n if (node.nodeType === TEXT_NODE) {\n return context.doc.createTextNode((node as Text).data);\n }\n if (node.nodeType !== ELEMENT_NODE) return null;\n const element = node as Element;\n if (SKIPPED_TAGS.has(element.localName) || context.exclude(element)) {\n return null;\n }\n const style = context.win.getComputedStyle(element);\n if (style.display === 'none') return null;\n\n const media = element.localName === 'img' || element.localName === 'canvas';\n const clone = context.doc.createElement(media ? 'img' : 'div');\n clone.setAttribute(\n 'style',\n inlineStyle(style, parent, context.defaults) + scrollShift(style, scroll),\n );\n if (media) {\n const source = mediaSource(element, context.doc);\n if (source) clone.setAttribute('src', source);\n return clone;\n }\n const clips = style.overflowX !== 'visible' || style.overflowY !== 'visible';\n if (clips && outside(element.getBoundingClientRect(), context.region)) {\n return clone;\n }\n const childScroll = [element.scrollLeft, element.scrollTop] as const;\n for (const child of renderedChildren(element)) {\n const copy = cloneNode(child, context, style, childScroll);\n if (copy) clone.appendChild(copy);\n }\n return clone;\n};\n\n/**\n * The color behind an element: its own background, or the first ancestor's\n * that isn't transparent, crossing shadow roots. White when nothing paints.\n */\nexport const effectiveBackground = (element: Element): Rgba => {\n const win = element.ownerDocument.defaultView!;\n let node: Element | null = element;\n while (node) {\n const color = parseNormalizedColor(\n win.getComputedStyle(node).backgroundColor,\n );\n if (color[3] > 0) return color;\n node =\n node.parentElement ??\n ((node.getRootNode() as Partial<ShadowRoot>).host as Element | null) ??\n null;\n }\n return [1, 1, 1, 1];\n};\n\n/**\n * Copies `root` into plain divs with inlined styles, ready to rasterize inside\n * an SVG `<foreignObject>`. The copy is pinned to the top-left of a frame the\n * size of `root`, painted with the color behind it, so transparent areas show\n * what the page shows there instead of nothing.\n *\n * The frame is rounded up to whole CSS pixels. The browser paints it in whole\n * pixels, so a fractional size would leave its last row or column part\n * transparent, and the glass shows a transparent image edge as a dark band.\n */\nexport const cloneBackdrop = (\n root: HTMLElement,\n options: CloneOptions,\n): HTMLElement => {\n const doc = root.ownerDocument;\n const win = doc.defaultView!;\n // The root's size in CSS pixels, which its copied contents lay out in,\n // rather than its scaled size when the page is drawn scaled.\n const bounds = root.getBoundingClientRect();\n const zoom = drawnScale(root);\n const width = bounds.width / zoom;\n const height = bounds.height / zoom;\n const [r, g, b, a] = effectiveBackground(root);\n const frame = doc.createElement('div');\n frame.setAttribute(\n 'style',\n `width:${Math.ceil(width)}px;height:${Math.ceil(height)}px;` +\n `overflow:hidden;` +\n `background:rgba(${r * 255},${g * 255},${b * 255},${a});`,\n );\n const context = { ...options, doc, win, defaults: defaultStyle(doc, win) };\n const clone = cloneNode(root, context, null, [0, 0]) as HTMLElement | null;\n if (clone) {\n // Whatever placed the root in the page (margins, offsets, transforms)\n // isn't part of the picture.\n clone.style.cssText +=\n `margin:0;position:relative;left:0;top:0;right:auto;bottom:auto;` +\n `transform:none;width:${width}px;height:${height}px;`;\n frame.appendChild(clone);\n }\n return frame;\n};\n","import {\n cloneBackdrop,\n effectiveBackground,\n type CloneOptions,\n} from './backdrop-clone';\nimport { luminance } from './css-color';\nimport { drawnScale } from './drawn-scale';\n\n/** An image of what sits behind a glass group. */\nexport type BackdropSnapshot = {\n image: HTMLCanvasElement;\n /** The captured region, relative to the backdrop root, in CSS pixels. */\n x: number;\n y: number;\n width: number;\n height: number;\n /** How bright the backdrop's background is, from 0 to 1. */\n luminance: number;\n};\n\nexport type SnapshotOptions = {\n /** Device pixels per CSS pixel to capture at. */\n scale: number;\n} & CloneOptions;\n\n// Keeps the image inside every GPU's texture limit (WebGL 1 guarantees far\n// less, but phones and desktops alike accept 4096).\nconst MAX_IMAGE_SIZE = 4096;\n\n/**\n * Captures part of `root` as an image. The browser can't hand page pixels to\n * WebGL, so the page is redrawn instead: the subtree is copied with inlined\n * styles (see backdrop-clone.ts), wrapped in an SVG `<foreignObject>` and\n * drawn to a canvas. The SVG's viewBox crops it to `region`, so only the area\n * the glass can show is rasterized.\n *\n * Resolves to null when the region doesn't overlap `root`.\n */\nexport const snapshotBackdrop = async (\n root: HTMLElement,\n options: SnapshotOptions,\n): Promise<BackdropSnapshot | null> => {\n const doc = root.ownerDocument;\n const win = doc.defaultView!;\n const bounds = root.getBoundingClientRect();\n const left = Math.max(options.region.left, bounds.left);\n const top = Math.max(options.region.top, bounds.top);\n const right = Math.min(options.region.right, bounds.right);\n const bottom = Math.min(options.region.bottom, bounds.bottom);\n if (right <= left || bottom <= top) return null;\n // The region and the root's box are in screen pixels, but the copy lays out\n // in CSS pixels: the two differ when the page is drawn scaled.\n const zoom = drawnScale(root);\n const x = (left - bounds.left) / zoom;\n const y = (top - bounds.top) / zoom;\n const width = (right - left) / zoom;\n const height = (bottom - top) / zoom;\n const scale = Math.min(\n options.scale,\n MAX_IMAGE_SIZE / Math.max(width, height),\n );\n\n const markup = new win.XMLSerializer().serializeToString(\n cloneBackdrop(root, options),\n );\n const pixelWidth = Math.max(1, Math.round(width * scale));\n const pixelHeight = Math.max(1, Math.round(height * scale));\n // The image's edges must be opaque: the glass clamps to them where its lens\n // looks past the image, so a transparent row there shows as a dark band.\n // Rounding the image's width and height separately leaves its shape a\n // little off the viewBox's, which the default `preserveAspectRatio` would\n // fit with an empty strip along one edge, so the viewBox is stretched\n // instead. The <foreignObject> matches the copy's frame, which is rounded up\n // to whole pixels (see cloneBackdrop).\n const svg =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${pixelWidth}\" ` +\n `height=\"${pixelHeight}\" viewBox=\"${x} ${y} ${width} ${height}\" ` +\n `preserveAspectRatio=\"none\">` +\n `<foreignObject width=\"${Math.ceil(bounds.width / zoom)}\" ` +\n `height=\"${Math.ceil(bounds.height / zoom)}\">` +\n `${markup}</foreignObject></svg>`;\n const picture = new win.Image();\n picture.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;\n await picture.decode();\n\n const image = doc.createElement('canvas');\n image.width = pixelWidth;\n image.height = pixelHeight;\n image.getContext('2d')!.drawImage(picture, 0, 0, pixelWidth, pixelHeight);\n return {\n image,\n x,\n y,\n width,\n height,\n luminance: luminance(effectiveBackground(root)),\n };\n};\n","/**\n * The most glass shapes one group draws. GLSL ES 1.0 (WebGL 1) needs a\n * constant array size and loop bound; a container rarely holds more than a\n * handful of shapes, and any past this aren't drawn.\n */\nexport const MAX_GLASS_SHAPES = 16;\n\n/** Full-screen quad. `v_uv` runs 0→1 with y pointing up, as GL does. */\nexport const QUAD_VERTEX_SHADER = `\nattribute vec2 a_position;\nvarying vec2 v_uv;\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}`;\n\n/** Copies a texture, downsampling the backdrop before it is blurred. */\nexport const COPY_FRAGMENT_SHADER = `\nprecision mediump float;\nvarying vec2 v_uv;\nuniform sampler2D u_source;\nvoid main() {\n gl_FragColor = texture2D(u_source, v_uv);\n}`;\n\n/**\n * One direction of a separable Gaussian blur. Sampling between two pixels lets\n * the linear filter average both at once, so five fetches cover nine pixels.\n */\nexport const BLUR_FRAGMENT_SHADER = `\nprecision mediump float;\nvarying vec2 v_uv;\nuniform sampler2D u_source;\nuniform vec2 u_direction;\nvoid main() {\n vec2 near = u_direction * 1.3846153846;\n vec2 far = u_direction * 3.2307692308;\n gl_FragColor = texture2D(u_source, v_uv) * 0.2270270270\n + (texture2D(u_source, v_uv + near) + texture2D(u_source, v_uv - near)) * 0.3162162162\n + (texture2D(u_source, v_uv + far) + texture2D(u_source, v_uv - far)) * 0.0702702703;\n}`;\n\n/**\n * Draws every glass shape of a group in one pass, in CSS pixels with y down.\n *\n * GLSL ES 1.0 only lets a loop's own counter index the uniform arrays, so the\n * per-shape distance is written out in each loop rather than in a helper.\n *\n * - Each shape is a rounded box signed distance field (SDF). A smooth minimum\n * unions them, so shapes closer than the container's `spacing` flow into one\n * another like iOS 26's glass container.\n * - The lens samples the backdrop outward near the rim, where the glass is\n * steepest, and slightly inward elsewhere. The rim shows the content just\n * outside it bent around the edge, and the middle reads a little magnified.\n * The SDF gradient gives the direction; its length fades the effect where\n * merged shapes crease, which would otherwise show a seam.\n * - `regular` glass mixes in a blurred, brightened backdrop; `clear` glass\n * keeps it sharp. Tint, a specular rim lit from the top left, and a press\n * glow for interactive glass go on top.\n */\nexport const GLASS_FRAGMENT_SHADER = `\nprecision highp float;\n#define MAX_SHAPES ${MAX_GLASS_SHAPES}\nvarying vec2 v_uv;\nuniform sampler2D u_backdrop;\nuniform sampler2D u_frosted;\nuniform vec2 u_size;\nuniform vec2 u_offset;\nuniform vec2 u_backdropSize;\nuniform float u_scale;\nuniform float u_smoothing;\nuniform float u_dark;\nuniform float u_shadow;\nuniform int u_count;\nuniform vec4 u_bounds[MAX_SHAPES];\nuniform vec4 u_material[MAX_SHAPES];\nuniform vec4 u_tint[MAX_SHAPES];\nuniform vec3 u_pointer;\n\nfloat roundedBox(vec2 p, vec2 halfSize, float radius) {\n vec2 q = abs(p) - halfSize + radius;\n return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;\n}\n\nfloat smoothUnion(float a, float b, float k) {\n if (k <= 0.0) return min(a, b);\n float h = max(k - abs(a - b), 0.0) / k;\n return min(a, b) - h * h * k * 0.25;\n}\n\nfloat scene(vec2 p) {\n float d = 1e5;\n for (int i = 0; i < MAX_SHAPES; i++) {\n if (i >= u_count) break;\n d = smoothUnion(d, roundedBox(p - u_bounds[i].xy, u_bounds[i].zw, u_material[i].x), u_smoothing);\n }\n return d;\n}\n\nvoid main() {\n vec2 p = vec2(v_uv.x, 1.0 - v_uv.y) * u_size;\n\n // Union the shapes, and blend each shape's material by how close it is, so\n // a merged bridge between two tints shades from one to the other.\n float d = 1e5;\n float weights = 0.0;\n float frost = 0.0;\n float lens = 0.0;\n vec4 tint = vec4(0.0);\n for (int i = 0; i < MAX_SHAPES; i++) {\n if (i >= u_count) break;\n float di = roundedBox(p - u_bounds[i].xy, u_bounds[i].zw, u_material[i].x);\n d = smoothUnion(d, di, u_smoothing);\n float w = exp(-max(di, 0.0) / max(u_smoothing * 0.3, 1.0)) + 1e-6;\n weights += w;\n frost += u_material[i].y * w;\n lens += min(u_bounds[i].z, u_bounds[i].w) * w;\n tint += u_tint[i] * w;\n }\n frost /= weights;\n lens = max(lens / weights, 1.0);\n tint /= weights;\n\n // One device pixel of anti-aliasing at the edge.\n float coverage = clamp(0.5 - d * u_scale, 0.0, 1.0);\n // A container can hug its shapes, so the shadow fades out before the canvas\n // edge rather than stopping at it in a hard line.\n vec2 inside = min(p, u_size - p);\n float shadow = u_shadow * 0.1 * exp(-max(d, 0.0) / 6.0)\n * smoothstep(0.0, 12.0, min(inside.x, inside.y));\n if (coverage <= 0.0) {\n gl_FragColor = vec4(0.0, 0.0, 0.0, d < 24.0 ? shadow : 0.0);\n return;\n }\n\n vec2 e = vec2(0.5, 0.0);\n vec2 gradient = vec2(\n scene(p + e.xy) - scene(p - e.xy),\n scene(p + e.yx) - scene(p - e.yx));\n float slope = length(gradient);\n vec2 normal = slope > 0.0 ? gradient / slope : vec2(0.0);\n gradient = normal * min(slope, 1.0);\n\n float depth = max(-d, 0.0);\n float rim = pow(1.0 - clamp(depth / lens, 0.0, 1.0), 3.0);\n vec2 offset = gradient * (lens * 0.45 * rim - max(lens - depth, 0.0) * 0.05);\n vec2 base = p + u_offset;\n vec2 uv = (base + offset) / u_backdropSize;\n\n // A touch of dispersion: red bends a little more than blue.\n vec3 sharp = vec3(\n texture2D(u_backdrop, (base + offset * 1.035) / u_backdropSize).r,\n texture2D(u_backdrop, uv).g,\n texture2D(u_backdrop, (base + offset * 0.965) / u_backdropSize).b);\n vec3 color = mix(sharp, texture2D(u_frosted, uv).rgb, frost);\n\n float brightness = dot(color, vec3(0.2126, 0.7152, 0.0722));\n color = mix(vec3(brightness), color, 1.0 + 0.3 * frost);\n color = mix(color, mix(vec3(1.0), vec3(0.12), u_dark), frost * mix(0.22, 0.34, u_dark));\n color *= 1.0 - 0.08 * u_dark * (1.0 - frost);\n color = mix(color, tint.rgb, tint.a);\n\n vec2 light = normalize(vec2(-0.6, -0.8));\n float facing = dot(normal, light);\n color += (1.0 - smoothstep(0.0, 1.5, depth)) * (0.22 + 0.58 * pow(abs(facing), 1.5)) * mix(0.75, 0.5, u_dark);\n color += (1.0 - smoothstep(0.0, lens * 0.5, depth)) * max(facing, 0.0) * 0.16;\n color += (1.0 - smoothstep(0.0, lens * 0.35, depth)) * max(-facing, 0.0) * 0.07;\n\n float reach = length(p - u_pointer.xy);\n color += u_pointer.z * 0.2 * exp(-reach * reach / (1.2 * lens * lens));\n\n gl_FragColor = vec4(clamp(color, 0.0, 1.0) * coverage, coverage + shadow * (1.0 - coverage));\n}`;\n","import { QUAD_VERTEX_SHADER } from './glass-shaders';\n\nexport type Program = {\n program: WebGLProgram;\n uniform: (name: string) => WebGLUniformLocation | null;\n};\n\nexport type Target = {\n texture: WebGLTexture;\n framebuffer: WebGLFramebuffer;\n};\n\nexport const compile = (\n gl: WebGLRenderingContext,\n fragmentSource: string,\n): Program | null => {\n const program = gl.createProgram();\n for (const [type, source] of [\n [gl.VERTEX_SHADER, QUAD_VERTEX_SHADER],\n [gl.FRAGMENT_SHADER, fragmentSource],\n ] as const) {\n const shader = gl.createShader(type)!;\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n gl.attachShader(program, shader);\n }\n // Every program shares the one quad buffer bound to attribute 0.\n gl.bindAttribLocation(program, 0, 'a_position');\n gl.linkProgram(program);\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) return null;\n const locations = new Map<string, WebGLUniformLocation | null>();\n const uniform = (name: string) => {\n if (!locations.has(name)) {\n locations.set(name, gl.getUniformLocation(program, name));\n }\n return locations.get(name)!;\n };\n return { program, uniform };\n};\n\nexport const createTexture = (gl: WebGLRenderingContext): WebGLTexture => {\n const texture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, texture);\n // WebGL 1 can't mipmap or repeat non-power-of-two textures; clamping also\n // stretches the backdrop's edge when the lens samples past it.\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n return texture;\n};\n\nexport const createTarget = (\n gl: WebGLRenderingContext,\n width: number,\n height: number,\n): Target => {\n const texture = createTexture(gl);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n width,\n height,\n 0,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n null,\n );\n const framebuffer = gl.createFramebuffer();\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n texture,\n 0,\n );\n return { texture, framebuffer };\n};\n","import type { Rgba } from './css-color';\nimport {\n compile,\n createTarget,\n createTexture,\n type Program,\n type Target,\n} from './glass-gl';\nimport {\n BLUR_FRAGMENT_SHADER,\n COPY_FRAGMENT_SHADER,\n GLASS_FRAGMENT_SHADER,\n MAX_GLASS_SHAPES,\n} from './glass-shaders';\n\n/** One glass shape, in CSS pixels relative to the group's canvas. */\nexport type GlassShapeFrame = {\n centerX: number;\n centerY: number;\n halfWidth: number;\n halfHeight: number;\n radius: number;\n /** 1 for `regular` (frosted) glass, 0 for `clear`. */\n frost: number;\n tint: Rgba;\n};\n\n/** Everything one frame of a glass group draws. */\nexport type GlassFrame = {\n /** Device pixels per CSS pixel. */\n scale: number;\n /** Canvas size, in CSS pixels. */\n width: number;\n height: number;\n /** Where the canvas's top-left corner sits in the backdrop, in CSS pixels. */\n offsetX: number;\n offsetY: number;\n /** Smooth-union radius, in CSS pixels: twice the container's `spacing`. */\n smoothing: number;\n /** 1 for the dark material, 0 for light. */\n dark: number;\n /** 1 to draw a soft shadow around the shapes (containers only). */\n shadow: number;\n shapes: readonly GlassShapeFrame[];\n /** Press glow: x and y in CSS pixels, then strength from 0 to 1. */\n pointer: readonly [number, number, number];\n};\n\n// Frosted glass blurs a copy of the backdrop at a quarter of its resolution:\n// three blur passes there cost little and soften it as much as iOS's material.\nconst FROST_DOWNSAMPLE = 4;\nconst FROST_PASSES = 3;\n\n/**\n * Draws Liquid Glass with WebGL 1 for Lynx for Web, where `<blur-view>` only\n * knows `backdrop-filter: blur()`. The backdrop is an image of what sits\n * behind the glass; the group code takes it (see backdrop-snapshot.ts) and the\n * renderer refracts it through the glass shapes.\n */\nexport class GlassRenderer {\n readonly #gl: WebGLRenderingContext;\n readonly #copy: Program;\n readonly #blur: Program;\n readonly #glass: Program;\n readonly #quad: WebGLBuffer;\n #backdrop: WebGLTexture | null = null;\n #frosted: [Target, Target] | null = null;\n #frostedSize = '';\n #backdropWidth = 1;\n #backdropHeight = 1;\n\n /**\n * Use `GlassRenderer.create`, which builds the programs this needs.\n */\n constructor(\n gl: WebGLRenderingContext,\n copy: Program,\n blur: Program,\n glass: Program,\n ) {\n this.#gl = gl;\n this.#copy = copy;\n this.#blur = blur;\n this.#glass = glass;\n this.#quad = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, this.#quad);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),\n gl.STATIC_DRAW,\n );\n gl.enableVertexAttribArray(0);\n gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);\n }\n\n /**\n * Null when the browser has no WebGL or can't build the shaders.\n */\n static create(canvas: HTMLCanvasElement): GlassRenderer | null {\n const gl = canvas.getContext('webgl', {\n alpha: true,\n premultipliedAlpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n });\n if (!gl) return null;\n const copy = compile(gl, COPY_FRAGMENT_SHADER);\n const blur = compile(gl, BLUR_FRAGMENT_SHADER);\n const glass = compile(gl, GLASS_FRAGMENT_SHADER);\n if (!copy || !blur || !glass) return null;\n return new GlassRenderer(gl, copy, blur, glass);\n }\n\n /**\n * True once the GPU dropped the context; the group then starts over.\n */\n get lost(): boolean {\n return this.#gl.isContextLost();\n }\n\n /**\n * Uploads a new backdrop image and blurs a copy of it for frosted glass.\n * `width` and `height` are its size in CSS pixels.\n */\n setBackdrop(image: HTMLCanvasElement, width: number, height: number): void {\n const gl = this.#gl;\n this.#backdropWidth = width;\n this.#backdropHeight = height;\n this.#backdrop ??= createTexture(gl);\n gl.bindTexture(gl.TEXTURE_2D, this.#backdrop);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);\n\n const w = Math.max(1, Math.round(image.width / FROST_DOWNSAMPLE));\n const h = Math.max(1, Math.round(image.height / FROST_DOWNSAMPLE));\n if (this.#frostedSize !== `${w}x${h}`) {\n this.#deleteFrosted();\n this.#frosted = [createTarget(gl, w, h), createTarget(gl, w, h)];\n this.#frostedSize = `${w}x${h}`;\n }\n const [a, b] = this.#frosted!;\n gl.viewport(0, 0, w, h);\n this.#pass(this.#copy, this.#backdrop, a);\n for (let i = 0; i < FROST_PASSES; i++) {\n this.#pass(this.#blur, a.texture, b, [1 / w, 0]);\n this.#pass(this.#blur, b.texture, a, [0, 1 / h]);\n }\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n }\n\n draw(frame: GlassFrame): void {\n const gl = this.#gl;\n const { uniform } = this.#glass;\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n if (!this.#backdrop) return;\n\n gl.useProgram(this.#glass.program);\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, this.#frosted![0].texture);\n gl.uniform1i(uniform('u_frosted'), 1);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this.#backdrop);\n gl.uniform1i(uniform('u_backdrop'), 0);\n\n gl.uniform2f(uniform('u_size'), frame.width, frame.height);\n gl.uniform2f(uniform('u_offset'), frame.offsetX, frame.offsetY);\n gl.uniform2f(\n uniform('u_backdropSize'),\n this.#backdropWidth,\n this.#backdropHeight,\n );\n gl.uniform1f(uniform('u_scale'), frame.scale);\n gl.uniform1f(uniform('u_smoothing'), frame.smoothing);\n gl.uniform1f(uniform('u_dark'), frame.dark);\n gl.uniform1f(uniform('u_shadow'), frame.shadow);\n gl.uniform3f(uniform('u_pointer'), ...frame.pointer);\n\n const shapes = frame.shapes.slice(0, MAX_GLASS_SHAPES);\n const bounds = new Float32Array(MAX_GLASS_SHAPES * 4);\n const material = new Float32Array(MAX_GLASS_SHAPES * 4);\n const tint = new Float32Array(MAX_GLASS_SHAPES * 4);\n shapes.forEach((shape, i) => {\n bounds.set(\n [shape.centerX, shape.centerY, shape.halfWidth, shape.halfHeight],\n i * 4,\n );\n material.set([shape.radius, shape.frost, 0, 0], i * 4);\n tint.set(shape.tint, i * 4);\n });\n gl.uniform1i(uniform('u_count'), shapes.length);\n gl.uniform4fv(uniform('u_bounds'), bounds);\n gl.uniform4fv(uniform('u_material'), material);\n gl.uniform4fv(uniform('u_tint'), tint);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n\n dispose(): void {\n const gl = this.#gl;\n this.#deleteFrosted();\n gl.deleteTexture(this.#backdrop);\n gl.deleteBuffer(this.#quad);\n for (const { program } of [this.#copy, this.#blur, this.#glass]) {\n gl.deleteProgram(program);\n }\n // Browsers cap live WebGL contexts (16 in Chrome); give this one back now\n // instead of waiting for garbage collection.\n gl.getExtension('WEBGL_lose_context')?.loseContext();\n }\n\n #pass(\n program: Program,\n source: WebGLTexture,\n target: Target,\n direction?: readonly [number, number],\n ): void {\n const gl = this.#gl;\n gl.useProgram(program.program);\n gl.bindFramebuffer(gl.FRAMEBUFFER, target.framebuffer);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, source);\n gl.uniform1i(program.uniform('u_source'), 0);\n if (direction) gl.uniform2f(program.uniform('u_direction'), ...direction);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n\n #deleteFrosted(): void {\n for (const target of this.#frosted ?? []) {\n this.#gl.deleteTexture(target.texture);\n this.#gl.deleteFramebuffer(target.framebuffer);\n }\n this.#frosted = null;\n }\n}\n","/** How far an interactive glass shape is pressed, and where. */\nexport type PressState = {\n /** 1 while a pointer is down on the shape, else 0. */\n target: number;\n /** Eased from 0 (at rest) to 1 (fully pressed). */\n value: number;\n /** The pointer, in viewport (client) coordinates. */\n x: number;\n y: number;\n};\n\nconst presses = new WeakMap<Element, PressState>();\n\n// Time constants of the ease, in milliseconds: iOS's glass swells quickly\n// under a finger and settles back more slowly.\nconst PRESS_IN_MS = 70;\nconst PRESS_OUT_MS = 180;\n\n/**\n * Follows pointer presses on a `<blur-view>`, for `glass-interactive`. The\n * listeners are passive and never stop propagation, so the element's own\n * Lynx touch and tap handlers still run. The attribute is checked when a press\n * starts, since it can be bound and change at any time.\n */\nexport const trackPress = (element: HTMLElement): void => {\n const state: PressState = { target: 0, value: 0, x: 0, y: 0 };\n presses.set(element, state);\n const follow = (event: PointerEvent) => {\n state.x = event.clientX;\n state.y = event.clientY;\n };\n const release = () => {\n state.target = 0;\n };\n const options = { passive: true };\n element.addEventListener(\n 'pointerdown',\n (event) => {\n if (!element.hasAttribute('glass-interactive')) return;\n state.target = 1;\n follow(event);\n },\n options,\n );\n element.addEventListener(\n 'pointermove',\n (event) => {\n if (state.target) follow(event);\n },\n options,\n );\n for (const type of ['pointerup', 'pointercancel', 'pointerleave']) {\n element.addEventListener(type, release, options);\n }\n};\n\nexport const pressOf = (element: Element): PressState | undefined =>\n presses.get(element);\n\n/**\n * Eases a press toward its target over `elapsed` milliseconds. Returns the\n * new value, snapping to the target once it's indistinguishable.\n */\nexport const stepPress = (state: PressState, elapsed: number): number => {\n const time = state.target ? PRESS_IN_MS : PRESS_OUT_MS;\n const next =\n state.target + (state.value - state.target) * Math.exp(-elapsed / time);\n state.value = Math.abs(next - state.target) < 0.001 ? state.target : next;\n return state.value;\n};\n","import { resolveCssColor } from './css-color';\nimport { pressOf, stepPress } from './glass-press';\nimport type { GlassShapeFrame } from './glass-renderer';\n\n/**\n * What a `<blur-view>` is to the glass code:\n * - `container`: a `glass-container`, which draws its glass children as one\n * group so nearby shapes merge.\n * - `standalone`: a `glass` element outside any container, its own group.\n * - `member`: a `glass` element its parent container draws.\n */\nexport type GlassRole = 'container' | 'standalone' | 'member';\n\nexport const glassRole = (element: Element): GlassRole | null => {\n const effect = element.getAttribute('blur-effect');\n if (effect === 'glass-container') return 'container';\n if (effect !== 'glass') return null;\n const parent = element.parentElement?.getAttribute('blur-effect');\n return parent === 'glass-container' ? 'member' : 'standalone';\n};\n\n/**\n * The shapes a container groups. iOS only merges the glass views placed\n * directly in the container, so only direct children count here too.\n */\nexport const containerShapes = (container: Element): HTMLElement[] =>\n Array.from(container.children).filter(\n (child): child is HTMLElement =>\n child.getAttribute('blur-effect') === 'glass',\n );\n\n/**\n * A corner radius as the shader needs it: one value in pixels, no larger than\n * half the shorter side. Computed styles give pixels or a percentage, and\n * `rounded-full` (9999px) clamps to a circle or a pill.\n */\nexport const cornerRadius = (\n value: string,\n width: number,\n height: number,\n): number => {\n const shorter = Math.min(width, height);\n const radius = value.endsWith('%')\n ? (parseFloat(value) / 100) * shorter\n : parseFloat(value) || 0;\n return Math.min(radius, shorter / 2);\n};\n\n// How much an interactive shape swells while pressed, as on iOS.\nconst PRESS_GROWTH = 0.06;\n\n/**\n * Reads one shape for a frame, relative to the group canvas at `origin`.\n * Advances its press animation by `elapsed` milliseconds; only containers let\n * a pressed shape `grow`, since a standalone shape's canvas is its own box\n * and Lynx clips anything drawn outside it.\n *\n * The shape's box and `origin` are in screen pixels, drawn at `zoom` screen\n * pixels per CSS pixel (see drawn-scale.ts); the frame is in CSS pixels, like\n * its corner radius.\n */\nexport const readShape = (\n element: HTMLElement,\n origin: DOMRect,\n zoom: number,\n elapsed: number,\n grow: boolean,\n): GlassShapeFrame & { press: number } => {\n const box = element.getBoundingClientRect();\n const left = (box.left - origin.left) / zoom;\n const top = (box.top - origin.top) / zoom;\n const width = box.width / zoom;\n const height = box.height / zoom;\n const style = element.ownerDocument.defaultView!.getComputedStyle(element);\n const press = pressOf(element);\n const pressed = press ? stepPress(press, elapsed) : 0;\n const swell = grow ? 1 + PRESS_GROWTH * pressed : 1;\n return {\n centerX: left + width / 2,\n centerY: top + height / 2,\n halfWidth: (width / 2) * swell,\n halfHeight: (height / 2) * swell,\n radius: cornerRadius(style.borderTopLeftRadius, width, height) * swell,\n frost: element.getAttribute('glass-style') === 'clear' ? 0 : 1,\n tint: resolveCssColor(\n element.ownerDocument,\n element.getAttribute('glass-tint-color'),\n ),\n press: pressed,\n };\n};\n","import { observeBackdrop } from './backdrop-observer';\nimport { snapshotBackdrop, type BackdropSnapshot } from './backdrop-snapshot';\nimport { parseNormalizedColor } from './css-color';\nimport { drawnScale } from './drawn-scale';\nimport { GlassRenderer, type GlassFrame } from './glass-renderer';\nimport { pressOf } from './glass-press';\nimport { containerShapes, readShape } from './glass-shapes';\n\n// The lens samples up to about half a shape's radius past its edge, so the\n// captured region reaches this far beyond the group.\nconst CAPTURE_MARGIN = 48;\n// Captures run on the main thread, so they're spaced out: at least this many\n// milliseconds apart, and four times as long as the last one took.\nconst MIN_CAPTURE_INTERVAL = 100;\n// Sharper than 2x costs memory and capture time for no visible gain.\nconst MAX_SCALE = 2;\n// Backdrops darker than this get the dark material, like iOS in dark mode.\nconst DARK_LUMINANCE = 0.4;\n\n/**\n * The element whose drawing a glass group refracts: the nearest ancestor that\n * paints over everything behind it, with an opaque background color or a\n * background image, or else the topmost one, the page. The glass's own parent\n * is often a row or a wrapper that draws nothing, while what the glass floats\n * over belongs to an ancestor: a card's gradient, or the screen's content.\n * iOS's glass shows whatever is on screen behind it.\n */\nexport const backdropOf = (root: HTMLElement): HTMLElement | null => {\n const win = root.ownerDocument.defaultView!;\n let element = root.parentElement;\n while (element?.parentElement) {\n const style = win.getComputedStyle(element);\n if (\n (style.backgroundImage && style.backgroundImage !== 'none') ||\n parseNormalizedColor(style.backgroundColor)[3] >= 1\n ) {\n return element;\n }\n element = element.parentElement;\n }\n return element;\n};\n\n/**\n * Draws one group of Liquid Glass on Lynx for Web: a `glass-container` and the\n * glass shapes directly inside it, or a lone `glass` element.\n *\n * A canvas in the root's shadow root, stacked under its children, draws every\n * shape refracting an image of the backdrop (see backdropOf), captured up to\n * the root. The image is captured again when anything in the backdrop (other\n * than the glass itself) changes, resizes or scrolls.\n */\nexport class GlassGroup {\n readonly root: HTMLElement;\n readonly container: boolean;\n readonly #win: Window;\n readonly #canvas: HTMLCanvasElement;\n readonly #renderer: GlassRenderer | null;\n readonly #backdrop: HTMLElement | null;\n #stopObserving: (() => void) | null = null;\n #snapshot: BackdropSnapshot | null = null;\n #stale = true;\n #capturing = false;\n #failed = false;\n #disposed = false;\n #nextCapture = 0;\n #drawn = '';\n\n constructor(root: HTMLElement, container: boolean) {\n this.root = root;\n this.container = container;\n const doc = root.ownerDocument;\n this.#win = doc.defaultView!;\n this.#canvas = doc.createElement('canvas');\n this.#canvas.setAttribute('aria-hidden', 'true');\n // Fades in over the frosted fallback once the first frame is drawn.\n this.#canvas.style.cssText =\n 'position:absolute;left:0;top:0;width:100%;height:100%;' +\n 'pointer-events:none;z-index:-1;opacity:0;transition:opacity 0.2s';\n const shadow = root.shadowRoot;\n shadow?.insertBefore(this.#canvas, shadow.querySelector('slot'));\n this.#renderer = shadow ? GlassRenderer.create(this.#canvas) : null;\n this.#backdrop = backdropOf(root);\n if (this.#renderer && this.#backdrop) {\n this.#stopObserving = observeBackdrop(this.#backdrop, root, () => {\n this.#stale = true;\n });\n }\n }\n\n /**\n * The glass elements this group draws.\n */\n get shapes(): HTMLElement[] {\n return this.container ? containerShapes(this.root) : [this.root];\n }\n\n /**\n * True once WebGL has drawn the glass, so the CSS fallback can go.\n */\n get active(): boolean {\n return this.#drawn !== '' && !this.#failed;\n }\n\n /**\n * True when the GPU dropped the context; the group must be rebuilt.\n */\n get lost(): boolean {\n return this.#renderer?.lost ?? false;\n }\n\n /**\n * Draws a frame if anything changed; `elapsed` is in milliseconds.\n */\n frame(elapsed: number): void {\n const renderer = this.#renderer;\n const backdrop = this.#backdrop;\n if (!renderer || !backdrop || this.#failed) return;\n // Boxes are measured in screen pixels, and the frame is drawn in CSS\n // pixels, which differ when the page is drawn scaled (see drawn-scale.ts).\n const origin = this.#canvas.getBoundingClientRect();\n const area = backdrop.getBoundingClientRect();\n const zoom = drawnScale(backdrop);\n if (this.#needsCapture(origin, area, zoom)) {\n this.#capture(backdrop, origin, zoom);\n }\n const snapshot = this.#snapshot;\n if (!snapshot) return;\n\n // Device pixels per CSS pixel, so the canvas stays sharp at any zoom.\n const scale = Math.min(this.#win.devicePixelRatio || 1, MAX_SCALE) * zoom;\n const elements = this.shapes;\n const shapes = elements.map((element) =>\n readShape(element, origin, zoom, elapsed, this.container),\n );\n // The press glow follows whichever shape is pressed the most.\n let pointer: [number, number, number] = [0, 0, 0];\n elements.forEach((element, i) => {\n const value = shapes[i]!.press;\n if (value > pointer[2]) {\n const { x, y } = pressOf(element)!;\n pointer = [(x - origin.left) / zoom, (y - origin.top) / zoom, value];\n }\n });\n const spacing = parseFloat(this.root.getAttribute('spacing') ?? '') || 0;\n const frame: GlassFrame = {\n scale,\n width: origin.width / zoom,\n height: origin.height / zoom,\n offsetX: (origin.left - area.left) / zoom - snapshot.x,\n offsetY: (origin.top - area.top) / zoom - snapshot.y,\n // Twice the spacing: the smooth union only bridges a gap up to half its\n // radius, and iOS merges shapes closer than `spacing`.\n smoothing: this.container ? spacing * 2 : 0,\n dark: this.#dark(snapshot),\n // Outside its shapes a container's canvas is empty space for a shadow;\n // a lone shape's canvas is its own box, where it would darken the corners.\n shadow: this.container ? 1 : 0,\n shapes,\n pointer,\n };\n const key = JSON.stringify(frame);\n if (key === this.#drawn) return;\n const width = Math.max(1, Math.round(frame.width * scale));\n const height = Math.max(1, Math.round(frame.height * scale));\n // Assigning a canvas size reallocates it even when the size is unchanged.\n if (this.#canvas.width !== width) this.#canvas.width = width;\n if (this.#canvas.height !== height) this.#canvas.height = height;\n renderer.draw(frame);\n this.#drawn = key;\n this.#canvas.style.opacity = '1';\n }\n\n dispose(): void {\n this.#disposed = true;\n this.#stopObserving?.();\n this.#renderer?.dispose();\n this.#canvas.remove();\n }\n\n #dark(snapshot: BackdropSnapshot): number {\n const forced = this.root.getAttribute('ios-user-interface-style');\n if (forced) return forced === 'dark' ? 1 : 0;\n return snapshot.luminance < DARK_LUMINANCE ? 1 : 0;\n }\n\n #needsCapture(origin: DOMRect, area: DOMRect, zoom: number): boolean {\n if (this.#capturing) return false;\n const snapshot = this.#snapshot;\n if (snapshot) {\n // Moving the whole group (not just its shapes) past the captured region\n // would refract the image's clamped edge, so capture around it again.\n const left = (Math.max(origin.left, area.left) - area.left) / zoom;\n const top = (Math.max(origin.top, area.top) - area.top) / zoom;\n const right = (Math.min(origin.right, area.right) - area.left) / zoom;\n const bottom = (Math.min(origin.bottom, area.bottom) - area.top) / zoom;\n if (\n left < snapshot.x - 1 ||\n top < snapshot.y - 1 ||\n right > snapshot.x + snapshot.width + 1 ||\n bottom > snapshot.y + snapshot.height + 1\n ) {\n this.#stale = true;\n }\n }\n return this.#stale && this.#win.performance.now() >= this.#nextCapture;\n }\n\n #capture(backdrop: HTMLElement, origin: DOMRect, zoom: number): void {\n const win = this.#win;\n this.#capturing = true;\n this.#stale = false;\n const started = win.performance.now();\n // The glass, and everything after it and after each of its ancestors in\n // the backdrop, paints on top of the glass, not behind it.\n const above = new Set<Element>([this.root]);\n for (\n let node: Element | null = this.root;\n node && node !== backdrop;\n node = node.parentElement\n ) {\n for (\n let sibling = node.nextElementSibling;\n sibling;\n sibling = sibling.nextElementSibling\n ) {\n above.add(sibling);\n }\n }\n // The region is in screen pixels, and the margin in CSS pixels.\n const margin = CAPTURE_MARGIN * zoom;\n snapshotBackdrop(backdrop, {\n exclude: (element) => above.has(element),\n region: {\n left: origin.left - margin,\n top: origin.top - margin,\n right: origin.right + margin,\n bottom: origin.bottom + margin,\n },\n scale: Math.min(win.devicePixelRatio || 1, MAX_SCALE) * zoom,\n })\n .then((snapshot) => {\n if (this.#disposed || !snapshot) return;\n this.#renderer!.setBackdrop(\n snapshot.image,\n snapshot.width,\n snapshot.height,\n );\n this.#snapshot = snapshot;\n this.#drawn = '';\n })\n .catch(() => {\n // The image wouldn't decode, or it tainted the canvas (Safari can\n // treat any <foreignObject> as cross-origin): keep the CSS fallback.\n this.#failed = true;\n })\n .finally(() => {\n this.#capturing = false;\n const now = win.performance.now();\n this.#nextCapture =\n now + Math.max(MIN_CAPTURE_INTERVAL, (now - started) * 4);\n });\n }\n}\n","/** How a `<blur-view>` on web is styled while the glass code looks after it. */\nexport type HostStyleState = {\n /** It's a glass shape that WebGL isn't drawing (yet): show frosted CSS. */\n fallback: boolean;\n /** WebGL draws this shape, so web-elements' own backdrop blur must go. */\n rendered: boolean;\n /** It holds a group's canvas, which must stack under its children. */\n hostsCanvas: boolean;\n};\n\nconst styles = new WeakMap<Element, HTMLStyleElement>();\n\nconst DEFAULT_FALLBACK_BLUR = 12;\n\n/**\n * The frosted look a glass shape has before WebGL takes over, or without it:\n * a backdrop blur with a bright inner rim, roughly the pre-iOS-26 material.\n * Author styles on the element itself still win, since a `:host` rule loses to\n * them, so a background set in the template is kept.\n */\nexport const fallbackGlassCss = (element: Element): string => {\n const clear = element.getAttribute('glass-style') === 'clear';\n const radius =\n parseFloat(element.getAttribute('blur-radius') ?? '') ||\n (clear ? DEFAULT_FALLBACK_BLUR / 3 : DEFAULT_FALLBACK_BLUR);\n const filter = `blur(${radius}px) saturate(${clear ? 140 : 180}%)`;\n const background =\n element.getAttribute('glass-tint-color') ||\n `rgba(255, 255, 255, ${clear ? 0.04 : 0.18})`;\n return (\n `:host{backdrop-filter:${filter};-webkit-backdrop-filter:${filter};` +\n `background-color:${background};box-shadow:inset 0 1px 0 ` +\n `rgba(255, 255, 255, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.25)}`\n );\n};\n\n/**\n * The UIKit blur material a non-glass `<blur-view>` gets on iOS, which\n * `blur-effect` picks (`light` by default). Besides blurring, each material\n * shifts what's behind it, while web-elements' `<x-blur-view>` only blurs. So\n * these approximate them, fitted to the iOS simulator's pixels in the\n * element-blur-view example: `light` brightens the backdrop by about a third,\n * `extra-light` washes it with white, and `dark` with black. Like on iOS, a\n * blur view with no blur radius shows no material. The `light` rule repeats\n * the blur because it replaces web-elements' own `backdrop-filter`.\n */\nexport const materialCss = (element: Element): string => {\n const effect = element.getAttribute('blur-effect') ?? 'light';\n const radius = parseFloat(element.getAttribute('blur-radius') ?? '');\n if (!radius || effect === 'glass' || effect === 'glass-container') {\n return '';\n }\n if (effect === 'extra-light') {\n return ':host{background-color:rgba(255, 255, 255, 0.75)}';\n }\n if (effect === 'dark') {\n return ':host{background-color:rgba(0, 0, 0, 0.6)}';\n }\n const filter = `blur(${radius}px) brightness(1.35)`;\n return `:host{backdrop-filter:${filter};-webkit-backdrop-filter:${filter}}`;\n};\n\nexport const hostStyleCss = (element: Element, state: HostStyleState): string =>\n [\n materialCss(element),\n state.hostsCanvas ? ':host{isolation:isolate}' : '',\n state.rendered\n ? ':host{backdrop-filter:none!important;-webkit-backdrop-filter:none!important}'\n : '',\n state.fallback ? fallbackGlassCss(element) : '',\n ].join('');\n\n/**\n * Applies `state` through a `<style>` in the element's shadow root, written\n * only when it changes. The rules stay inside the element: Lynx owns its\n * `class` and `style` attributes, and an attribute of our own would show up in\n * the backdrop's mutation observer as a change to capture.\n */\nexport const applyHostStyle = (\n element: HTMLElement,\n state: HostStyleState,\n): void => {\n const root = element.shadowRoot;\n if (!root) return;\n const css = hostStyleCss(element, state);\n let style = styles.get(element);\n if (!style) {\n if (!css) return;\n style = element.ownerDocument.createElement('style');\n styles.set(element, style);\n }\n // Appended (again) last, so it follows web-elements' own dynamic style.\n if (style.parentNode !== root) root.appendChild(style);\n if (style.textContent !== css) style.textContent = css;\n};\n","import { GlassGroup } from './glass-group';\nimport { applyHostStyle } from './glass-host-style';\nimport { trackPress } from './glass-press';\nimport { glassRole } from './glass-shapes';\n\n// The attributes that change what a `<blur-view>` looks like as glass.\nconst GLASS_ATTRIBUTES = [\n 'blur-effect',\n 'blur-radius',\n 'glass-style',\n 'glass-tint-color',\n 'glass-interactive',\n 'spacing',\n 'ios-user-interface-style',\n];\n\n// How often removed `<blur-view>`s are checked for being put back.\nconst DETACHED_POLL_MS = 1000;\n// Caps a frame's elapsed time, so a tab returning from the background doesn't\n// jump its press animations.\nconst MAX_ELAPSED_MS = 100;\n\n// The page's window, as `Document.defaultView` types it: with constructors\n// such as IntersectionObserver, which `Window` alone doesn't declare.\ntype PageWindow = Window & typeof globalThis;\n\nconst managers = new WeakMap<PageWindow, GlassManager>();\n\n/**\n * Looks after every `<blur-view>` of one page on Lynx for Web. It tracks which\n * are on screen, builds a `GlassGroup` for each visible container or lone\n * glass element, and runs their frames while any is visible. Each element's\n * shadow-root style follows: frosted CSS until WebGL draws it, then none.\n */\nexport class GlassManager {\n readonly #win: PageWindow;\n readonly #visible = new Set<HTMLElement>();\n readonly #groups = new Map<HTMLElement, GlassGroup>();\n readonly #detached = new Set<WeakRef<HTMLElement>>();\n readonly #intersection: IntersectionObserver;\n readonly #attributes: MutationObserver;\n #frame = 0;\n #poll = 0;\n #last = 0;\n\n /**\n * Use `GlassManager.for`, which keeps one manager per page.\n */\n constructor(win: PageWindow) {\n this.#win = win;\n this.#intersection = new win.IntersectionObserver((entries) =>\n this.#onIntersection(entries),\n );\n this.#attributes = new win.MutationObserver(() => this.#wake());\n }\n\n static for(win: PageWindow): GlassManager {\n let manager = managers.get(win);\n if (!manager) {\n manager = new GlassManager(win);\n managers.set(win, manager);\n }\n return manager;\n }\n\n register(element: HTMLElement): void {\n this.#intersection.observe(element);\n this.#attributes.observe(element, {\n attributes: true,\n attributeFilter: GLASS_ATTRIBUTES,\n });\n trackPress(element);\n }\n\n #onIntersection(entries: IntersectionObserverEntry[]): void {\n for (const { target, isIntersecting } of entries) {\n const element = target as HTMLElement;\n if (isIntersecting) {\n this.#visible.add(element);\n continue;\n }\n this.#visible.delete(element);\n // Observing a removed element would keep it alive after Lynx drops it.\n // Hold it weakly instead, in case it's put back (a detached view).\n if (!element.isConnected) {\n this.#intersection.unobserve(element);\n this.#detached.add(new WeakRef(element));\n if (!this.#poll) {\n this.#poll = this.#win.setInterval(\n () => this.#checkDetached(),\n DETACHED_POLL_MS,\n );\n }\n }\n }\n this.#wake();\n }\n\n #checkDetached(): void {\n for (const ref of this.#detached) {\n const element = ref.deref();\n // Still removed, and not yet garbage collected: keep checking.\n if (element && !element.isConnected) continue;\n if (element) this.#intersection.observe(element);\n this.#detached.delete(ref);\n }\n if (!this.#detached.size) {\n this.#win.clearInterval(this.#poll);\n this.#poll = 0;\n }\n }\n\n #wake(): void {\n if (this.#frame) return;\n this.#frame = this.#win.requestAnimationFrame((now) => this.#tick(now));\n }\n\n #tick(now: number): void {\n this.#frame = 0;\n const elapsed = this.#last ? Math.min(now - this.#last, MAX_ELAPSED_MS) : 0;\n this.#last = now;\n\n const roots = new Map<HTMLElement, boolean>();\n for (const element of this.#visible) {\n const role = glassRole(element);\n if (role === 'container' || role === 'standalone') {\n roots.set(element, role === 'container');\n }\n }\n for (const [root, group] of this.#groups) {\n if (roots.get(root) !== group.container || group.lost) {\n group.dispose();\n this.#groups.delete(root);\n }\n }\n for (const [root, container] of roots) {\n if (!this.#groups.has(root)) {\n this.#groups.set(root, new GlassGroup(root, container));\n }\n }\n\n const styled = new Set(this.#visible);\n const rendered = new Set<HTMLElement>();\n for (const group of this.#groups.values()) {\n group.frame(elapsed);\n for (const shape of group.shapes) {\n styled.add(shape);\n if (group.active) rendered.add(shape);\n }\n }\n for (const element of styled) {\n applyHostStyle(element, {\n hostsCanvas: this.#groups.get(element)?.active ?? false,\n rendered: rendered.has(element),\n fallback:\n element.getAttribute('blur-effect') === 'glass' &&\n !rendered.has(element),\n });\n }\n\n // Keep drawing while glass is on screen: shapes can move every frame\n // (dragged, animated) without any event this code would hear about.\n if (this.#groups.size) this.#wake();\n else this.#last = 0;\n }\n}\n","import type { ElementRef } from '../types/lynx';\nimport { applyBlurViewLayout } from './blur-view-layout';\nimport { GlassManager } from './glass-manager';\n\n/**\n * Gives a `<blur-view>` on Lynx for Web what web-elements' `<x-blur-view>`\n * lacks: a view's layout (see blur-view-layout.ts), and Liquid Glass.\n *\n * On iOS 26, `blur-effect=\"glass\"` and `\"glass-container\"` render UIKit's\n * glass. Lynx for Web turns `<blur-view>` into an `<x-blur-view>` custom\n * element that only implements `blur-radius`, so glass elements would show at\n * most a frosted blur, and merging and refraction not at all. This draws them\n * with WebGL instead (see glass-group.ts), from the same attributes.\n *\n * Called for every `<blur-view>` the main thread creates. On web that thread\n * runs in an iframe while its elements live in the page, so everything here\n * goes through the element's own window, never this realm's globals.\n */\nexport const attachWebGlass = (element: ElementRef): void => {\n const node = element as Partial<HTMLElement>;\n const win = node.ownerDocument?.defaultView;\n if (!win) return;\n // Every blur view needs it, glass or not, and before its first paint, which\n // this microtask after creation still is.\n applyBlurViewLayout(node as HTMLElement);\n // Only a real element in a browser can host the glass.\n if (!win.IntersectionObserver) return;\n try {\n GlassManager.for(win).register(node as HTMLElement);\n } catch {\n // Glass is decoration: never let it break rendering.\n }\n};\n"],"mappings":"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"}
|