@opentabs-dev/browser-extension 0.0.34
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/dist/background-log-state.d.ts +10 -0
- package/dist/background-log-state.d.ts.map +1 -0
- package/dist/background-log-state.js +11 -0
- package/dist/background-log-state.js.map +1 -0
- package/dist/background-message-handlers.d.ts +41 -0
- package/dist/background-message-handlers.d.ts.map +1 -0
- package/dist/background-message-handlers.js +214 -0
- package/dist/background-message-handlers.js.map +1 -0
- package/dist/background.d.ts +2 -0
- package/dist/background.d.ts.map +1 -0
- package/dist/background.js +3780 -0
- package/dist/background.js.map +1 -0
- package/dist/bg-log-state.d.ts +10 -0
- package/dist/bg-log-state.d.ts.map +1 -0
- package/dist/bg-log-state.js +11 -0
- package/dist/bg-log-state.js.map +1 -0
- package/dist/browser-commands/content-commands.d.ts +25 -0
- package/dist/browser-commands/content-commands.d.ts.map +1 -0
- package/dist/browser-commands/content-commands.js +166 -0
- package/dist/browser-commands/content-commands.js.map +1 -0
- package/dist/browser-commands/cookie-commands.d.ts +14 -0
- package/dist/browser-commands/cookie-commands.d.ts.map +1 -0
- package/dist/browser-commands/cookie-commands.js +99 -0
- package/dist/browser-commands/cookie-commands.js.map +1 -0
- package/dist/browser-commands/extension-commands.d.ts +12 -0
- package/dist/browser-commands/extension-commands.d.ts.map +1 -0
- package/dist/browser-commands/extension-commands.js +386 -0
- package/dist/browser-commands/extension-commands.js.map +1 -0
- package/dist/browser-commands/helpers.d.ts +35 -0
- package/dist/browser-commands/helpers.d.ts.map +1 -0
- package/dist/browser-commands/helpers.js +121 -0
- package/dist/browser-commands/helpers.js.map +1 -0
- package/dist/browser-commands/index.d.ts +11 -0
- package/dist/browser-commands/index.d.ts.map +1 -0
- package/dist/browser-commands/index.js +10 -0
- package/dist/browser-commands/index.js.map +1 -0
- package/dist/browser-commands/interaction-commands.d.ts +23 -0
- package/dist/browser-commands/interaction-commands.d.ts.map +1 -0
- package/dist/browser-commands/interaction-commands.js +353 -0
- package/dist/browser-commands/interaction-commands.js.map +1 -0
- package/dist/browser-commands/key-press-command.d.ts +2 -0
- package/dist/browser-commands/key-press-command.d.ts.map +1 -0
- package/dist/browser-commands/key-press-command.js +144 -0
- package/dist/browser-commands/key-press-command.js.map +1 -0
- package/dist/browser-commands/network-commands.d.ts +6 -0
- package/dist/browser-commands/network-commands.d.ts.map +1 -0
- package/dist/browser-commands/network-commands.js +69 -0
- package/dist/browser-commands/network-commands.js.map +1 -0
- package/dist/browser-commands/resource-commands.d.ts +37 -0
- package/dist/browser-commands/resource-commands.d.ts.map +1 -0
- package/dist/browser-commands/resource-commands.js +153 -0
- package/dist/browser-commands/resource-commands.js.map +1 -0
- package/dist/browser-commands/scroll-command.d.ts +2 -0
- package/dist/browser-commands/scroll-command.d.ts.map +1 -0
- package/dist/browser-commands/scroll-command.js +133 -0
- package/dist/browser-commands/scroll-command.js.map +1 -0
- package/dist/browser-commands/tab-commands.d.ts +33 -0
- package/dist/browser-commands/tab-commands.d.ts.map +1 -0
- package/dist/browser-commands/tab-commands.js +121 -0
- package/dist/browser-commands/tab-commands.js.map +1 -0
- package/dist/browser-commands.d.ts +36 -0
- package/dist/browser-commands.d.ts.map +1 -0
- package/dist/browser-commands.js +1931 -0
- package/dist/browser-commands.js.map +1 -0
- package/dist/confirmation-badge.d.ts +17 -0
- package/dist/confirmation-badge.d.ts.map +1 -0
- package/dist/confirmation-badge.js +64 -0
- package/dist/confirmation-badge.js.map +1 -0
- package/dist/constants.d.ts +79 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +79 -0
- package/dist/constants.js.map +1 -0
- package/dist/dispatch-helpers.d.ts +61 -0
- package/dist/dispatch-helpers.d.ts.map +1 -0
- package/dist/dispatch-helpers.js +149 -0
- package/dist/dispatch-helpers.js.map +1 -0
- package/dist/extension-messages.d.ts +146 -0
- package/dist/extension-messages.d.ts.map +1 -0
- package/dist/extension-messages.js +2 -0
- package/dist/extension-messages.js.map +1 -0
- package/dist/iife-injection.d.ts +55 -0
- package/dist/iife-injection.d.ts.map +1 -0
- package/dist/iife-injection.js +474 -0
- package/dist/iife-injection.js.map +1 -0
- package/dist/json-rpc-errors.d.ts +8 -0
- package/dist/json-rpc-errors.d.ts.map +1 -0
- package/dist/json-rpc-errors.js +8 -0
- package/dist/json-rpc-errors.js.map +1 -0
- package/dist/known-methods.d.ts +19 -0
- package/dist/known-methods.d.ts.map +1 -0
- package/dist/known-methods.js +68 -0
- package/dist/known-methods.js.map +1 -0
- package/dist/log-collector.d.ts +45 -0
- package/dist/log-collector.d.ts.map +1 -0
- package/dist/log-collector.js +99 -0
- package/dist/log-collector.js.map +1 -0
- package/dist/message-router.d.ts +28 -0
- package/dist/message-router.d.ts.map +1 -0
- package/dist/message-router.js +367 -0
- package/dist/message-router.js.map +1 -0
- package/dist/messaging.d.ts +15 -0
- package/dist/messaging.d.ts.map +1 -0
- package/dist/messaging.js +41 -0
- package/dist/messaging.js.map +1 -0
- package/dist/network-capture.d.ts +56 -0
- package/dist/network-capture.d.ts.map +1 -0
- package/dist/network-capture.js +374 -0
- package/dist/network-capture.js.map +1 -0
- package/dist/offscreen/index.d.ts +16 -0
- package/dist/offscreen/index.d.ts.map +1 -0
- package/dist/offscreen/index.js +549 -0
- package/dist/offscreen/index.js.map +1 -0
- package/dist/plugin-storage.d.ts +19 -0
- package/dist/plugin-storage.d.ts.map +1 -0
- package/dist/plugin-storage.js +100 -0
- package/dist/plugin-storage.js.map +1 -0
- package/dist/rate-limiter.d.ts +18 -0
- package/dist/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter.js +53 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/resource-prompt-dispatch.d.ts +14 -0
- package/dist/resource-prompt-dispatch.d.ts.map +1 -0
- package/dist/resource-prompt-dispatch.js +195 -0
- package/dist/resource-prompt-dispatch.js.map +1 -0
- package/dist/sanitize-error.d.ts +8 -0
- package/dist/sanitize-error.d.ts.map +1 -0
- package/dist/sanitize-error.js +25 -0
- package/dist/sanitize-error.js.map +1 -0
- package/dist/sanitize-svg.d.ts +20 -0
- package/dist/sanitize-svg.d.ts.map +1 -0
- package/dist/sanitize-svg.js +296 -0
- package/dist/sanitize-svg.js.map +1 -0
- package/dist/side-panel/App.d.ts +3 -0
- package/dist/side-panel/App.d.ts.map +1 -0
- package/dist/side-panel/App.js +147 -0
- package/dist/side-panel/App.js.map +1 -0
- package/dist/side-panel/bridge.d.ts +50 -0
- package/dist/side-panel/bridge.d.ts.map +1 -0
- package/dist/side-panel/bridge.js +113 -0
- package/dist/side-panel/bridge.js.map +1 -0
- package/dist/side-panel/components/ConfirmationDialog.d.ts +16 -0
- package/dist/side-panel/components/ConfirmationDialog.d.ts.map +1 -0
- package/dist/side-panel/components/ConfirmationDialog.js +39 -0
- package/dist/side-panel/components/ConfirmationDialog.js.map +1 -0
- package/dist/side-panel/components/EmptyStates.d.ts +8 -0
- package/dist/side-panel/components/EmptyStates.d.ts.map +1 -0
- package/dist/side-panel/components/EmptyStates.js +40 -0
- package/dist/side-panel/components/EmptyStates.js.map +1 -0
- package/dist/side-panel/components/ErrorBoundary.d.ts +23 -0
- package/dist/side-panel/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/side-panel/components/ErrorBoundary.js +28 -0
- package/dist/side-panel/components/ErrorBoundary.js.map +1 -0
- package/dist/side-panel/components/FailedPluginCard.d.ts +6 -0
- package/dist/side-panel/components/FailedPluginCard.d.ts.map +1 -0
- package/dist/side-panel/components/FailedPluginCard.js +9 -0
- package/dist/side-panel/components/FailedPluginCard.js.map +1 -0
- package/dist/side-panel/components/Footer.d.ts +3 -0
- package/dist/side-panel/components/Footer.d.ts.map +1 -0
- package/dist/side-panel/components/Footer.js +32 -0
- package/dist/side-panel/components/Footer.js.map +1 -0
- package/dist/side-panel/components/Header.d.ts +5 -0
- package/dist/side-panel/components/Header.d.ts.map +1 -0
- package/dist/side-panel/components/Header.js +6 -0
- package/dist/side-panel/components/Header.js.map +1 -0
- package/dist/side-panel/components/PluginCard.d.ts +10 -0
- package/dist/side-panel/components/PluginCard.d.ts.map +1 -0
- package/dist/side-panel/components/PluginCard.js +50 -0
- package/dist/side-panel/components/PluginCard.js.map +1 -0
- package/dist/side-panel/components/PluginIcon.d.ts +21 -0
- package/dist/side-panel/components/PluginIcon.d.ts.map +1 -0
- package/dist/side-panel/components/PluginIcon.js +48 -0
- package/dist/side-panel/components/PluginIcon.js.map +1 -0
- package/dist/side-panel/components/PluginList.d.ts +11 -0
- package/dist/side-panel/components/PluginList.d.ts.map +1 -0
- package/dist/side-panel/components/PluginList.js +17 -0
- package/dist/side-panel/components/PluginList.js.map +1 -0
- package/dist/side-panel/components/ToolIcon.d.ts +7 -0
- package/dist/side-panel/components/ToolIcon.d.ts.map +1 -0
- package/dist/side-panel/components/ToolIcon.js +8 -0
- package/dist/side-panel/components/ToolIcon.js.map +1 -0
- package/dist/side-panel/components/ToolRow.d.ts +11 -0
- package/dist/side-panel/components/ToolRow.d.ts.map +1 -0
- package/dist/side-panel/components/ToolRow.js +8 -0
- package/dist/side-panel/components/ToolRow.js.map +1 -0
- package/dist/side-panel/components/VersionMismatchBanner.d.ts +3 -0
- package/dist/side-panel/components/VersionMismatchBanner.d.ts.map +1 -0
- package/dist/side-panel/components/VersionMismatchBanner.js +5 -0
- package/dist/side-panel/components/VersionMismatchBanner.js.map +1 -0
- package/dist/side-panel/components/retro/Accordion.d.ts +8 -0
- package/dist/side-panel/components/retro/Accordion.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Accordion.js +15 -0
- package/dist/side-panel/components/retro/Accordion.js.map +1 -0
- package/dist/side-panel/components/retro/Alert.d.ts +25 -0
- package/dist/side-panel/components/retro/Alert.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Alert.js +33 -0
- package/dist/side-panel/components/retro/Alert.js.map +1 -0
- package/dist/side-panel/components/retro/Badge.d.ts +15 -0
- package/dist/side-panel/components/retro/Badge.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Badge.js +23 -0
- package/dist/side-panel/components/retro/Badge.js.map +1 -0
- package/dist/side-panel/components/retro/Button.d.ts +13 -0
- package/dist/side-panel/components/retro/Button.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Button.js +33 -0
- package/dist/side-panel/components/retro/Button.js.map +1 -0
- package/dist/side-panel/components/retro/Empty.d.ts +31 -0
- package/dist/side-panel/components/retro/Empty.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Empty.js +25 -0
- package/dist/side-panel/components/retro/Empty.js.map +1 -0
- package/dist/side-panel/components/retro/Input.d.ts +8 -0
- package/dist/side-panel/components/retro/Input.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Input.js +7 -0
- package/dist/side-panel/components/retro/Input.js.map +1 -0
- package/dist/side-panel/components/retro/Loader.d.ts +14 -0
- package/dist/side-panel/components/retro/Loader.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Loader.js +30 -0
- package/dist/side-panel/components/retro/Loader.js.map +1 -0
- package/dist/side-panel/components/retro/Menu.d.ts +9 -0
- package/dist/side-panel/components/retro/Menu.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Menu.js +17 -0
- package/dist/side-panel/components/retro/Menu.js.map +1 -0
- package/dist/side-panel/components/retro/NumberStepper.d.ts +18 -0
- package/dist/side-panel/components/retro/NumberStepper.d.ts.map +1 -0
- package/dist/side-panel/components/retro/NumberStepper.js +38 -0
- package/dist/side-panel/components/retro/NumberStepper.js.map +1 -0
- package/dist/side-panel/components/retro/Progress.d.ts +9 -0
- package/dist/side-panel/components/retro/Progress.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Progress.js +6 -0
- package/dist/side-panel/components/retro/Progress.js.map +1 -0
- package/dist/side-panel/components/retro/Switch.d.ts +4 -0
- package/dist/side-panel/components/retro/Switch.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Switch.js +6 -0
- package/dist/side-panel/components/retro/Switch.js.map +1 -0
- package/dist/side-panel/components/retro/Text.d.ts +11 -0
- package/dist/side-panel/components/retro/Text.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Text.js +28 -0
- package/dist/side-panel/components/retro/Text.js.map +1 -0
- package/dist/side-panel/components/retro/Tooltip.d.ts +12 -0
- package/dist/side-panel/components/retro/Tooltip.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Tooltip.js +32 -0
- package/dist/side-panel/components/retro/Tooltip.js.map +1 -0
- package/dist/side-panel/constants.d.ts +5 -0
- package/dist/side-panel/constants.d.ts.map +1 -0
- package/dist/side-panel/constants.js +5 -0
- package/dist/side-panel/constants.js.map +1 -0
- package/dist/side-panel/hooks/useServerNotifications.d.ts +21 -0
- package/dist/side-panel/hooks/useServerNotifications.d.ts.map +1 -0
- package/dist/side-panel/hooks/useServerNotifications.js +93 -0
- package/dist/side-panel/hooks/useServerNotifications.js.map +1 -0
- package/dist/side-panel/hooks/useTheme.d.ts +8 -0
- package/dist/side-panel/hooks/useTheme.d.ts.map +1 -0
- package/dist/side-panel/hooks/useTheme.js +30 -0
- package/dist/side-panel/hooks/useTheme.js.map +1 -0
- package/dist/side-panel/index.d.ts +2 -0
- package/dist/side-panel/index.d.ts.map +1 -0
- package/dist/side-panel/index.js +12 -0
- package/dist/side-panel/index.js.map +1 -0
- package/dist/side-panel/lib/cn.d.ts +3 -0
- package/dist/side-panel/lib/cn.d.ts.map +1 -0
- package/dist/side-panel/lib/cn.js +4 -0
- package/dist/side-panel/lib/cn.js.map +1 -0
- package/dist/side-panel/lib/utils.d.ts +3 -0
- package/dist/side-panel/lib/utils.d.ts.map +1 -0
- package/dist/side-panel/lib/utils.js +4 -0
- package/dist/side-panel/lib/utils.js.map +1 -0
- package/dist/side-panel/side-panel.js +78034 -0
- package/dist/side-panel/styles.css +2 -0
- package/dist/side-panel-state.d.ts +11 -0
- package/dist/side-panel-state.d.ts.map +1 -0
- package/dist/side-panel-state.js +38 -0
- package/dist/side-panel-state.js.map +1 -0
- package/dist/side-panel-toggle.d.ts +3 -0
- package/dist/side-panel-toggle.d.ts.map +1 -0
- package/dist/side-panel-toggle.js +31 -0
- package/dist/side-panel-toggle.js.map +1 -0
- package/dist/tab-matching.d.ts +51 -0
- package/dist/tab-matching.d.ts.map +1 -0
- package/dist/tab-matching.js +160 -0
- package/dist/tab-matching.js.map +1 -0
- package/dist/tab-state.d.ts +56 -0
- package/dist/tab-state.d.ts.map +1 -0
- package/dist/tab-state.js +282 -0
- package/dist/tab-state.js.map +1 -0
- package/dist/tool-dispatch.d.ts +19 -0
- package/dist/tool-dispatch.d.ts.map +1 -0
- package/dist/tool-dispatch.js +336 -0
- package/dist/tool-dispatch.js.map +1 -0
- package/dist/types.d.ts +82 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/icons/icon-128.png +0 -0
- package/icons/icon-16.png +0 -0
- package/icons/icon-32.png +0 -0
- package/icons/icon-48.png +0 -0
- package/icons/icon.svg +6 -0
- package/manifest.json +38 -0
- package/offscreen/offscreen.html +10 -0
- package/package.json +49 -0
- package/side-panel/dark-mode.js +29 -0
- package/side-panel/fonts/archivo-black-latin.woff2 +0 -0
- package/side-panel/fonts/space-grotesk-latin.woff2 +0 -0
- package/side-panel/fonts/space-mono-400-latin.woff2 +0 -0
- package/side-panel/fonts/space-mono-700-latin.woff2 +0 -0
- package/side-panel/fonts.css +34 -0
- package/side-panel/side-panel.html +16 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--font-sans:"Space Grotesk", sans-serif;--font-mono:"Space Mono", monospace;--color-yellow-400:oklch(85.2% .199 91.936);--color-gray-500:oklch(55.1% .027 264.364);--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--leading-tight:1.25;--leading-snug:1.375;--animate-bounce:bounce 1s infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--radius:var(--radius);--font-head:"Archivo Black", sans-serif;--color-background:var(--background);--color-foreground:var(--foreground);--color-primary:var(--primary);--color-primary-foreground:var(--primary-foreground);--color-secondary:var(--secondary);--color-secondary-foreground:var(--secondary-foreground);--color-primary-hover:var(--primary-hover);--color-secondary-hover:var(--secondary-hover);--color-card:var(--card);--color-card-foreground:var(--card-foreground);--color-muted:var(--muted);--color-muted-foreground:var(--muted-foreground);--color-accent:var(--accent);--color-accent-foreground:var(--accent-foreground);--color-destructive:var(--destructive);--color-success:var(--success);--color-border:var(--border)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.relative{position:relative}.static{position:static}.sticky{position:sticky}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-1\/2{top:50%}.right-2{right:calc(var(--spacing) * 2)}.bottom-0{bottom:calc(var(--spacing) * 0)}.left-2{left:calc(var(--spacing) * 2)}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mx-0\.5{margin-inline:calc(var(--spacing) * .5)}.mx-3{margin-inline:calc(var(--spacing) * 3)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-40{margin-top:calc(var(--spacing) * 40)}.mr-5{margin-right:calc(var(--spacing) * 5)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.ml-4{margin-left:calc(var(--spacing) * 4)}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-3{height:calc(var(--spacing) * 3)}.h-4{height:calc(var(--spacing) * 4)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-9{height:calc(var(--spacing) * 9)}.h-12{height:calc(var(--spacing) * 12)}.h-\[18px\]{height:18px}.h-full{height:100%}.max-h-20{max-height:calc(var(--spacing) * 20)}.min-h-screen{min-height:100vh}.w-3{width:calc(var(--spacing) * 3)}.w-4{width:calc(var(--spacing) * 4)}.w-6{width:calc(var(--spacing) * 6)}.w-9{width:calc(var(--spacing) * 9)}.w-11{width:calc(var(--spacing) * 11)}.w-12{width:calc(var(--spacing) * 12)}.w-16{width:calc(var(--spacing) * 16)}.w-20{width:calc(var(--spacing) * 20)}.w-24{width:calc(var(--spacing) * 24)}.w-56{width:calc(var(--spacing) * 56)}.w-64{width:calc(var(--spacing) * 64)}.w-80{width:calc(var(--spacing) * 80)}.w-\[6ch\]{width:6ch}.w-\[18px\]{width:18px}.w-full{width:100%}.max-w-\[320px\]{max-width:320px}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:calc(var(--spacing) * 0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.origin-\[--radix-tooltip-content-transform-origin\]{transform-origin:--radix-tooltip-content-transform-origin}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-bounce{animation:var(--animate-bounce)}.animate-in{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.rounded{border-radius:var(--radius)}.rounded-\[8px\]{border-radius:8px}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-t-2{border-top-style:var(--tw-border-style);border-top-width:2px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-accent{border-color:var(--color-accent)}.border-accent-foreground{border-color:var(--color-accent-foreground)}.border-border{border-color:var(--color-border)}.border-card{border-color:var(--color-card)}.border-current{border-color:currentColor}.border-destructive,.border-destructive\/40{border-color:var(--color-destructive)}@supports (color:color-mix(in lab, red, red)){.border-destructive\/40{border-color:color-mix(in oklab, var(--color-destructive) 40%, transparent)}}.border-destructive\/50{border-color:var(--color-destructive)}@supports (color:color-mix(in lab, red, red)){.border-destructive\/50{border-color:color-mix(in oklab, var(--color-destructive) 50%, transparent)}}.border-destructive\/60{border-color:var(--color-destructive)}@supports (color:color-mix(in lab, red, red)){.border-destructive\/60{border-color:color-mix(in oklab, var(--color-destructive) 60%, transparent)}}.border-muted-foreground{border-color:var(--color-muted-foreground)}.border-success{border-color:var(--color-success)}.bg-\[\#ffdb33\]{background-color:#ffdb33}.bg-accent{background-color:var(--color-accent)}.bg-accent-foreground{background-color:var(--color-accent-foreground)}.bg-accent\/10{background-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.bg-accent\/10{background-color:color-mix(in oklab, var(--color-accent) 10%, transparent)}}.bg-accent\/20{background-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.bg-accent\/20{background-color:color-mix(in oklab, var(--color-accent) 20%, transparent)}}.bg-accent\/30{background-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.bg-accent\/30{background-color:color-mix(in oklab, var(--color-accent) 30%, transparent)}}.bg-background{background-color:var(--color-background)}.bg-card{background-color:var(--color-card)}.bg-destructive,.bg-destructive\/10{background-color:var(--color-destructive)}@supports (color:color-mix(in lab, red, red)){.bg-destructive\/10{background-color:color-mix(in oklab, var(--color-destructive) 10%, transparent)}}.bg-destructive\/20{background-color:var(--color-destructive)}@supports (color:color-mix(in lab, red, red)){.bg-destructive\/20{background-color:color-mix(in oklab, var(--color-destructive) 20%, transparent)}}.bg-foreground{background-color:var(--color-foreground)}.bg-muted,.bg-muted\/50{background-color:var(--color-muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/50{background-color:color-mix(in oklab, var(--color-muted) 50%, transparent)}}.bg-primary{background-color:var(--color-primary)}.bg-secondary{background-color:var(--color-secondary)}.bg-success,.bg-success\/20{background-color:var(--color-success)}@supports (color:color-mix(in lab, red, red)){.bg-success\/20{background-color:color-mix(in oklab, var(--color-success) 20%, transparent)}}.bg-transparent{background-color:#0000}.bg-yellow-400{background-color:var(--color-yellow-400)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-16{padding:calc(var(--spacing) * 16)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-16{padding-block:calc(var(--spacing) * 16)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pr-3\.5{padding-right:calc(var(--spacing) * 3.5)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pr-5{padding-right:calc(var(--spacing) * 5)}.pr-8{padding-right:calc(var(--spacing) * 8)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-9{padding-left:calc(var(--spacing) * 9)}.text-center{text-align:center}.align-middle{vertical-align:middle}.font-head{font-family:var(--font-head)}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.leading-none{--tw-leading:1;line-height:1}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-accent-foreground{color:var(--color-accent-foreground)}.text-background{color:var(--color-background)}.text-card-foreground{color:var(--color-card-foreground)}.text-destructive,.text-destructive\/80{color:var(--color-destructive)}@supports (color:color-mix(in lab, red, red)){.text-destructive\/80{color:color-mix(in oklab, var(--color-destructive) 80%, transparent)}}.text-foreground{color:var(--color-foreground)}.text-gray-500{color:var(--color-gray-500)}.text-muted-foreground{color:var(--color-muted-foreground)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-secondary-foreground{color:var(--color-secondary-foreground)}.text-success{color:var(--color-success)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.decoration-primary{-webkit-text-decoration-color:var(--color-primary);-webkit-text-decoration-color:var(--color-primary);text-decoration-color:var(--color-primary)}.underline-offset-2{text-underline-offset:2px}.shadow{--tw-shadow:3px 3px 0 0 var(--tw-shadow-color,var(--border));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:4px 4px 0 0 var(--tw-shadow-color,var(--border));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:2px 2px 0 0 var(--tw-shadow-color,var(--border));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xs{--tw-shadow:1px 1px 0 0 var(--tw-shadow-color,var(--border));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-0{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-destructive{--tw-shadow-color:var(--color-destructive)}@supports (color:color-mix(in lab, red, red)){.shadow-destructive{--tw-shadow-color:color-mix(in oklab, var(--color-destructive) var(--tw-shadow-alpha), transparent)}}.shadow-primary{--tw-shadow-color:var(--color-primary)}@supports (color:color-mix(in lab, red, red)){.shadow-primary{--tw-shadow-color:color-mix(in oklab, var(--color-primary) var(--tw-shadow-alpha), transparent)}}.outline-hidden{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.outline-hidden{outline-offset:2px;outline:2px solid #0000}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.fade-in-0{--tw-enter-opacity:0}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.select-text{-webkit-user-select:text;user-select:text}.zoom-in-95{--tw-enter-scale:.95}.\[opentabs\:offscreen\]{opentabs:offscreen}.\[opentabs\:side-panel\]{opentabs:side-panel}.running{animation-play-state:running}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.focus-within\:shadow-xs:focus-within{--tw-shadow:1px 1px 0 0 var(--tw-shadow-color,var(--border));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}@media (hover:hover){.hover\:translate-y-0\.5:hover{--tw-translate-y:calc(var(--spacing) * .5);translate:var(--tw-translate-x) var(--tw-translate-y)}.hover\:translate-y-1:hover{--tw-translate-y:calc(var(--spacing) * 1);translate:var(--tw-translate-x) var(--tw-translate-y)}.hover\:bg-accent:hover{background-color:var(--color-accent)}.hover\:bg-muted:hover,.hover\:bg-muted\/50:hover{background-color:var(--color-muted)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab, var(--color-muted) 50%, transparent)}}.hover\:bg-primary-hover:hover{background-color:var(--color-primary-hover)}.hover\:bg-secondary-hover:hover{background-color:var(--color-secondary-hover)}.hover\:text-foreground:hover{color:var(--color-foreground)}.hover\:underline:hover{text-decoration-line:underline}.hover\:shadow:hover{--tw-shadow:3px 3px 0 0 var(--tw-shadow-color,var(--border));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.hover\:shadow-none:hover{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.hover\:shadow-sm:hover{--tw-shadow:2px 2px 0 0 var(--tw-shadow-color,var(--border));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}.focus\:shadow-xs:focus{--tw-shadow:1px 1px 0 0 var(--tw-shadow-color,var(--border));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:outline-hidden:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.focus\:outline-hidden:focus{outline-offset:2px;outline:2px solid #0000}}.active\:translate-x-1:active{--tw-translate-x:calc(var(--spacing) * 1);translate:var(--tw-translate-x) var(--tw-translate-y)}.active\:translate-y-2:active{--tw-translate-y:calc(var(--spacing) * 2);translate:var(--tw-translate-x) var(--tw-translate-y)}.active\:shadow-none:active{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.data-\[highlighted\]\:bg-accent[data-highlighted]{background-color:var(--color-accent)}.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y:calc(2*var(--spacing)*-1)}.data-\[side\=left\]\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x:calc(2*var(--spacing))}.data-\[side\=right\]\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x:calc(2*var(--spacing)*-1)}.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y:calc(2*var(--spacing))}.data-\[state\=checked\]\:translate-x-5[data-state=checked]{--tw-translate-x:calc(var(--spacing) * 5);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[state\=checked\]\:bg-background[data-state=checked]{background-color:var(--color-background)}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:var(--color-primary)}.data-\[state\=closed\]\:animate-accordion-up[data-state=closed]{animation:accordion-up var(--tw-animation-duration,var(--tw-duration,.2s))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=closed\]\:animate-out[data-state=closed]{animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity:0}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale:.95}.data-\[state\=open\]\:animate-accordion-down[data-state=open]{animation:accordion-down var(--tw-animation-duration,var(--tw-duration,.2s))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=open\]\:shadow-sm[data-state=open]{--tw-shadow:2px 2px 0 0 var(--tw-shadow-color,var(--border));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.data-\[state\=unchecked\]\:translate-x-0[data-state=unchecked]{--tw-translate-x:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}@media (min-width:48rem){.md\:p-8{padding:calc(var(--spacing) * 8)}.md\:text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}}@media (min-width:64rem){.lg\:px-8{padding-inline:calc(var(--spacing) * 8)}.lg\:py-3{padding-block:calc(var(--spacing) * 3)}.lg\:text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.lg\:text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.lg\:text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&\>div\]\:h-2>div{height:calc(var(--spacing) * 2)}.\[\&\>div\]\:h-3>div{height:calc(var(--spacing) * 3)}.\[\&\>div\]\:h-4>div{height:calc(var(--spacing) * 4)}.\[\&\>div\]\:w-2>div{width:calc(var(--spacing) * 2)}.\[\&\>div\]\:w-3>div{width:calc(var(--spacing) * 3)}.\[\&\>div\]\:w-4>div{width:calc(var(--spacing) * 4)}.\[\&\>div\]\:border-border>div{border-color:var(--color-border)}.\[\&\>div\]\:bg-primary>div{background-color:var(--color-primary)}.\[\&\>div\]\:bg-secondary>div{background-color:var(--color-secondary)}.\[\&\>div\]\:bg-transparent>div{background-color:#0000}.\[\&\[data-state\=open\]\>svg\]\:rotate-180[data-state=open]>svg{rotate:180deg}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}:root{--radius:0;--background:#fff;--foreground:#000;--card:#fff;--card-foreground:#000;--primary:#ffdb33;--primary-hover:#fc0;--primary-foreground:#000;--secondary:#000;--secondary-hover:#1a1a1a;--secondary-foreground:#fff;--muted:#ccc;--muted-foreground:#5a5a5a;--accent:#fae583;--accent-foreground:#000;--destructive:#e63946;--destructive-foreground:#fff;--success:#16a34a;--success-foreground:#fff;--border:#000;--avatar-0:#c62828;--avatar-1:#d17000;--avatar-2:#a67a00;--avatar-3:#117a34;--avatar-4:#0a7070;--avatar-5:#1a5bb5;--avatar-6:#3d3daa;--avatar-7:#6430b0;--avatar-8:#b31d6a;--avatar-9:#3d5060}.dark{--background:#1a1a1a;--foreground:#f5f5f5;--card:#242424;--card-foreground:#f5f5f5;--primary:#ffdb33;--primary-hover:#fc0;--primary-foreground:#000;--secondary:#3a3a3a;--secondary-hover:#4a4a4a;--secondary-foreground:#f5f5f5;--muted:#3f3f46;--muted-foreground:#a0a0a0;--accent:#fae583;--accent-foreground:#000;--destructive:#e63946;--destructive-foreground:#fff;--success:#22c55e;--success-foreground:#000;--border:#5c5c5c;--avatar-0:#ef5350;--avatar-1:#ff9800;--avatar-2:#c8a415;--avatar-3:#2ecc71;--avatar-4:#26a69a;--avatar-5:#42a5f5;--avatar-6:#7c6de5;--avatar-7:#9c5cf0;--avatar-8:#e84d8a;--avatar-9:#78909c}body{background:var(--background);width:100%;min-height:100vh;color:var(--foreground);font-family:var(--font-sans);margin:0;padding:0}#root{width:100%;min-height:100vh}@keyframes pulse-dot{0%,to{opacity:1}50%{opacity:.5}}.animate-pulse-dot{animation:2s ease-in-out infinite pulse-dot}@keyframes tool-pulse{0%,to{background-color:#0000}50%{background-color:color-mix(in srgb, var(--primary) 5%, transparent)}}.animate-tool-pulse{animation:1.5s ease-in-out infinite tool-pulse}@keyframes accordion-down{0%{height:0}to{height:var(--radix-accordion-content-height,var(--bits-accordion-content-height,var(--reka-accordion-content-height,var(--kb-accordion-content-height,var(--ngp-accordion-content-height,auto)))))}}@keyframes accordion-up{0%{height:var(--radix-accordion-content-height,var(--bits-accordion-content-height,var(--reka-accordion-content-height,var(--kb-accordion-content-height,var(--ngp-accordion-content-height,auto)))))}to{height:0}}.animate-accordion-down{animation:.2s ease-out accordion-down}.animate-accordion-up{animation:.2s ease-out accordion-up}.hide-number-spinner::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.hide-number-spinner::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@keyframes bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0));filter:blur(var(--tw-enter-blur,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0));filter:blur(var(--tw-exit-blur,0))}}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Write the set of window IDs with open side panels to chrome.storage.local (best-effort). */
|
|
2
|
+
export declare const persistOpenWindows: (windowIds: Set<number>) => void;
|
|
3
|
+
/**
|
|
4
|
+
* Read stored window IDs from chrome.storage.local, validate each against
|
|
5
|
+
* currently open windows, reopen side panels in valid windows, and return
|
|
6
|
+
* the set of window IDs that were successfully reopened.
|
|
7
|
+
*/
|
|
8
|
+
export declare const restoreSidePanels: () => Promise<Set<number>>;
|
|
9
|
+
/** Remove the side panel state from chrome.storage.local. */
|
|
10
|
+
export declare const clearSidePanelState: () => void;
|
|
11
|
+
//# sourceMappingURL=side-panel-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"side-panel-state.d.ts","sourceRoot":"","sources":["../src/side-panel-state.ts"],"names":[],"mappings":"AAEA,+FAA+F;AAC/F,eAAO,MAAM,kBAAkB,GAAI,WAAW,GAAG,CAAC,MAAM,CAAC,KAAG,IAE3D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,QAAa,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAsB7D,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,mBAAmB,QAAO,IAEtC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { SIDE_PANEL_WINDOWS_KEY } from './constants.js';
|
|
2
|
+
/** Write the set of window IDs with open side panels to chrome.storage.local (best-effort). */
|
|
3
|
+
export const persistOpenWindows = (windowIds) => {
|
|
4
|
+
chrome.storage.local.set({ [SIDE_PANEL_WINDOWS_KEY]: [...windowIds] }).catch(() => { });
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Read stored window IDs from chrome.storage.local, validate each against
|
|
8
|
+
* currently open windows, reopen side panels in valid windows, and return
|
|
9
|
+
* the set of window IDs that were successfully reopened.
|
|
10
|
+
*/
|
|
11
|
+
export const restoreSidePanels = async () => {
|
|
12
|
+
const data = await chrome.storage.local.get(SIDE_PANEL_WINDOWS_KEY);
|
|
13
|
+
const stored = data[SIDE_PANEL_WINDOWS_KEY];
|
|
14
|
+
if (!Array.isArray(stored) || stored.length === 0)
|
|
15
|
+
return new Set();
|
|
16
|
+
const allWindows = await chrome.windows.getAll();
|
|
17
|
+
const validWindowIds = new Set(allWindows.map(w => w.id).filter((id) => id !== undefined));
|
|
18
|
+
const restored = new Set();
|
|
19
|
+
for (const windowId of stored) {
|
|
20
|
+
if (typeof windowId !== 'number' || !validWindowIds.has(windowId))
|
|
21
|
+
continue;
|
|
22
|
+
try {
|
|
23
|
+
await chrome.sidePanel.open({ windowId });
|
|
24
|
+
restored.add(windowId);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Window may have closed between the getAll check and the open call
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Write back the cleaned-up set (removes stale IDs)
|
|
31
|
+
persistOpenWindows(restored);
|
|
32
|
+
return restored;
|
|
33
|
+
};
|
|
34
|
+
/** Remove the side panel state from chrome.storage.local. */
|
|
35
|
+
export const clearSidePanelState = () => {
|
|
36
|
+
chrome.storage.local.remove(SIDE_PANEL_WINDOWS_KEY).catch(() => { });
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=side-panel-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"side-panel-state.js","sourceRoot":"","sources":["../src/side-panel-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD,+FAA+F;AAC/F,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,SAAsB,EAAQ,EAAE;IACjE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,sBAAsB,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AACzF,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,IAA0B,EAAE;IAChE,MAAM,IAAI,GAA4B,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAC7F,MAAM,MAAM,GAAG,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,GAAG,EAAE,CAAC;IAEpE,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;IACjD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAgB,EAAE,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC;IAEzG,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,KAAK,MAAM,QAAQ,IAAI,MAAM,EAAE,CAAC;QAC9B,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS;QAC5E,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC1C,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;QACtE,CAAC;IACH,CAAC;IAED,oDAAoD;IACpD,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC7B,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,6DAA6D;AAC7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAS,EAAE;IAC5C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"side-panel-toggle.d.ts","sourceRoot":"","sources":["../src/side-panel-toggle.ts"],"names":[],"mappings":"AAOA,gFAAgF;AAChF,eAAO,MAAM,mBAAmB,QAAO,IA0BtC,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Side panel toggle — manages per-window open state and toggles the side panel
|
|
2
|
+
// via the action click handler. The onOpened/onClosed events and close() method
|
|
3
|
+
// require Chrome 141+. On older versions (114–140), the toggle-to-close behavior
|
|
4
|
+
// is unavailable and the action click always opens the side panel.
|
|
5
|
+
const openWindows = new Set();
|
|
6
|
+
/** Initialize side panel toggle behavior and register Chrome event listeners */
|
|
7
|
+
export const initSidePanelToggle = () => {
|
|
8
|
+
// Take manual control of the side panel so we can open/close it on action click.
|
|
9
|
+
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: false }).catch(() => { });
|
|
10
|
+
// Chrome 141+ — track open/close state per window for toggle behavior.
|
|
11
|
+
// On older Chrome (114–140), these APIs are undefined; openWindows stays
|
|
12
|
+
// empty and the action click always opens the side panel.
|
|
13
|
+
const canToggle = 'onOpened' in chrome.sidePanel;
|
|
14
|
+
if (canToggle) {
|
|
15
|
+
chrome.sidePanel.onOpened.addListener(({ windowId }) => {
|
|
16
|
+
openWindows.add(windowId);
|
|
17
|
+
});
|
|
18
|
+
chrome.sidePanel.onClosed.addListener(({ windowId }) => {
|
|
19
|
+
openWindows.delete(windowId);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
chrome.action.onClicked.addListener(({ windowId }) => {
|
|
23
|
+
if (canToggle && openWindows.has(windowId)) {
|
|
24
|
+
chrome.sidePanel.close({ windowId }).catch(() => { });
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
chrome.sidePanel.open({ windowId }).catch(() => { });
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=side-panel-toggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"side-panel-toggle.js","sourceRoot":"","sources":["../src/side-panel-toggle.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,gFAAgF;AAChF,iFAAiF;AACjF,mEAAmE;AAEnE,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;AAEtC,gFAAgF;AAChF,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAS,EAAE;IAC5C,iFAAiF;IACjF,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAAE,sBAAsB,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAErF,uEAAuE;IACvE,yEAAyE;IACzE,0DAA0D;IAC1D,MAAM,SAAS,GAAG,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC;IAEjD,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YACrD,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YACrD,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;QACnD,IAAI,SAAS,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACvD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACtD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { PluginMeta } from './extension-messages.js';
|
|
2
|
+
/**
|
|
3
|
+
* Checks if a URL matches any of the given Chrome match patterns.
|
|
4
|
+
*
|
|
5
|
+
* @param url - The full URL to test (e.g., `https://app.slack.com/client`)
|
|
6
|
+
* @param patterns - Chrome extension match patterns to test against
|
|
7
|
+
* @returns `true` if the URL matches at least one pattern
|
|
8
|
+
*/
|
|
9
|
+
export declare const urlMatchesPatterns: (url: string, patterns: string[]) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Tests a single URL against a Chrome extension match pattern.
|
|
12
|
+
*
|
|
13
|
+
* Pattern format: `<scheme>://<host>[:<port>]/<path>` where scheme is
|
|
14
|
+
* `*`, `http`, `https`, or `ftp`; host supports `*` (any host) and
|
|
15
|
+
* `*.domain` (subdomain wildcard); path supports `*` as a glob.
|
|
16
|
+
*
|
|
17
|
+
* Examples:
|
|
18
|
+
* - `*://localhost:9516/*` matches `http://localhost:9516/anything`
|
|
19
|
+
* - `*://*.slack.com/*` matches `https://app.slack.com/anything`
|
|
20
|
+
* - `http://example.com/*` matches `http://example.com/anything`
|
|
21
|
+
*
|
|
22
|
+
* @param url - The full URL to test
|
|
23
|
+
* @param pattern - A Chrome extension match pattern string
|
|
24
|
+
* @returns `true` if the URL matches the pattern
|
|
25
|
+
*/
|
|
26
|
+
export declare const matchPattern: (url: string, pattern: string) => boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Finds all open tabs matching a plugin's URL patterns, sorted by rank (best first).
|
|
29
|
+
*
|
|
30
|
+
* Ranking prefers (in order):
|
|
31
|
+
* 1. Active tab in the focused window
|
|
32
|
+
* 2. Active tab in any window
|
|
33
|
+
* 3. Any tab in the focused window
|
|
34
|
+
* 4. First matching tab
|
|
35
|
+
*
|
|
36
|
+
* This enables fallback: when the best-ranked tab is not ready, callers can
|
|
37
|
+
* try subsequent tabs in order.
|
|
38
|
+
*
|
|
39
|
+
* @param plugin - Plugin metadata containing `urlPatterns` to match against
|
|
40
|
+
* @returns Matching tabs sorted by rank (highest-priority first), deduplicated by tab ID
|
|
41
|
+
*/
|
|
42
|
+
export declare const findAllMatchingTabs: (plugin: PluginMeta) => Promise<chrome.tabs.Tab[]>;
|
|
43
|
+
/**
|
|
44
|
+
* Finds the best matching tab for a plugin's URL patterns.
|
|
45
|
+
*
|
|
46
|
+
* @param plugin - Plugin metadata containing `urlPatterns` to match against
|
|
47
|
+
* @returns The highest-ranked matching tab, or `null` if no matching tabs exist.
|
|
48
|
+
* See {@link findAllMatchingTabs} for ranking details.
|
|
49
|
+
*/
|
|
50
|
+
export declare const findMatchingTab: (plugin: PluginMeta) => Promise<chrome.tabs.Tab | null>;
|
|
51
|
+
//# sourceMappingURL=tab-matching.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tab-matching.d.ts","sourceRoot":"","sources":["../src/tab-matching.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,KAAK,MAAM,EAAE,UAAU,MAAM,EAAE,KAAG,OAKpE,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,EAAE,SAAS,MAAM,KAAG,OAyD3D,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,GAAU,QAAQ,UAAU,KAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAyCvF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAU,QAAQ,UAAU,KAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAGxF,CAAC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if a URL matches any of the given Chrome match patterns.
|
|
3
|
+
*
|
|
4
|
+
* @param url - The full URL to test (e.g., `https://app.slack.com/client`)
|
|
5
|
+
* @param patterns - Chrome extension match patterns to test against
|
|
6
|
+
* @returns `true` if the URL matches at least one pattern
|
|
7
|
+
*/
|
|
8
|
+
export const urlMatchesPatterns = (url, patterns) => {
|
|
9
|
+
for (const pattern of patterns) {
|
|
10
|
+
if (matchPattern(url, pattern))
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
return false;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Tests a single URL against a Chrome extension match pattern.
|
|
17
|
+
*
|
|
18
|
+
* Pattern format: `<scheme>://<host>[:<port>]/<path>` where scheme is
|
|
19
|
+
* `*`, `http`, `https`, or `ftp`; host supports `*` (any host) and
|
|
20
|
+
* `*.domain` (subdomain wildcard); path supports `*` as a glob.
|
|
21
|
+
*
|
|
22
|
+
* Examples:
|
|
23
|
+
* - `*://localhost:9516/*` matches `http://localhost:9516/anything`
|
|
24
|
+
* - `*://*.slack.com/*` matches `https://app.slack.com/anything`
|
|
25
|
+
* - `http://example.com/*` matches `http://example.com/anything`
|
|
26
|
+
*
|
|
27
|
+
* @param url - The full URL to test
|
|
28
|
+
* @param pattern - A Chrome extension match pattern string
|
|
29
|
+
* @returns `true` if the URL matches the pattern
|
|
30
|
+
*/
|
|
31
|
+
export const matchPattern = (url, pattern) => {
|
|
32
|
+
const matchResult = pattern.match(/^(\*|https?|ftp):\/\/(.+?)(\/.*)$/);
|
|
33
|
+
if (!matchResult?.[1] || !matchResult[2] || !matchResult[3])
|
|
34
|
+
return false;
|
|
35
|
+
const [, scheme, hostWithPort, path] = matchResult;
|
|
36
|
+
// Separate host and optional port from the pattern's host portion.
|
|
37
|
+
// Examples: "localhost:9516" → host="localhost", port="9516"
|
|
38
|
+
// "*.slack.com" → host="*.slack.com", port=""
|
|
39
|
+
// "*" → host="*", port=""
|
|
40
|
+
let patternHost;
|
|
41
|
+
let patternPort;
|
|
42
|
+
const colonIdx = hostWithPort.lastIndexOf(':');
|
|
43
|
+
// Only split on colon if what follows looks like a port number (all digits)
|
|
44
|
+
// and the host isn't just "*" — avoids misinterpreting IPv6 or *.host:port
|
|
45
|
+
if (colonIdx > 0 && /^\d+$/.test(hostWithPort.slice(colonIdx + 1))) {
|
|
46
|
+
patternHost = hostWithPort.slice(0, colonIdx);
|
|
47
|
+
patternPort = hostWithPort.slice(colonIdx + 1);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
patternHost = hostWithPort;
|
|
51
|
+
patternPort = '';
|
|
52
|
+
}
|
|
53
|
+
let parsed;
|
|
54
|
+
try {
|
|
55
|
+
parsed = new URL(url);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
// Scheme match
|
|
61
|
+
if (scheme !== '*' && parsed.protocol !== `${scheme}:`)
|
|
62
|
+
return false;
|
|
63
|
+
if (scheme === '*' && !['http:', 'https:'].includes(parsed.protocol))
|
|
64
|
+
return false;
|
|
65
|
+
// Port match — if the pattern specifies a port, the URL must have that port.
|
|
66
|
+
// URL.port is "" for default ports (80 for http, 443 for https).
|
|
67
|
+
if (patternPort) {
|
|
68
|
+
if (parsed.port !== patternPort)
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
// Host match
|
|
72
|
+
if (patternHost !== '*') {
|
|
73
|
+
if (patternHost.startsWith('*.')) {
|
|
74
|
+
const suffix = patternHost.slice(2);
|
|
75
|
+
if (parsed.hostname !== suffix && !parsed.hostname.endsWith(`.${suffix}`))
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
if (parsed.hostname !== patternHost)
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Path match — convert glob to regex
|
|
84
|
+
if (path !== '/*') {
|
|
85
|
+
const pathRegex = new RegExp('^' + path.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*') + '$');
|
|
86
|
+
if (!pathRegex.test(parsed.pathname))
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Finds all open tabs matching a plugin's URL patterns, sorted by rank (best first).
|
|
93
|
+
*
|
|
94
|
+
* Ranking prefers (in order):
|
|
95
|
+
* 1. Active tab in the focused window
|
|
96
|
+
* 2. Active tab in any window
|
|
97
|
+
* 3. Any tab in the focused window
|
|
98
|
+
* 4. First matching tab
|
|
99
|
+
*
|
|
100
|
+
* This enables fallback: when the best-ranked tab is not ready, callers can
|
|
101
|
+
* try subsequent tabs in order.
|
|
102
|
+
*
|
|
103
|
+
* @param plugin - Plugin metadata containing `urlPatterns` to match against
|
|
104
|
+
* @returns Matching tabs sorted by rank (highest-priority first), deduplicated by tab ID
|
|
105
|
+
*/
|
|
106
|
+
export const findAllMatchingTabs = async (plugin) => {
|
|
107
|
+
// Collect all matching tabs across all URL patterns, deduplicating by tab ID
|
|
108
|
+
const seen = new Set();
|
|
109
|
+
const allMatches = [];
|
|
110
|
+
for (const pattern of plugin.urlPatterns) {
|
|
111
|
+
let tabs;
|
|
112
|
+
try {
|
|
113
|
+
tabs = await chrome.tabs.query({ url: pattern });
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
for (const tab of tabs) {
|
|
119
|
+
if (tab.id !== undefined && !seen.has(tab.id)) {
|
|
120
|
+
seen.add(tab.id);
|
|
121
|
+
allMatches.push(tab);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (allMatches.length <= 1)
|
|
126
|
+
return allMatches;
|
|
127
|
+
// Determine the focused window for ranking
|
|
128
|
+
let focusedWindowId;
|
|
129
|
+
try {
|
|
130
|
+
const focusedWindow = await chrome.windows.getLastFocused();
|
|
131
|
+
focusedWindowId = focusedWindow.id;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Cannot determine focused window — ranking falls back to insertion order
|
|
135
|
+
}
|
|
136
|
+
// Rank: active+focused > active > focused > other
|
|
137
|
+
const rank = (tab) => {
|
|
138
|
+
const inFocused = focusedWindowId !== undefined && tab.windowId === focusedWindowId;
|
|
139
|
+
if (tab.active && inFocused)
|
|
140
|
+
return 3;
|
|
141
|
+
if (tab.active)
|
|
142
|
+
return 2;
|
|
143
|
+
if (inFocused)
|
|
144
|
+
return 1;
|
|
145
|
+
return 0;
|
|
146
|
+
};
|
|
147
|
+
return allMatches.slice().sort((a, b) => rank(b) - rank(a));
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Finds the best matching tab for a plugin's URL patterns.
|
|
151
|
+
*
|
|
152
|
+
* @param plugin - Plugin metadata containing `urlPatterns` to match against
|
|
153
|
+
* @returns The highest-ranked matching tab, or `null` if no matching tabs exist.
|
|
154
|
+
* See {@link findAllMatchingTabs} for ranking details.
|
|
155
|
+
*/
|
|
156
|
+
export const findMatchingTab = async (plugin) => {
|
|
157
|
+
const tabs = await findAllMatchingTabs(plugin);
|
|
158
|
+
return tabs[0] ?? null;
|
|
159
|
+
};
|
|
160
|
+
//# sourceMappingURL=tab-matching.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tab-matching.js","sourceRoot":"","sources":["../src/tab-matching.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAW,EAAE,QAAkB,EAAW,EAAE;IAC7E,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;IAC9C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAE,OAAe,EAAW,EAAE;IACpE,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAE1E,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG,WAAW,CAAC;IAEnD,mEAAmE;IACnE,6DAA6D;IAC7D,0DAA0D;IAC1D,gDAAgD;IAChD,IAAI,WAAmB,CAAC;IACxB,IAAI,WAAmB,CAAC;IACxB,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/C,4EAA4E;IAC5E,2EAA2E;IAC3E,IAAI,QAAQ,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC9C,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IACjD,CAAC;SAAM,CAAC;QACN,WAAW,GAAG,YAAY,CAAC;QAC3B,WAAW,GAAG,EAAE,CAAC;IACnB,CAAC;IAED,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IAED,eAAe;IACf,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,QAAQ,KAAK,GAAG,MAAM,GAAG;QAAE,OAAO,KAAK,CAAC;IACrE,IAAI,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IAEnF,6EAA6E;IAC7E,iEAAiE;IACjE,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW;YAAE,OAAO,KAAK,CAAC;IAChD,CAAC;IAED,aAAa;IACb,IAAI,WAAW,KAAK,GAAG,EAAE,CAAC;QACxB,IAAI,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACpC,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC;gBAAE,OAAO,KAAK,CAAC;QAC1F,CAAC;aAAM,CAAC;YACN,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW;gBAAE,OAAO,KAAK,CAAC;QACpD,CAAC;IACH,CAAC;IAED,qCAAqC;IACrC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;QAC1G,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;YAAE,OAAO,KAAK,CAAC;IACrD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,MAAkB,EAA8B,EAAE;IAC1F,6EAA6E;IAC7E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,UAAU,GAAsB,EAAE,CAAC;IAEzC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACzC,IAAI,IAAuB,CAAC;QAC5B,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,GAAG,CAAC,EAAE,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC9C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACjB,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,UAAU,CAAC;IAE9C,2CAA2C;IAC3C,IAAI,eAAmC,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC5D,eAAe,GAAG,aAAa,CAAC,EAAE,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;IAC5E,CAAC;IAED,kDAAkD;IAClD,MAAM,IAAI,GAAG,CAAC,GAAoB,EAAU,EAAE;QAC5C,MAAM,SAAS,GAAG,eAAe,KAAK,SAAS,IAAI,GAAG,CAAC,QAAQ,KAAK,eAAe,CAAC;QACpF,IAAI,GAAG,CAAC,MAAM,IAAI,SAAS;YAAE,OAAO,CAAC,CAAC;QACtC,IAAI,GAAG,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC;QACzB,IAAI,SAAS;YAAE,OAAO,CAAC,CAAC;QACxB,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;IAEF,OAAO,UAAU,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,MAAkB,EAAmC,EAAE;IAC3F,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC/C,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACzB,CAAC,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { PluginMeta, PluginTabStateInfo } from './extension-messages.js';
|
|
2
|
+
import type { TabState } from '@opentabs-dev/shared';
|
|
3
|
+
/**
|
|
4
|
+
* Compute the tab state for a single plugin by checking all matching tabs
|
|
5
|
+
* for adapter readiness. Reports 'ready' if ANY matching tab is ready,
|
|
6
|
+
* 'unavailable' if tabs exist but none are ready, 'closed' if no tabs match.
|
|
7
|
+
*/
|
|
8
|
+
declare const computePluginTabState: (plugin: PluginMeta) => Promise<PluginTabStateInfo>;
|
|
9
|
+
/**
|
|
10
|
+
* Scan all open tabs and send tab.syncAll to MCP server with current state
|
|
11
|
+
* of all known plugins. Called after sync.full is processed so the extension
|
|
12
|
+
* has up-to-date plugin metadata before reporting tab states.
|
|
13
|
+
*
|
|
14
|
+
* Also populates the lastKnownState cache so subsequent checkTabChanged /
|
|
15
|
+
* checkTabRemoved calls can suppress redundant notifications.
|
|
16
|
+
*/
|
|
17
|
+
declare const sendTabSyncAll: () => Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Clear the last-known state cache. Called on WebSocket disconnect so the
|
|
20
|
+
* next connect triggers a full sync without stale cache interference.
|
|
21
|
+
*/
|
|
22
|
+
declare const clearTabStateCache: () => void;
|
|
23
|
+
/**
|
|
24
|
+
* Remove tab-state tracking entries for a single plugin. Called when a plugin
|
|
25
|
+
* is uninstalled or removed during sync.full so the maps do not grow
|
|
26
|
+
* unboundedly during long-running sessions.
|
|
27
|
+
*/
|
|
28
|
+
declare const clearPluginTabState: (pluginName: string) => void;
|
|
29
|
+
/**
|
|
30
|
+
* Update the last-known state for a single plugin, serialized through the
|
|
31
|
+
* plugin lock so it cannot interleave with checkTabChanged / checkTabRemoved
|
|
32
|
+
* reads and writes for the same plugin. Called by handlePluginUpdate in
|
|
33
|
+
* message-router.ts after computing the new state via computePluginTabState.
|
|
34
|
+
*/
|
|
35
|
+
declare const updateLastKnownState: (pluginName: string, state: TabState) => Promise<void>;
|
|
36
|
+
/** Return a snapshot of last-known tab states for all plugins. */
|
|
37
|
+
declare const getLastKnownStates: () => ReadonlyMap<string, TabState>;
|
|
38
|
+
/**
|
|
39
|
+
* Check if a tab removal affects any plugin's tab state. All plugins are
|
|
40
|
+
* checked because chrome.tabs.get fails for removed tabs and onRemoved
|
|
41
|
+
* provides no URL, so pattern matching is not possible.
|
|
42
|
+
*/
|
|
43
|
+
declare const checkTabRemoved: (_removedTabId: number) => Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Check if a tab URL change or page load affects any plugin's tab state.
|
|
46
|
+
* Only plugins whose patterns match the changed URL or that have an active
|
|
47
|
+
* (non-closed) state are checked, avoiding O(n × scripting calls) per event.
|
|
48
|
+
*
|
|
49
|
+
* Optimized paths:
|
|
50
|
+
* - URL change: plugins matching the new URL OR plugins with active state
|
|
51
|
+
* - status=complete: the tab's URL is fetched once and matched against all
|
|
52
|
+
* plugin patterns, avoiding per-plugin chrome.tabs queries
|
|
53
|
+
*/
|
|
54
|
+
declare const checkTabChanged: (changedTabId: number, changeInfo: chrome.tabs.OnUpdatedInfo) => Promise<void>;
|
|
55
|
+
export { checkTabChanged, checkTabRemoved, clearPluginTabState, clearTabStateCache, computePluginTabState, getLastKnownStates, sendTabSyncAll, updateLastKnownState, };
|
|
56
|
+
//# sourceMappingURL=tab-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tab-state.d.ts","sourceRoot":"","sources":["../src/tab-state.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAgFrD;;;;GAIG;AACH,QAAA,MAAM,qBAAqB,GAAU,QAAQ,UAAU,KAAG,OAAO,CAAC,kBAAkB,CA8BnF,CAAC;AAEF;;;;;;;GAOG;AACH,QAAA,MAAM,cAAc,QAAa,OAAO,CAAC,IAAI,CAyD5C,CAAC;AAEF;;;GAGG;AACH,QAAA,MAAM,kBAAkB,QAAO,IAG9B,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,mBAAmB,GAAI,YAAY,MAAM,KAAG,IAGjD,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,oBAAoB,GAAI,YAAY,MAAM,EAAE,OAAO,QAAQ,KAAG,OAAO,CAAC,IAAI,CAI5E,CAAC;AAEL,kEAAkE;AAClE,QAAA,MAAM,kBAAkB,QAAO,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAmB,CAAC;AA4B/E;;;;GAIG;AACH,QAAA,MAAM,eAAe,GAAU,eAAe,MAAM,KAAG,OAAO,CAAC,IAAI,CAMlE,CAAC;AAEF;;;;;;;;;GASG;AACH,QAAA,MAAM,eAAe,GAAU,cAAc,MAAM,EAAE,YAAY,MAAM,CAAC,IAAI,CAAC,aAAa,KAAG,OAAO,CAAC,IAAI,CA0CxG,CAAC;AAEF,OAAO,EACL,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,GACrB,CAAC"}
|