@oddsquad/vite-plugin-lit 0.2.3 → 0.3.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/CHANGELOG.md +64 -0
- package/LICENSE +28 -0
- package/README.md +153 -0
- package/bin.mjs +154 -0
- package/client.d.ts +61 -0
- package/dist/client/assets/browser-agent-rpc-BXhoSh1z-BvWe4sTJ.js +69 -0
- package/dist/client/assets/browser-agent-rpc-BXhoSh1z-BvWe4sTJ.js.map +1 -0
- package/dist/client/assets/index-CFrVgNfS.js +9740 -0
- package/dist/client/assets/index-CFrVgNfS.js.map +1 -0
- package/{panel → dist/client}/index.html +1 -0
- package/index.d.ts.map +1 -1
- package/index.js +2 -2
- package/index.js.map +1 -1
- package/lib/color-scheme.d.ts.map +1 -1
- package/lib/color-scheme.js +17 -21
- package/lib/color-scheme.js.map +1 -1
- package/lib/devframe/definition.d.ts +45 -0
- package/lib/devframe/definition.d.ts.map +1 -0
- package/lib/devframe/definition.js +547 -0
- package/lib/devframe/definition.js.map +1 -0
- package/lib/devframe/icon.d.ts +8 -0
- package/lib/devframe/icon.d.ts.map +1 -0
- package/lib/devframe/icon.js +21 -0
- package/lib/devframe/icon.js.map +1 -0
- package/lib/devframe/paths.d.ts +12 -0
- package/lib/devframe/paths.d.ts.map +1 -0
- package/lib/devframe/paths.js +38 -0
- package/lib/devframe/paths.js.map +1 -0
- package/lib/devframe/protocol.d.ts +218 -0
- package/lib/devframe/protocol.d.ts.map +1 -0
- package/lib/devframe/protocol.js +76 -0
- package/lib/devframe/protocol.js.map +1 -0
- package/lib/devframe/source.d.ts +49 -0
- package/lib/devframe/source.d.ts.map +1 -0
- package/lib/devframe/source.js +23 -0
- package/lib/devframe/source.js.map +1 -0
- package/lib/devframe/vite.d.ts +116 -0
- package/lib/devframe/vite.d.ts.map +1 -0
- package/lib/devframe/vite.js +291 -0
- package/lib/devframe/vite.js.map +1 -0
- package/lib/http.d.ts +29 -0
- package/lib/http.d.ts.map +1 -0
- package/lib/http.js +35 -0
- package/lib/http.js.map +1 -0
- package/lib/icons.d.ts +2 -0
- package/lib/icons.d.ts.map +1 -1
- package/lib/icons.js +10 -4
- package/lib/icons.js.map +1 -1
- package/lib/plugin.d.ts +15 -4
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +640 -574
- package/lib/plugin.js.map +1 -1
- package/lib/runtime/css.d.ts +2 -2
- package/lib/runtime/css.d.ts.map +1 -1
- package/lib/runtime/css.js +34 -34
- package/lib/runtime/css.js.map +1 -1
- package/lib/runtime/edge-panel.d.ts.map +1 -1
- package/lib/runtime/edge-panel.js +82 -91
- package/lib/runtime/edge-panel.js.map +1 -1
- package/lib/runtime/fonts.d.ts.map +1 -1
- package/lib/runtime/fonts.js +1 -1
- package/lib/runtime/fonts.js.map +1 -1
- package/lib/runtime/indicator.d.ts.map +1 -1
- package/lib/runtime/indicator.js +71 -74
- package/lib/runtime/indicator.js.map +1 -1
- package/lib/runtime/inspector/collect.d.ts.map +1 -1
- package/lib/runtime/inspector/collect.js +83 -90
- package/lib/runtime/inspector/collect.js.map +1 -1
- package/lib/runtime/inspector/highlight.d.ts +16 -0
- package/lib/runtime/inspector/highlight.d.ts.map +1 -0
- package/lib/runtime/inspector/highlight.js +66 -0
- package/lib/runtime/inspector/highlight.js.map +1 -0
- package/lib/runtime/inspector/install.d.ts.map +1 -1
- package/lib/runtime/inspector/install.js +180 -205
- package/lib/runtime/inspector/install.js.map +1 -1
- package/lib/runtime/inspector/serialize.d.ts.map +1 -1
- package/lib/runtime/inspector/serialize.js +86 -107
- package/lib/runtime/inspector/serialize.js.map +1 -1
- package/lib/runtime/intern.d.ts.map +1 -1
- package/lib/runtime/intern.js +31 -29
- package/lib/runtime/intern.js.map +1 -1
- package/lib/runtime/overrides.d.ts.map +1 -1
- package/lib/runtime/overrides.js +14 -13
- package/lib/runtime/overrides.js.map +1 -1
- package/lib/runtime/patch.d.ts +8 -0
- package/lib/runtime/patch.d.ts.map +1 -1
- package/lib/runtime/patch.js +321 -282
- package/lib/runtime/patch.js.map +1 -1
- package/lib/runtime/source-meta.d.ts.map +1 -1
- package/lib/runtime/source-meta.js +1 -1
- package/lib/runtime/source-meta.js.map +1 -1
- package/lib/runtime/source-overlay/editors.d.ts.map +1 -1
- package/lib/runtime/source-overlay/editors.js +27 -27
- package/lib/runtime/source-overlay/editors.js.map +1 -1
- package/lib/runtime/source-overlay/mask-path.d.ts.map +1 -1
- package/lib/runtime/source-overlay/mask-path.js +15 -15
- package/lib/runtime/source-overlay/mask-path.js.map +1 -1
- package/lib/runtime/source-overlay/overlay-element.d.ts.map +1 -1
- package/lib/runtime/source-overlay/overlay-element.js +347 -356
- package/lib/runtime/source-overlay/overlay-element.js.map +1 -1
- package/lib/runtime/source-overlay/source-host.d.ts.map +1 -1
- package/lib/runtime/source-overlay/source-host.js +64 -71
- package/lib/runtime/source-overlay/source-host.js.map +1 -1
- package/lib/runtime/source-overlay/template.d.ts.map +1 -1
- package/lib/runtime/source-overlay/template.js +3 -3
- package/lib/runtime/source-overlay/template.js.map +1 -1
- package/lib/runtime/source-overlay.d.ts.map +1 -1
- package/lib/runtime/source-overlay.js +5 -2
- package/lib/runtime/source-overlay.js.map +1 -1
- package/lib/runtime/timeline/clock.d.ts.map +1 -1
- package/lib/runtime/timeline/clock.js +2 -2
- package/lib/runtime/timeline/clock.js.map +1 -1
- package/lib/runtime/timeline/flash.d.ts +39 -0
- package/lib/runtime/timeline/flash.d.ts.map +1 -0
- package/lib/runtime/timeline/flash.js +169 -0
- package/lib/runtime/timeline/flash.js.map +1 -0
- package/lib/runtime/timeline/identity.d.ts.map +1 -1
- package/lib/runtime/timeline/identity.js +27 -27
- package/lib/runtime/timeline/identity.js.map +1 -1
- package/lib/runtime/timeline/input.d.ts.map +1 -1
- package/lib/runtime/timeline/input.js +54 -67
- package/lib/runtime/timeline/input.js.map +1 -1
- package/lib/runtime/timeline/install.d.ts.map +1 -1
- package/lib/runtime/timeline/install.js +38 -29
- package/lib/runtime/timeline/install.js.map +1 -1
- package/lib/runtime/timeline/lifecycle.d.ts +8 -0
- package/lib/runtime/timeline/lifecycle.d.ts.map +1 -1
- package/lib/runtime/timeline/lifecycle.js +149 -133
- package/lib/runtime/timeline/lifecycle.js.map +1 -1
- package/lib/runtime/timeline/public-api.d.ts.map +1 -1
- package/lib/runtime/timeline/public-api.js +9 -9
- package/lib/runtime/timeline/public-api.js.map +1 -1
- package/lib/runtime/timeline/render.d.ts.map +1 -1
- package/lib/runtime/timeline/render.js +70 -75
- package/lib/runtime/timeline/render.js.map +1 -1
- package/lib/runtime/timeline/transport.d.ts.map +1 -1
- package/lib/runtime/timeline/transport.js +39 -43
- package/lib/runtime/timeline/transport.js.map +1 -1
- package/lib/segmented-tabs.d.ts +3 -1
- package/lib/segmented-tabs.d.ts.map +1 -1
- package/lib/segmented-tabs.js +136 -107
- package/lib/segmented-tabs.js.map +1 -1
- package/lib/snapshot.d.ts +28 -0
- package/lib/snapshot.d.ts.map +1 -0
- package/lib/snapshot.js +57 -0
- package/lib/snapshot.js.map +1 -0
- package/lib/source-meta.d.ts.map +1 -1
- package/lib/source-meta.js +176 -162
- package/lib/source-meta.js.map +1 -1
- package/lib/timeline/derive.d.ts +152 -0
- package/lib/timeline/derive.d.ts.map +1 -0
- package/lib/timeline/derive.js +242 -0
- package/lib/timeline/derive.js.map +1 -0
- package/lib/timeline-plugin.d.ts.map +1 -1
- package/lib/timeline-plugin.js +304 -321
- package/lib/timeline-plugin.js.map +1 -1
- package/lib/tokens.d.ts.map +1 -1
- package/lib/tokens.js +17 -18
- package/lib/tokens.js.map +1 -1
- package/lib/transform.d.ts.map +1 -1
- package/lib/transform.js +62 -57
- package/lib/transform.js.map +1 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +1 -1
- package/lib/types.js.map +1 -1
- package/lib/wrap-table.d.ts.map +1 -1
- package/lib/wrap-table.js +19 -17
- package/lib/wrap-table.js.map +1 -1
- package/package.json +77 -13
- package/types/hmr-incompatibility.d.ts +59 -0
- package/types/hmr-incompatibility.d.ts.map +1 -0
- package/types/hmr-incompatibility.js +30 -0
- package/types/hmr-incompatibility.js.map +1 -0
- package/types/in-page.d.ts +49 -0
- package/types/in-page.d.ts.map +1 -0
- package/types/in-page.js +33 -0
- package/types/in-page.js.map +1 -0
- package/types/inspector.d.ts.map +1 -1
- package/types/inspector.js.map +1 -1
- package/types/snapshot.d.ts +44 -0
- package/types/snapshot.d.ts.map +1 -0
- package/types/snapshot.js +7 -0
- package/types/snapshot.js.map +1 -0
- package/types/timeline.d.ts +11 -0
- package/types/timeline.d.ts.map +1 -1
- package/types/timeline.js.map +1 -1
- package/panel/components-view.d.ts +0 -60
- package/panel/components-view.d.ts.map +0 -1
- package/panel/components-view.js +0 -587
- package/panel/components-view.js.map +0 -1
- package/panel/devtools-settings.d.ts +0 -41
- package/panel/devtools-settings.d.ts.map +0 -1
- package/panel/devtools-settings.js +0 -463
- package/panel/devtools-settings.js.map +0 -1
- package/panel/lit-devtools-panel.d.ts +0 -37
- package/panel/lit-devtools-panel.d.ts.map +0 -1
- package/panel/lit-devtools-panel.js +0 -185
- package/panel/lit-devtools-panel.js.map +0 -1
- package/panel/timeline-event-list.d.ts +0 -43
- package/panel/timeline-event-list.d.ts.map +0 -1
- package/panel/timeline-event-list.js +0 -416
- package/panel/timeline-event-list.js.map +0 -1
- package/panel/timeline-layers.d.ts +0 -25
- package/panel/timeline-layers.d.ts.map +0 -1
- package/panel/timeline-layers.js +0 -96
- package/panel/timeline-layers.js.map +0 -1
- package/panel/timeline-view.d.ts +0 -38
- package/panel/timeline-view.d.ts.map +0 -1
- package/panel/timeline-view.js +0 -234
- package/panel/timeline-view.js.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes per release. Versions before 0.3.0 predate this file; see the
|
|
4
|
+
git history for those.
|
|
5
|
+
|
|
6
|
+
## 0.3.0 — 2026-09-17
|
|
7
|
+
|
|
8
|
+
The DevTools half of the plugin was rebuilt on
|
|
9
|
+
[devframe](https://www.npmjs.com/package/devframe), and most of what follows
|
|
10
|
+
falls out of that: the panel is no longer tied to Vite DevTools, and the same
|
|
11
|
+
data it shows is reachable by a coding agent over MCP.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **The panel runs on devframe.** The bespoke transport is gone. The panel
|
|
16
|
+
works docked in Vite DevTools, in its own tab, or standalone from the CLI.
|
|
17
|
+
- **`lit-devtools` CLI.** `lit-devtools dev` serves the panel without a Vite
|
|
18
|
+
dev server of its own; `lit-devtools mcp` exposes the panel's data to an MCP
|
|
19
|
+
client over stdio, discovering a running dev server on its own.
|
|
20
|
+
- **MCP tools for agents** — list the component tree, read recent timeline
|
|
21
|
+
events, start and stop a recording, and read why a module fell back to a full
|
|
22
|
+
reload instead of a hot patch.
|
|
23
|
+
- **Updates tab.** The timeline reads as an explainer for a single update:
|
|
24
|
+
what changed, which components re-rendered, and what it cost.
|
|
25
|
+
- **Session export.** A recorded session can be written out as a static copy of
|
|
26
|
+
the panel — shareable, no dev server needed to open it.
|
|
27
|
+
- **Deep links.** Panel views are addressable, so a link opens the tab, the
|
|
28
|
+
selected element, or an exported snapshot at the right place.
|
|
29
|
+
- **Flash on update.** An opt-in fading outline over every element that
|
|
30
|
+
finishes an update, with an optional ramp colouring it by updates per second.
|
|
31
|
+
- **Ambient types for `virtual:lit-plugin/timeline`**, shipped in
|
|
32
|
+
`@oddsquad/vite-plugin-lit/client` alongside the CSS query declarations.
|
|
33
|
+
Following the custom-layers guide no longer means silencing `TS2307`.
|
|
34
|
+
- **Documentation site** at <https://oddcelot.github.io/vite-plugin-lit/>, and
|
|
35
|
+
a CI workflow that type checks, lints, tests and builds every push.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- Panel settings persist per developer through devframe's settings store
|
|
40
|
+
instead of per browser, so they follow you across browsers and survive
|
|
41
|
+
clearing site data. `localStorage` stays as the page's boot-time cache.
|
|
42
|
+
- Source links open through the shared open-in-editor service and resolve
|
|
43
|
+
against the Vite root.
|
|
44
|
+
- The docked panel draws its hover outline over a direct page channel rather
|
|
45
|
+
than routing through the dev server.
|
|
46
|
+
- Tooling moved to Vite+ (oxfmt, oxlint, tsgolint); dependencies updated to
|
|
47
|
+
TypeScript 7, Vite 8.3, es-module-lexer 3 and magic-string 1.
|
|
48
|
+
- The README is a front door now; the long-form guides live on the docs site.
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
|
|
52
|
+
- **`virtual:lit-plugin/timeline` broke `vite build`.** Both hooks lived on the
|
|
53
|
+
serve-only plugin, so nothing claimed the specifier during a build and the
|
|
54
|
+
bundler failed on a module the developer never wrote. It now resolves in dev
|
|
55
|
+
and build alike, stubbing itself out in any build.
|
|
56
|
+
- The dev-server endpoints reject cross-site requests.
|
|
57
|
+
- Source metadata is injected in the component class's own scope, so it can no
|
|
58
|
+
longer reference a class that isn't in scope.
|
|
59
|
+
- The DevTools element watch survives a hot patch; `updated()` is resolved
|
|
60
|
+
lazily rather than captured once.
|
|
61
|
+
- Recording state is synced to a page runtime when it connects, so a reload
|
|
62
|
+
mid-recording keeps recording.
|
|
63
|
+
- `recent-events` works when called with no arguments, and the documented MCP
|
|
64
|
+
endpoint path matches the one the server serves.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017 Google LLC. All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# @oddsquad/vite-plugin-lit
|
|
2
|
+
|
|
3
|
+
A Vite plugin for Lit projects with true HMR, CSS delivery helpers for shadow
|
|
4
|
+
roots, and a DevTools timeline.
|
|
5
|
+
|
|
6
|
+
**[Documentation →](https://oddcelot.github.io/vite-plugin-lit/)**
|
|
7
|
+
|
|
8
|
+
Based on `@lit-labs/vite-plugin-lit` (formerly `@lit-labs/vite-hmr`) from the
|
|
9
|
+
[lit monorepo](https://github.com/lit/lit), which is kept checked out as a
|
|
10
|
+
read-only [submodule](./lit) here for reference and opt-in canary testing
|
|
11
|
+
against lit `main`.
|
|
12
|
+
|
|
13
|
+
## Why
|
|
14
|
+
|
|
15
|
+
lit-html decides "is this the same template?" by **object identity** of the
|
|
16
|
+
`TemplateStringsArray`, not by content. Vite HMR re-executes an edited module,
|
|
17
|
+
so a one-character edit rebuilds the component's entire subtree and takes
|
|
18
|
+
focus, scroll, input state, and child `@state` with it.
|
|
19
|
+
|
|
20
|
+
This plugin fixes that with two cooperating mechanisms:
|
|
21
|
+
|
|
22
|
+
1. **Template-strings interning** — the `html`/`svg`/`mathml`/`css` tags are
|
|
23
|
+
wrapped in dev so strings arrays are canonicalized by content, and only the
|
|
24
|
+
edited template rebuilds its part of the DOM.
|
|
25
|
+
2. **In-place class patching** — the duplicate `customElements.define` from the
|
|
26
|
+
re-executed module patches the originally-registered class in place, then
|
|
27
|
+
restores reactive property values through the new accessors.
|
|
28
|
+
|
|
29
|
+
[How it works →](https://oddcelot.github.io/vite-plugin-lit/getting-started/how-it-works/)
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
// vite.config.ts
|
|
35
|
+
import {defineConfig} from 'vite';
|
|
36
|
+
import {litPlugin} from '@oddsquad/vite-plugin-lit';
|
|
37
|
+
|
|
38
|
+
export default defineConfig({
|
|
39
|
+
plugins: [litPlugin()],
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The HMR feature only applies to the dev server (`apply: 'serve'`); production
|
|
44
|
+
builds are untouched. The CSS queries (`?hmr-url`, `?css-sheet`) and Lightning
|
|
45
|
+
CSS literal processing apply in both dev and build.
|
|
46
|
+
|
|
47
|
+
## Features
|
|
48
|
+
|
|
49
|
+
- **[HMR that keeps state](https://oddcelot.github.io/vite-plugin-lit/guides/hmr/)**
|
|
50
|
+
— what survives an edit, and what falls back to a reload.
|
|
51
|
+
- **[Stylesheets at scale](https://oddcelot.github.io/vite-plugin-lit/guides/stylesheets/)**
|
|
52
|
+
— one shared `CSSStyleSheet` for thousands of shadow roots, hot-swapped
|
|
53
|
+
without re-rendering, from a bare `?css-sheet` import.
|
|
54
|
+
- **[DevTools timeline](https://oddcelot.github.io/vite-plugin-lit/guides/devtools-timeline/)**
|
|
55
|
+
— a layered event recorder and live component inspector inside Vite DevTools.
|
|
56
|
+
- **[Source overlay](https://oddcelot.github.io/vite-plugin-lit/guides/source-overlay/)**
|
|
57
|
+
— click any element in the page to open its source in your editor.
|
|
58
|
+
- **[Agent access](#coding-agents-mcp)** — the same component tree and timeline
|
|
59
|
+
as MCP tools, for coding agents.
|
|
60
|
+
- **[Ecosystem support](https://oddcelot.github.io/vite-plugin-lit/guides/ecosystem/)**
|
|
61
|
+
— signals, context, tasks, and the virtualizer across a patch.
|
|
62
|
+
|
|
63
|
+
Reference:
|
|
64
|
+
[options](https://oddcelot.github.io/vite-plugin-lit/reference/options/) ·
|
|
65
|
+
[environment variables](https://oddcelot.github.io/vite-plugin-lit/reference/environment-variables/) ·
|
|
66
|
+
[import queries](https://oddcelot.github.io/vite-plugin-lit/reference/import-queries/) ·
|
|
67
|
+
[runtime API](https://oddcelot.github.io/vite-plugin-lit/reference/runtime-api/) ·
|
|
68
|
+
[limitations](https://oddcelot.github.io/vite-plugin-lit/reference/limitations/) ·
|
|
69
|
+
[benchmarks](https://oddcelot.github.io/vite-plugin-lit/reference/benchmarks/)
|
|
70
|
+
|
|
71
|
+
## Coding agents (MCP)
|
|
72
|
+
|
|
73
|
+
The DevTools panel's data is also exposed as MCP tools — `lit_list-components`,
|
|
74
|
+
`lit_component-details`, `lit_recent-events`, `lit_get-meta`,
|
|
75
|
+
`lit_hmr-incompatibilities`, `lit_set-recording` — so an agent can read the
|
|
76
|
+
live component tree and timeline instead of guessing from source.
|
|
77
|
+
|
|
78
|
+
These answer only while a Vite dev server with DevTools is **running**. There
|
|
79
|
+
is no stored data and nothing to go stale: with the server down an agent gets
|
|
80
|
+
a connection error, not an empty answer.
|
|
81
|
+
|
|
82
|
+
Point an MCP client at it either way:
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
# Auto-discovers every running dev server on this machine.
|
|
86
|
+
claude mcp add lit-devtools -- npx -y @oddsquad/vite-plugin-lit mcp
|
|
87
|
+
|
|
88
|
+
# Or dial one server directly, if you'd rather pin the port.
|
|
89
|
+
claude mcp add lit-devtools -- npx -y mcp-remote http://localhost:5179/__devtools/__mcp
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The equivalent `claude_desktop_config.json` / `mcp.json` entry:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"mcpServers": {
|
|
97
|
+
"lit-devtools": {
|
|
98
|
+
"command": "npx",
|
|
99
|
+
"args": ["-y", "@oddsquad/vite-plugin-lit", "mcp"]
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The two differ in how the server is found, not in what it can do:
|
|
106
|
+
|
|
107
|
+
- **`... vite-plugin-lit mcp`** runs devframe's connector over stdio. The
|
|
108
|
+
plugin publishes each running dev server to devframe's instance registry,
|
|
109
|
+
and the connector lists them through two gateway tools
|
|
110
|
+
(`devframe_connect_list-instances`, `devframe_connect_call-tool`) — so one
|
|
111
|
+
entry covers every project you have running, with no port to keep in sync.
|
|
112
|
+
Being a shared connector, it surfaces every devframe on the machine, not
|
|
113
|
+
only this plugin's tools.
|
|
114
|
+
- **`mcp-remote <url>`** bridges stdio to one fixed URL and depends on no
|
|
115
|
+
discovery at all. Reach for it if registry discovery is unavailable — the
|
|
116
|
+
plugin logs a warning saying so at startup, naming the reason.
|
|
117
|
+
|
|
118
|
+
The CLI also has `lit-devtools dev`, a standalone devframe server with no page
|
|
119
|
+
attached. It exists to prove the panel definition runs without Vite (a
|
|
120
|
+
framework-neutrality harness, and the groundwork for non-Vite adapters); it
|
|
121
|
+
cannot show a real component tree, so it is not a way to inspect an app
|
|
122
|
+
without a dev server.
|
|
123
|
+
|
|
124
|
+
## Playground
|
|
125
|
+
|
|
126
|
+
A manually inspectable fixture app (also the source for the e2e fixtures), and
|
|
127
|
+
self-contained enough to open on
|
|
128
|
+
[StackBlitz](https://stackblitz.com/github/oddcelot/vite-plugin-lit/tree/main/playground)
|
|
129
|
+
straight from the repo URL. Run it locally from the repo root:
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
pnpm dev # builds the plugin, then serves http://localhost:5179
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Development
|
|
136
|
+
|
|
137
|
+
Requires Node 26 and pnpm 12 (`corepack enable` picks up the pinned version).
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
pnpm install # workspace: root package + playground + docs
|
|
141
|
+
pnpm build # tsc + panel assets -> ./lib, ./panel, ./index.js
|
|
142
|
+
pnpm exec vp check # format, lint, type check
|
|
143
|
+
pnpm test # unit + e2e
|
|
144
|
+
pnpm docs:dev # the documentation site
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
More in
|
|
148
|
+
[Development](https://oddcelot.github.io/vite-plugin-lit/contributing/development/)
|
|
149
|
+
and [Testing](https://oddcelot.github.io/vite-plugin-lit/contributing/testing/).
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
BSD-3-Clause. See [LICENSE](./LICENSE).
|
package/bin.mjs
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2026 Google LLC
|
|
5
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `lit-devtools` — the package's command line.
|
|
10
|
+
*
|
|
11
|
+
* Built on a bare `cac()` instance rather than devframe's `createCac()`
|
|
12
|
+
* adapter, deliberately. Two things make the wrapper the wrong fit here:
|
|
13
|
+
*
|
|
14
|
+
* 1. Its `mcp` subcommand runs `createMcpServer(definition, ...)`, which
|
|
15
|
+
* executes the definition's `setup()` fresh and in-process. This
|
|
16
|
+
* package's definition reads a `TimelineSource`, and a CLI has no page
|
|
17
|
+
* to attach — so that server would answer every component query with an
|
|
18
|
+
* empty list, forever, while looking perfectly healthy. An MCP server
|
|
19
|
+
* that is confidently wrong is worse than no MCP server. The `mcp`
|
|
20
|
+
* command below proxies an *already-running* dev server instead.
|
|
21
|
+
* 2. It registers `dev` as cac's default command (`[...args]`), not a named
|
|
22
|
+
* one, and cac resolves commands first-match-wins — so its built-in
|
|
23
|
+
* subcommands cannot be cleanly overridden after the fact, only spliced
|
|
24
|
+
* out of `cli.commands`. Hand-rolling is less code than fighting that.
|
|
25
|
+
*
|
|
26
|
+
* `cac` and `@devframes/agentic` are optional peers, imported dynamically
|
|
27
|
+
* and only on the path that needs them, so installing this package without
|
|
28
|
+
* them stays supported.
|
|
29
|
+
*
|
|
30
|
+
* @see plans/roadmap/03-cli-and-stdio-mcp.md
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import process from 'node:process';
|
|
34
|
+
import {createLitDevframe} from './lib/devframe/definition.js';
|
|
35
|
+
import {createNullSource} from './lib/devframe/source.js';
|
|
36
|
+
import {PACKAGE_VERSION} from './lib/devframe/paths.js';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Standalone `dev` default port. Deliberately *not* the playground's 5179
|
|
40
|
+
* (`playground/vite.config.ts`): running `pnpm run dev` and `lit-devtools
|
|
41
|
+
* dev` against the same checkout is a normal thing to do while working on
|
|
42
|
+
* this package, and two servers fighting over one port is a worse first
|
|
43
|
+
* experience than a port nobody has to think about.
|
|
44
|
+
*/
|
|
45
|
+
const DEFAULT_DEV_PORT = 5180;
|
|
46
|
+
|
|
47
|
+
/** Fail with a readable message instead of a module-resolution stack trace. */
|
|
48
|
+
const requirePeer = async (specifier, hint) => {
|
|
49
|
+
try {
|
|
50
|
+
return await import(specifier);
|
|
51
|
+
} catch {
|
|
52
|
+
console.error(
|
|
53
|
+
`[lit-devtools] this command needs the optional peer "${hint}". ` +
|
|
54
|
+
`Install it and retry:\n\n npm install -D ${hint}\n`
|
|
55
|
+
);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const main = async () => {
|
|
61
|
+
const {default: cac} = await requirePeer('cac', 'cac');
|
|
62
|
+
const cli = cac('lit-devtools');
|
|
63
|
+
|
|
64
|
+
cli
|
|
65
|
+
.command('dev', 'Start a standalone devframe dev server (no page attached)')
|
|
66
|
+
.option('--port <port>', 'Port to listen on', {default: DEFAULT_DEV_PORT})
|
|
67
|
+
.option('--host <host>', 'Host to bind to', {default: 'localhost'})
|
|
68
|
+
.option('--open', 'Open the browser on start')
|
|
69
|
+
.action(async (flags) => {
|
|
70
|
+
const {createDevServer} = await import('devframe/adapters/dev');
|
|
71
|
+
// A standalone server has no Vite and no page, so the component tree
|
|
72
|
+
// is empty by construction. This command is a framework-neutrality
|
|
73
|
+
// harness for the definition, not a way to inspect a real app --
|
|
74
|
+
// for that, run your Vite dev server with DevTools enabled.
|
|
75
|
+
await createDevServer(
|
|
76
|
+
createLitDevframe({
|
|
77
|
+
source: createNullSource(),
|
|
78
|
+
version: PACKAGE_VERSION,
|
|
79
|
+
}),
|
|
80
|
+
{
|
|
81
|
+
host: flags.host,
|
|
82
|
+
port: Number(flags.port),
|
|
83
|
+
flags: {open: Boolean(flags.open)},
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
cli
|
|
89
|
+
.command('build', 'Explain how to export a static snapshot of a session')
|
|
90
|
+
.action(() => {
|
|
91
|
+
// Deliberately not implemented here. A snapshot worth attaching to an
|
|
92
|
+
// issue is a *recorded session*, and the session lives in the running
|
|
93
|
+
// dev server's memory -- a fresh CLI process has no page, no timeline
|
|
94
|
+
// and no component tree, so anything it could build would be an empty
|
|
95
|
+
// shell. The export therefore runs inside the dev server that holds
|
|
96
|
+
// the data; see plans/roadmap/08-static-snapshot.md.
|
|
97
|
+
console.error(
|
|
98
|
+
`[lit-devtools] A static snapshot is exported from a running ` +
|
|
99
|
+
`session, not from this CLI.\n` +
|
|
100
|
+
`Record what you want to report in the DevTools Lit panel, then ` +
|
|
101
|
+
`press "Export snapshot" in the Timeline tab. The dev server ` +
|
|
102
|
+
`writes a self-contained panel directory you can zip onto an issue.`
|
|
103
|
+
);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
cli
|
|
108
|
+
.command('mcp', 'Start a stdio MCP server proxying running dev servers')
|
|
109
|
+
.option(
|
|
110
|
+
'--port <port>',
|
|
111
|
+
'Also probe this port for an instance the registry does not list. ' +
|
|
112
|
+
'Probes <origin>/__connection.json at the ROOT path only, so this ' +
|
|
113
|
+
'finds a standalone "lit-devtools dev" server but NOT a ' +
|
|
114
|
+
'Vite-hosted one (mounted under /__devtools/) -- for those, rely ' +
|
|
115
|
+
'on registry discovery. Repeatable.'
|
|
116
|
+
)
|
|
117
|
+
.option(
|
|
118
|
+
'--token <token>',
|
|
119
|
+
'Bearer token presented to each instance MCP route, for a dev server ' +
|
|
120
|
+
'whose DevTools auth gate is enabled.'
|
|
121
|
+
)
|
|
122
|
+
.action(async (flags) => {
|
|
123
|
+
const {startConnectServer} = await requirePeer(
|
|
124
|
+
'@devframes/agentic/connect',
|
|
125
|
+
'@devframes/agentic'
|
|
126
|
+
);
|
|
127
|
+
// This is devframe's own generic connector: it discovers every
|
|
128
|
+
// devframe instance on the machine, not just this package's. Its two
|
|
129
|
+
// gateway tools (`devframe_connect_list-instances` /
|
|
130
|
+
// `devframe_connect_call-tool`) are how an agent reaches the `lit_*`
|
|
131
|
+
// tools, one hop in.
|
|
132
|
+
const ports = [flags.port]
|
|
133
|
+
.flat()
|
|
134
|
+
.filter((p) => p != null)
|
|
135
|
+
.map(Number)
|
|
136
|
+
.filter((p) => Number.isInteger(p) && p > 0);
|
|
137
|
+
|
|
138
|
+
await startConnectServer({
|
|
139
|
+
...(ports.length > 0 ? {ports} : {}),
|
|
140
|
+
...(flags.token ? {authToken: String(flags.token)} : {}),
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
cli.help();
|
|
145
|
+
cli.version(PACKAGE_VERSION);
|
|
146
|
+
|
|
147
|
+
cli.parse(process.argv, {run: false});
|
|
148
|
+
await cli.runMatchedCommand();
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
main().catch((error) => {
|
|
152
|
+
console.error(`[lit-devtools] ${error?.stack ?? error}`);
|
|
153
|
+
process.exit(1);
|
|
154
|
+
});
|
package/client.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Ambient types for the import queries provided by the Lit Vite plugin.
|
|
9
|
+
*
|
|
10
|
+
* Reference via tsconfig (`"types": ["@oddsquad/vite-plugin-lit/client"]`) or
|
|
11
|
+
* `/// <reference types="@oddsquad/vite-plugin-lit/client" />`.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
declare module '*.css?hmr-url' {
|
|
15
|
+
const href: string;
|
|
16
|
+
export default href;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare module '*.css?css-sheet' {
|
|
20
|
+
const sheet: CSSStyleSheet;
|
|
21
|
+
export default sheet;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
declare module 'virtual:lit-plugin/timeline' {
|
|
25
|
+
export interface TimelineLayer {
|
|
26
|
+
id: string;
|
|
27
|
+
label: string;
|
|
28
|
+
/** 0xRRGGBB */
|
|
29
|
+
color: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface TimelineEvent<TData = unknown> {
|
|
33
|
+
layerId: string;
|
|
34
|
+
/** Milliseconds since the current recording started. */
|
|
35
|
+
time: number;
|
|
36
|
+
data: TData;
|
|
37
|
+
title?: string;
|
|
38
|
+
subtitle?: string;
|
|
39
|
+
/** Pairs a start event with its matching end event in the same update group. */
|
|
40
|
+
groupId?: number | string;
|
|
41
|
+
logType?: 'default' | 'warning' | 'error';
|
|
42
|
+
/** Set by the plugin's built-in capture layers; not needed for custom events. */
|
|
43
|
+
meta?: {
|
|
44
|
+
elementId?: number;
|
|
45
|
+
tagName?: string;
|
|
46
|
+
source?: {file: string; line: number};
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Emit a custom timeline event from app code. No-ops in production or
|
|
52
|
+
* when the `timeline` option is disabled.
|
|
53
|
+
*/
|
|
54
|
+
export function addTimelineEvent(event: TimelineEvent): void;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Register a custom timeline layer and announce it to the panel.
|
|
58
|
+
* Idempotent — duplicate ids are ignored.
|
|
59
|
+
*/
|
|
60
|
+
export function addTimelineLayer(layer: TimelineLayer): void;
|
|
61
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { n as onBrowserAgentToolsChanged, r as nanoid, t as listBrowserAgentTools } from "./index-CFrVgNfS.js";
|
|
2
|
+
//#region node_modules/.pnpm/devframe@1.0.0_@devframes+agentic@1.0.0_cac@7.0.0_srvx@1.0.5/node_modules/devframe/dist/browser-agent-rpc-BXhoSh1z.mjs
|
|
3
|
+
var CLIENT_ID_STORAGE_KEY = "devframe:client-id";
|
|
4
|
+
var memoryClientId;
|
|
5
|
+
/**
|
|
6
|
+
* This browser tab's stable client id: one nanoid per tab, persisted in
|
|
7
|
+
* `sessionStorage` so it survives page reloads and RPC reconnects. The node
|
|
8
|
+
* side uses it to tell connected tabs apart across reconnects (see #394).
|
|
9
|
+
*
|
|
10
|
+
* Tab duplication copies `sessionStorage`, so two tabs can briefly share an id
|
|
11
|
+
* until per-tab disambiguation lands with the wider tab-metadata work.
|
|
12
|
+
*/
|
|
13
|
+
function resolveClientId(win = globalThis.window) {
|
|
14
|
+
try {
|
|
15
|
+
const storage = win?.sessionStorage;
|
|
16
|
+
if (storage) {
|
|
17
|
+
let id = storage.getItem(CLIENT_ID_STORAGE_KEY);
|
|
18
|
+
if (!id) {
|
|
19
|
+
id = nanoid();
|
|
20
|
+
storage.setItem(CLIENT_ID_STORAGE_KEY, id);
|
|
21
|
+
}
|
|
22
|
+
return id;
|
|
23
|
+
}
|
|
24
|
+
} catch {}
|
|
25
|
+
memoryClientId ??= nanoid();
|
|
26
|
+
return memoryClientId;
|
|
27
|
+
}
|
|
28
|
+
/** Mirror this document's browser-agent registry over its existing RPC connection. */
|
|
29
|
+
function setupBrowserAgentRpcBridge(rpc) {
|
|
30
|
+
rpc.client.register({
|
|
31
|
+
name: "devframe:agent:invoke-client-tool",
|
|
32
|
+
type: "action",
|
|
33
|
+
jsonSerializable: true,
|
|
34
|
+
handler: async (id, args) => {
|
|
35
|
+
const tool = listBrowserAgentTools().find((tool) => tool.id === id);
|
|
36
|
+
if (!tool) throw new Error(`[devframe/agent] browser tool "${id}" not found`);
|
|
37
|
+
return await tool.invoke(args);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
let queued = false;
|
|
41
|
+
let disposed = false;
|
|
42
|
+
let lastSyncedCount = 0;
|
|
43
|
+
const sync = () => {
|
|
44
|
+
if (queued || disposed) return;
|
|
45
|
+
queued = true;
|
|
46
|
+
queueMicrotask(async () => {
|
|
47
|
+
queued = false;
|
|
48
|
+
if (disposed) return;
|
|
49
|
+
const manifests = listBrowserAgentTools().map(({ invoke: _, ...manifest }) => manifest);
|
|
50
|
+
if (manifests.length === 0 && lastSyncedCount === 0) return;
|
|
51
|
+
lastSyncedCount = manifests.length;
|
|
52
|
+
await rpc.callOptional("devframe:agent:sync-client-tools", resolveClientId(), manifests).catch(() => {});
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
const stopTools = onBrowserAgentToolsChanged(sync);
|
|
56
|
+
const stopConnection = rpc.events.on("connection:status", (status) => {
|
|
57
|
+
if (status === "connected") sync();
|
|
58
|
+
});
|
|
59
|
+
sync();
|
|
60
|
+
return () => {
|
|
61
|
+
disposed = true;
|
|
62
|
+
stopTools();
|
|
63
|
+
stopConnection();
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
export { setupBrowserAgentRpcBridge };
|
|
68
|
+
|
|
69
|
+
//# sourceMappingURL=browser-agent-rpc-BXhoSh1z-BvWe4sTJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-agent-rpc-BXhoSh1z-BvWe4sTJ.js","names":[],"sources":["../../../node_modules/.pnpm/devframe@1.0.0_@devframes+agentic@1.0.0_cac@7.0.0_srvx@1.0.5/node_modules/devframe/dist/browser-agent-rpc-BXhoSh1z.mjs"],"sourcesContent":["import { nanoid } from \"./utils/nanoid.mjs\";\nimport { n as onBrowserAgentToolsChanged, t as listBrowserAgentTools } from \"./browser-agent-Pu-FLk6I.mjs\";\n//#region src/client/client-id.ts\nconst CLIENT_ID_STORAGE_KEY = \"devframe:client-id\";\nlet memoryClientId;\n/**\n* This browser tab's stable client id: one nanoid per tab, persisted in\n* `sessionStorage` so it survives page reloads and RPC reconnects. The node\n* side uses it to tell connected tabs apart across reconnects (see #394).\n*\n* Tab duplication copies `sessionStorage`, so two tabs can briefly share an id\n* until per-tab disambiguation lands with the wider tab-metadata work.\n*/\nfunction resolveClientId(win = globalThis.window) {\n\ttry {\n\t\tconst storage = win?.sessionStorage;\n\t\tif (storage) {\n\t\t\tlet id = storage.getItem(CLIENT_ID_STORAGE_KEY);\n\t\t\tif (!id) {\n\t\t\t\tid = nanoid();\n\t\t\t\tstorage.setItem(CLIENT_ID_STORAGE_KEY, id);\n\t\t\t}\n\t\t\treturn id;\n\t\t}\n\t} catch {}\n\tmemoryClientId ??= nanoid();\n\treturn memoryClientId;\n}\n//#endregion\n//#region src/client/browser-agent-rpc.ts\n/** Mirror this document's browser-agent registry over its existing RPC connection. */\nfunction setupBrowserAgentRpcBridge(rpc) {\n\trpc.client.register({\n\t\tname: \"devframe:agent:invoke-client-tool\",\n\t\ttype: \"action\",\n\t\tjsonSerializable: true,\n\t\thandler: async (id, args) => {\n\t\t\tconst tool = listBrowserAgentTools().find((tool) => tool.id === id);\n\t\t\tif (!tool) throw new Error(`[devframe/agent] browser tool \"${id}\" not found`);\n\t\t\treturn await tool.invoke(args);\n\t\t}\n\t});\n\tlet queued = false;\n\tlet disposed = false;\n\tlet lastSyncedCount = 0;\n\tconst sync = () => {\n\t\tif (queued || disposed) return;\n\t\tqueued = true;\n\t\tqueueMicrotask(async () => {\n\t\t\tqueued = false;\n\t\t\tif (disposed) return;\n\t\t\tconst manifests = listBrowserAgentTools().map(({ invoke: _, ...manifest }) => manifest);\n\t\t\tif (manifests.length === 0 && lastSyncedCount === 0) return;\n\t\t\tlastSyncedCount = manifests.length;\n\t\t\tawait rpc.callOptional(\"devframe:agent:sync-client-tools\", resolveClientId(), manifests).catch(() => {});\n\t\t});\n\t};\n\tconst stopTools = onBrowserAgentToolsChanged(sync);\n\tconst stopConnection = rpc.events.on(\"connection:status\", (status) => {\n\t\tif (status === \"connected\") sync();\n\t});\n\tsync();\n\treturn () => {\n\t\tdisposed = true;\n\t\tstopTools();\n\t\tstopConnection();\n\t};\n}\n//#endregion\nexport { setupBrowserAgentRpcBridge };\n"],"x_google_ignoreList":[0],"mappings":";;AAGA,IAAM,wBAAwB;AAC9B,IAAI;;;;;;;;;AASJ,SAAS,gBAAgB,MAAM,WAAW,QAAQ;CACjD,IAAI;EACH,MAAM,UAAU,KAAK;EACrB,IAAI,SAAS;GACZ,IAAI,KAAK,QAAQ,QAAQ,qBAAqB;GAC9C,IAAI,CAAC,IAAI;IACR,KAAK,OAAO;IACZ,QAAQ,QAAQ,uBAAuB,EAAE;GAC1C;GACA,OAAO;EACR;CACD,QAAQ,CAAC;CACT,mBAAmB,OAAO;CAC1B,OAAO;AACR;;AAIA,SAAS,2BAA2B,KAAK;CACxC,IAAI,OAAO,SAAS;EACnB,MAAM;EACN,MAAM;EACN,kBAAkB;EAClB,SAAS,OAAO,IAAI,SAAS;GAC5B,MAAM,OAAO,sBAAsB,CAAC,CAAC,MAAM,SAAS,KAAK,OAAO,EAAE;GAClE,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,kCAAkC,GAAG,YAAY;GAC5E,OAAO,MAAM,KAAK,OAAO,IAAI;EAC9B;CACD,CAAC;CACD,IAAI,SAAS;CACb,IAAI,WAAW;CACf,IAAI,kBAAkB;CACtB,MAAM,aAAa;EAClB,IAAI,UAAU,UAAU;EACxB,SAAS;EACT,eAAe,YAAY;GAC1B,SAAS;GACT,IAAI,UAAU;GACd,MAAM,YAAY,sBAAsB,CAAC,CAAC,KAAK,EAAE,QAAQ,GAAG,GAAG,eAAe,QAAQ;GACtF,IAAI,UAAU,WAAW,KAAK,oBAAoB,GAAG;GACrD,kBAAkB,UAAU;GAC5B,MAAM,IAAI,aAAa,oCAAoC,gBAAgB,GAAG,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC;EACxG,CAAC;CACF;CACA,MAAM,YAAY,2BAA2B,IAAI;CACjD,MAAM,iBAAiB,IAAI,OAAO,GAAG,sBAAsB,WAAW;EACrE,IAAI,WAAW,aAAa,KAAK;CAClC,CAAC;CACD,KAAK;CACL,aAAa;EACZ,WAAW;EACX,UAAU;EACV,eAAe;CAChB;AACD"}
|