@graview/render 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +96 -0
- package/README.md +43 -2
- package/dist/gpu.d.ts +6 -0
- package/dist/gpu.d.ts.map +1 -0
- package/dist/gpu.js +23 -0
- package/dist/gpu.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/interaction/pointer-router.d.ts +94 -0
- package/dist/interaction/pointer-router.d.ts.map +1 -0
- package/dist/interaction/pointer-router.js +148 -0
- package/dist/interaction/pointer-router.js.map +1 -0
- package/dist/platform/html-in-canvas.d.ts +100 -0
- package/dist/platform/html-in-canvas.d.ts.map +1 -0
- package/dist/platform/html-in-canvas.js +172 -0
- package/dist/platform/html-in-canvas.js.map +1 -0
- package/dist/platform/matrix.d.ts +53 -0
- package/dist/platform/matrix.d.ts.map +1 -0
- package/dist/platform/matrix.js +61 -0
- package/dist/platform/matrix.js.map +1 -0
- package/dist/scene/compositor.d.ts +112 -0
- package/dist/scene/compositor.d.ts.map +1 -0
- package/dist/scene/compositor.js +340 -0
- package/dist/scene/compositor.js.map +1 -0
- package/dist/scene/compositor.wgsl.d.ts +15 -0
- package/dist/scene/compositor.wgsl.d.ts.map +1 -0
- package/dist/scene/compositor.wgsl.js +106 -0
- package/dist/scene/compositor.wgsl.js.map +1 -0
- package/dist/scene/connectors.d.ts +60 -0
- package/dist/scene/connectors.d.ts.map +1 -0
- package/dist/scene/connectors.js +95 -0
- package/dist/scene/connectors.js.map +1 -0
- package/dist/scene/frame-plan.d.ts +83 -0
- package/dist/scene/frame-plan.d.ts.map +1 -0
- package/dist/scene/frame-plan.js +119 -0
- package/dist/scene/frame-plan.js.map +1 -0
- package/dist/scene/from-layout.d.ts +14 -0
- package/dist/scene/from-layout.d.ts.map +1 -0
- package/dist/scene/from-layout.js +35 -0
- package/dist/scene/from-layout.js.map +1 -0
- package/dist/scene/plane.d.ts +68 -0
- package/dist/scene/plane.d.ts.map +1 -0
- package/dist/scene/plane.js +94 -0
- package/dist/scene/plane.js.map +1 -0
- package/package.json +64 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Elastic License 2.0
|
|
2
|
+
|
|
3
|
+
## Acceptance
|
|
4
|
+
|
|
5
|
+
By using the software, you agree to all of the terms and conditions below.
|
|
6
|
+
|
|
7
|
+
## Copyright License
|
|
8
|
+
|
|
9
|
+
The licensor grants you a non-exclusive, royalty-free, worldwide,
|
|
10
|
+
non-sublicensable, non-transferable license to use, copy, distribute, make
|
|
11
|
+
available, and prepare derivative works of the software, in each case subject
|
|
12
|
+
to the limitations and conditions below.
|
|
13
|
+
|
|
14
|
+
## Limitations
|
|
15
|
+
|
|
16
|
+
You may not provide the software to third parties as a hosted or managed
|
|
17
|
+
service, where the service provides users with access to any substantial set
|
|
18
|
+
of the features or functionality of the software.
|
|
19
|
+
|
|
20
|
+
You may not move, change, disable, or circumvent the license key
|
|
21
|
+
functionality in the software, and you may not remove or obscure any
|
|
22
|
+
functionality in the software that is protected by the license key.
|
|
23
|
+
|
|
24
|
+
You may not alter, remove, or obscure any licensing, copyright, or other
|
|
25
|
+
notices of the licensor in the software. Any use of the licensor's trademarks
|
|
26
|
+
is subject to applicable law.
|
|
27
|
+
|
|
28
|
+
## Patents
|
|
29
|
+
|
|
30
|
+
The licensor grants you a license, under any patent claims the licensor can
|
|
31
|
+
license, or becomes able to license, to make, have made, use, sell, offer for
|
|
32
|
+
sale, import and have imported the software, in each case subject to the
|
|
33
|
+
limitations and conditions in this license. This license does not cover any
|
|
34
|
+
patent claims that you cause to be infringed by modifications or additions to
|
|
35
|
+
the software. If you or your company make any written claim that the software
|
|
36
|
+
infringes or contributes to infringement of any patent, your patent license
|
|
37
|
+
for the software granted under these terms ends immediately. If your company
|
|
38
|
+
makes such a claim, your patent license ends immediately for work on behalf
|
|
39
|
+
of your company.
|
|
40
|
+
|
|
41
|
+
## Notices
|
|
42
|
+
|
|
43
|
+
You must ensure that anyone who gets a copy of any part of the software from
|
|
44
|
+
you also gets a copy of these terms.
|
|
45
|
+
|
|
46
|
+
If you modify the software, you must include in any modified copies of the
|
|
47
|
+
software prominent notices stating that you have modified the software.
|
|
48
|
+
|
|
49
|
+
## No Other Rights
|
|
50
|
+
|
|
51
|
+
These terms do not imply any licenses other than those expressly granted in
|
|
52
|
+
these terms.
|
|
53
|
+
|
|
54
|
+
## Termination
|
|
55
|
+
|
|
56
|
+
If you use the software in violation of these terms, such use is not
|
|
57
|
+
licensed, and your licenses will automatically terminate. If the licensor
|
|
58
|
+
provides you with a notice of your violation, and you cease all violation of
|
|
59
|
+
this license no later than 30 days after you receive that notice, your
|
|
60
|
+
licenses will be reinstated retroactively. However, if you violate these
|
|
61
|
+
terms after such reinstatement, any additional violation of these terms will
|
|
62
|
+
cause your licenses to terminate automatically and permanently.
|
|
63
|
+
|
|
64
|
+
## No Liability
|
|
65
|
+
|
|
66
|
+
*As far as the law allows, the software comes as is, without any warranty or
|
|
67
|
+
condition, and the licensor will not be liable to you for any damages arising
|
|
68
|
+
out of these terms or the use or nature of the software, under any kind of
|
|
69
|
+
legal claim.*
|
|
70
|
+
|
|
71
|
+
## Definitions
|
|
72
|
+
|
|
73
|
+
The **licensor** is the entity offering these terms, and the **software** is
|
|
74
|
+
the software the licensor makes available under these terms, including any
|
|
75
|
+
portion of it.
|
|
76
|
+
|
|
77
|
+
**you** refers to the individual or entity agreeing to these terms.
|
|
78
|
+
|
|
79
|
+
**your company** is any legal entity, sole proprietorship, or other kind of
|
|
80
|
+
organization that you work for, plus all organizations that have control
|
|
81
|
+
over, are under the control of, or are under common control with that
|
|
82
|
+
organization. **control** means ownership of substantially all the assets of
|
|
83
|
+
an entity, or the power to direct its management and policies by vote,
|
|
84
|
+
contract, or otherwise. Control can be direct or indirect.
|
|
85
|
+
|
|
86
|
+
**your licenses** are all the licenses granted to you for the software under
|
|
87
|
+
these terms.
|
|
88
|
+
|
|
89
|
+
**use** means anything you do with the software requiring one of your
|
|
90
|
+
licenses.
|
|
91
|
+
|
|
92
|
+
**trademark** means trademarks, service marks, and similar rights.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
Copyright 2025-2026 En Dash Consulting
|
package/README.md
CHANGED
|
@@ -1,3 +1,44 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @graview/render
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The spatial renderer: three planes, an affine transform per plane, and
|
|
4
|
+
connectors drawn in SVG over the scene.
|
|
5
|
+
|
|
6
|
+
## Two paths, and which one ships
|
|
7
|
+
|
|
8
|
+
**The DOM path is what ships.** Each view is an ordinary element with a CSS
|
|
9
|
+
`matrix3d` — the same affine transform the GPU path uses, applied by the
|
|
10
|
+
browser. It is fully interactive, fully accessible, and every claim this
|
|
11
|
+
project makes about the interface is verified against it.
|
|
12
|
+
|
|
13
|
+
**The GPU capture path is EXPERIMENTAL.** It rasterises each view's DOM
|
|
14
|
+
subtree with `CanvasDrawElement` and composites the textures with per-plane
|
|
15
|
+
blur, which is the part a shader is genuinely better at. It needs Chrome Canary
|
|
16
|
+
with `--enable-blink-features=CanvasDrawElement`.
|
|
17
|
+
|
|
18
|
+
It used to bring the renderer process down on a click. That is fixed. The cause
|
|
19
|
+
was not the click: a plain hover over a captured view killed it just as
|
|
20
|
+
reliably, and a keyboard selection of the same node did not. What is fatal is
|
|
21
|
+
the browser's own hit-test descending into a `layoutsubtree` canvas child, so on
|
|
22
|
+
this path the hosts carry `pointer-events: none` and `PointerRouter` answers
|
|
23
|
+
instead — which it had to anyway, because `updateElementGeometry` does not
|
|
24
|
+
redirect hit-testing in this build. `scripts/verify-capture.mjs` holds the
|
|
25
|
+
claim: the pointer survives, a click still reaches the node that was drawn, and
|
|
26
|
+
the keyboard still reaches the views.
|
|
27
|
+
|
|
28
|
+
It stays experimental for a different reason: capture falls off a cliff past
|
|
29
|
+
~128 live captures a frame, and every other claim this project makes is
|
|
30
|
+
verified against the DOM path.
|
|
31
|
+
|
|
32
|
+
It is published rather than withheld because `@graview/react` depends on this
|
|
33
|
+
package for the plane model, the transforms and the frame planner, all of which
|
|
34
|
+
both paths share. Opting into the capture path is an explicit
|
|
35
|
+
`attachRenderer` — nothing reaches it by accident.
|
|
36
|
+
|
|
37
|
+
## What is stable here
|
|
38
|
+
|
|
39
|
+
- `PLANE_STYLES`, `styleFor`, `mixStyles`, `transformFor` — the plane model.
|
|
40
|
+
- `planFrame` — what to capture, what to draw, where each view lands.
|
|
41
|
+
- `routePointer` — hit-testing a click against drawn geometry.
|
|
42
|
+
|
|
43
|
+
The compositor, the WGSL and the `html-in-canvas` platform bindings move with
|
|
44
|
+
the browser feature they are built on.
|
package/dist/gpu.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { captureElement, captureElementImage, clearElementGeometry, detectCapabilities, IDENTITY, isAffine, perspectiveProbeMatrix, planeTransform, PlatformUnavailableError, requestPaint, setLayoutSubtree, toDOMMatrix, updateElementGeometry, } from "./platform/html-in-canvas.js";
|
|
2
|
+
export type { CaptureMethodName, CaptureSource, ElementImage, GeometryUpdate, Matrix4, PlatformCapabilities, } from "./platform/html-in-canvas.js";
|
|
3
|
+
export { Compositor, packUniform } from "./scene/compositor.js";
|
|
4
|
+
export type { CompositorDeps, CompositorOptions, SceneView, SurfaceLike, VgpuLike, } from "./scene/compositor.js";
|
|
5
|
+
export { COMPOSITOR_WGSL } from "./scene/compositor.wgsl.js";
|
|
6
|
+
//# sourceMappingURL=gpu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gpu.d.ts","sourceRoot":"","sources":["../src/gpu.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,QAAQ,EACR,QAAQ,EACR,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,qBAAqB,GACtB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,cAAc,EACd,OAAO,EACP,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAChE,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,QAAQ,GACT,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC"}
|
package/dist/gpu.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The capture path: rasterise a DOM subtree into a texture and composite the
|
|
3
|
+
* textures with per-plane blur.
|
|
4
|
+
*
|
|
5
|
+
* A separate entry because its declarations name WebGPU globals, which are
|
|
6
|
+
* ambient rather than importable — a consumer reaching this needs
|
|
7
|
+
* `@webgpu/types` in their own compilation, and a consumer who never touches
|
|
8
|
+
* it should not. It is also the experimental half of this package: it needs
|
|
9
|
+
* Chrome Canary with `--enable-blink-features=CanvasDrawElement`, and capture
|
|
10
|
+
* falls off a cliff past ~128 live captures a frame.
|
|
11
|
+
*
|
|
12
|
+
* The renderer-process crash on pointer input is fixed — the hosts are out of
|
|
13
|
+
* hit-testing on this path, because the browser's hit-test descending into a
|
|
14
|
+
* `layoutsubtree` child is what was fatal, not the click. See
|
|
15
|
+
* `scripts/verify-capture.mjs`.
|
|
16
|
+
*/
|
|
17
|
+
// The platform seam. Every HTML-in-Canvas call in the framework goes here.
|
|
18
|
+
// The platform seam. Every HTML-in-Canvas call in the framework goes here.
|
|
19
|
+
export { captureElement, captureElementImage, clearElementGeometry, detectCapabilities, IDENTITY, isAffine, perspectiveProbeMatrix, planeTransform, PlatformUnavailableError, requestPaint, setLayoutSubtree, toDOMMatrix, updateElementGeometry, } from "./platform/html-in-canvas.js";
|
|
20
|
+
// Capture and composite.
|
|
21
|
+
export { Compositor, packUniform } from "./scene/compositor.js";
|
|
22
|
+
export { COMPOSITOR_WGSL } from "./scene/compositor.wgsl.js";
|
|
23
|
+
//# sourceMappingURL=gpu.js.map
|
package/dist/gpu.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gpu.js","sourceRoot":"","sources":["../src/gpu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,2EAA2E;AAC3E,2EAA2E;AAC3E,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,QAAQ,EACR,QAAQ,EACR,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,qBAAqB,GACtB,MAAM,8BAA8B,CAAC;AAUtC,yBAAyB;AACzB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAQhE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { IDENTITY, isAffine, perspectiveProbeMatrix, planeTransform, toDOMMatrix, } from "./platform/matrix.js";
|
|
2
|
+
export type { Matrix4 } from "./platform/matrix.js";
|
|
3
|
+
export { LIGHT_PLANE_STYLES, PLANES, PLANE_STYLES, mixStyles, styleFor, transformFor, } from "./scene/plane.js";
|
|
4
|
+
export type { PlaneIndex, PlaneStyle, Scheme } from "./scene/plane.js";
|
|
5
|
+
export { planFrame } from "./scene/frame-plan.js";
|
|
6
|
+
export type { CaptureCommand, ConnectorDraw, FramePlan, GeometryReport, PlanOptions, PlannedConnector, PlannedView, ViewDraw, } from "./scene/frame-plan.js";
|
|
7
|
+
export { fromLayout } from "./scene/from-layout.js";
|
|
8
|
+
export { CONNECTOR_DASH, connectorStroke, connectorStyle, hueFor, connectorWidth, distinguishable, } from "./scene/connectors.js";
|
|
9
|
+
export type { ConnectorStyle, EndCap, StrokePattern } from "./scene/connectors.js";
|
|
10
|
+
export { PointerRouter, hitTest, invertPlaneTransform, toLocal } from "./interaction/pointer-router.js";
|
|
11
|
+
export type { LocalHit, Placement, PointerRouterOptions } from "./interaction/pointer-router.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,sBAAsB,EACtB,cAAc,EACd,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAGpD,OAAO,EACL,kBAAkB,EAClB,MAAM,EACN,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,YAAY,GACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAGvE,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,YAAY,EACV,cAAc,EACd,aAAa,EACb,SAAS,EACT,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,QAAQ,GACT,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGpD,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,MAAM,EACN,cAAc,EACd,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGnF,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AACxG,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The MAIN entry carries no WebGPU types.
|
|
3
|
+
*
|
|
4
|
+
* The plane model, the frame planner, the connector treatment and the pointer
|
|
5
|
+
* router are what every app uses, and they are pure geometry. The capture path
|
|
6
|
+
* is a different thing: it names `GPUDevice`, `GPUQueue` and `GPUTexture` in
|
|
7
|
+
* its declarations, and those are ambient globals from `@webgpu/types` rather
|
|
8
|
+
* than importable ones — so a `.d.ts` mentioning them makes every consumer
|
|
9
|
+
* install that package to typecheck an import they may never reach.
|
|
10
|
+
*
|
|
11
|
+
* Splitting it out is not a workaround. It matches what this package already
|
|
12
|
+
* says about itself: the DOM path is what ships and the capture path is
|
|
13
|
+
* experimental, and now the type surface says so too. Reach it explicitly:
|
|
14
|
+
*
|
|
15
|
+
* import { Compositor } from "@graview/render/gpu";
|
|
16
|
+
*
|
|
17
|
+
* Found by typechecking a scratch project against the packed tarballs, which
|
|
18
|
+
* is the only place a public surface's ambient requirements show up.
|
|
19
|
+
*/
|
|
20
|
+
// Affine geometry: pure, and free of any ambient global.
|
|
21
|
+
export { IDENTITY, isAffine, perspectiveProbeMatrix, planeTransform, toDOMMatrix, } from "./platform/matrix.js";
|
|
22
|
+
// The plane model: discrete depths and their atmospheric treatment.
|
|
23
|
+
export { LIGHT_PLANE_STYLES, PLANES, PLANE_STYLES, mixStyles, styleFor, transformFor, } from "./scene/plane.js";
|
|
24
|
+
// The frame, as data: what captures, what draws, and where it lands.
|
|
25
|
+
export { planFrame } from "./scene/frame-plan.js";
|
|
26
|
+
export { fromLayout } from "./scene/from-layout.js";
|
|
27
|
+
// Connector treatment, derived per edge kind.
|
|
28
|
+
export { CONNECTOR_DASH, connectorStroke, connectorStyle, hueFor, connectorWidth, distinguishable, } from "./scene/connectors.js";
|
|
29
|
+
// Pointer routing, until the platform redirects hit-testing itself.
|
|
30
|
+
export { PointerRouter, hitTest, invertPlaneTransform, toLocal } from "./interaction/pointer-router.js";
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,yDAAyD;AACzD,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,sBAAsB,EACtB,cAAc,EACd,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAG9B,oEAAoE;AACpE,OAAO,EACL,kBAAkB,EAClB,MAAM,EACN,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,YAAY,GACb,MAAM,kBAAkB,CAAC;AAG1B,qEAAqE;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAWlD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,8CAA8C;AAC9C,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,MAAM,EACN,cAAc,EACd,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAG/B,oEAAoE;AACpE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { Matrix4 } from "../platform/matrix.js";
|
|
2
|
+
/**
|
|
3
|
+
* Routes pointer events against where views were DRAWN, not where their
|
|
4
|
+
* source elements are laid out.
|
|
5
|
+
*
|
|
6
|
+
* This exists because of a measured platform gap, not a design preference:
|
|
7
|
+
* `updateElementGeometry` is accepted by Chromium 154 and does not redirect
|
|
8
|
+
* hit-testing (see `docs/platform-findings.md`). Keep calling it — it costs
|
|
9
|
+
* nothing and will start working — and route pointers here meanwhile, so the
|
|
10
|
+
* zoomed-out scene stays interactive rather than becoming a picture.
|
|
11
|
+
*
|
|
12
|
+
* Accessibility does NOT need this fallback: the source elements remain real,
|
|
13
|
+
* focusable DOM inside the `layoutsubtree` canvas, which the probe confirmed.
|
|
14
|
+
*/
|
|
15
|
+
export interface Placement {
|
|
16
|
+
/** The live element this quad was captured from. */
|
|
17
|
+
readonly element: Element;
|
|
18
|
+
/** Where it was drawn, in canvas pixels. Affine only. */
|
|
19
|
+
readonly transform: Matrix4;
|
|
20
|
+
/** The element's own size in CSS pixels, before the transform. */
|
|
21
|
+
readonly width: number;
|
|
22
|
+
readonly height: number;
|
|
23
|
+
/** Higher wins when quads overlap — plane 0 is nearest the viewer. */
|
|
24
|
+
readonly depth: number;
|
|
25
|
+
}
|
|
26
|
+
export interface LocalHit {
|
|
27
|
+
readonly placement: Placement;
|
|
28
|
+
/** Coordinates inside the element's own box, in CSS pixels. */
|
|
29
|
+
readonly x: number;
|
|
30
|
+
readonly y: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Inverts the affine part of a column-major 4x4 that only ever carries
|
|
34
|
+
* scale and translation in x/y. Restricting the shape is what makes the
|
|
35
|
+
* inverse exact and cheap — and the plane model emits nothing else.
|
|
36
|
+
*/
|
|
37
|
+
export declare function invertPlaneTransform(transform: Matrix4): {
|
|
38
|
+
scaleX: number;
|
|
39
|
+
scaleY: number;
|
|
40
|
+
translateX: number;
|
|
41
|
+
translateY: number;
|
|
42
|
+
} | null;
|
|
43
|
+
/** Canvas-space point to element-local point, or null if outside the quad. */
|
|
44
|
+
export declare function toLocal(placement: Placement, canvasX: number, canvasY: number): LocalHit | null;
|
|
45
|
+
/**
|
|
46
|
+
* The topmost placement under a canvas-space point. Depth ordering is
|
|
47
|
+
* explicit rather than array order, so a renderer may draw back-to-front
|
|
48
|
+
* without changing what a click means.
|
|
49
|
+
*/
|
|
50
|
+
export declare function hitTest(placements: readonly Placement[], canvasX: number, canvasY: number): LocalHit | null;
|
|
51
|
+
export interface PointerRouterOptions {
|
|
52
|
+
/**
|
|
53
|
+
* Set true once a browser redirects hit-testing itself, to stand the
|
|
54
|
+
* router down rather than double-handling every event.
|
|
55
|
+
*/
|
|
56
|
+
readonly platformHandlesHitTesting?: boolean;
|
|
57
|
+
/** Events to intercept. Defaults to the ones a view actually needs. */
|
|
58
|
+
readonly events?: readonly string[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Attaches to the scene canvas, maps each pointer event onto the element that
|
|
62
|
+
* was drawn under the cursor, and replays it there.
|
|
63
|
+
*
|
|
64
|
+
* The replay targets the deepest real element at the corresponding point of
|
|
65
|
+
* the source element's own layout box — the source subtree is still laid out
|
|
66
|
+
* and hit-testable at its layout position, so the browser's own hit-testing
|
|
67
|
+
* does the hard part and this only has to move the coordinates.
|
|
68
|
+
*/
|
|
69
|
+
export declare class PointerRouter {
|
|
70
|
+
private readonly canvas;
|
|
71
|
+
private readonly options;
|
|
72
|
+
private placements;
|
|
73
|
+
private readonly detachers;
|
|
74
|
+
private replaying;
|
|
75
|
+
constructor(canvas: HTMLCanvasElement, options?: PointerRouterOptions);
|
|
76
|
+
/** Called by the renderer every time the scene's geometry changes. */
|
|
77
|
+
setPlacements(placements: readonly Placement[]): void;
|
|
78
|
+
attach(): () => void;
|
|
79
|
+
detach(): void;
|
|
80
|
+
/**
|
|
81
|
+
* The deepest real element at the corresponding point inside the source
|
|
82
|
+
* view's own layout box.
|
|
83
|
+
*
|
|
84
|
+
* `elementFromPoint` is not enough here: under `layoutsubtree` every
|
|
85
|
+
* immediate child of the canvas is laid out at the canvas origin, so all
|
|
86
|
+
* views stack on top of each other in layout space and the singular call
|
|
87
|
+
* always returns whichever one is topmost. Walking `elementsFromPoint` and
|
|
88
|
+
* taking the first hit that belongs to the view we actually want is what
|
|
89
|
+
* makes routing correct with overlapping views.
|
|
90
|
+
*/
|
|
91
|
+
private deepestAt;
|
|
92
|
+
private route;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=pointer-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer-router.d.ts","sourceRoot":"","sources":["../../src/interaction/pointer-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,+DAA+D;IAC/D,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,OAAO,GACjB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAUnF;AAED,8EAA8E;AAC9E,wBAAgB,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAO/F;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACrB,UAAU,EAAE,SAAS,SAAS,EAAE,EAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,QAAQ,GAAG,IAAI,CAQjB;AAED,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,OAAO,CAAC;IAC7C,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAID;;;;;;;;GAQG;AACH,qBAAa,aAAa;IAMtB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,SAAS,CAAS;gBAGP,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,oBAAyB;IAGrD,sEAAsE;IACtE,aAAa,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,GAAG,IAAI;IAIrD,MAAM,IAAI,MAAM,IAAI;IAUpB,MAAM,IAAI,IAAI;IAId;;;;;;;;;;OAUG;IACH,OAAO,CAAC,SAAS;IAejB,OAAO,CAAC,KAAK;CA4Cd"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inverts the affine part of a column-major 4x4 that only ever carries
|
|
3
|
+
* scale and translation in x/y. Restricting the shape is what makes the
|
|
4
|
+
* inverse exact and cheap — and the plane model emits nothing else.
|
|
5
|
+
*/
|
|
6
|
+
export function invertPlaneTransform(transform) {
|
|
7
|
+
const scaleX = transform[0];
|
|
8
|
+
const scaleY = transform[5];
|
|
9
|
+
if (scaleX === 0 || scaleY === 0)
|
|
10
|
+
return null;
|
|
11
|
+
return {
|
|
12
|
+
scaleX: 1 / scaleX,
|
|
13
|
+
scaleY: 1 / scaleY,
|
|
14
|
+
translateX: transform[12],
|
|
15
|
+
translateY: transform[13],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Canvas-space point to element-local point, or null if outside the quad. */
|
|
19
|
+
export function toLocal(placement, canvasX, canvasY) {
|
|
20
|
+
const inverse = invertPlaneTransform(placement.transform);
|
|
21
|
+
if (!inverse)
|
|
22
|
+
return null;
|
|
23
|
+
const x = (canvasX - inverse.translateX) * inverse.scaleX;
|
|
24
|
+
const y = (canvasY - inverse.translateY) * inverse.scaleY;
|
|
25
|
+
if (x < 0 || y < 0 || x > placement.width || y > placement.height)
|
|
26
|
+
return null;
|
|
27
|
+
return { placement, x, y };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The topmost placement under a canvas-space point. Depth ordering is
|
|
31
|
+
* explicit rather than array order, so a renderer may draw back-to-front
|
|
32
|
+
* without changing what a click means.
|
|
33
|
+
*/
|
|
34
|
+
export function hitTest(placements, canvasX, canvasY) {
|
|
35
|
+
let best = null;
|
|
36
|
+
for (const placement of placements) {
|
|
37
|
+
const hit = toLocal(placement, canvasX, canvasY);
|
|
38
|
+
if (!hit)
|
|
39
|
+
continue;
|
|
40
|
+
if (!best || placement.depth < best.placement.depth)
|
|
41
|
+
best = hit;
|
|
42
|
+
}
|
|
43
|
+
return best;
|
|
44
|
+
}
|
|
45
|
+
const DEFAULT_EVENTS = ["pointerdown", "pointerup", "click", "dblclick", "contextmenu"];
|
|
46
|
+
/**
|
|
47
|
+
* Attaches to the scene canvas, maps each pointer event onto the element that
|
|
48
|
+
* was drawn under the cursor, and replays it there.
|
|
49
|
+
*
|
|
50
|
+
* The replay targets the deepest real element at the corresponding point of
|
|
51
|
+
* the source element's own layout box — the source subtree is still laid out
|
|
52
|
+
* and hit-testable at its layout position, so the browser's own hit-testing
|
|
53
|
+
* does the hard part and this only has to move the coordinates.
|
|
54
|
+
*/
|
|
55
|
+
export class PointerRouter {
|
|
56
|
+
canvas;
|
|
57
|
+
options;
|
|
58
|
+
placements = [];
|
|
59
|
+
detachers = [];
|
|
60
|
+
replaying = false;
|
|
61
|
+
constructor(canvas, options = {}) {
|
|
62
|
+
this.canvas = canvas;
|
|
63
|
+
this.options = options;
|
|
64
|
+
}
|
|
65
|
+
/** Called by the renderer every time the scene's geometry changes. */
|
|
66
|
+
setPlacements(placements) {
|
|
67
|
+
this.placements = placements;
|
|
68
|
+
}
|
|
69
|
+
attach() {
|
|
70
|
+
if (this.options.platformHandlesHitTesting)
|
|
71
|
+
return () => { };
|
|
72
|
+
for (const type of this.options.events ?? DEFAULT_EVENTS) {
|
|
73
|
+
const handler = (event) => this.route(event);
|
|
74
|
+
this.canvas.addEventListener(type, handler, true);
|
|
75
|
+
this.detachers.push(() => this.canvas.removeEventListener(type, handler, true));
|
|
76
|
+
}
|
|
77
|
+
return () => this.detach();
|
|
78
|
+
}
|
|
79
|
+
detach() {
|
|
80
|
+
for (const detach of this.detachers.splice(0))
|
|
81
|
+
detach();
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The deepest real element at the corresponding point inside the source
|
|
85
|
+
* view's own layout box.
|
|
86
|
+
*
|
|
87
|
+
* `elementFromPoint` is not enough here: under `layoutsubtree` every
|
|
88
|
+
* immediate child of the canvas is laid out at the canvas origin, so all
|
|
89
|
+
* views stack on top of each other in layout space and the singular call
|
|
90
|
+
* always returns whichever one is topmost. Walking `elementsFromPoint` and
|
|
91
|
+
* taking the first hit that belongs to the view we actually want is what
|
|
92
|
+
* makes routing correct with overlapping views.
|
|
93
|
+
*/
|
|
94
|
+
deepestAt(hit) {
|
|
95
|
+
const view = hit.placement.element;
|
|
96
|
+
const rect = view.getBoundingClientRect();
|
|
97
|
+
const x = rect.left + hit.x;
|
|
98
|
+
const y = rect.top + hit.y;
|
|
99
|
+
const stack = typeof document.elementsFromPoint === "function"
|
|
100
|
+
? document.elementsFromPoint(x, y)
|
|
101
|
+
: [document.elementFromPoint(x, y)].filter((el) => el !== null);
|
|
102
|
+
for (const candidate of stack) {
|
|
103
|
+
if (candidate === view || view.contains(candidate))
|
|
104
|
+
return candidate;
|
|
105
|
+
}
|
|
106
|
+
return view;
|
|
107
|
+
}
|
|
108
|
+
route(event) {
|
|
109
|
+
if (this.replaying)
|
|
110
|
+
return;
|
|
111
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
112
|
+
const hit = hitTest(this.placements, event.clientX - rect.left, event.clientY - rect.top);
|
|
113
|
+
if (!hit)
|
|
114
|
+
return;
|
|
115
|
+
const view = hit.placement.element;
|
|
116
|
+
const sourceRect = view.getBoundingClientRect();
|
|
117
|
+
const target = this.deepestAt(hit);
|
|
118
|
+
event.preventDefault();
|
|
119
|
+
event.stopPropagation();
|
|
120
|
+
this.replaying = true;
|
|
121
|
+
try {
|
|
122
|
+
target.dispatchEvent(new PointerEvent(event.type, {
|
|
123
|
+
bubbles: true,
|
|
124
|
+
cancelable: true,
|
|
125
|
+
composed: true,
|
|
126
|
+
clientX: sourceRect.left + hit.x,
|
|
127
|
+
clientY: sourceRect.top + hit.y,
|
|
128
|
+
pointerId: event.pointerId,
|
|
129
|
+
pointerType: event.pointerType,
|
|
130
|
+
button: event.button,
|
|
131
|
+
buttons: event.buttons,
|
|
132
|
+
ctrlKey: event.ctrlKey,
|
|
133
|
+
shiftKey: event.shiftKey,
|
|
134
|
+
altKey: event.altKey,
|
|
135
|
+
metaKey: event.metaKey,
|
|
136
|
+
}));
|
|
137
|
+
if (event.type === "pointerdown" && target instanceof HTMLElement) {
|
|
138
|
+
// Focus follows the pointer, so keyboard use continues from where the
|
|
139
|
+
// click landed rather than from the canvas.
|
|
140
|
+
target.focus({ preventScroll: true });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
this.replaying = false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=pointer-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer-router.js","sourceRoot":"","sources":["../../src/interaction/pointer-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE platform seam. Every call into the HTML-in-Canvas API passes through
|
|
3
|
+
* this module and nowhere else.
|
|
4
|
+
*
|
|
5
|
+
* The API is mid-origin-trial and its naming is still settling — the WICG
|
|
6
|
+
* README calls the capture entry point `drawElementImageToTexture` in one
|
|
7
|
+
* place and `copyElementImageToTexture` in another — so the whole surface is
|
|
8
|
+
* resolved once, at runtime, behind names of our own. When the spec settles,
|
|
9
|
+
* exactly one file changes.
|
|
10
|
+
*
|
|
11
|
+
* Verified against Chrome Canary 154.0.8032.0 with
|
|
12
|
+
* `--enable-blink-features=CanvasDrawElement`. What that build actually
|
|
13
|
+
* exposes, and the exact call shapes, are recorded in
|
|
14
|
+
* `docs/platform-findings.md`; the shapes below are what it accepts, not what
|
|
15
|
+
* the README suggests.
|
|
16
|
+
*/
|
|
17
|
+
import { IDENTITY, isAffine, perspectiveProbeMatrix, planeTransform, toDOMMatrix, type Matrix4 } from "./matrix.js";
|
|
18
|
+
export { IDENTITY, isAffine, perspectiveProbeMatrix, planeTransform, toDOMMatrix };
|
|
19
|
+
export type { Matrix4 };
|
|
20
|
+
export type CaptureMethodName = "drawElementImageToTexture" | "copyElementImageToTexture";
|
|
21
|
+
/** A 4x4 column-major matrix, the shape `canvasTransform` expects. */
|
|
22
|
+
export interface ElementImage {
|
|
23
|
+
readonly width: number;
|
|
24
|
+
readonly height: number;
|
|
25
|
+
close(): void;
|
|
26
|
+
}
|
|
27
|
+
/** What may be captured or positioned: the live element, or its paint record. */
|
|
28
|
+
export type CaptureSource = Element | ElementImage;
|
|
29
|
+
export interface GeometryUpdate {
|
|
30
|
+
/** Where the element was actually drawn, in canvas space. */
|
|
31
|
+
readonly canvasTransform: Matrix4 | DOMMatrix;
|
|
32
|
+
}
|
|
33
|
+
export interface PlatformCapabilities {
|
|
34
|
+
/** The API is present in some form. */
|
|
35
|
+
readonly available: boolean;
|
|
36
|
+
/** Which spelling of the capture call this build exposes. */
|
|
37
|
+
readonly captureMethod: CaptureMethodName | null;
|
|
38
|
+
/** `updateElementGeometry` is present, so geometry can be reported. */
|
|
39
|
+
readonly geometrySync: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Whether reporting geometry actually redirects hit-testing. Separate from
|
|
42
|
+
* `geometrySync` on purpose: Chromium 154 accepts the call and ignores it
|
|
43
|
+
* for hit-testing, and the difference is the difference between an
|
|
44
|
+
* interactive scene and a picture.
|
|
45
|
+
*/
|
|
46
|
+
readonly hitTestFollowsGeometry: "yes" | "no" | "unknown";
|
|
47
|
+
/** The canvas supports `layoutsubtree`. */
|
|
48
|
+
readonly layoutSubtree: boolean;
|
|
49
|
+
/** `paint` events and `requestPaint()` — the capture-safe moment. */
|
|
50
|
+
readonly paintEvents: boolean;
|
|
51
|
+
readonly webgpu: boolean;
|
|
52
|
+
/** Everything needed to composite views at depth. */
|
|
53
|
+
readonly usable: boolean;
|
|
54
|
+
readonly notes: readonly string[];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Resolves what this browser can actually do. Called once; everything else in
|
|
58
|
+
* the renderer branches on the result rather than sniffing again.
|
|
59
|
+
*/
|
|
60
|
+
export declare function detectCapabilities(queue?: GPUQueue, canvas?: HTMLCanvasElement): PlatformCapabilities;
|
|
61
|
+
export declare class PlatformUnavailableError extends Error {
|
|
62
|
+
readonly capabilities: PlatformCapabilities;
|
|
63
|
+
constructor(capabilities: PlatformCapabilities);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Captures a DOM element (or a previously taken paint record) into an
|
|
67
|
+
* existing GPU texture.
|
|
68
|
+
*
|
|
69
|
+
* Two preconditions the errors do not make obvious:
|
|
70
|
+
* - the element must be a descendant of a `<canvas layoutsubtree>`, and
|
|
71
|
+
* - that canvas must have a CONFIGURED WebGPU context of its own, or the call
|
|
72
|
+
* fails with "containing canvas does not have a rendering context".
|
|
73
|
+
*
|
|
74
|
+
* The texture is written in place, so the caller keeps ownership and no copy
|
|
75
|
+
* happens on our side.
|
|
76
|
+
*/
|
|
77
|
+
export declare function captureElement(queue: GPUQueue, source: CaptureSource, texture: GPUTexture): void;
|
|
78
|
+
/**
|
|
79
|
+
* Takes a cached paint record for an element. Only valid inside a `paint`
|
|
80
|
+
* event — outside one the browser has no paint record and throws
|
|
81
|
+
* `InvalidStateError`.
|
|
82
|
+
*/
|
|
83
|
+
export declare function captureElementImage(canvas: HTMLCanvasElement, element: Element): ElementImage;
|
|
84
|
+
/**
|
|
85
|
+
* Tells the browser where an element was actually drawn.
|
|
86
|
+
*
|
|
87
|
+
* The intent of the spec is that hit-testing, focus order, screen readers and
|
|
88
|
+
* find-in-page then resolve against the drawn pixels. In Chromium 154 the
|
|
89
|
+
* call is accepted and has no observable effect on hit-testing — see
|
|
90
|
+
* `docs/platform-findings.md`. Call it anyway (it costs nothing and will
|
|
91
|
+
* start working), and route pointers through `PointerRouter` meanwhile.
|
|
92
|
+
*/
|
|
93
|
+
export declare function updateElementGeometry(canvas: HTMLCanvasElement, source: CaptureSource, update: GeometryUpdate): void;
|
|
94
|
+
/** Drops a reported geometry, returning the element to its layout position. */
|
|
95
|
+
export declare function clearElementGeometry(canvas: HTMLCanvasElement, source: CaptureSource): void;
|
|
96
|
+
/** Asks for a `paint` event — the moment at which capture is legal. */
|
|
97
|
+
export declare function requestPaint(canvas: HTMLCanvasElement): void;
|
|
98
|
+
/** Marks a canvas as owning its descendants' layout. */
|
|
99
|
+
export declare function setLayoutSubtree(canvas: HTMLCanvasElement, on?: boolean): void;
|
|
100
|
+
//# sourceMappingURL=html-in-canvas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-in-canvas.d.ts","sourceRoot":"","sources":["../../src/platform/html-in-canvas.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,sBAAsB,EACtB,cAAc,EACd,WAAW,EACX,KAAK,OAAO,EACb,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,sBAAsB,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC;AACnF,YAAY,EAAE,OAAO,EAAE,CAAC;AAExB,MAAM,MAAM,iBAAiB,GACzB,2BAA2B,GAC3B,2BAA2B,CAAC;AAOhC,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,KAAK,IAAI,IAAI,CAAC;CACf;AAED,iFAAiF;AACjF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,YAAY,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,eAAe,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/C;AAED,MAAM,WAAW,oBAAoB;IACnC,uCAAuC;IACvC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,6DAA6D;IAC7D,QAAQ,CAAC,aAAa,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjD,uEAAuE;IACvE,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,sBAAsB,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1D,2CAA2C;IAC3C,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,qEAAqE;IACrE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAoBD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,CAAC,EAAE,QAAQ,EAChB,MAAM,CAAC,EAAE,iBAAiB,GACzB,oBAAoB,CA0DtB;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IACrC,QAAQ,CAAC,YAAY,EAAE,oBAAoB;gBAAlC,YAAY,EAAE,oBAAoB;CAIxD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,QAAQ,EACf,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,UAAU,GAClB,IAAI,CAUN;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,OAAO,GACf,YAAY,CAMd;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,cAAc,GACrB,IAAI,CAMN;AAED,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,aAAa,GACpB,IAAI,CAEN;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAE5D;AAED,wDAAwD;AACxD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,EAAE,EAAE,UAAO,GAAG,IAAI,CAK3E"}
|