@visulima/dev-toolbar 0.0.1 → 1.0.0-alpha.10

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.
Files changed (158) hide show
  1. package/CHANGELOG.md +223 -0
  2. package/LICENSE.md +188 -0
  3. package/README.md +304 -29
  4. package/bin/mcp.js +29 -0
  5. package/dist/apps/a11y/a11y-app.d.ts +4 -0
  6. package/dist/apps/a11y/a11y-store.d.ts +42 -0
  7. package/dist/apps/a11y/a11y-tooltip.d.ts +10 -0
  8. package/dist/apps/a11y/index.d.ts +3 -0
  9. package/dist/apps/a11y/index.js +21 -0
  10. package/dist/apps/annotations/annotations-app.d.ts +4 -0
  11. package/dist/apps/annotations/index.d.ts +3 -0
  12. package/dist/apps/annotations/index.js +18 -0
  13. package/dist/apps/assets/assets-app.d.ts +4 -0
  14. package/dist/apps/assets/index.d.ts +3 -0
  15. package/dist/apps/assets/index.js +16 -0
  16. package/dist/apps/inspector/a11y-capture.d.ts +12 -0
  17. package/dist/apps/inspector/annotation-overlay.d.ts +55 -0
  18. package/dist/apps/inspector/annotation-settings.d.ts +33 -0
  19. package/dist/apps/inspector/element-utils.d.ts +115 -0
  20. package/dist/apps/inspector/freeze-animations.d.ts +22 -0
  21. package/dist/apps/inspector/index.d.ts +3 -0
  22. package/dist/apps/inspector/index.js +30 -0
  23. package/dist/apps/inspector/inspector-app.d.ts +14 -0
  24. package/dist/apps/inspector/rulers.d.ts +14 -0
  25. package/dist/apps/inspector/theme-palette.d.ts +34 -0
  26. package/dist/apps/module-graph/index.d.ts +3 -0
  27. package/dist/apps/module-graph/index.js +20 -0
  28. package/dist/apps/module-graph/module-graph-app.d.ts +4 -0
  29. package/dist/apps/performance/index.d.ts +3 -0
  30. package/dist/apps/performance/index.js +17 -0
  31. package/dist/apps/performance/performance-app.d.ts +4 -0
  32. package/dist/apps/performance/performance-tooltip.d.ts +4 -0
  33. package/dist/apps/seo/index.d.ts +3 -0
  34. package/dist/apps/seo/index.js +17 -0
  35. package/dist/apps/seo/seo-app.d.ts +4 -0
  36. package/dist/apps/settings/index.d.ts +3 -0
  37. package/dist/apps/settings/index.js +17 -0
  38. package/dist/apps/settings/settings-app.d.ts +4 -0
  39. package/dist/apps/tailwind/index.d.ts +3 -0
  40. package/dist/apps/tailwind/index.js +7 -0
  41. package/dist/apps/tailwind/tailwind-app.d.ts +4 -0
  42. package/dist/apps/timeline/index.d.ts +3 -0
  43. package/dist/apps/timeline/index.js +18 -0
  44. package/dist/apps/timeline/timeline-app.d.ts +4 -0
  45. package/dist/apps/vite-config/index.d.ts +3 -0
  46. package/dist/apps/vite-config/index.js +16 -0
  47. package/dist/apps/vite-config/vite-config-app.d.ts +4 -0
  48. package/dist/client/overlay.d.ts +1 -0
  49. package/dist/client/overlay.js +1 -0
  50. package/dist/hooks/create-hook.d.ts +12 -0
  51. package/dist/hooks/events.d.ts +7 -0
  52. package/dist/hooks/global-hook.d.ts +15 -0
  53. package/dist/hooks/index.d.ts +6 -0
  54. package/dist/index.d.ts +8 -0
  55. package/dist/index.js +1 -0
  56. package/dist/mcp/server.d.ts +12 -0
  57. package/dist/mcp/server.js +1 -0
  58. package/dist/packem_chunks/inject-source.js +9 -0
  59. package/dist/packem_shared/Alert-D2CvX4fw.js +1 -0
  60. package/dist/packem_shared/Badge-BEgU04nl.js +1 -0
  61. package/dist/packem_shared/Button-Bkx66Co7.js +1 -0
  62. package/dist/packem_shared/Card-CJa4vHVc.js +1 -0
  63. package/dist/packem_shared/Icon-B6UHkC0o.js +1 -0
  64. package/dist/packem_shared/Input-Cs6aduTi.js +1 -0
  65. package/dist/packem_shared/Label-DyCng4Cp.js +1 -0
  66. package/dist/packem_shared/Popover-BtFVaZYg.js +1 -0
  67. package/dist/packem_shared/Progress-DN6zn-0l.js +1 -0
  68. package/dist/packem_shared/Select-DgQ4ss-s.js +1 -0
  69. package/dist/packem_shared/Separator-D38mKeZv.js +1 -0
  70. package/dist/packem_shared/Skeleton-Dv-tcA1P.js +1 -0
  71. package/dist/packem_shared/Switch-C3NTpeoR.js +1 -0
  72. package/dist/packem_shared/Tabs-DKWMiawt.js +1 -0
  73. package/dist/packem_shared/Textarea-Yfg3dLZi.js +1 -0
  74. package/dist/packem_shared/Tooltip-CioncSXj.js +1 -0
  75. package/dist/packem_shared/annotation-settings-Bv0TH4WI.js +1 -0
  76. package/dist/packem_shared/annotation-store-bLQRYMaI.js +1 -0
  77. package/dist/packem_shared/clsx-wGlvpUfw.js +1 -0
  78. package/dist/packem_shared/createClientRPCContext-DgRxrllw.js +1 -0
  79. package/dist/packem_shared/createDevToolbarHook-4bZZiHPI.js +1 -0
  80. package/dist/packem_shared/createServerRPCContext-D-yZrEjs.js +1 -0
  81. package/dist/packem_shared/getTimelineStore-B1cfjWV8.js +1 -0
  82. package/dist/packem_shared/loadSettings-hvjR4fcS.js +1 -0
  83. package/dist/packem_shared/setupGlobalHook-CCf9Logv.js +1 -0
  84. package/dist/packem_shared/sharedToolbarStylesheet-CaTdYhVe.js +2 -0
  85. package/dist/packem_shared/store-DaUtLjf3.js +1 -0
  86. package/dist/packem_shared/use-frame-state-CxrlPUM5.js +1 -0
  87. package/dist/packem_shared/use-theme-zpm4zmqP.js +1 -0
  88. package/dist/performance/monitor.d.ts +116 -0
  89. package/dist/rpc/client.d.ts +9 -0
  90. package/dist/rpc/functions/annotations.d.ts +28 -0
  91. package/dist/rpc/functions/assets.d.ts +16 -0
  92. package/dist/rpc/functions/module-graph.d.ts +17 -0
  93. package/dist/rpc/functions/open-in-editor.d.ts +16 -0
  94. package/dist/rpc/functions/tailwind-config.d.ts +15 -0
  95. package/dist/rpc/functions/vite-config.d.ts +83 -0
  96. package/dist/rpc/server.d.ts +15 -0
  97. package/dist/store/annotation-store.d.ts +41 -0
  98. package/dist/timeline/capture.d.ts +8 -0
  99. package/dist/timeline/index.d.ts +8 -0
  100. package/dist/timeline/store.d.ts +42 -0
  101. package/dist/toolbar/app-manager.d.ts +104 -0
  102. package/dist/toolbar/components/app-button.d.ts +18 -0
  103. package/dist/toolbar/components/app-canvas.d.ts +12 -0
  104. package/dist/toolbar/components/app-tooltip-overlay.d.ts +12 -0
  105. package/dist/toolbar/components/first-visit-hint.d.ts +15 -0
  106. package/dist/toolbar/components/index.d.ts +4 -0
  107. package/dist/toolbar/components/pinned-tooltip-card.d.ts +22 -0
  108. package/dist/toolbar/components/toolbar-bar.d.ts +9 -0
  109. package/dist/toolbar/components/toolbar-container.d.ts +49 -0
  110. package/dist/toolbar/components/vite-overlay-button.d.ts +14 -0
  111. package/dist/toolbar/context/index.d.ts +2 -0
  112. package/dist/toolbar/context/toolbar-context.d.ts +107 -0
  113. package/dist/toolbar/global-api.d.ts +24 -0
  114. package/dist/toolbar/helpers.d.ts +8 -0
  115. package/dist/toolbar/hooks/index.d.ts +10 -0
  116. package/dist/toolbar/hooks/use-apps.d.ts +15 -0
  117. package/dist/toolbar/hooks/use-frame-state.d.ts +110 -0
  118. package/dist/toolbar/hooks/use-panel-visible.d.ts +23 -0
  119. package/dist/toolbar/hooks/use-position.d.ts +24 -0
  120. package/dist/toolbar/hooks/use-theme.d.ts +15 -0
  121. package/dist/toolbar/hooks/use-toolbar.d.ts +16 -0
  122. package/dist/toolbar/index.d.ts +50 -0
  123. package/dist/toolbar/index.js +21 -0
  124. package/dist/toolbar/settings.d.ts +17 -0
  125. package/dist/toolbar/stylesheet.d.ts +3 -0
  126. package/dist/toolbar/utils/index.d.ts +12 -0
  127. package/dist/types/annotations.d.ts +156 -0
  128. package/dist/types/app.d.ts +175 -0
  129. package/dist/types/global-api.d.ts +91 -0
  130. package/dist/types/hooks.d.ts +86 -0
  131. package/dist/types/index.d.ts +13 -0
  132. package/dist/types/messaging.d.ts +43 -0
  133. package/dist/types/rpc.d.ts +137 -0
  134. package/dist/types/timeline.d.ts +62 -0
  135. package/dist/types/toolbar.d.ts +56 -0
  136. package/dist/ui/components/alert.d.ts +19 -0
  137. package/dist/ui/components/badge.d.ts +9 -0
  138. package/dist/ui/components/button.d.ts +11 -0
  139. package/dist/ui/components/card.d.ts +16 -0
  140. package/dist/ui/components/icon.d.ts +19 -0
  141. package/dist/ui/components/input.d.ts +7 -0
  142. package/dist/ui/components/label.d.ts +7 -0
  143. package/dist/ui/components/popover.d.ts +27 -0
  144. package/dist/ui/components/progress.d.ts +7 -0
  145. package/dist/ui/components/select.d.ts +54 -0
  146. package/dist/ui/components/separator.d.ts +8 -0
  147. package/dist/ui/components/skeleton.d.ts +6 -0
  148. package/dist/ui/components/switch.d.ts +11 -0
  149. package/dist/ui/components/tabs.d.ts +28 -0
  150. package/dist/ui/components/textarea.d.ts +7 -0
  151. package/dist/ui/components/tooltip.d.ts +19 -0
  152. package/dist/ui/index.d.ts +18 -0
  153. package/dist/ui/index.js +1 -0
  154. package/dist/vite/inject-source.d.ts +24 -0
  155. package/dist/vite/matcher.d.ts +6 -0
  156. package/dist/vite-plugin.d.ts +149 -0
  157. package/dist/vite-plugin.js +5 -0
  158. package/package.json +144 -7
