mirror of
https://github.com/Tencent/BrowserSkill.git
synced 2026-09-10 13:01:23 +08:00
feat(dsh-plugin-browserskill): reskin the overlay with BrowserSkill's own UI system
The previous pass aligned the observation overlay with the dsh shell; the product call is the opposite direction — the floating card should read as a BrowserSkill surface, not a shell-native widget. - Reuse @browser-skill/ui directly (Button, cn); status dots spec'd after the extension popup's ConnectionStatusIndicator; Remix icons for interrupt/pin/warn/pop-out. - Compile the BSK tailwind utility sheet scoped under the .bsk-obs root class (scripts/build-client-css.mjs + postcss-prefix-selector) and ship the oklch design tokens on the same scope, so nothing leaks into the host shell and the shell theme cannot bleed back. tsdown injects .nomodule.css verbatim (minified, unhashed) alongside the hashed CSS modules. - BSK ships no shared tooltip, so the one-time interrupt semantics hint is a card-spec bubble (bg-card/border/12px radius), retired after first use. - Tests: pin react/react-dom to this package's 18.x copies in vitest — the ui package sources peer on react ^19 and would otherwise emit react-19 (transitional) elements that the react-18 renderer rejects. Production is unaffected (react stays external, provided by the shell). - stylelint: ignore the generated bsk-ui.nomodule.css.
This commit is contained in:
@@ -3,3 +3,6 @@
|
||||
**/.output/**
|
||||
**/target/**
|
||||
**/node_modules/**
|
||||
# Generated client CSS (tailwind compile output); built by
|
||||
# packages/dsh-plugin-browserskill/scripts/build-client-css.mjs.
|
||||
**/dsh-plugin-browserskill/src/client/bsk-ui.nomodule.css
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
lib/
|
||||
src/client/bsk-ui.nomodule.css
|
||||
.bsk-ui.input.css
|
||||
.bsk-ui.raw.css
|
||||
|
||||
@@ -76,8 +76,13 @@ All fields are optional and validated through the plugin's Schemastery `Config`:
|
||||
When the plugin runs inside the dsh Web UI, an **observation overlay** floats over the app
|
||||
(registered into the `shell.overlay` seat): a breathing thumbnail per owned session plus its
|
||||
current action and elapsed time. The card docks at the top-right of the content area (clear of
|
||||
the composer and the shell's header controls) and follows the shell's own visual language —
|
||||
shared `ui-primitives` controls and `--dsw-alias-*` semantic tokens throughout.
|
||||
the composer and the shell's header controls) and wears the **BrowserSkill product family's own
|
||||
look**: the overlay reuses `@browser-skill/ui` components (`Button`, `cn`) and its oklch design
|
||||
tokens (`--card`, `--primary`, `--destructive`, `--ring`, …), status dots spec'd after the
|
||||
extension popup's connection indicator, and Remix icons. The BSK utility sheet is compiled
|
||||
scoped under the `.bsk-obs` root class (`scripts/build-client-css.mjs`), so the overlay looks
|
||||
like the BrowserSkill extension without leaking a single selector into the host shell — and the
|
||||
shell's theme cannot bleed back in.
|
||||
|
||||
- **Lifecycle**: hidden while the plugin owns no sessions; appears on the first
|
||||
`browser_session_start`; disappears when all sessions stop (or the plugin unloads).
|
||||
|
||||
@@ -34,9 +34,10 @@
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsdown",
|
||||
"build": "node scripts/build-client-css.mjs && tsdown",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test": "vitest run"
|
||||
"test": "vitest run",
|
||||
"build:css": "node scripts/build-client-css.mjs"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@deepseek-ai/cordis": "^4.0.1",
|
||||
@@ -82,16 +83,24 @@
|
||||
"@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
|
||||
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
||||
"@deepseek-ai/schemastery": "^3.18.1",
|
||||
"@tailwindcss/cli": "^4.3.3",
|
||||
"@testing-library/react": "^16.1.0",
|
||||
"@types/node": "^22.10.0",
|
||||
"@types/react": "~18.3.1",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"happy-dom": "^15.11.7",
|
||||
"lightningcss": "^1.30.0",
|
||||
"postcss": "^8.5.0",
|
||||
"postcss-prefix-selector": "^2.1.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"tailwindcss": "^4.3.3",
|
||||
"tsdown": "^0.22.14",
|
||||
"typescript": "^5.8.0",
|
||||
"vitest": "^4.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@browser-skill/ui": "workspace:*",
|
||||
"@remixicon/react": "^4.9.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Build the scoped BrowserSkill-UI utility sheet for the dsh client bundle.
|
||||
*
|
||||
* The overlay reuses @browser-skill/ui components (shadcn-style, Tailwind v4
|
||||
* utility classes). Those classes need a stylesheet — but a global utility
|
||||
* sheet inside the dsh page would collide with the host UI, so the compiled
|
||||
* output is scope-prefixed under `.bsk-obs` (the overlay root class):
|
||||
* 1. tailwindcss compiles the utilities used by packages/ui + our client;
|
||||
* 2. postcss-prefix-selector nests every rule under .bsk-obs.
|
||||
* Token values themselves live in src/client/bsk-tokens.nomodule.css
|
||||
* (hand-mirrored from packages/ui/src/styles/tailwind.css).
|
||||
*
|
||||
* Output: src/client/bsk-ui.nomodule.css (gitignored build artifact).
|
||||
*/
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import postcss from "postcss";
|
||||
import prefixer from "postcss-prefix-selector";
|
||||
|
||||
const pkgRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
||||
const input = join(pkgRoot, ".bsk-ui.input.css");
|
||||
const rawOut = join(pkgRoot, ".bsk-ui.raw.css");
|
||||
const finalOut = join(pkgRoot, "src/client/bsk-ui.nomodule.css");
|
||||
|
||||
// The canonical sheet can't be imported directly (its own `@import
|
||||
// "tailwindcss"` must resolve from a package that has it), so we inline the
|
||||
// canonical @theme block read from packages/ui at build time.
|
||||
const canonical = readFileSync(join(pkgRoot, "..", "ui", "src", "styles", "tailwind.css"), "utf8");
|
||||
const themeBlock = canonical.match(/@theme inline \{[\s\S]*?\n\}/)?.[0];
|
||||
if (themeBlock === undefined) throw new Error("canonical @theme inline block not found");
|
||||
writeFileSync(
|
||||
input,
|
||||
[
|
||||
'@import "tailwindcss";',
|
||||
"@custom-variant dark (&:is(.dark *));",
|
||||
themeBlock,
|
||||
'@source "../ui/src";',
|
||||
'@source "./src/client";',
|
||||
"",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
execFileSync(
|
||||
process.execPath,
|
||||
[
|
||||
join(pkgRoot, "node_modules", "@tailwindcss", "cli", "dist", "index.mjs"),
|
||||
"-i",
|
||||
input,
|
||||
"-o",
|
||||
rawOut,
|
||||
],
|
||||
{ cwd: pkgRoot, stdio: "inherit" },
|
||||
);
|
||||
|
||||
const result = await postcss([
|
||||
prefixer({
|
||||
prefix: ".bsk-obs",
|
||||
transform(prefix, selector, prefixedSelector) {
|
||||
// Root-level anchors collapse onto the scope root itself.
|
||||
if (selector === ":root" || selector === "html" || selector === "body") return prefix;
|
||||
if (selector.startsWith(prefix)) return selector;
|
||||
return prefixedSelector;
|
||||
},
|
||||
}),
|
||||
]).process(readFileSync(rawOut, "utf8"), { from: rawOut });
|
||||
|
||||
mkdirSync(dirname(finalOut), { recursive: true });
|
||||
writeFileSync(finalOut, result.css);
|
||||
console.log(`bsk-ui sheet: ${result.css.length} bytes -> ${finalOut}`);
|
||||
@@ -1,8 +1,10 @@
|
||||
/* Observation overlay: floating card + collapsed capsule. Every color,
|
||||
surface, shadow, and label style rides the dsh --dsw-alias-* semantic
|
||||
tokens (dsh 0.1 ships no spacing/radius scales — those stay px, same as
|
||||
dsh's own components). The shell overlay layer is click-through, so the
|
||||
card and capsule opt back into pointer events themselves. */
|
||||
/* Observation overlay skin, BrowserSkill family: colors/radius ride the BSK
|
||||
design tokens (--card/--border/--primary/--destructive/--ring/--radius,
|
||||
defined on the .bsk-obs scope root by bsk-tokens.nomodule.css — values
|
||||
mirrored from packages/ui/src/styles/tailwind.css). Layout-only here;
|
||||
component chrome (buttons etc.) comes from @browser-skill/ui plus the
|
||||
scope-prefixed utility sheet. The shell overlay layer is click-through, so
|
||||
the card and capsule opt back into pointer events themselves. */
|
||||
|
||||
.card {
|
||||
position: fixed;
|
||||
@@ -10,11 +12,12 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
pointer-events: auto;
|
||||
background: var(--dsw-alias-bg-overlay);
|
||||
border: 1px solid var(--dsw-alias-border-l2);
|
||||
border-radius: 10px;
|
||||
box-shadow: var(--dsw-shadow-lv2);
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
box-shadow: 0 8px 28px rgb(0 0 0 / 18%);
|
||||
overflow: hidden;
|
||||
color: var(--card-foreground);
|
||||
}
|
||||
|
||||
.body {
|
||||
@@ -22,9 +25,9 @@
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
font: var(--dsw-font-base-16, inherit);
|
||||
font-size: 12px;
|
||||
color: var(--dsw-alias-label-primary);
|
||||
background: var(--card);
|
||||
color: var(--card-foreground);
|
||||
}
|
||||
|
||||
.header {
|
||||
@@ -35,34 +38,7 @@
|
||||
cursor: move;
|
||||
user-select: none;
|
||||
touch-action: none;
|
||||
border-bottom: 1px solid var(--dsw-alias-border-l2);
|
||||
}
|
||||
|
||||
.dot {
|
||||
flex: none;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: var(--dsw-alias-label-tertiary);
|
||||
}
|
||||
|
||||
.dot[data-state="active"] {
|
||||
background: var(--dsw-alias-state-success-primary);
|
||||
animation: bsk-obs-pulse 1.6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.dot[data-state="error"] {
|
||||
background: var(--dsw-alias-state-error-primary);
|
||||
}
|
||||
@keyframes bsk-obs-pulse {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.35;
|
||||
}
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.status-text {
|
||||
@@ -81,15 +57,15 @@
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 2px;
|
||||
border-radius: 4px;
|
||||
border-radius: calc(var(--radius) - 6px);
|
||||
font: inherit;
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
color: var(--muted-foreground);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icon-button:hover {
|
||||
color: var(--dsw-alias-label-secondary);
|
||||
background: var(--dsw-alias-interactive-bg-hover);
|
||||
color: var(--foreground);
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.stage {
|
||||
@@ -99,7 +75,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--dsw-alias-bg-base);
|
||||
background: var(--background);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -120,7 +96,7 @@
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
color: var(--muted-foreground);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@@ -134,9 +110,9 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--dsw-alias-state-warn-primary);
|
||||
border: 1px solid var(--dsw-alias-state-warn-primary);
|
||||
background: var(--dsw-alias-bg-overlay);
|
||||
color: oklch(0.7 0.19 60);
|
||||
border: 1px solid oklch(0.7 0.19 60);
|
||||
background: var(--card);
|
||||
}
|
||||
|
||||
.actions {
|
||||
@@ -145,17 +121,27 @@
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
padding: 6px 8px;
|
||||
border-top: 1px solid var(--dsw-alias-border-l2);
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
/* Destructive action, styled like the shell's own danger affordances. */
|
||||
.interrupt {
|
||||
color: var(--dsw-alias-state-error-primary);
|
||||
border-color: var(--dsw-alias-state-error-primary);
|
||||
.interrupt-wrap {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.interrupt:not(:disabled):hover {
|
||||
background: var(--dsw-alias-interactive-bg-hover-danger);
|
||||
.hint {
|
||||
position: absolute;
|
||||
bottom: calc(100% + 6px);
|
||||
left: 0;
|
||||
width: 220px;
|
||||
padding: 6px 8px;
|
||||
border-radius: calc(var(--radius) - 4px);
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
color: var(--muted-foreground);
|
||||
font-size: 11px;
|
||||
box-shadow: 0 4px 14px rgb(0 0 0 / 16%);
|
||||
z-index: 41;
|
||||
}
|
||||
|
||||
.resize-handle {
|
||||
@@ -175,8 +161,8 @@
|
||||
bottom: 3px;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-right: 2px solid var(--dsw-alias-label-tertiary);
|
||||
border-bottom: 2px solid var(--dsw-alias-label-tertiary);
|
||||
border-right: 2px solid var(--muted-foreground);
|
||||
border-bottom: 2px solid var(--muted-foreground);
|
||||
}
|
||||
|
||||
.capsule {
|
||||
@@ -190,16 +176,16 @@
|
||||
padding: 6px 12px;
|
||||
pointer-events: auto;
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--dsw-alias-border-l2);
|
||||
background: var(--dsw-alias-bg-overlay);
|
||||
box-shadow: var(--dsw-shadow-lv1);
|
||||
border: 1px solid var(--border);
|
||||
background: var(--card);
|
||||
box-shadow: 0 4px 14px rgb(0 0 0 / 16%);
|
||||
font-size: 12px;
|
||||
color: var(--dsw-alias-label-secondary);
|
||||
color: var(--muted-foreground);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capsule:hover {
|
||||
background: var(--dsw-alias-interactive-bg-hover);
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.strip {
|
||||
@@ -207,22 +193,22 @@
|
||||
gap: 6px;
|
||||
padding: 4px 8px;
|
||||
overflow-x: auto;
|
||||
border-top: 1px solid var(--dsw-alias-border-l2);
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.strip-item {
|
||||
position: relative;
|
||||
flex: none;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--dsw-alias-border-l2);
|
||||
border-radius: calc(var(--radius) - 6px);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.strip-item[data-focused] {
|
||||
border-color: var(--dsw-alias-brand-primary);
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.strip-item[data-state="error"] {
|
||||
border-color: var(--dsw-alias-state-error-primary);
|
||||
border-color: var(--destructive);
|
||||
}
|
||||
|
||||
.strip-item[data-state="dead"] {
|
||||
@@ -235,16 +221,16 @@
|
||||
gap: 4px;
|
||||
padding: 3px 6px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
border-radius: calc(var(--radius) - 6px);
|
||||
background: none;
|
||||
font: inherit;
|
||||
font-size: 11px;
|
||||
color: var(--dsw-alias-label-secondary);
|
||||
color: var(--muted-foreground);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.strip-main:hover {
|
||||
background: var(--dsw-alias-interactive-bg-hover);
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.strip-thumb {
|
||||
@@ -252,7 +238,7 @@
|
||||
height: 20px;
|
||||
overflow: hidden;
|
||||
border-radius: 3px;
|
||||
background: var(--dsw-alias-bg-base);
|
||||
background: var(--background);
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
@@ -274,7 +260,7 @@
|
||||
}
|
||||
|
||||
.pin-badge {
|
||||
color: var(--dsw-alias-brand-primary);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.strip-interrupt {
|
||||
@@ -287,9 +273,9 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid var(--dsw-alias-state-error-primary);
|
||||
background: var(--dsw-alias-bg-overlay);
|
||||
color: var(--dsw-alias-state-error-primary);
|
||||
border: 1px solid var(--destructive);
|
||||
background: var(--card);
|
||||
color: var(--destructive);
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -303,14 +289,10 @@
|
||||
.capsule:focus-visible,
|
||||
.strip-main:focus-visible,
|
||||
.strip-interrupt:focus-visible {
|
||||
outline: 2px solid var(--dsw-alias-brand-primary);
|
||||
outline: 2px solid var(--ring);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.dot[data-state="active"] {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
@@ -3,19 +3,31 @@
|
||||
// composer's way); collapsed = a status capsule; "pop out" upgrades the same
|
||||
// content to a native Document PiP window (user gesture required by the
|
||||
// browser). Multi-session renders a meeting-style strip under the focus view.
|
||||
// Visuals ride dsh's shared primitives and --dsw-alias-* tokens throughout,
|
||||
// so the card reads as a native part of the shell, not a foreign widget.
|
||||
// Visuals follow the BrowserSkill product family: @browser-skill/ui components
|
||||
// and oklch tokens on a .bsk-obs scope root, so the card reads as BSK's own
|
||||
// surface without leaking styles into (or inheriting themes from) the shell.
|
||||
|
||||
import { Button, cn } from "@browser-skill/ui";
|
||||
import {
|
||||
RiArrowDownSLine,
|
||||
RiErrorWarningLine,
|
||||
RiPictureInPicture2Line,
|
||||
RiPushpinFill,
|
||||
RiStopMiniFill,
|
||||
} from "@remixicon/react";
|
||||
|
||||
// remixicon's component types target @types/react 19 while the dsh shell
|
||||
// runs react 18 — a compile-time-only recast keeps the 18 typecheck happy.
|
||||
type IconComponent = (props: { size?: number | string; className?: string }) => ReactNode;
|
||||
const asIcon = (component: unknown): IconComponent => component as IconComponent;
|
||||
const IconStop = asIcon(RiStopMiniFill);
|
||||
const IconPip = asIcon(RiPictureInPicture2Line);
|
||||
const IconDown = asIcon(RiArrowDownSLine);
|
||||
const IconWarn = asIcon(RiErrorWarningLine);
|
||||
const IconPin = asIcon(RiPushpinFill);
|
||||
|
||||
import {
|
||||
Button,
|
||||
IconChevronDownOutline14,
|
||||
IconRightUpOutline16,
|
||||
IconStopFill16,
|
||||
IconWarningOutline16,
|
||||
StateDot,
|
||||
Tooltip,
|
||||
} from "@deepseek-ai/dsh-client-ui-primitives";
|
||||
import {
|
||||
type ReactNode,
|
||||
type PointerEvent as ReactPointerEvent,
|
||||
useCallback,
|
||||
useEffect,
|
||||
@@ -94,19 +106,23 @@ export function statusOf(obs: SessionObservation): "active" | "idle" | "error" {
|
||||
return obs.action === "idle" ? "idle" : "active";
|
||||
}
|
||||
|
||||
function dotStateOf(
|
||||
state: "active" | "idle" | "error" | "dead",
|
||||
): "done" | "ongoing" | "error" | "warning" {
|
||||
switch (state) {
|
||||
case "active":
|
||||
return "ongoing";
|
||||
case "error":
|
||||
return "error";
|
||||
case "dead":
|
||||
return "warning";
|
||||
default:
|
||||
return "done";
|
||||
}
|
||||
/** Flat status dot, specced after the BSK popup's ConnectionStatusIndicator. */
|
||||
function StatusDot({ state }: { state: "active" | "idle" | "error" | "dead" }) {
|
||||
const color =
|
||||
state === "active"
|
||||
? "bg-emerald-500"
|
||||
: state === "error"
|
||||
? "bg-red-500"
|
||||
: state === "dead"
|
||||
? "bg-amber-500"
|
||||
: "bg-muted-foreground/40";
|
||||
return (
|
||||
<span
|
||||
className={cn("size-2 shrink-0 rounded-full ring-2 ring-background", color)}
|
||||
data-state={state}
|
||||
aria-hidden
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** One strip item: mini frame, id, status dot, hover interrupt, pin toggle. */
|
||||
@@ -149,21 +165,8 @@ function StripItem(props: {
|
||||
)}
|
||||
</span>
|
||||
<span className={css["strip-id"]}>{obs.sessionId}</span>
|
||||
<StateDot state={dotStateOf(state)} />
|
||||
{pinned ? (
|
||||
<svg
|
||||
className={css["pin-badge"]}
|
||||
width="9"
|
||||
height="9"
|
||||
viewBox="0 0 10 10"
|
||||
aria-label="pinned"
|
||||
>
|
||||
<path
|
||||
d="M6.5 0.8 9.2 3.5 8.3 4.4 7.9 4 6.2 6.9 6.6 8.7 6 9.4 3.4 5.4 1 7.9 0.6 7.3 2.5 6 3.1 6.6 5.9 2.1 5.5 1.7Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
) : null}
|
||||
<StatusDot state={state} />
|
||||
{pinned ? <IconPin size={9} className={css["pin-badge"]} aria-label="pinned" /> : null}
|
||||
</button>
|
||||
{hover && !pinned && obs.dead !== true ? (
|
||||
<button
|
||||
@@ -176,7 +179,7 @@ function StripItem(props: {
|
||||
void store.interrupt(obs.sessionId);
|
||||
}}
|
||||
>
|
||||
<IconStopFill16 size={8} />
|
||||
<IconStop size={9} />
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -211,7 +214,8 @@ function OverlayBody(props: {
|
||||
onHeaderPointerDown,
|
||||
} = props;
|
||||
const [interrupting, setInterrupting] = useState(false);
|
||||
// One-time semantics hint: a shared Tooltip that retires after first use.
|
||||
// One-time semantics hint bubble, retired after the first interrupt.
|
||||
const [hintOpen, setHintOpen] = useState(false);
|
||||
const [hintSeen, setHintSeen] = useState(false);
|
||||
|
||||
const thumbId = focus?.thumbnailAttachmentId;
|
||||
@@ -241,14 +245,14 @@ function OverlayBody(props: {
|
||||
const state = !available ? "error" : focus !== undefined ? statusOf(focus) : "idle";
|
||||
|
||||
return (
|
||||
<div className={css.body} data-state={state} data-in-pip={inPip || undefined}>
|
||||
<div className={cn(css.body, "bsk-obs")} data-state={state} data-in-pip={inPip || undefined}>
|
||||
<div
|
||||
className={css.header}
|
||||
data-testid="obs-header"
|
||||
onPointerDown={onHeaderPointerDown}
|
||||
role="presentation"
|
||||
>
|
||||
<StateDot state={state === "error" ? "error" : state === "active" ? "ongoing" : "done"} />
|
||||
<StatusDot state={state === "error" ? "error" : state === "active" ? "active" : "idle"} />
|
||||
<span className={css["status-text"]}>{statusText}</span>
|
||||
{onCollapse !== undefined ? (
|
||||
<button
|
||||
@@ -257,7 +261,7 @@ function OverlayBody(props: {
|
||||
aria-label="Collapse"
|
||||
onClick={onCollapse}
|
||||
>
|
||||
<IconChevronDownOutline14 />
|
||||
<IconDown size={14} />
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -280,7 +284,7 @@ function OverlayBody(props: {
|
||||
)}
|
||||
{thumb?.status === "error" ? (
|
||||
<span className={css.badge} aria-label="thumbnail failed">
|
||||
<IconWarningOutline16 size={12} />
|
||||
<IconWarn size={12} />
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -299,34 +303,41 @@ function OverlayBody(props: {
|
||||
</div>
|
||||
) : null}
|
||||
<div className={css.actions}>
|
||||
<Tooltip
|
||||
label="Interrupt stops only the current browser action — the agent run continues (use the chat Stop button to halt the run)."
|
||||
side="top"
|
||||
maxWidth={240}
|
||||
disabled={hintSeen}
|
||||
<span
|
||||
className={css["interrupt-wrap"]}
|
||||
onPointerEnter={() => {
|
||||
if (!hintSeen) setHintOpen(true);
|
||||
}}
|
||||
onPointerLeave={() => setHintOpen(false)}
|
||||
>
|
||||
<span className={css["interrupt-wrap"]}>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className={css.interrupt}
|
||||
icon={<IconStopFill16 />}
|
||||
disabled={!canInterrupt}
|
||||
aria-label="Interrupt the current browser action"
|
||||
onClick={onInterrupt}
|
||||
>
|
||||
{interrupting ? "Interrupting…" : "Interrupt"}
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="text-destructive border-destructive/60 hover:bg-destructive/10"
|
||||
disabled={!canInterrupt}
|
||||
aria-label="Interrupt the current browser action"
|
||||
onClick={onInterrupt}
|
||||
>
|
||||
<IconStop size={14} />
|
||||
{interrupting ? "Interrupting…" : "Interrupt"}
|
||||
</Button>
|
||||
{/* BSK ships no shared tooltip component; this bubble follows the BSK
|
||||
card spec (bg-card, border, 12px radius, caption text). */}
|
||||
{hintOpen && !hintSeen ? (
|
||||
<span className={css.hint} role="tooltip">
|
||||
Interrupt stops only the current browser action — the agent run continues (use the
|
||||
chat Stop button to halt the run).
|
||||
</span>
|
||||
) : null}
|
||||
</span>
|
||||
{onPopOut !== undefined ? (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
icon={<IconRightUpOutline16 />}
|
||||
aria-label="Pop out into a mini window"
|
||||
onClick={onPopOut}
|
||||
>
|
||||
<IconPip size={14} />
|
||||
Pop out
|
||||
</Button>
|
||||
) : null}
|
||||
@@ -457,12 +468,12 @@ export function ObservationOverlay({ store }: { store: ObservationClientStore })
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={css.capsule}
|
||||
className={cn(css.capsule, "bsk-obs")}
|
||||
data-state={state}
|
||||
aria-label="Expand browser observation overlay"
|
||||
onClick={() => setCollapsed(false)}
|
||||
>
|
||||
<StateDot state={dotStateOf(state)} />
|
||||
<StatusDot state={state} />
|
||||
<span className={css["capsule-text"]}>
|
||||
{snapshot.sessions.length} session{snapshot.sessions.length === 1 ? "" : "s"}
|
||||
{focus !== undefined && focus.action !== "idle"
|
||||
@@ -478,7 +489,7 @@ export function ObservationOverlay({ store }: { store: ObservationClientStore })
|
||||
? { left: pos.x, top: pos.y, width: size.w, height: size.h }
|
||||
: { right: EDGE_MARGIN, top: TOP_OFFSET, width: size.w, height: size.h };
|
||||
return (
|
||||
<div className={css.card} style={style} data-obs-card data-testid="obs-card">
|
||||
<div className={cn(css.card, "bsk-obs")} style={style} data-obs-card data-testid="obs-card">
|
||||
{body}
|
||||
<div
|
||||
className={css["resize-handle"]}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* BrowserSkill UI design tokens, scoped to the observation overlay root.
|
||||
* VALUES MIRROR packages/ui/src/styles/tailwind.css (:root and .dark) — keep
|
||||
* in sync with that file; it is the canonical source. Scoped here (instead of
|
||||
* :root) so the dsh host theme can neither leak in nor be polluted by us.
|
||||
* Dark follows prefers-color-scheme, same as the extension popup.
|
||||
*/
|
||||
.bsk-obs {
|
||||
color-scheme: light dark;
|
||||
--background: oklch(0.99 0.005 50);
|
||||
--foreground: oklch(0.14 0.03 50);
|
||||
--card: oklch(0.995 0.003 50 / 0.82);
|
||||
--card-foreground: oklch(0.14 0.03 50);
|
||||
--primary: oklch(0.62 0.22 45);
|
||||
--primary-foreground: oklch(0.99 0.01 50);
|
||||
--secondary: oklch(0.96 0.04 65);
|
||||
--secondary-foreground: oklch(0.25 0.08 65);
|
||||
--muted: oklch(0.96 0.01 50);
|
||||
--muted-foreground: oklch(0.55 0.04 50);
|
||||
--accent: oklch(0.96 0.04 65);
|
||||
--accent-foreground: oklch(0.25 0.08 65);
|
||||
--destructive: oklch(0.6 0.25 25);
|
||||
--destructive-foreground: oklch(0.99 0.01 50);
|
||||
--border: oklch(0.9 0.025 60);
|
||||
--input: oklch(0.9 0.025 60);
|
||||
--ring: oklch(0.62 0.22 45);
|
||||
--radius: 0.75rem;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.bsk-obs {
|
||||
--background: oklch(0.2 0.02 50);
|
||||
--foreground: oklch(0.98 0.01 50);
|
||||
--card: oklch(0.24 0.02 50 / 0.82);
|
||||
--card-foreground: oklch(0.98 0.01 50);
|
||||
--primary: oklch(0.7 0.18 45);
|
||||
--primary-foreground: oklch(0.14 0.03 50);
|
||||
--secondary: oklch(0.32 0.03 60);
|
||||
--secondary-foreground: oklch(0.98 0.01 50);
|
||||
--muted: oklch(0.3 0.02 50);
|
||||
--muted-foreground: oklch(0.75 0.03 50);
|
||||
--accent: oklch(0.32 0.03 60);
|
||||
--accent-foreground: oklch(0.98 0.01 50);
|
||||
--destructive: oklch(0.45 0.2 25);
|
||||
--destructive-foreground: oklch(0.98 0.01 50);
|
||||
--border: oklch(0.35 0.02 60);
|
||||
--input: oklch(0.35 0.02 60);
|
||||
--ring: oklch(0.7 0.18 45);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,10 @@ import type { ClientContext, ISessions, SessionId } from "@deepseek-ai/dsh-clien
|
||||
import type {} from "@deepseek-ai/dsh-client-ui-layout/client";
|
||||
import type { ToolCallViewProps } from "@deepseek-ai/dsh-client-ui-tool/client";
|
||||
import { createElement } from "react";
|
||||
// Scope-prefixed BSK design tokens and utility sheet (injected verbatim as
|
||||
// <style> tags; selectors stay unhashed so `cn(..., "bsk-obs")` roots match).
|
||||
import "./bsk-tokens.nomodule.css";
|
||||
import "./bsk-ui.nomodule.css";
|
||||
import { ObservationOverlay } from "./ObservationOverlay";
|
||||
import { type EventSourceLike, ObservationClientStore } from "./observation-store";
|
||||
import { ScreenshotToolView } from "./ScreenshotToolView";
|
||||
|
||||
@@ -109,11 +109,11 @@ describe("ObservationOverlay", () => {
|
||||
const h = makeHarness([BUSY]);
|
||||
render(<ObservationOverlay store={h.store} />);
|
||||
const button = await screen.findByRole("button", { name: /Interrupt the current/ });
|
||||
fireEvent.mouseOver(button);
|
||||
fireEvent.pointerEnter(button);
|
||||
await screen.findByRole("tooltip");
|
||||
fireEvent.mouseLeave(button);
|
||||
fireEvent.pointerLeave(button);
|
||||
fireEvent.click(button);
|
||||
fireEvent.mouseOver(button);
|
||||
fireEvent.pointerEnter(button);
|
||||
expect(screen.queryByRole("tooltip")).toBeNull();
|
||||
});
|
||||
|
||||
|
||||
@@ -71,7 +71,10 @@ const client: UserConfig = {
|
||||
{
|
||||
name: "bsk-css-modules-inline",
|
||||
resolveId(source: string, importer: string | undefined) {
|
||||
if (!source.endsWith(".module.css")) return null;
|
||||
// `.module.css` gets hashed class maps; `.nomodule.css` is injected
|
||||
// verbatim (minified) — used for the scope-prefixed BSK utility sheet
|
||||
// and tokens, whose selectors must survive untouched.
|
||||
if (!source.endsWith(".module.css") && !source.endsWith(".nomodule.css")) return null;
|
||||
const abs = importer !== undefined ? resolvePath(dirname(importer), source) : source;
|
||||
return CSS_VIRTUAL_PREFIX + abs + CSS_VIRTUAL_SUFFIX;
|
||||
},
|
||||
@@ -80,10 +83,11 @@ const client: UserConfig = {
|
||||
const fileId = virtualId.slice(CSS_VIRTUAL_PREFIX.length, -CSS_VIRTUAL_SUFFIX.length);
|
||||
this.addWatchFile(fileId);
|
||||
const source = await readFile(fileId);
|
||||
const isModule = fileId.endsWith(".module.css");
|
||||
const { code, exports: cssExports } = transform({
|
||||
filename: fileId,
|
||||
code: source,
|
||||
cssModules: { pattern: "[hash]_[local]" },
|
||||
...(isModule ? { cssModules: { pattern: "[hash]_[local]" } } : {}),
|
||||
minify: true,
|
||||
});
|
||||
const classMap: Record<string, string> = {};
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
import { createRequire } from "node:module";
|
||||
import path from "node:path";
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
// @browser-skill/ui ships raw source and peers on react ^19, while the dsh
|
||||
// shell — and therefore the production client bundle, where react is
|
||||
// external — runs react 18. Pin every react import in tests to this
|
||||
// package's react 18 copy, or elements created inside ui components come out
|
||||
// as react-19 "transitional" elements that the react-18 renderer rejects.
|
||||
const reactDir = path.dirname(require.resolve("react/package.json"));
|
||||
const reactDomDir = path.dirname(require.resolve("react-dom/package.json"));
|
||||
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
react: reactDir,
|
||||
"react-dom": reactDomDir,
|
||||
},
|
||||
},
|
||||
test: {
|
||||
environment: "node",
|
||||
include: ["tests/**/*.test.ts", "tests/**/*.test.tsx"],
|
||||
|
||||
Generated
+366
@@ -83,6 +83,13 @@ importers:
|
||||
version: 0.20.26(@types/node@25.8.0)(jiti@2.7.0)(rolldown@1.2.4)(rollup@4.60.4)
|
||||
|
||||
packages/dsh-plugin-browserskill:
|
||||
dependencies:
|
||||
'@browser-skill/ui':
|
||||
specifier: workspace:*
|
||||
version: link:../ui
|
||||
'@remixicon/react':
|
||||
specifier: ^4.9.0
|
||||
version: 4.9.0(react@18.3.1)
|
||||
devDependencies:
|
||||
'@deepseek-ai/cordis':
|
||||
specifier: ^4.0.1
|
||||
@@ -117,6 +124,9 @@ importers:
|
||||
'@deepseek-ai/schemastery':
|
||||
specifier: ^3.18.1
|
||||
version: 3.18.1
|
||||
'@tailwindcss/cli':
|
||||
specifier: ^4.3.3
|
||||
version: 4.3.3
|
||||
'@testing-library/react':
|
||||
specifier: ^16.1.0
|
||||
version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
@@ -135,12 +145,21 @@ importers:
|
||||
lightningcss:
|
||||
specifier: ^1.30.0
|
||||
version: 1.32.0
|
||||
postcss:
|
||||
specifier: ^8.5.0
|
||||
version: 8.5.14
|
||||
postcss-prefix-selector:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1(postcss@8.5.14)
|
||||
react:
|
||||
specifier: ^18.2.0
|
||||
version: 18.3.1
|
||||
react-dom:
|
||||
specifier: ^18.2.0
|
||||
version: 18.3.1(react@18.3.1)
|
||||
tailwindcss:
|
||||
specifier: ^4.3.3
|
||||
version: 4.3.3
|
||||
tsdown:
|
||||
specifier: ^0.22.14
|
||||
version: 0.22.14(typescript@5.9.3)
|
||||
@@ -1186,6 +1205,88 @@ packages:
|
||||
'@oxc-project/types@0.144.0':
|
||||
resolution: {integrity: sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==}
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@parcel/watcher-darwin-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@parcel/watcher-darwin-x64@2.5.1':
|
||||
resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@parcel/watcher-freebsd-x64@2.5.1':
|
||||
resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@parcel/watcher-linux-arm-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@parcel/watcher-win32-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@parcel/watcher-win32-ia32@2.5.1':
|
||||
resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@parcel/watcher-win32-x64@2.5.1':
|
||||
resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@parcel/watcher@2.5.1':
|
||||
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
|
||||
'@pnpm/config.env-replace@1.1.0':
|
||||
resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==}
|
||||
engines: {node: '>=12.22.0'}
|
||||
@@ -1541,63 +1642,124 @@ packages:
|
||||
'@standard-schema/spec@1.1.0':
|
||||
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
||||
|
||||
'@tailwindcss/cli@4.3.3':
|
||||
resolution: {integrity: sha512-ZvS/n1ZHOBKcVlhkt8l5NNr1EDXk1NboYO5CYDOs6NUmvT9z6bzkwsosaJftY57T/3gWNzWMJzIXLodZC8ssdw==}
|
||||
hasBin: true
|
||||
|
||||
'@tailwindcss/node@4.3.0':
|
||||
resolution: {integrity: sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==}
|
||||
|
||||
'@tailwindcss/node@4.3.3':
|
||||
resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==}
|
||||
|
||||
'@tailwindcss/oxide-android-arm64@4.3.0':
|
||||
resolution: {integrity: sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@tailwindcss/oxide-android-arm64@4.3.3':
|
||||
resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@tailwindcss/oxide-darwin-arm64@4.3.0':
|
||||
resolution: {integrity: sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@tailwindcss/oxide-darwin-arm64@4.3.3':
|
||||
resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@tailwindcss/oxide-darwin-x64@4.3.0':
|
||||
resolution: {integrity: sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@tailwindcss/oxide-darwin-x64@4.3.3':
|
||||
resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@tailwindcss/oxide-freebsd-x64@4.3.0':
|
||||
resolution: {integrity: sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@tailwindcss/oxide-freebsd-x64@4.3.3':
|
||||
resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0':
|
||||
resolution: {integrity: sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
|
||||
resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-gnu@4.3.0':
|
||||
resolution: {integrity: sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
|
||||
resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.3.0':
|
||||
resolution: {integrity: sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.3.3':
|
||||
resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.3.0':
|
||||
resolution: {integrity: sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.3.3':
|
||||
resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.3.0':
|
||||
resolution: {integrity: sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.3.3':
|
||||
resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-wasm32-wasi@4.3.0':
|
||||
resolution: {integrity: sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
@@ -1610,22 +1772,50 @@ packages:
|
||||
- '@emnapi/wasi-threads'
|
||||
- tslib
|
||||
|
||||
'@tailwindcss/oxide-wasm32-wasi@4.3.3':
|
||||
resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
cpu: [wasm32]
|
||||
bundledDependencies:
|
||||
- '@napi-rs/wasm-runtime'
|
||||
- '@emnapi/core'
|
||||
- '@emnapi/runtime'
|
||||
- '@tybys/wasm-util'
|
||||
- '@emnapi/wasi-threads'
|
||||
- tslib
|
||||
|
||||
'@tailwindcss/oxide-win32-arm64-msvc@4.3.0':
|
||||
resolution: {integrity: sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
|
||||
resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@tailwindcss/oxide-win32-x64-msvc@4.3.0':
|
||||
resolution: {integrity: sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@tailwindcss/oxide-win32-x64-msvc@4.3.3':
|
||||
resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@tailwindcss/oxide@4.3.0':
|
||||
resolution: {integrity: sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==}
|
||||
engines: {node: '>= 20'}
|
||||
|
||||
'@tailwindcss/oxide@4.3.3':
|
||||
resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==}
|
||||
engines: {node: '>= 20'}
|
||||
|
||||
'@tailwindcss/vite@4.3.0':
|
||||
resolution: {integrity: sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==}
|
||||
peerDependencies:
|
||||
@@ -2269,6 +2459,11 @@ packages:
|
||||
destr@2.0.5:
|
||||
resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
|
||||
|
||||
detect-libc@1.0.3:
|
||||
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
|
||||
engines: {node: '>=0.10'}
|
||||
hasBin: true
|
||||
|
||||
detect-libc@2.1.2:
|
||||
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -2338,6 +2533,10 @@ packages:
|
||||
resolution: {integrity: sha512-wE4fDO8OjJhrPFH69HUQStq5oKvGRTNXEyW+k5C/pUQLASSsTu7obd2V3GvCDgPcY9AWjhJ4jz9Kh7iRvrxhJg==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
enhanced-resolve@5.24.5:
|
||||
resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
entities@4.5.0:
|
||||
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
||||
engines: {node: '>=0.12'}
|
||||
@@ -3119,6 +3318,10 @@ packages:
|
||||
mlly@1.8.2:
|
||||
resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==}
|
||||
|
||||
mri@1.2.0:
|
||||
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
@@ -3138,6 +3341,9 @@ packages:
|
||||
nanospinner@1.2.2:
|
||||
resolution: {integrity: sha512-Zt/AmG6qRU3e+WnzGGLuMCEAO/dAu45stNbHY223tUxldaDAeE+FxSPsd9Q+j+paejmm0ZbrNVs5Sraqy3dRxA==}
|
||||
|
||||
node-addon-api@7.1.1:
|
||||
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
||||
|
||||
node-fetch-native@1.6.7:
|
||||
resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==}
|
||||
|
||||
@@ -3259,6 +3465,11 @@ packages:
|
||||
pkg-types@2.3.1:
|
||||
resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==}
|
||||
|
||||
postcss-prefix-selector@2.1.1:
|
||||
resolution: {integrity: sha512-ZBgf427Et6+XnrnJ9VXtJEKCjJwTvn2wn/qMg+wvvlRhIeFIAxdbrlZZ0CSsWYMJfcyPLBh8ogj5O1kb/Mcx3g==}
|
||||
peerDependencies:
|
||||
postcss: ^8.0.0
|
||||
|
||||
postcss-resolve-nested-selector@0.1.6:
|
||||
resolution: {integrity: sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==}
|
||||
|
||||
@@ -3668,6 +3879,9 @@ packages:
|
||||
tailwindcss@4.3.0:
|
||||
resolution: {integrity: sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==}
|
||||
|
||||
tailwindcss@4.3.3:
|
||||
resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==}
|
||||
|
||||
tapable@2.3.3:
|
||||
resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -5086,6 +5300,66 @@ snapshots:
|
||||
|
||||
'@oxc-project/types@0.144.0': {}
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-darwin-arm64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-darwin-x64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-freebsd-x64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-arm-glibc@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-win32-arm64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-win32-ia32@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-win32-x64@2.5.1':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher@2.5.1':
|
||||
dependencies:
|
||||
detect-libc: 1.0.3
|
||||
is-glob: 4.0.3
|
||||
micromatch: 4.0.8
|
||||
node-addon-api: 7.1.1
|
||||
optionalDependencies:
|
||||
'@parcel/watcher-android-arm64': 2.5.1
|
||||
'@parcel/watcher-darwin-arm64': 2.5.1
|
||||
'@parcel/watcher-darwin-x64': 2.5.1
|
||||
'@parcel/watcher-freebsd-x64': 2.5.1
|
||||
'@parcel/watcher-linux-arm-glibc': 2.5.1
|
||||
'@parcel/watcher-linux-arm-musl': 2.5.1
|
||||
'@parcel/watcher-linux-arm64-glibc': 2.5.1
|
||||
'@parcel/watcher-linux-arm64-musl': 2.5.1
|
||||
'@parcel/watcher-linux-x64-glibc': 2.5.1
|
||||
'@parcel/watcher-linux-x64-musl': 2.5.1
|
||||
'@parcel/watcher-win32-arm64': 2.5.1
|
||||
'@parcel/watcher-win32-ia32': 2.5.1
|
||||
'@parcel/watcher-win32-x64': 2.5.1
|
||||
|
||||
'@pnpm/config.env-replace@1.1.0': {}
|
||||
|
||||
'@pnpm/network.ca-file@1.0.2':
|
||||
@@ -5102,6 +5376,10 @@ snapshots:
|
||||
dependencies:
|
||||
quansync: 1.0.0
|
||||
|
||||
'@remixicon/react@4.9.0(react@18.3.1)':
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
|
||||
'@remixicon/react@4.9.0(react@19.2.6)':
|
||||
dependencies:
|
||||
react: 19.2.6
|
||||
@@ -5316,6 +5594,16 @@ snapshots:
|
||||
|
||||
'@standard-schema/spec@1.1.0': {}
|
||||
|
||||
'@tailwindcss/cli@4.3.3':
|
||||
dependencies:
|
||||
'@parcel/watcher': 2.5.1
|
||||
'@tailwindcss/node': 4.3.3
|
||||
'@tailwindcss/oxide': 4.3.3
|
||||
enhanced-resolve: 5.24.5
|
||||
mri: 1.2.0
|
||||
picocolors: 1.1.1
|
||||
tailwindcss: 4.3.3
|
||||
|
||||
'@tailwindcss/node@4.3.0':
|
||||
dependencies:
|
||||
'@jridgewell/remapping': 2.3.5
|
||||
@@ -5326,42 +5614,88 @@ snapshots:
|
||||
source-map-js: 1.2.1
|
||||
tailwindcss: 4.3.0
|
||||
|
||||
'@tailwindcss/node@4.3.3':
|
||||
dependencies:
|
||||
'@jridgewell/remapping': 2.3.5
|
||||
enhanced-resolve: 5.24.5
|
||||
jiti: 2.7.0
|
||||
lightningcss: 1.32.0
|
||||
magic-string: 0.30.21
|
||||
source-map-js: 1.2.1
|
||||
tailwindcss: 4.3.3
|
||||
|
||||
'@tailwindcss/oxide-android-arm64@4.3.0':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-android-arm64@4.3.3':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-darwin-arm64@4.3.0':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-darwin-arm64@4.3.3':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-darwin-x64@4.3.0':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-darwin-x64@4.3.3':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-freebsd-x64@4.3.0':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-freebsd-x64@4.3.3':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-gnu@4.3.0':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.3.0':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.3.3':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.3.0':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.3.3':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.3.0':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.3.3':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-wasm32-wasi@4.3.0':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-wasm32-wasi@4.3.3':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-win32-arm64-msvc@4.3.0':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-win32-x64-msvc@4.3.0':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-win32-x64-msvc@4.3.3':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide@4.3.0':
|
||||
optionalDependencies:
|
||||
'@tailwindcss/oxide-android-arm64': 4.3.0
|
||||
@@ -5377,6 +5711,21 @@ snapshots:
|
||||
'@tailwindcss/oxide-win32-arm64-msvc': 4.3.0
|
||||
'@tailwindcss/oxide-win32-x64-msvc': 4.3.0
|
||||
|
||||
'@tailwindcss/oxide@4.3.3':
|
||||
optionalDependencies:
|
||||
'@tailwindcss/oxide-android-arm64': 4.3.3
|
||||
'@tailwindcss/oxide-darwin-arm64': 4.3.3
|
||||
'@tailwindcss/oxide-darwin-x64': 4.3.3
|
||||
'@tailwindcss/oxide-freebsd-x64': 4.3.3
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3
|
||||
'@tailwindcss/oxide-linux-arm64-gnu': 4.3.3
|
||||
'@tailwindcss/oxide-linux-arm64-musl': 4.3.3
|
||||
'@tailwindcss/oxide-linux-x64-gnu': 4.3.3
|
||||
'@tailwindcss/oxide-linux-x64-musl': 4.3.3
|
||||
'@tailwindcss/oxide-wasm32-wasi': 4.3.3
|
||||
'@tailwindcss/oxide-win32-arm64-msvc': 4.3.3
|
||||
'@tailwindcss/oxide-win32-x64-msvc': 4.3.3
|
||||
|
||||
'@tailwindcss/vite@4.3.0(vite@8.0.13(@types/node@25.8.0)(esbuild@0.27.7)(jiti@2.7.0))':
|
||||
dependencies:
|
||||
'@tailwindcss/node': 4.3.0
|
||||
@@ -5958,6 +6307,8 @@ snapshots:
|
||||
|
||||
destr@2.0.5: {}
|
||||
|
||||
detect-libc@1.0.3: {}
|
||||
|
||||
detect-libc@2.1.2: {}
|
||||
|
||||
devlop@1.1.0:
|
||||
@@ -6017,6 +6368,11 @@ snapshots:
|
||||
graceful-fs: 4.2.11
|
||||
tapable: 2.3.3
|
||||
|
||||
enhanced-resolve@5.24.5:
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
tapable: 2.3.3
|
||||
|
||||
entities@4.5.0: {}
|
||||
|
||||
entities@7.0.1: {}
|
||||
@@ -6936,6 +7292,8 @@ snapshots:
|
||||
pkg-types: 1.3.1
|
||||
ufo: 1.6.4
|
||||
|
||||
mri@1.2.0: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
multimatch@6.0.0:
|
||||
@@ -6953,6 +7311,8 @@ snapshots:
|
||||
dependencies:
|
||||
picocolors: 1.1.1
|
||||
|
||||
node-addon-api@7.1.1: {}
|
||||
|
||||
node-fetch-native@1.6.7: {}
|
||||
|
||||
node-forge@1.4.0: {}
|
||||
@@ -7095,6 +7455,10 @@ snapshots:
|
||||
exsolve: 1.0.8
|
||||
pathe: 2.0.3
|
||||
|
||||
postcss-prefix-selector@2.1.1(postcss@8.5.14):
|
||||
dependencies:
|
||||
postcss: 8.5.14
|
||||
|
||||
postcss-resolve-nested-selector@0.1.6: {}
|
||||
|
||||
postcss-safe-parser@7.0.1(postcss@8.5.14):
|
||||
@@ -7574,6 +7938,8 @@ snapshots:
|
||||
|
||||
tailwindcss@4.3.0: {}
|
||||
|
||||
tailwindcss@4.3.3: {}
|
||||
|
||||
tapable@2.3.3: {}
|
||||
|
||||
thread-stream@3.1.0:
|
||||
|
||||
Reference in New Issue
Block a user