package/README.md CHANGED
@@ -1,45 +1,320 @@
1
- # @visulima/dev-toolbar
1
+ <!-- START_PACKAGE_OG_IMAGE_PLACEHOLDER -->
2
2
 
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
3
+ <a href="https://www.anolilab.com/open-source" align="center">
4
4
 
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
5
+ <img src="__assets__/package-og.svg" alt="dev-toolbar" />
6
6
 
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
7
+ </a>
8
8
 
9
- ## Purpose
9
+ <h3 align="center">Devtools is a set of tools for building advanced devtools for your application</h3>
10
10
 
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@visulima/dev-toolbar`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
11
+ <!-- END_PACKAGE_OG_IMAGE_PLACEHOLDER -->
15
12
 
16
- ## What is OIDC Trusted Publishing?
13
+ <br />
17
14
 
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
15
+ <div align="center">
19
16
 
20
- ## Setup Instructions
17
+ [![typescript-image][typescript-badge]][typescript-url]
18
+ [![mit licence][license-badge]][license]
19
+ [![npm downloads][npm-downloads-badge]][npm-downloads]
20
+ [![Chat][chat-badge]][chat]
21
+ [![PRs Welcome][prs-welcome-badge]][prs-welcome]
21
22
 
22
- To properly configure OIDC trusted publishing for this package:
23
+ </div>
23
24
 
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
25
+ ---
28
26
 
29
- ## DO NOT USE THIS PACKAGE
27
+ <div align="center">
28
+ <p>
29
+ <sup>
30
+ Daniel Bannert's open source work is supported by the community on <a href="https://github.com/sponsors/prisis">GitHub Sponsors</a>
31
+ </sup>
32
+ </p>
33
+ </div>
30
34
 
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
35
+ ---
36
36
 
37
- ## More Information
37
+ ## Overview
38
38
 
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
39
+ `@visulima/dev-toolbar` is a framework-agnostic development toolbar for **any Vite project** — React, Vue, Svelte, SolidJS, or plain HTML. Inspired by Astro DevToolbar, Vue DevTools, and Nuxt DevTools, it provides a consistent developer experience regardless of your framework.
42
40
 
43
- ---
41
+ The toolbar renders inside a Shadow DOM custom element (zero style leakage), communicates with the Vite dev server over type-safe RPC, and ships **nine built-in apps** covering the most common development workflows.
42
+
43
+ ## Install
44
+
45
+ ```sh
46
+ npm install -D @visulima/dev-toolbar
47
+ ```
48
+
49
+ ```sh
50
+ pnpm add -D @visulima/dev-toolbar
51
+ ```
52
+
53
+ ```sh
54
+ yarn add -D @visulima/dev-toolbar
55
+ ```
56
+
57
+ ## Quick Start
58
+
59
+ Add the plugin to your `vite.config.ts`:
60
+
61
+ ```ts
62
+ import { defineConfig } from "vite";
63
+ import { devToolbar } from "@visulima/dev-toolbar/vite";
64
+
65
+ export default defineConfig({
66
+ plugins: [devToolbar()],
67
+ });
68
+ ```
69
+
70
+ Start your dev server and press **`Alt`+`Shift`+`D`** to open the toolbar.
71
+
72
+ ## Built-in Apps
73
+
74
+ | App | What it does |
75
+ | ----------------- | ----------------------------------------------------------------------------- |
76
+ | **Accessibility** | axe-core WCAG audit with live element overlays and sessionStorage persistence |
77
+ | **Performance** | Web Vitals (LCP, INP, CLS, FCP, TTFB), resource timing, navigation waterfall |
78
+ | **SEO** | Social preview cards for 7 platforms + full meta tag audit |
79
+ | **Timeline** | Chronological event log from your app and integrated libraries |
80
+ | **Module Graph** | Browse and filter Vite's live module dependency graph |
81
+ | **Vite Config** | Inspect the fully resolved Vite configuration |
82
+ | **Inspector** | Click any element to jump to its JSX source in your editor |
83
+ | **Tailwind** | Browse all resolved Tailwind CSS design tokens and their values |
84
+ | **Settings** | Theme, toolbar behaviour, panel sizing, and custom keyboard shortcuts |
85
+
86
+ All apps are enabled by default. Disable individual apps via plugin options:
87
+
88
+ ```ts
89
+ devToolbar({
90
+ apps: {
91
+ performance: false,
92
+ seo: false,
93
+ },
94
+ });
95
+ ```
96
+
97
+ ## Plugin Options
98
+
99
+ ```ts
100
+ devToolbar({
101
+ // Built-in apps (all true by default)
102
+ apps: {
103
+ a11y: true,
104
+ moduleGraph: true,
105
+ performance: true,
106
+ seo: true,
107
+ settings: true,
108
+ timeline: true,
109
+ viteConfig: true,
110
+ inspector: true,
111
+ tailwind: true,
112
+ },
113
+
114
+ // Register custom apps
115
+ customApps: [],
116
+
117
+ // Toolbar pill placement
118
+ placement: "bottom-center", // "bottom-left" | "bottom-center" | "bottom-right"
119
+ position: "bottom", // "bottom" | "top" | "left" | "right"
120
+
121
+ // Panel defaults (users can override via Settings app)
122
+ height: 60, // % of viewport height
123
+ width: 80, // % of viewport width
124
+ minimizePanelInactive: 5000, // ms; -1 = never auto-hide
125
+ closeOnOutsideClick: true,
126
+
127
+ // Keyboard shortcuts (project-level defaults)
128
+ keybindings: {
129
+ toggle: "Alt+Shift+D",
130
+ close: "Escape",
131
+ },
132
+
133
+ // Strip toolbar from production builds (default: true)
134
+ removeDevtoolsOnBuild: true,
135
+
136
+ // Force a specific editor for "Open in editor" (auto-detected if omitted)
137
+ editor: "webstorm",
138
+
139
+ // JSX source injection for click-to-source in the inspector
140
+ injectSource: {
141
+ enabled: true, // set false to opt out
142
+ ignore: {
143
+ files: ["**/generated/**"], // glob patterns
144
+ components: ["StrictMode"], // component names
145
+ },
146
+ },
147
+ });
148
+ ```
149
+
150
+ See the [full configuration reference](./docs/configuration.mdx) for all options.
151
+
152
+ ## Keyboard Shortcuts
153
+
154
+ | Action | Default |
155
+ | ------------------------- | ----------------- |
156
+ | Toggle toolbar open/close | `Alt`+`Shift`+`D` |
157
+ | Close active app / panel | `Escape` |
158
+
159
+ Both shortcuts are configurable in the Settings app or via plugin options.
160
+
161
+ ## Custom Apps
162
+
163
+ Build your own devtools panel with a Preact component:
164
+
165
+ ```tsx
166
+ /** @jsxImportSource preact */
167
+ import type { ComponentChildren } from "preact";
168
+ import type { AppComponentProps } from "@visulima/dev-toolbar";
169
+
170
+ const MyApp = ({ helpers }: AppComponentProps): ComponentChildren => {
171
+ return <div class="p-5">Hello from My App!</div>;
172
+ };
173
+ ```
174
+
175
+ ```ts
176
+ // vite.config.ts
177
+ devToolbar({
178
+ customApps: [
179
+ {
180
+ id: "my-package:my-app",
181
+ name: "My App",
182
+ icon: myIconSvg, // raw SVG string
183
+ component: MyApp,
184
+ tooltip: MyTooltip, // optional hover summary
185
+ },
186
+ ],
187
+ });
188
+ ```
189
+
190
+ See the [custom apps guide](./docs/custom-apps/creating-apps.mdx) for a step-by-step walkthrough including RPC, tooltips, and styling.
191
+
192
+ ## RPC — Server ↔ Client Communication
193
+
194
+ Call Node.js functions from your app component over the Vite HMR WebSocket:
195
+
196
+ ```ts
197
+ // Add server functions in vite.config.ts
198
+ devToolbar({
199
+ serverFunctions: {
200
+ async getRoutes() {
201
+ const files = await fs.readdir("src/pages");
202
+ return files.map((f) => `/${f.replace(/\.(tsx?|jsx?)$/, "")}`);
203
+ },
204
+ },
205
+ });
206
+
207
+ // Call from your app component
208
+ const routes = await helpers.rpc.getRoutes();
209
+ ```
210
+
211
+ Built-in RPC functions: `getViteConfig()`, `getModuleGraph()`, `openInEditor(file, line, col)`.
212
+
213
+ ## Global API
214
+
215
+ Programmatic control from any script or the browser console:
216
+
217
+ ```ts
218
+ const api = (window as any).__VISULIMA_DEVTOOLS__;
219
+
220
+ // Open an app
221
+ await api.openApp("dev-toolbar:a11y");
222
+
223
+ // Show a notification badge on an app button
224
+ api.notify("my-package:monitor", "warning");
225
+
226
+ // Update toolbar settings
227
+ api.updateSettings({ viewMode: "fullscreen" });
228
+
229
+ // Access RPC from outside a component
230
+ const config = await api.rpc.getViteConfig();
231
+ ```
232
+
233
+ ## Library Integration
234
+
235
+ Add zero-dependency devtools support to your library. Users get devtools automatically when they install the toolbar — no extra configuration needed:
236
+
237
+ ```ts
238
+ function installDevTools(instance: MyLibrary): void {
239
+ const hook = (window as any).__DEV_TOOLBAR_HOOK__;
240
+ if (!hook) return;
241
+
242
+ hook.registerApp({
243
+ id: "my-library:devtools",
244
+ name: "My Library",
245
+ icon: iconSvg,
246
+ component: MyLibraryPanel,
247
+ });
248
+
249
+ instance.on("action", (action) => {
250
+ hook.addTimelineEvent("my-library", {
251
+ id: crypto.randomUUID(),
252
+ title: action.type,
253
+ time: Date.now(),
254
+ level: "info",
255
+ data: action,
256
+ });
257
+ });
258
+ }
259
+ ```
260
+
261
+ See the [library integration guide](./docs/integrations/library-integration.mdx) for the full pattern.
262
+
263
+ ## Documentation
264
+
265
+ All docs are in the [`docs/`](./docs/) folder in Fumadocs MDX format:
266
+
267
+ | Page | Contents |
268
+ | ------------------------------------------------------------------ | ---------------------------------------- |
269
+ | [Getting Started](./docs/getting-started.mdx) | Install, framework examples, first steps |
270
+ | [Configuration](./docs/configuration.mdx) | Full plugin options reference |
271
+ | [Accessibility](./docs/built-in-apps/accessibility.mdx) | axe-core, overlays, WCAG standards |
272
+ | [Performance](./docs/built-in-apps/performance.mdx) | Web Vitals thresholds, timing APIs |
273
+ | [SEO](./docs/built-in-apps/seo.mdx) | Social previews, meta tag audit |
274
+ | [Timeline](./docs/built-in-apps/timeline.mdx) | Event structure, emitting events |
275
+ | [Module Graph](./docs/built-in-apps/module-graph.mdx) | Search, ext badges, importer view |
276
+ | [Vite Config](./docs/built-in-apps/vite-config.mdx) | Resolved config sections |
277
+ | [Settings](./docs/built-in-apps/settings.mdx) | All settings, localStorage schema |
278
+ | [Creating Apps](./docs/custom-apps/creating-apps.mdx) | Step-by-step custom app guide |
279
+ | [App API](./docs/custom-apps/app-api.mdx) | TypeScript interface reference |
280
+ | [RPC](./docs/custom-apps/rpc.mdx) | Server functions, type-safe pattern |
281
+ | [Global API](./docs/custom-apps/global-api.mdx) | `__VISULIMA_DEVTOOLS__` reference |
282
+ | [Library Integration](./docs/integrations/library-integration.mdx) | Zero-dependency hook pattern |
283
+
284
+ ## Supported Node.js Versions
285
+
286
+ Libraries in this ecosystem make the best effort to track
287
+ [Node.js' release schedule](https://github.com/nodejs/release#release-schedule).
288
+ Here's [a post on why we think this is important](https://medium.com/the-node-js-collection/maintainers-should-consider-following-node-js-release-schedule-ab08ed4de71a).
289
+
290
+ ## Contributing
291
+
292
+ If you would like to help take a look at the [list of issues](https://github.com/visulima/visulima/issues) and check our [Contributing](https://github.com/visulima/visulima/blob/main/.github/CONTRIBUTING.md) guidelines.
293
+
294
+ > **Note:** please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
295
+
296
+ ## Credits
297
+
298
+ - [Daniel Bannert](https://github.com/prisis)
299
+ - [All Contributors](https://github.com/visulima/visulima/graphs/contributors)
300
+
301
+ ## Made with ❤️ at Anolilab
302
+
303
+ This is an open-source project and will always remain free to use. If you think it's cool, please star it 🌟. [Anolilab](https://www.anolilab.com/open-source) is a Development and AI Studio. Contact us at [hello@anolilab.com](mailto:hello@anolilab.com) if you need any help with these technologies or just want to say hi!
304
+
305
+ ## License
306
+
307
+ The visulima dev-toolbar is open-sourced software licensed under the [MIT][license]
308
+
309
+ <!-- badges -->
44
310
 
45
- **Maintained for OIDC setup purposes only**
311
+ [license-badge]: https://img.shields.io/npm/l/@visulima/dev-toolbar?style=for-the-badge
312
+ [license]: https://github.com/visulima/visulima/blob/main/LICENSE
313
+ [npm-downloads-badge]: https://img.shields.io/npm/dm/@visulima/dev-toolbar?style=for-the-badge
314
+ [npm-downloads]: https://www.npmjs.com/package/@visulima/dev-toolbar
315
+ [prs-welcome-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=for-the-badge
316
+ [prs-welcome]: https://github.com/visulima/visulima/blob/main/.github/CONTRIBUTING.md
317
+ [chat-badge]: https://img.shields.io/discord/932323359193186354.svg?style=for-the-badge
318
+ [chat]: https://discord.gg/TtFJY8xkFK
319
+ [typescript-badge]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
320
+ [typescript-url]: https://www.typescriptlang.org/
package/bin/mcp.js ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MCP server for `@visulima/dev-toolbar` annotations.
5
+ *
6
+ * Usage:
7
+ * npx visulima-dev-toolbar-mcp
8
+ *
9
+ * Configure in .mcp.json:
10
+ * {
11
+ * "mcpServers": {
12
+ * "dev-toolbar": {
13
+ * "command": "npx",
14
+ * "args": ["visulima-dev-toolbar-mcp"],
15
+ * "cwd": "/absolute/path/to/project"
16
+ * }
17
+ * }
18
+ * }
19
+ *
20
+ * Requires @modelcontextprotocol/sdk to be installed.
21
+ */
22
+
23
+ // eslint-disable-next-line antfu/no-import-dist -- bin entry point runs after build
24
+ import { startMcpServer } from "../dist/mcp/server";
25
+
26
+ startMcpServer().catch((error) => {
27
+ console.error("Failed to start MCP server:", error);
28
+ process.exit(1);
29
+ });
@@ -0,0 +1,4 @@
1
+ import type { ComponentChildren } from "preact";
2
+ import type { AppComponentProps } from "../../types/app.d.ts";
3
+ declare const A11yApp: (_props: AppComponentProps) => ComponentChildren;
4
+ export default A11yApp;
@@ -0,0 +1,42 @@
1
+ type Severity = "critical" | "minor" | "moderate" | "serious";
2
+ type Standard = "best-practice" | "wcag21aa" | "wcag22aa" | "wcag2a";
3
+ interface A11yNode {
4
+ html: string;
5
+ selector: string;
6
+ }
7
+ interface A11yIssue {
8
+ helpUrl: string;
9
+ id: string;
10
+ impact: Severity;
11
+ message: string;
12
+ nodes: A11yNode[];
13
+ wcagTags: string[];
14
+ }
15
+ interface A11yStoreState {
16
+ isScanning: boolean;
17
+ issues: A11yIssue[];
18
+ lastScan: string | undefined;
19
+ scanError: string | undefined;
20
+ showOverlays: boolean;
21
+ standard: Standard;
22
+ }
23
+ declare const SEVERITY_ORDER: Severity[];
24
+ type Listener = () => void;
25
+ declare class A11yStore {
26
+ private listeners;
27
+ private state;
28
+ constructor();
29
+ clearHighlights(): void;
30
+ getState(): Readonly<A11yStoreState>;
31
+ highlightIssue(issue: A11yIssue): void;
32
+ scan(disabledRules?: string[]): Promise<void>;
33
+ setShowOverlays(show: boolean): void;
34
+ setStandard(standard: Standard): void;
35
+ subscribe(listener: Listener): () => void;
36
+ private notify;
37
+ private persist;
38
+ private update;
39
+ }
40
+ declare const a11yStore: A11yStore;
41
+ export type { A11yIssue, A11yNode, A11yStoreState, Severity, Standard };
42
+ export { a11yStore, SEVERITY_ORDER };
@@ -0,0 +1,10 @@
1
+ import type { ComponentChildren } from "preact";
2
+ import type { AppTooltipProps } from "../../types/app.d.ts";
3
+ /**
4
+ * Hover tooltip for the Accessibility app button.
5
+ * Shows a summary of scan results and quick action buttons.
6
+ * @param _props Tooltip props (unused; reads from a11yStore directly)
7
+ * @returns Rendered tooltip component
8
+ */
9
+ declare const A11yTooltip: (_props: AppTooltipProps) => ComponentChildren;
10
+ export default A11yTooltip;
@@ -0,0 +1,3 @@
1
+ import type { DevToolbarApp } from "../../types/app.d.ts";
2
+ declare const a11yApp: DevToolbarApp;
3
+ export default a11yApp;
@@ -0,0 +1,21 @@
1
+ var X=Object.defineProperty;var O=(a,e)=>X(a,"name",{value:e,configurable:!0});import{addHookName as k}from"preact/devtools";import{clsx as d}from"../../packem_shared/clsx-wGlvpUfw.js";import{useState as C,useEffect as L}from"preact/hooks";import{jsxs as i,jsx as t,Fragment as W}from"preact/jsx-runtime";import w from"../../packem_shared/Button-Bkx66Co7.js";import{Alert as Y,AlertDescription as Z}from"../../packem_shared/Alert-D2CvX4fw.js";const ee=`<!-- @license lucide-static v1.8.0 - ISC -->
2
+ <svg
3
+ class="lucide lucide-accessibility"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="24"
6
+ height="24"
7
+ viewBox="0 0 24 24"
8
+ fill="none"
9
+ stroke="currentColor"
10
+ stroke-width="2"
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ >
14
+ <circle cx="16" cy="4" r="1" />
15
+ <path d="m18 19 1-7-6 1" />
16
+ <path d="m5 8 3-3 5.5 3-2.36 3.5" />
17
+ <path d="M4.24 14.5a5 5 0 0 0 6.88 6" />
18
+ <path d="M13.76 17.5a5 5 0 0 0-6.88-6" />
19
+ </svg>
20
+ `;var te=Object.defineProperty,x=O((a,e)=>te(a,"name",{value:e,configurable:!0}),"i$3");const E=["critical","serious","moderate","minor"],re={critical:"rgb(239,68,68)",minor:"rgb(100,116,139)",moderate:"rgb(249,115,22)",serious:"rgb(234,179,8)"},se={"best-practice":["best-practice"],wcag2a:["wcag2a"],wcag21aa:["wcag2a","wcag2aa","wcag21a","wcag21aa"],wcag22aa:["wcag2a","wcag2aa","wcag21a","wcag21aa","wcag22a","wcag22aa"]},_="__vdt_a11y__",ne=x(()=>{try{const a=sessionStorage.getItem(_);if(a){const e=JSON.parse(a);if(Array.isArray(e.issues))return{issues:e.issues,lastScan:e.lastScan??void 0}}}catch{}return{issues:[],lastScan:void 0}},"loadFromSession"),z=x((a,e)=>{const n=a;n.dataset.vdtA11y=e,n.style.setProperty("outline",`2px solid ${re[e]}`,"important"),n.style.setProperty("outline-offset","2px","important")},"setHighlight"),I=x(()=>{for(const a of document.querySelectorAll("[data-vdt-a11y]")){const e=a;delete e.dataset.vdtA11y,e.style.removeProperty("outline"),e.style.removeProperty("outline-offset")}},"clearHighlightsDOM"),H=x(a=>{I();for(const e of a)for(const n of e.nodes)try{const r=document.querySelector(n.selector);r&&z(r,e.impact)}catch{}},"applyOverlaysDOM"),ae=x(a=>{const e=a.at(-1);return Array.isArray(e)?e.join(" "):String(e??"")},"nodeSelector"),ie=x((a,e)=>{const n=[];for(const r of a)e.includes(r.id)||n.push({helpUrl:r.helpUrl,id:r.id,impact:r.impact??"minor",message:r.help,nodes:r.nodes.map(o=>({html:o.html,selector:ae(o.target)})),wcagTags:r.tags.filter(o=>o.startsWith("wcag")||o==="best-practice")});return n},"convertViolations"),oe=x(async a=>{const e=await import("axe-core"),n=typeof e.default?.run=="function"?e.default:e;if(typeof n.run!="function")throw new TypeError("axe-core could not be loaded — .run is not available");return n.run(document,{exclude:[["dev-toolbar"]],runOnly:{type:"tag",values:se[a]}})},"runAxeScan");class ce{static{O(this,"v")}static{x(this,"A11yStore")}listeners=new Set;state;constructor(){const{issues:e,lastScan:n}=ne();this.state={isScanning:!1,issues:e,lastScan:n,scanError:void 0,showOverlays:!1,standard:"wcag21aa"}}clearHighlights(){I()}getState(){return this.state}highlightIssue(e){I();let n=!1;for(const r of e.nodes)try{const o=document.querySelector(r.selector);o&&(z(o,e.impact),n||(o.scrollIntoView({behavior:"smooth",block:"center"}),n=!0))}catch{}}async scan(e=[]){if(!this.state.isScanning){this.update({isScanning:!0,scanError:void 0});try{const n=await oe(this.state.standard),r=ie(n.violations,e);this.update({isScanning:!1,issues:r,lastScan:new Date().toISOString()}),this.persist(),this.state.showOverlays&&H(r)}catch(n){this.update({isScanning:!1,scanError:n instanceof Error?n.message:String(n)})}}}setShowOverlays(e){this.update({showOverlays:e}),e?H(this.state.issues):I()}setStandard(e){this.update({standard:e})}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}notify(){for(const e of this.listeners)e()}persist(){try{sessionStorage.setItem(_,JSON.stringify({issues:this.state.issues,lastScan:this.state.lastScan}))}catch{}}update(e){this.state={...this.state,...e},this.notify()}}const l=new ce;var le=Object.defineProperty,c=O((a,e)=>le(a,"name",{value:e,configurable:!0}),"i$2");const N={critical:"Critical",minor:"Minor",moderate:"Moderate",serious:"Serious"},J={critical:"text-destructive",minor:"text-muted-foreground",moderate:"text-warning-foreground",serious:"text-warning-foreground"},de={critical:"bg-destructive/10 border-destructive/30",minor:"bg-foreground/4 border-border",moderate:"bg-warning/10 border-warning/30",serious:"bg-warning/10 border-warning/30"},ue={critical:"bg-destructive",minor:"bg-muted-foreground/50",moderate:"bg-warning",serious:"bg-warning"},ge=c(({count:a,isActive:e,onClick:n,severity:r})=>i("button",{class:d("flex flex-col items-center gap-1 px-3 py-2.5 border cursor-pointer transition-colors",e?"ring-1 ring-inset ring-primary/40":"hover:bg-foreground/6",de[r]),onClick:n,title:`${e?"Clear":"Filter by"} ${N[r]}`,type:"button",children:[t("span",{class:d("text-xl font-bold tabular-nums leading-none",J[r]),children:a}),t("span",{class:"text-[0.6rem] font-semibold uppercase tracking-wider text-muted-foreground",children:N[r]})]}),"SeverityBucket"),pe=c(({isSelected:a,issue:e,onClick:n,onDisable:r})=>i("div",{class:d("p-3 border cursor-pointer transition-colors",a?"bg-foreground/6 border-primary/30":"border-border hover:bg-foreground/3"),onClick:n,children:[i("div",{class:"flex items-start gap-2 mb-1.5",children:[t("span",{class:d("mt-1 size-2 rounded-full shrink-0",ue[e.impact])}),t("span",{class:"text-[0.75rem] font-semibold text-foreground flex-1 leading-snug",children:e.id}),t("span",{class:d("text-[0.6rem] font-bold uppercase tracking-wide shrink-0",J[e.impact]),children:N[e.impact]})]}),t("p",{class:"text-[0.7rem] text-muted-foreground leading-relaxed mb-2 ml-4",children:e.message}),e.nodes.length>0&&i("div",{class:"mb-2 ml-4 space-y-0.5",children:[e.nodes.slice(0,3).map((o,p)=>t("code",{class:"block text-[0.65rem] text-foreground/70 font-mono bg-foreground/5 px-2 py-1 truncate",children:o.selector},p)),e.nodes.length>3&&i("span",{class:"text-[0.62rem] text-muted-foreground/60",children:["+",e.nodes.length-3," more element",e.nodes.length>4?"s":""]})]}),i("div",{class:"flex items-center gap-2 flex-wrap ml-4",children:[e.wcagTags.slice(0,3).map(o=>t("span",{class:"text-[0.58rem] font-mono uppercase bg-primary/8 text-primary/70 border border-primary/20 px-1.5 py-0.5",children:o},o)),t("span",{class:"flex-1"}),t("a",{class:"text-[0.62rem] text-primary/70 hover:text-primary transition-colors",href:e.helpUrl,onClick:c(o=>o.stopPropagation(),"onClick"),rel:"noopener noreferrer",target:"_blank",children:"Learn more ↗"}),t("button",{class:"text-[0.62rem] text-muted-foreground/60 hover:text-muted-foreground transition-colors cursor-pointer bg-transparent border-0 p-0",onClick:c(o=>{o.stopPropagation(),r(e.id)},"onClick"),title:"Disable this rule for current session",type:"button",children:"Disable"})]})]}),"IssueCard"),me=c(a=>{const[e,n]=k(C(()=>l.getState()),"storeState"),[r,o]=k(C([]),"disabledRules"),[p,M]=k(C(void 0),"minSeverity"),[S,v]=k(C(void 0),"activeIssueId"),[m,f]=k(C(void 0),"filterSeverity");L(()=>l.subscribe(()=>n(l.getState())),[]),L(()=>l.clearHighlights.bind(l),[]);const{isScanning:b,issues:h,lastScan:u,scanError:$,showOverlays:T,standard:q}=e,U=u!==void 0||$!==void 0,P=c(()=>{f(void 0),v(void 0),l.scan(r).catch(()=>{})},"handleScan"),V=c(s=>{S===s.id?(v(void 0),l.clearHighlights(),T&&l.setShowOverlays(!0)):(v(s.id),l.highlightIssue(s))},"handleIssueClick"),F=c(s=>{o(g=>[...g,s])},"handleDisableRule"),R=h.filter(s=>!(r.includes(s.id)||m&&s.impact!==m||p&&E.indexOf(s.impact)>E.indexOf(p))),K=c(s=>h.filter(g=>!r.includes(g.id)&&g.impact===s).length,"countBy");return i("div",{class:"flex flex-col h-full",children:[i("div",{class:"shrink-0 flex items-center gap-2 px-4 py-2.5 border-b border-border bg-foreground/2 flex-wrap",children:[t(w,{class:d(b?"border-primary/30 text-primary/50 bg-primary/5":""),disabled:b,onClick:P,size:"sm",variant:"outline",children:b?"Scanning…":"Scan page"}),i("label",{class:"flex items-center gap-1.5 text-[0.7rem] text-muted-foreground",children:["Standard",i("select",{class:"bg-card border border-border text-foreground text-[0.7rem] px-1.5 py-1 cursor-pointer",onChange:c(s=>l.setStandard(s.target.value),"onChange"),style:"color-scheme: dark",value:q,children:[t("option",{value:"wcag21aa",children:"WCAG 2.1 AA"}),t("option",{value:"wcag22aa",children:"WCAG 2.2 AA"}),t("option",{value:"wcag2a",children:"WCAG 2.0 A"}),t("option",{value:"best-practice",children:"Best Practice"})]})]}),i("label",{class:"flex items-center gap-1.5 text-[0.7rem] text-muted-foreground",children:["Min",i("select",{class:"bg-card border border-border text-foreground text-[0.7rem] px-1.5 py-1 cursor-pointer",onChange:c(s=>{const{value:g}=s.target;M(g||void 0)},"onChange"),style:"color-scheme: dark",value:p??"",children:[t("option",{value:"",children:"All"}),t("option",{value:"critical",children:"Critical only"}),t("option",{value:"serious",children:"Serious+"}),t("option",{value:"moderate",children:"Moderate+"})]})]}),t(w,{class:d(T?"border-primary/30 text-primary bg-primary/8":""),onClick:c(()=>l.setShowOverlays(!T),"onClick"),size:"sm",title:"Toggle visual highlights on affected elements",variant:"outline",children:"Overlays"}),U&&h.length>0&&i(W,{children:[t(w,{class:"ml-auto",onClick:c(()=>{const s=new Blob([JSON.stringify(h,void 0,2)],{type:"application/json"}),g=URL.createObjectURL(s),A=document.createElement("a");A.href=g,A.download="a11y-audit.json",A.click(),URL.revokeObjectURL(g)},"onClick"),size:"sm",title:"Export audit results as JSON",variant:"outline",children:"JSON"}),t(w,{onClick:c(()=>{const s=c(y=>`"${y.replaceAll('"','""')}"`,"q"),g=["Rule ID","Severity","Message","Selector","HTML","WCAG Tags"].join(","),A=h.flatMap(y=>y.nodes.map(G=>[s(y.id),s(y.impact),s(y.message),s(G.selector),s(G.html),s(y.wcagTags.join("; "))].join(","))),Q=new Blob([[g,...A].join(`
21
+ `)],{type:"text/csv"}),B=URL.createObjectURL(Q),D=document.createElement("a");D.href=B,D.download="a11y-audit.csv",D.click(),URL.revokeObjectURL(B)},"onClick"),size:"sm",title:"Export audit results as CSV",variant:"outline",children:"CSV"})]})]}),i("div",{class:"flex-1 overflow-y-auto devtools-content-scroll",children:[$&&t(Y,{class:"rounded-none border-x-0 border-t-0",variant:"destructive",children:i(Z,{children:["Scan failed: ",$]})}),!U&&!b&&i("div",{class:"flex flex-col items-center justify-center gap-4 p-8 min-h-48 text-center",children:[t("p",{class:"text-[0.8125rem] text-muted-foreground max-w-sm",children:"Run an accessibility audit using axe-core to detect WCAG violations on this page."}),t(w,{onClick:P,variant:"outline",children:"Start scan"})]}),b&&t("div",{class:"flex items-center justify-center gap-3 p-8 min-h-48",children:t("span",{class:"text-[0.8rem] text-muted-foreground",children:"Scanning for accessibility issues…"})}),U&&!b&&!$&&i("div",{class:"p-5 space-y-4",children:[t("div",{class:"grid grid-cols-4 gap-2",children:E.map(s=>t(ge,{count:K(s),isActive:m===s,onClick:c(()=>f(m===s?void 0:s),"onClick"),severity:s},s))}),R.length===0?i("div",{class:"p-6 text-center border border-border",children:[t("p",{class:"text-[0.8125rem] font-medium text-foreground/70",children:h.length===0?"No violations found!":"No issues match the current filters."}),h.length===0&&t("p",{class:"mt-1 text-[0.7rem] text-muted-foreground",children:"Great — the page passes all rules for the selected standard."})]}):i("section",{children:[i("div",{class:"flex items-center gap-2 mb-2",children:[i("span",{class:"text-[0.65rem] font-bold uppercase tracking-[0.1em] text-muted-foreground",children:[t("span",{"aria-hidden":"true",class:"text-primary/50",children:"//"})," ",R.length," issue",R.length===1?"":"s",m?` · ${N[m]} only`:""]}),m&&t(w,{class:"h-auto p-0 text-[0.62rem]",onClick:c(()=>f(void 0),"onClick"),variant:"link",children:"Clear ×"})]}),t("div",{class:"space-y-2",children:R.map(s=>t(pe,{isSelected:S===s.id,issue:s,onClick:c(()=>V(s),"onClick"),onDisable:F},s.id))})]}),r.length>0&&i("div",{class:"flex items-center gap-2 text-[0.65rem] text-muted-foreground/60",children:[i("span",{children:[r.length," rule",r.length===1?"":"s"," disabled this session."]}),t(w,{class:"h-auto p-0 text-[0.62rem]",onClick:c(()=>o([]),"onClick"),variant:"link",children:"Reset"})]})]})]})]})},"A11yApp");var he=Object.defineProperty,j=O((a,e)=>he(a,"name",{value:e,configurable:!0}),"i$1");const fe={critical:"text-destructive",minor:"text-muted-foreground",moderate:"text-warning-foreground",serious:"text-warning-foreground"},be={critical:"Crit",minor:"Min",moderate:"Mod",serious:"Ser"},xe=j(a=>{const e=new Date(a).getTime();if(Number.isNaN(e))return"unknown";const n=Math.max(0,Math.floor((Date.now()-e)/1e3));if(n<10)return"just now";if(n<60)return`${n}s ago`;const r=Math.floor(n/60);return r<60?`${r} min ago`:`${Math.floor(r/60)} hr ago`},"formatElapsed"),ve=j(a=>{const[e,n]=k(C(()=>l.getState()),"state");L(()=>l.subscribe(()=>n(l.getState())),[]);const{isScanning:r,issues:o,lastScan:p,showOverlays:M}=e,S=o.length,v={critical:0,minor:0,moderate:0,serious:0};for(const u of o)v[u.impact]=(v[u.impact]??0)+1;const m=j(u=>v[u],"countBy");let f;r?f="Scanning…":p?f="Re-scan":f="Scan";const b=M?"border-primary/30 text-primary bg-primary/8":"border-border text-muted-foreground bg-transparent hover:text-foreground",h=o.length===0?"border-border/50 text-muted-foreground/40 bg-transparent cursor-not-allowed":d("cursor-pointer",b);return i("div",{class:"space-y-3 min-w-[200px]",children:[p?i(W,{children:[i("div",{class:"flex items-baseline gap-2",children:[t("span",{class:d("text-2xl font-bold tabular-nums leading-none",S>0?"text-destructive":"text-success-foreground"),children:S}),i("span",{class:"text-[0.65rem] text-muted-foreground",children:["violation",S===1?"":"s"]})]}),t("div",{class:"grid grid-cols-4 gap-1.5",children:E.map(u=>i("div",{class:"flex flex-col items-center gap-0.5",children:[t("span",{class:d("text-[0.85rem] font-bold tabular-nums leading-none",fe[u]),children:m(u)}),t("span",{class:"text-[0.55rem] uppercase tracking-wide text-muted-foreground/70",children:be[u]})]},u))}),i("p",{class:"text-[0.62rem] text-muted-foreground/50",children:["Scanned ",xe(p)]})]}):i("div",{children:[t("p",{class:"text-[0.72rem] text-muted-foreground",children:"No scan run yet."}),t("p",{class:"text-[0.65rem] text-muted-foreground/50 mt-0.5",children:"Scan this page to detect WCAG violations."})]}),i("div",{class:"flex items-center gap-2 pt-2 border-t border-border/50",children:[t("button",{class:d("flex-1 px-2.5 py-1.5 text-[0.7rem] font-medium border transition-colors cursor-pointer",r?"border-primary/30 text-primary/50 bg-primary/5 cursor-not-allowed":"border-border text-foreground bg-transparent hover:bg-foreground/5"),disabled:r,onClick:j(()=>{l.scan().catch(()=>{})},"onClick"),type:"button",children:f}),t("button",{class:d("px-2.5 py-1.5 text-[0.7rem] border transition-colors",h),disabled:o.length===0,onClick:j(()=>l.setShowOverlays(!M),"onClick"),title:"Toggle visual highlights on affected elements",type:"button",children:"Overlays"})]})]})},"A11yTooltip"),je={component:me,icon:ee,id:"dev-toolbar:a11y",name:"Accessibility",tooltip:ve};export{je as default};
@@ -0,0 +1,4 @@
1
+ import type { ComponentChildren } from "preact";
2
+ import type { AppComponentProps } from "../../types/app.d.ts";
3
+ declare const AnnotationsApp: ({ helpers }: AppComponentProps) => ComponentChildren;
4
+ export default AnnotationsApp;
@@ -0,0 +1,3 @@
1
+ import type { DevToolbarApp } from "../../types/app.d.ts";
2
+ declare const annotationsApp: DevToolbarApp;
3
+ export default annotationsApp;
@@ -0,0 +1,18 @@
1
+ var j=Object.defineProperty;var z=(t,s)=>j(t,"name",{value:s,configurable:!0});import{addHookName as c}from"preact/devtools";import{clsx as h}from"../../packem_shared/clsx-wGlvpUfw.js";import{useState as p,useCallback as S,useEffect as q}from"preact/hooks";import{s as Q,M as H,l as K}from"../../packem_shared/annotation-settings-Bv0TH4WI.js";import{jsx as e,jsxs as r}from"preact/jsx-runtime";import g from"../../packem_shared/Button-Bkx66Co7.js";import U from"../../packem_shared/Textarea-Yfg3dLZi.js";const V=`<!-- @license lucide-static v1.8.0 - ISC -->
2
+ <svg
3
+ class="lucide lucide-message-square-plus"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="24"
6
+ height="24"
7
+ viewBox="0 0 24 24"
8
+ fill="none"
9
+ stroke="currentColor"
10
+ stroke-width="2"
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ >
14
+ <path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z" />
15
+ <path d="M12 8v6" />
16
+ <path d="M9 11h6" />
17
+ </svg>
18
+ `;var G=Object.defineProperty,a=z((t,s)=>G(t,"name",{value:s,configurable:!0}),"o");const I={approve:"Approve",change:"Change",fix:"Fix",question:"Question"},M={approve:"bg-green-500/20 text-green-400 border-green-500/30",change:"bg-yellow-500/20 text-yellow-400 border-yellow-500/30",fix:"bg-destructive/20 text-destructive border-destructive/30",question:"bg-blue-500/20 text-blue-400 border-blue-500/30"},F={blocking:"Blocking",important:"Important",suggestion:"Suggestion"},$={blocking:"text-destructive",important:"text-warning-foreground",suggestion:"text-muted-foreground"},A={acknowledged:"Acknowledged",dismissed:"Dismissed",pending:"Pending",resolved:"Resolved"},Y=a(({active:t,counts:s,onFilter:i})=>e("div",{class:"flex gap-1.5",children:["all","pending","acknowledged","resolved","dismissed"].map(n=>r("button",{class:h("px-2.5 py-1 text-[0.65rem] font-medium border cursor-pointer transition-colors",t===n?"bg-primary/10 border-primary/30 text-primary":"bg-foreground/3 border-border text-muted-foreground hover:bg-foreground/6"),onClick:a(()=>i(n),"onClick"),type:"button",children:[n==="all"?"All":A[n]," (",s[n],")"]},n))}),"StatusFilters"),_=a(({annotation:t,isSelected:s,onClick:i,onDelete:n,onDismiss:d,onResolve:m})=>r("div",{class:h("p-3 border cursor-pointer transition-colors",s?"bg-foreground/6 border-primary/30":"border-border hover:bg-foreground/3"),onClick:i,children:[r("div",{class:"flex items-start gap-2 mb-1.5",children:[e("span",{class:h("text-[0.6rem] font-bold uppercase px-1.5 py-0.5 border shrink-0",M[t.intent]),children:I[t.intent]}),e("span",{class:h("text-[0.6rem] font-semibold uppercase tracking-wide shrink-0",$[t.severity]),children:F[t.severity]}),e("span",{class:"flex-1"}),t.resolvedBy&&r("span",{class:"text-[0.58rem] text-muted-foreground/60",children:["by ",t.resolvedBy]}),e("span",{class:"text-[0.58rem] text-muted-foreground/60",children:A[t.status]})]}),e("p",{class:"text-[0.7rem] text-foreground leading-relaxed mb-1.5 line-clamp-2",children:t.comment}),e("div",{class:"flex items-center gap-2 mb-1.5",children:r("code",{class:"text-[0.62rem] text-foreground/60 font-mono bg-foreground/5 px-1.5 py-0.5 truncate",children:[t.elementTag,t.elementPath?` · ${t.elementPath}`:""]})}),t.source&&e("div",{class:"mb-1.5",children:e("code",{class:"text-[0.6rem] text-primary/60 font-mono",children:t.source})}),e("div",{class:"text-[0.58rem] text-muted-foreground/50 truncate mb-2",children:t.url}),t.thread&&t.thread.length>0&&r("div",{class:"text-[0.6rem] text-muted-foreground/60 mb-2",children:[t.thread.length," message",t.thread.length===1?"":"s"," in thread"]}),t.status==="pending"&&r("div",{class:"flex items-center gap-1.5",onClick:a(u=>u.stopPropagation(),"onClick"),children:[e(g,{class:"h-auto py-0.5 px-2 text-[0.6rem]",onClick:m,size:"sm",variant:"outline",children:"Resolve"}),e(g,{class:"h-auto py-0.5 px-2 text-[0.6rem]",onClick:d,size:"sm",variant:"outline",children:"Dismiss"}),e("span",{class:"flex-1"}),e(g,{class:"h-auto py-0.5 px-2 text-[0.6rem] text-destructive hover:text-destructive",onClick:n,size:"sm",variant:"ghost",children:"Delete"})]})]}),"AnnotationCard"),J=a(({annotation:t,helpers:s,onBack:i,onRefresh:n})=>{const[d,m]=c(p(""),"message"),u=S(async()=>{const l=d.trim();l&&(await s.rpc.updateAnnotation?.(t.id,{threadMessage:{content:l,role:"human",timestamp:new Date().toISOString()}}),m(""),n())},[t.id,s,d,n]);return r("div",{class:"p-4 space-y-3",children:[e(g,{class:"h-auto py-0.5 px-2 text-[0.65rem]",onClick:i,size:"sm",variant:"ghost",children:"← Back"}),r("div",{class:"flex items-center gap-2 flex-wrap",children:[e("span",{class:h("text-[0.65rem] font-bold uppercase px-2 py-0.5 border",M[t.intent]),children:I[t.intent]}),e("span",{class:h("text-[0.65rem] font-semibold",$[t.severity]),children:F[t.severity]}),e("span",{class:"text-[0.6rem] text-muted-foreground ml-auto",children:A[t.status]})]}),e("div",{class:"text-[0.75rem] text-foreground leading-relaxed border border-border p-3",children:t.comment}),r("div",{class:"space-y-1 text-[0.65rem]",children:[r("div",{class:"flex gap-2",children:[e("span",{class:"text-muted-foreground w-16 shrink-0",children:"Element"}),r("code",{class:"text-foreground/70 font-mono",children:[t.elementTag,t.cssClasses?` .${t.cssClasses}`:""]})]}),t.source&&r("div",{class:"flex gap-2",children:[e("span",{class:"text-muted-foreground w-16 shrink-0",children:"Source"}),e("code",{class:"text-primary/70 font-mono",children:t.source})]}),r("div",{class:"flex gap-2",children:[e("span",{class:"text-muted-foreground w-16 shrink-0",children:"URL"}),e("span",{class:"text-foreground/60 truncate",children:t.url})]}),r("div",{class:"flex gap-2",children:[e("span",{class:"text-muted-foreground w-16 shrink-0",children:"Created"}),e("span",{class:"text-foreground/60",children:new Date(t.createdAt).toLocaleString()})]})]}),r("div",{children:[r("div",{class:"text-[0.65rem] font-bold uppercase tracking-[0.1em] text-muted-foreground mb-2",children:[e("span",{"aria-hidden":"true",class:"text-primary/50",children:"// "}),"Thread (",t.thread?.length??0,")"]}),t.thread&&t.thread.length>0&&e("div",{class:"space-y-2 mb-3",children:t.thread.map(l=>r("div",{class:"border border-border p-2",children:[r("div",{class:"flex items-center gap-2 mb-1",children:[e("span",{class:"text-[0.62rem] font-semibold text-primary/70",children:l.role}),e("span",{class:"text-[0.55rem] text-muted-foreground/50",children:new Date(l.timestamp).toLocaleString()})]}),e("p",{class:"text-[0.68rem] text-foreground/80 leading-relaxed whitespace-pre-wrap",children:l.content})]},`${l.role}-${l.timestamp}`))}),r("div",{class:"space-y-2",children:[e(U,{class:"text-[0.7rem] min-h-[60px]",onChange:a(l=>m(l.target.value),"onChange"),placeholder:"Add a message to the thread...",value:d}),e(g,{class:"text-[0.65rem]",disabled:!d.trim(),onClick:u,size:"sm",variant:"outline",children:"Send"})]})]})]})},"AnnotationDetail"),W=a(({onChange:t,settings:s})=>{const i=a(n=>{const d={...s,...n};Q(d),t(d)},"update");return r("div",{class:"space-y-3 p-4 border-t border-border",children:[r("div",{class:"text-[0.65rem] font-bold uppercase tracking-[0.1em] text-muted-foreground",children:[e("span",{"aria-hidden":"true",class:"text-primary/50",children:"// "}),"Settings"]}),r("label",{class:"flex items-center gap-2 text-[0.7rem] text-foreground",children:[e("span",{class:"text-muted-foreground w-24 shrink-0",children:"Output Detail"}),r("select",{class:"flex-1 bg-card border border-border text-foreground text-[0.65rem] px-1.5 py-1 cursor-pointer",onChange:a(n=>i({outputDetail:n.target.value}),"onChange"),style:"color-scheme: dark",value:s.outputDetail,children:[e("option",{value:"compact",children:"Compact"}),e("option",{value:"standard",children:"Standard"}),e("option",{value:"detailed",children:"Detailed"}),e("option",{value:"forensic",children:"Forensic"})]})]}),r("div",{class:"flex items-center gap-2 text-[0.7rem]",children:[e("span",{class:"text-muted-foreground w-24 shrink-0",children:"Marker Color"}),e("div",{class:"flex gap-1.5",children:H.map(n=>e("button",{class:h("w-5 h-5 rounded-full border-2 cursor-pointer p-0 transition-all",n.name===s.markerColorName?"border-foreground scale-110":"border-transparent hover:scale-110"),onClick:a(()=>i({markerColorName:n.name}),"onClick"),style:{background:n.bg},title:n.label,type:"button"},n.name))})]}),r("label",{class:"flex items-center gap-2 text-[0.7rem] text-foreground",children:[e("span",{class:"text-muted-foreground w-24 shrink-0",children:"Marker Click"}),r("select",{class:"flex-1 bg-card border border-border text-foreground text-[0.65rem] px-1.5 py-1 cursor-pointer",onChange:a(n=>i({markerClickBehavior:n.target.value}),"onChange"),style:"color-scheme: dark",value:s.markerClickBehavior,children:[e("option",{value:"detail",children:"Show Detail"}),e("option",{value:"edit",children:"Edit"}),e("option",{value:"delete",children:"Delete"})]})]}),r("label",{class:"flex items-center gap-2 text-[0.7rem] text-foreground cursor-pointer",children:[e("input",{checked:s.blockInteractions,class:"cursor-pointer",onChange:a(n=>i({blockInteractions:n.target.checked}),"onChange"),type:"checkbox"}),e("span",{children:"Block page interactions while inspecting"})]})]})},"AnnotationSettingsPanel"),X=a(({helpers:t})=>{const[s,i]=c(p([]),"annotations"),[n,d]=c(p(!1),"loading"),[m,u]=c(p(),"error"),[l,E]=c(p("pending"),"filterStatus"),[b,P]=c(p("all"),"filterIntent"),[k,D]=c(p(),"selectedId"),[y,L]=c(p(!1),"showSettings"),[N,O]=c(p(()=>K()),"settings"),x=S(async()=>{d(!0),u(void 0);try{const o=await t.rpc.getAnnotations?.();i(o??[])}catch(o){u(o instanceof Error?o.message:String(o))}finally{d(!1)}},[t]);q(()=>{x().catch(()=>{})},[x]);const R=s.filter(o=>!(l!=="all"&&o.status!==l||b!=="all"&&o.intent!==b)),f=a(o=>s.filter(v=>v.status===o).length,"countByStatus"),T={acknowledged:f("acknowledged"),all:s.length,dismissed:f("dismissed"),pending:f("pending"),resolved:f("resolved")},B=k?s.find(o=>o.id===k):void 0,C=S(async(o,v)=>{try{await(v==="delete"?t.rpc.deleteAnnotation?.(o):t.rpc.updateAnnotation?.(o,{status:v==="resolve"?"resolved":"dismissed"})),await x()}catch(w){console.error(`[annotations] ${v} failed for ${o}:`,w),u(w instanceof Error?w.message:`Failed to ${v} annotation`)}},[t,x]);return B?e(J,{annotation:B,helpers:t,onBack:a(()=>D(void 0),"onBack"),onRefresh:a(()=>x().catch(()=>{}),"onRefresh")}):r("div",{class:"flex flex-col h-full",children:[r("div",{class:"shrink-0 flex items-center gap-2 px-4 py-2.5 border-b border-border bg-foreground/2 flex-wrap",children:[e(g,{disabled:n,onClick:a(()=>x().catch(()=>{}),"onClick"),size:"sm",variant:"outline",children:n?"Loading…":"Refresh"}),e(g,{class:h("text-[0.65rem]",y&&"bg-primary/10 text-primary"),onClick:a(()=>L(!y),"onClick"),size:"sm",variant:"ghost",children:"Settings"}),e("span",{class:"flex-1"}),r("select",{class:"bg-card border border-border text-foreground text-[0.65rem] px-1.5 py-1 cursor-pointer",onChange:a(o=>P(o.target.value),"onChange"),style:"color-scheme: dark",value:b,children:[e("option",{value:"all",children:"All intents"}),e("option",{value:"fix",children:"Fix"}),e("option",{value:"change",children:"Change"}),e("option",{value:"question",children:"Question"}),e("option",{value:"approve",children:"Approve"})]})]}),r("div",{class:"flex-1 overflow-y-auto devtools-content-scroll",children:[m&&e("div",{class:"p-3 text-[0.7rem] text-destructive bg-destructive/10 border-b border-destructive/20",children:m}),r("div",{class:"p-4 space-y-3",children:[e(Y,{active:l,counts:T,onFilter:E}),R.length===0?r("div",{class:"p-6 text-center border border-border",children:[e("p",{class:"text-[0.8125rem] font-medium text-foreground/70",children:s.length===0?"No annotations yet":"No annotations match filters"}),e("p",{class:"mt-1 text-[0.7rem] text-muted-foreground",children:s.length===0?'Use the Inspector to click an element and select "Annotate".':"Try changing the status or intent filter."})]}):e("div",{class:"space-y-2",children:R.map(o=>e(_,{annotation:o,isSelected:k===o.id,onClick:a(()=>D(o.id),"onClick"),onDelete:a(()=>C(o.id,"delete").catch(()=>{}),"onDelete"),onDismiss:a(()=>C(o.id,"dismiss").catch(()=>{}),"onDismiss"),onResolve:a(()=>C(o.id,"resolve").catch(()=>{}),"onResolve")},o.id))})]})]}),y&&e(W,{onChange:O,settings:N})]})},"AnnotationsApp"),le={component:X,icon:V,id:"dev-toolbar:annotations",name:"Annotations"};export{le as default};
@@ -0,0 +1,4 @@
1
+ import type { ComponentChildren } from "preact";
2
+ import type { AppComponentProps } from "../../types/app.d.ts";
3
+ declare const AssetsApp: ({ helpers }: AppComponentProps) => ComponentChildren;
4
+ export default AssetsApp;
@@ -0,0 +1,3 @@
1
+ import type { DevToolbarApp } from "../../types/app.d.ts";
2
+ declare const assetsApp: DevToolbarApp;
3
+ export default assetsApp;
@@ -0,0 +1,16 @@
1
+ var B=Object.defineProperty;var P=(t,i)=>B(t,"name",{value:i,configurable:!0});import{addHookName as a}from"preact/devtools";import{clsx as u}from"../../packem_shared/clsx-wGlvpUfw.js";import{useState as s,useRef as N,useEffect as C}from"preact/hooks";import{jsx as e,jsxs as l}from"preact/jsx-runtime";import c from"../../packem_shared/Button-Bkx66Co7.js";import E from"../../packem_shared/Input-Cs6aduTi.js";const H=`<!-- @license lucide-static v1.8.0 - ISC -->
2
+ <svg
3
+ class="lucide lucide-folder-open"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="24"
6
+ height="24"
7
+ viewBox="0 0 24 24"
8
+ fill="none"
9
+ stroke="currentColor"
10
+ stroke-width="2"
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ >
14
+ <path d="m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2" />
15
+ </svg>
16
+ `;var O=Object.defineProperty,o=P((t,i)=>O(t,"name",{value:i,configurable:!0}),"o");const j=o(t=>!Number.isFinite(t)||t<0?"–":t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`,"formatSize"),A=o(t=>t.startsWith("/")&&!t.includes(":")?t:"#","safePublicPath"),M=[{label:"All",value:"all"},{label:"Images",value:"image"},{label:"Videos",value:"video"},{label:"Audio",value:"audio"},{label:"Fonts",value:"font"},{label:"Text",value:"text"},{label:"Other",value:"other"}],D={audio:"bg-yellow-500/15 text-yellow-400 border-yellow-500/30",font:"bg-orange-500/15 text-orange-400 border-orange-500/30",image:"bg-blue-500/15 text-blue-400 border-blue-500/30",other:"bg-foreground/6 text-muted-foreground border-border",text:"bg-emerald-500/15 text-emerald-400 border-emerald-500/30",video:"bg-purple-500/15 text-purple-400 border-purple-500/30"},z=o(({type:t})=>e("span",{class:u("inline-flex px-1.5 py-0.5 text-[0.6rem] font-mono font-bold uppercase border",D[t]),children:t}),"TypeBadge"),V=o(({asset:t})=>{const i=A(t.publicPath);if(i!=="#"){if(t.type==="image")return e("div",{class:"flex items-center justify-center bg-foreground/4 border border-border h-32 overflow-hidden",children:e("img",{alt:t.publicPath,class:"max-w-full max-h-full object-contain",onError:o(p=>{p.target.style.display="none"},"onError"),src:i})});if(t.type==="video")return e("div",{class:"flex items-center justify-center bg-foreground/4 border border-border h-32 overflow-hidden",children:e("video",{class:"max-w-full max-h-full",preload:"metadata",src:i})});if(t.type==="audio")return e("div",{class:"flex items-center justify-center bg-foreground/4 border border-border h-14 px-2",children:e("audio",{class:"w-full",controls:!0,preload:"none",src:i})})}},"AssetPreview"),K=o(({helpers:t})=>{const[i,p]=a(s([]),"assets"),[F,f]=a(s(!0),"loading"),[g,v]=a(s(void 0),"error"),[y,T]=a(s(""),"search"),[d,S]=a(s("all"),"typeFilter"),[n,b]=a(s(void 0),"selected"),[I,w]=a(s(!1),"copied"),m=a(N(void 0),"copyTimerRef");C(()=>()=>{clearTimeout(m.current)},[]);const h=o(()=>{f(!0),v(void 0),b(void 0),t.rpc.getStaticAssets().then(r=>{p(r),f(!1)}).catch(r=>{v(r.message??"Failed to load assets"),f(!1)})},"load");C(()=>{h()},[]);const x=i.filter(r=>{const k=y.toLowerCase(),R=!k||r.publicPath.toLowerCase().includes(k),$=d==="all"||r.type===d;return R&&$}),L=o(r=>{navigator.clipboard.writeText(r.publicPath).then(()=>{clearTimeout(m.current),w(!0),m.current=setTimeout(w,1500,!1)}).catch(()=>{})},"copyPath");return F?l("div",{class:"flex flex-col items-center justify-center h-full gap-3 p-8 select-none",children:[e("div",{"aria-hidden":"true",class:"flex gap-1.5 items-center",children:[0,160,320].map(r=>e("span",{class:"size-1.5 bg-primary/50 rounded-full animate-pulse",style:{animationDelay:`${r}ms`}},r))}),e("span",{class:"text-[0.75rem] text-muted-foreground",children:"Scanning assets…"})]}):g?l("div",{class:"flex flex-col items-center justify-center h-full gap-3 p-8 text-center",children:[e("p",{class:"text-[0.8rem] text-destructive",children:g}),e(c,{onClick:h,size:"sm",variant:"outline",children:"Retry"})]}):l("div",{class:"flex flex-col h-full",children:[l("div",{class:"flex items-center gap-2 px-4 py-2.5 border-b border-border shrink-0 flex-wrap",children:[e(E,{class:"flex-1 min-w-32 bg-foreground/4 font-mono text-[0.8rem] placeholder:text-muted-foreground/50 focus-visible:border-primary/50 border-border",onInput:o(r=>{T(r.target.value)},"onInput"),placeholder:"Filter assets…",type:"text",value:y}),l("span",{class:"text-[0.7rem] text-muted-foreground shrink-0",children:[x.length," / ",i.length]}),e(c,{onClick:h,size:"sm",variant:"outline",children:"Refresh"})]}),e("div",{"aria-label":"Filter by type",class:"flex items-center gap-1.5 px-4 py-2 border-b border-border shrink-0 flex-wrap",role:"group",children:M.map(r=>e("button",{"aria-pressed":d===r.value,class:u("px-2.5 py-0.5 text-[0.7rem] font-medium border cursor-pointer transition-colors duration-100",d===r.value?"bg-primary/15 text-primary border-primary/30":"bg-foreground/4 text-muted-foreground border-border hover:bg-foreground/8 hover:text-foreground"),onClick:o(()=>{S(r.value)},"onClick"),type:"button",children:r.label},r.value))}),l("div",{class:"flex flex-1 min-h-0 overflow-hidden",children:[e("div",{class:"flex-1 overflow-auto divide-y divide-border/30",role:"list",children:x.length===0?e("div",{class:"flex items-center justify-center p-8 text-[0.8rem] text-muted-foreground",children:i.length===0?"No assets found in public directory.":"No assets match the current filter."}):x.map(r=>l("button",{"aria-label":r.publicPath,"aria-selected":n?.publicPath===r.publicPath,class:u("w-full flex items-center gap-3 px-4 py-2.5 text-left border-0 bg-transparent cursor-pointer","hover:bg-foreground/4 transition-colors duration-100",n?.publicPath===r.publicPath&&"bg-primary/6"),onClick:o(()=>{b(n?.publicPath===r.publicPath?void 0:r)},"onClick"),role:"option",type:"button",children:[e(z,{type:r.type}),e("span",{class:"flex-1 text-[0.775rem] font-mono text-foreground/80 truncate min-w-0",children:r.publicPath}),e("span",{class:"shrink-0 text-[0.65rem] text-muted-foreground",children:j(r.size)})]},r.publicPath))}),n&&l("div",{class:"border-l border-border bg-background w-72 shrink-0 flex flex-col overflow-hidden",children:[l("div",{class:"flex items-center justify-between gap-2 px-4 py-3 border-b border-border shrink-0",children:[e("span",{class:"text-[0.7rem] font-semibold text-foreground uppercase tracking-wide",children:"Asset Info"}),e(c,{"aria-label":"Close",class:"h-6 w-6 text-xs",onClick:o(()=>{b(void 0)},"onClick"),size:"icon",variant:"ghost",children:"✕"})]}),l("div",{class:"flex-1 overflow-auto p-4 space-y-4",children:[e(V,{asset:n}),l("div",{children:[e("div",{class:"text-[0.6rem] uppercase tracking-wider text-muted-foreground mb-1",children:"Path"}),e("code",{class:"text-[0.7rem] font-mono text-foreground/80 break-all",children:n.publicPath})]}),l("div",{children:[e("div",{class:"text-[0.6rem] uppercase tracking-wider text-muted-foreground mb-1",children:"Type"}),e(z,{type:n.type})]}),l("div",{children:[e("div",{class:"text-[0.6rem] uppercase tracking-wider text-muted-foreground mb-1",children:"Size"}),e("span",{class:"text-[0.8rem] font-mono text-foreground",children:j(n.size)})]}),l("div",{children:[e("div",{class:"text-[0.6rem] uppercase tracking-wider text-muted-foreground mb-1",children:"Last Modified"}),e("span",{class:"text-[0.75rem] text-foreground/80",children:new Date(n.mtime).toLocaleString()})]}),l("div",{class:"flex flex-col gap-2 pt-1",children:[e(c,{class:"w-full text-[0.75rem]",onClick:o(()=>{L(n)},"onClick"),size:"sm",variant:"outline",children:I?"Copied!":"Copy URL"}),e("a",{class:u("w-full text-[0.75rem] inline-flex items-center justify-center","px-3 py-1.5 border border-border bg-transparent","text-foreground hover:bg-foreground/6 transition-colors duration-100"),href:A(n.publicPath),rel:"noopener noreferrer",target:"_blank",children:"Open in browser"})]})]})]})]})]})},"AssetsApp"),X={component:K,icon:H,id:"dev-toolbar:assets",name:"Assets"};export{X as default};
@@ -0,0 +1,12 @@
1
+ interface A11yInfo {
2
+ ariaAttributes: Record<string, string>;
3
+ focusable: boolean;
4
+ role: string | null;
5
+ tabindex: number | null;
6
+ }
7
+ /** Collect accessibility-relevant attributes from an element. */
8
+ declare const captureA11yInfo: (element: Element) => A11yInfo;
9
+ /** Format A11yInfo as a plain-text summary for clipboard. */
10
+ declare const formatA11yText: (info: A11yInfo) => string;
11
+ export { captureA11yInfo, formatA11yText };
12
+ export type { A11yInfo };