@flesler/cursor-canvas-web 1.0.2 → 1.1.1
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/README.md +9 -8
- package/dist/cursor-canvas.cjs +1 -1
- package/dist/cursor-canvas.js +702 -746
- package/dist/host-tokens-Cjzmp0z_.cjs +1 -0
- package/dist/host-tokens-Dh2BFFjv.js +412 -0
- package/dist/runtime/index.d.ts +5 -7
- package/dist/runtime.cjs +5 -1
- package/dist/runtime.js +109 -14
- package/package.json +22 -13
- package/src/vendor/canvas/SKILL.md +113 -0
- package/src/vendor/canvas-sdk/callout-tone-icons.d.ts +10 -0
- package/src/vendor/canvas-sdk/canvas-tokens.d.ts +259 -0
- package/src/vendor/canvas-sdk/chart-primitives.d.ts +272 -0
- package/src/vendor/canvas-sdk/collapsible-section.d.ts +66 -0
- package/src/vendor/canvas-sdk/dag-layout.d.ts +101 -0
- package/src/vendor/canvas-sdk/diff-view.d.ts +129 -0
- package/src/vendor/canvas-sdk/form-primitives.d.ts +194 -0
- package/src/vendor/canvas-sdk/hooks.d.ts +173 -0
- package/src/vendor/canvas-sdk/index.d.ts +65 -0
- package/src/vendor/canvas-sdk/internal/canvas-action-dispatch.d.ts +17 -0
- package/src/vendor/canvas-sdk/manifest.json +5 -0
- package/src/vendor/canvas-sdk/swatch.d.ts +39 -0
- package/src/vendor/canvas-sdk/theme.d.ts +107 -0
- package/src/vendor/canvas-sdk/todo-list.d.ts +48 -0
- package/src/vendor/canvas-sdk/ui-primitives.d.ts +569 -0
- package/src/vendor/canvas-sdk/usage-bar.d.ts +55 -0
- package/dist/shim/charts.d.ts +0 -66
- package/dist/shim/cursor-canvas.d.ts +0 -278
- package/dist/shim/dag.d.ts +0 -55
- package/dist/shim/diff.d.ts +0 -23
- package/dist/shim/theme.d.ts +0 -323
- package/dist/shim/todo.d.ts +0 -22
- package/dist/shim/use-tokens.d.ts +0 -6
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flesler/cursor-canvas-web",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.1",
|
|
5
5
|
"repository": "github:flesler/cursor-canvas-web",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"description": "Deploy your Cursor canvases to the web.",
|
|
@@ -19,17 +19,21 @@
|
|
|
19
19
|
},
|
|
20
20
|
"sideEffects": false,
|
|
21
21
|
"files": [
|
|
22
|
-
"dist"
|
|
22
|
+
"dist",
|
|
23
|
+
"src/vendor"
|
|
23
24
|
],
|
|
24
25
|
"main": "./dist/cursor-canvas.cjs",
|
|
25
26
|
"module": "./dist/cursor-canvas.js",
|
|
26
|
-
"types": "./
|
|
27
|
+
"types": "./src/vendor/canvas-sdk/index.d.ts",
|
|
27
28
|
"exports": {
|
|
28
29
|
".": {
|
|
29
|
-
"types": "./
|
|
30
|
+
"types": "./src/vendor/canvas-sdk/index.d.ts",
|
|
30
31
|
"import": "./dist/cursor-canvas.js",
|
|
31
32
|
"require": "./dist/cursor-canvas.cjs"
|
|
32
33
|
},
|
|
34
|
+
"./canvas-sdk": {
|
|
35
|
+
"types": "./src/vendor/canvas-sdk/index.d.ts"
|
|
36
|
+
},
|
|
33
37
|
"./runtime": {
|
|
34
38
|
"types": "./dist/runtime/index.d.ts",
|
|
35
39
|
"import": "./dist/runtime.js",
|
|
@@ -48,16 +52,20 @@
|
|
|
48
52
|
"test": "vitest run",
|
|
49
53
|
"test:watch": "vitest",
|
|
50
54
|
"sync:sdk": "bash scripts/sync-cursor-sdk-snapshot.sh",
|
|
51
|
-
"check:sdk-exports": "
|
|
52
|
-
"test:contract": "pnpm run
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
+
"check:sdk-exports": "tsx scripts/diff-sdk-exports.ts --strict",
|
|
56
|
+
"test:contract": "pnpm run check:sdk-exports && tsx scripts/generate-contract-consumer.ts && tsc --noEmit && pnpm run build:lib",
|
|
57
|
+
"test:contract:fast": "pnpm run check:sdk-exports && tsx scripts/generate-contract-consumer.ts && tsc --noEmit",
|
|
58
|
+
"check:sdk-live": "tsx scripts/diff-sdk-exports.ts --strict \"${HOME}/.cursor/skills-cursor/canvas/sdk/index.d.ts\"",
|
|
59
|
+
"test:contract:strict": "pnpm run test:contract",
|
|
55
60
|
"test:contract:ci": "pnpm run test:contract",
|
|
56
61
|
"sync:demo": "bash scripts/sync-demo-canvas.sh",
|
|
57
62
|
"demo:screenshot": "bash scripts/readme-screenshot.sh",
|
|
63
|
+
"test:demo-screenshots": "bash scripts/test-demo-screenshots.sh",
|
|
64
|
+
"test:demo-screenshots:update": "bash scripts/test-demo-screenshots.sh --update",
|
|
65
|
+
"test:render-compat": "bash scripts/test-render-compat.sh",
|
|
58
66
|
"ci:local": "pnpm typecheck && pnpm lint && pnpm test && pnpm test:contract:ci",
|
|
59
67
|
"prepare": "[ \"$CI\" != \"true\" ] && [ -d node_modules/husky ] && husky || true",
|
|
60
|
-
"prepublishOnly": "pnpm typecheck && pnpm test && pnpm build:lib"
|
|
68
|
+
"prepublishOnly": "pnpm typecheck && pnpm test && pnpm run check:sdk-exports && pnpm build:lib"
|
|
61
69
|
},
|
|
62
70
|
"peerDependencies": {
|
|
63
71
|
"@mantine/charts": "^8.3.0",
|
|
@@ -71,9 +79,6 @@
|
|
|
71
79
|
"@mantine/charts": "^8.3.18",
|
|
72
80
|
"@mantine/core": "^8.3.18",
|
|
73
81
|
"@mantine/hooks": "^8.3.18",
|
|
74
|
-
"react": "^18.3.1",
|
|
75
|
-
"react-dom": "^18.3.1",
|
|
76
|
-
"recharts": "^3.10.1",
|
|
77
82
|
"@testing-library/jest-dom": "^6.6.3",
|
|
78
83
|
"@testing-library/react": "^16.2.0",
|
|
79
84
|
"@types/node": "^22.13.1",
|
|
@@ -87,10 +92,14 @@
|
|
|
87
92
|
"husky": "^9.1.7",
|
|
88
93
|
"jsdom": "^26.0.0",
|
|
89
94
|
"prettier": "^3.5.1",
|
|
95
|
+
"react": "^18.3.1",
|
|
96
|
+
"react-dom": "^18.3.1",
|
|
97
|
+
"recharts": "^3.10.1",
|
|
98
|
+
"tsx": "^4.21.0",
|
|
90
99
|
"typescript": "^5.7.3",
|
|
91
100
|
"typescript-eslint": "^8.24.0",
|
|
92
101
|
"vite": "^6.1.0",
|
|
93
102
|
"vite-plugin-dts": "^5.0.2",
|
|
94
|
-
"vitest": "^
|
|
103
|
+
"vitest": "^4.1.11"
|
|
95
104
|
}
|
|
96
105
|
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: canvas
|
|
3
|
+
description: >-
|
|
4
|
+
A Cursor Canvas is a live React app that the user can open beside the chat.
|
|
5
|
+
You MUST use a canvas when the agent produces a standalone analytical artifact
|
|
6
|
+
— quantitative analyses, billing investigations, security audits, architecture
|
|
7
|
+
reviews, data-heavy content, timelines, charts, tables, interactive
|
|
8
|
+
explorations, repeatable tools, or any response that benefits from visual
|
|
9
|
+
layout. Especially prefer a canvas when presenting results from MCP tools
|
|
10
|
+
(Datadog, Databricks, Linear, Sentry, Slack, etc.) where the data is the
|
|
11
|
+
deliverable — render it in a rich canvas rather than dumping it into a
|
|
12
|
+
markdown table or code block. If you catch yourself about to write a markdown
|
|
13
|
+
table, stop and use a canvas instead. You MUST also read this skill whenever
|
|
14
|
+
you create, edit, or debug any .canvas.tsx file.
|
|
15
|
+
metadata:
|
|
16
|
+
surfaces:
|
|
17
|
+
- ide
|
|
18
|
+
- cloud
|
|
19
|
+
environments:
|
|
20
|
+
- local
|
|
21
|
+
- cloud
|
|
22
|
+
---
|
|
23
|
+
A canvas is a single `.canvas.tsx` file the IDE compiles so the user can open it beside the chat. Follow the workflow below in order.
|
|
24
|
+
|
|
25
|
+
## Workflow
|
|
26
|
+
|
|
27
|
+
### 1. Decide whether to use a canvas
|
|
28
|
+
|
|
29
|
+
The trigger is **user intent**, not response shape. Ask: would the user benefit from viewing this output as its **own durable standalone artifact outside the transcript**, separate from the chat? If the output is a means to an end (a drafted message, a code fix, a dashboard in another tool), skip the canvas.
|
|
30
|
+
|
|
31
|
+
**Use a canvas when the agent produces new standalone analytical output:**
|
|
32
|
+
- Quantitative analyses and metrics breakdowns (e.g. "send 500 requests and tell me how many fail")
|
|
33
|
+
- Billing or account investigations that surface structured findings from database queries
|
|
34
|
+
- Security audits or architecture reviews with categorized findings
|
|
35
|
+
- Cross-system data analyses and overlap reports
|
|
36
|
+
- Structured data from MCP tools (Databricks, Datadog, etc.) where a durable standalone artifact is the deliverable
|
|
37
|
+
- Financial analyses, margin decompositions, usage trend reports
|
|
38
|
+
- Large tables the user wants to revisit or refine
|
|
39
|
+
|
|
40
|
+
**Do NOT use a canvas when:**
|
|
41
|
+
- The user asks for work in a **specific tool** — "create a Datadog dashboard" means give them a Datadog dashboard, not a canvas
|
|
42
|
+
- The user has a **specific deliverable** — "draft a support response", "fix this code", "make this PR"
|
|
43
|
+
- The user is **working within an existing artifact** — improving an HTML dashboard, editing an existing file
|
|
44
|
+
- The user is doing **targeted debugging** or active development, even if structured findings emerge along the way
|
|
45
|
+
- An immutable visual output belongs inside the transcript rather than in a durable standalone artifact
|
|
46
|
+
- Short factual answers, one-off file edits, or quick clarifying questions
|
|
47
|
+
- MCP tools are queried as an **intermediate step** for a different deliverable (e.g. querying Stripe to draft a support reply)
|
|
48
|
+
|
|
49
|
+
### 2. Write the canvas
|
|
50
|
+
|
|
51
|
+
**Location.** Canvases live at `/Users/<user>/.cursor/projects/<workspace>/canvases/<name>.canvas.tsx`. The IDE only detects canvases written directly inside that exact directory — subfolders, alternate extensions, and other locations are not picked up. For a new canvas, always use the write file tool to create the `.canvas.tsx` file at that exact path; do not stop after telling the user the path or showing code in chat. Treat that managed `canvases/` directory as pre-provisioned by Cursor itself: write the canvas file directly there and do **not** spend turns creating the directory with `mkdir` or checking whether it exists before writing. Listing its contents for other purposes (e.g. checking for existing canvases) is fine. If you can't determine the workspace directory from absolute paths already in your environment (terminals, transcripts, recently-viewed files), list `~/.cursor/projects/` rather than guessing. Use a descriptive kebab-case filename ending in `.canvas.tsx`; preserve acronym capitalization and lowercase the rest.
|
|
52
|
+
|
|
53
|
+
**File rules:**
|
|
54
|
+
- Exactly one `.canvas.tsx` file per canvas. Never create helper files, style files, or supporting modules.
|
|
55
|
+
- Import **only** from `cursor/canvas`. No relative imports, no npm packages, no Node built-ins.
|
|
56
|
+
- Default-export the top-level component.
|
|
57
|
+
- Embed all data inline. **No `fetch()`, no network calls.**
|
|
58
|
+
|
|
59
|
+
**Never render empty states.** A canvas exists to show real content. If a section, chart, table, or component has no data to display, **omit it** — do not render it with placeholder text ("Add header here", "TODO", "Example"), a "No data" message, an empty array, zeroed rows, or an empty chart frame. If the entire canvas would be empty because you don't have the underlying data, do not produce a canvas — tell the user what's missing and ask for it instead.
|
|
60
|
+
|
|
61
|
+
**Label every plot.** Charts and tables must be self-describing — a reader looking at the canvas alone should know exactly what they're seeing. For every plot include:
|
|
62
|
+
- A title naming the **specific metric** (not "Metrics" — "API error rate by service").
|
|
63
|
+
- **Axis labels with units** on both axes (e.g. "Date", "Latency (ms)").
|
|
64
|
+
- A **legend** when more than one series is shown, with the exact series names from the source data.
|
|
65
|
+
- The **source and time range** in a small caption (e.g. "Source: Datadog · last 7 days"). If a value is a transformation (mean, p95, normalized, smoothed), say so in the label.
|
|
66
|
+
|
|
67
|
+
**Component discovery:** prefer built-in `cursor/canvas` components over hand-rolled markup. The full public surface (components, hooks, prop types, tokens) is declared in `~/.cursor/skills-cursor/canvas/sdk/index.d.ts` and its sibling `.d.ts` files — read them when you need exact exports, prop shapes, or hook signatures rather than guessing. Referencing an export that does not exist is the most common runtime error.
|
|
68
|
+
|
|
69
|
+
Apply the Design guidance below as you write, and complete its Pre-delivery self-check before returning the canvas.
|
|
70
|
+
|
|
71
|
+
## Design guidance
|
|
72
|
+
|
|
73
|
+
Be creative. The SDK gives you expressive building blocks — use them in whatever combination best serves the content. But avoid slop: no gradients, no emojis, no box-shadows, no rainbow coloring. Cursor canvases are flat, minimal, and purposeful.
|
|
74
|
+
|
|
75
|
+
### Visual hierarchy
|
|
76
|
+
|
|
77
|
+
Not everything deserves equal treatment. Primary content gets more space, larger headings, and accent color. Supporting content stays compact. Squint test: blur your eyes — can you tell what matters?
|
|
78
|
+
|
|
79
|
+
**Color.** All colors from `useHostTheme()` tokens — read its JSDoc in the SDK declarations for the return shape and usage pattern. No hardcoded hex. Use accent color deliberately, not on everything.
|
|
80
|
+
|
|
81
|
+
### Slop patterns — forbidden
|
|
82
|
+
|
|
83
|
+
These specific patterns produce low-quality output. If 2+ are present, redesign.
|
|
84
|
+
|
|
85
|
+
- **Gradients** — no `linear-gradient`, `radial-gradient`, `background-clip: text`.
|
|
86
|
+
- **Emojis** — no emoji as icons, status indicators, bullets, or section markers.
|
|
87
|
+
- **Box shadows** — no `box-shadow`. Flat surfaces only.
|
|
88
|
+
- **Wall of identical cards** — every section wrapped in the same card style with no variation. Mix open sections with cards.
|
|
89
|
+
- **Rainbow coloring** — a different color on every element. Most elements are neutral; color is used sparingly with purpose.
|
|
90
|
+
- **Giant text** — font sizes above H1 (24px), or bold text stuffed in CardHeader.
|
|
91
|
+
- **Decorative borders** — colored borders on every element. Borders are structural (subtle stroke tokens), not decorative.
|
|
92
|
+
|
|
93
|
+
### Pre-delivery self-check
|
|
94
|
+
|
|
95
|
+
Before returning canvas code, verify:
|
|
96
|
+
1. Does the layout have visual hierarchy? One thing should stand out.
|
|
97
|
+
2. Is there variety in the composition? Not just a single column of uniform blocks.
|
|
98
|
+
3. Slop check: scan for the forbidden patterns above.
|
|
99
|
+
|
|
100
|
+
## Introducing the canvas
|
|
101
|
+
|
|
102
|
+
Whenever you mention a canvas to the user — one you created, updated, or want them to open — **always** include a markdown link to that `.canvas.tsx` file using its full absolute path (for example, `[Billing Review](/Users/<user>/.cursor/projects/<workspace>/canvases/billing-review.canvas.tsx)`). Use a short descriptive label as the link text; do not refer to a canvas by name or path alone without the link.
|
|
103
|
+
|
|
104
|
+
When you create a canvas, add a short note in your chat response telling the user they can open it beside the chat, with that link:
|
|
105
|
+
|
|
106
|
+
- **First canvas** — if no other `.canvas.tsx` files exist in the workspace's `canvases/` directory, include one sentence explaining what a canvas is.
|
|
107
|
+
- **Unsolicited canvas** — if the user didn't ask for a canvas, include one sentence explaining why you chose it over plain text.
|
|
108
|
+
|
|
109
|
+
Both can apply at once; one or two sentences total is enough. Skip the intro for subsequent canvases unless you are mentioning that canvas again (still link it).
|
|
110
|
+
|
|
111
|
+
## Troubleshooting
|
|
112
|
+
|
|
113
|
+
If a canvas appears blank or missing, the most common cause is that it was not written under `/Users/<user>/.cursor/projects/<workspace>/canvases/` exactly — re-save it to that path. Do not debug this by trying to create the managed directory manually; focus on correcting the file path instead. Users can click the canvas file path in the response to open it, just like any other file path in Cursor. Every canvas edit returns a `Canvas TypeScript check` line in the tool result reporting the file's current type errors (or "no errors") — treat that as the authoritative diagnostics signal.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { JSX } from "react";
|
|
2
|
+
type CalloutToneIconGlyph = "info" | "warning" | "circles-check" | "exclamation-circle";
|
|
3
|
+
type CalloutToneForIcon = "info" | "success" | "warning" | "danger" | "neutral";
|
|
4
|
+
/** Maps `Callout` tone to the same cursor icons used by `@anysphere/ui` toasts. */
|
|
5
|
+
export declare const calloutToneIconGlyph: Record<Exclude<CalloutToneForIcon, "neutral">, CalloutToneIconGlyph>;
|
|
6
|
+
export declare function CalloutToneIcon({ tone, color, }: {
|
|
7
|
+
tone: CalloutToneForIcon;
|
|
8
|
+
color: string;
|
|
9
|
+
}): JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design tokens for `cursor/canvas` (standalone; no UI framework dependency).
|
|
3
|
+
*
|
|
4
|
+
* Color values are pinned copies of the `packages/ui` cursor-core themes
|
|
5
|
+
* (`src/tokens/themes/cursor-core/{dark,light}.ts`) resolved through
|
|
6
|
+
* `CURSOR_SEMANTIC_RULES` (`src/tokens/semantic-schema.ts`). Alpha-hex entries
|
|
7
|
+
* are `base` at the rule's `mixTransparent` percent so they composite
|
|
8
|
+
* correctly over any surface. When the ui tokens change, re-derive these —
|
|
9
|
+
* they do not update automatically.
|
|
10
|
+
*
|
|
11
|
+
* Mapping (dark base #F0F0F0, light base #141414):
|
|
12
|
+
* - foreground* → text-primary/secondary/tertiary/quaternary (100/74/60/36%)
|
|
13
|
+
* - editor/chrome/sidebar/elevated → the core surface hexes (elevated = editor)
|
|
14
|
+
* - fill* → bg-primary/secondary/tertiary/quaternary (20/14/8/6%)
|
|
15
|
+
* - stroke* → stroke-primary/secondary/tertiary (20/12/8%)
|
|
16
|
+
* - strokeFocused → core `focus` at full opacity (NOT `--cursor-stroke-focused`,
|
|
17
|
+
* which is 15% and layered with other cues in the app; in a canvas this is
|
|
18
|
+
* the sole focus affordance)
|
|
19
|
+
* - accent/button* → bg-accent / action-label / bg-accent-hover (mixTwo base 10%)
|
|
20
|
+
* - link → text-link (= core blue)
|
|
21
|
+
* - diff*Line → the core diff line backgrounds; diffStrip* keep the
|
|
22
|
+
* canvas-specific alphas on the core green/red hues
|
|
23
|
+
*/
|
|
24
|
+
export declare const canvasPaletteDark: CanvasPalette;
|
|
25
|
+
export declare const canvasPaletteLight: CanvasPalette;
|
|
26
|
+
export declare const canvasPaletteGrokDark: CanvasPalette;
|
|
27
|
+
export declare const canvasPaletteGrokLight: CanvasPalette;
|
|
28
|
+
/**
|
|
29
|
+
* Parse a CSS hex color (`#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`) into 0–255
|
|
30
|
+
* RGB components. Returns `undefined` for anything we can't confidently parse
|
|
31
|
+
* (named colors, `rgb()`, etc.) so callers can fall back to the base palette.
|
|
32
|
+
*
|
|
33
|
+
* Hand-rolled rather than reusing a shared color util because this package is
|
|
34
|
+
* deliberately dependency-light (it is bundled into every canvas), and the host
|
|
35
|
+
* only ever sends hex (VS Code's `Color.Format.CSS.formatHex`).
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseHexColor(value: string): {
|
|
38
|
+
r: number;
|
|
39
|
+
g: number;
|
|
40
|
+
b: number;
|
|
41
|
+
} | undefined;
|
|
42
|
+
/** Visual brand for canvas token resolve. Unknown values become `"cursor"`. */
|
|
43
|
+
export type CanvasHostThemeBrand = "cursor" | "grok";
|
|
44
|
+
export interface CanvasHostThemeOverrides {
|
|
45
|
+
readonly brand?: CanvasHostThemeBrand;
|
|
46
|
+
readonly primary?: string;
|
|
47
|
+
readonly editorBackground?: string;
|
|
48
|
+
readonly editorForeground?: string;
|
|
49
|
+
}
|
|
50
|
+
/** Unknown / omitted brand keeps the Cursor tables. */
|
|
51
|
+
export declare function parseCanvasHostThemeBrand(value: unknown): CanvasHostThemeBrand;
|
|
52
|
+
/**
|
|
53
|
+
* Overlay workbench editor surface colors onto the base palette so the canvas
|
|
54
|
+
* body and primitives using `bg.editor` match the active VS Code theme
|
|
55
|
+
* instead of the fixed Cursor light/dark editor hex.
|
|
56
|
+
*/
|
|
57
|
+
export declare function applyWorkbenchSurfaces(palette: CanvasPalette, surfaces: Pick<CanvasHostThemeOverrides, "editorBackground" | "editorForeground">): CanvasPalette;
|
|
58
|
+
/**
|
|
59
|
+
* Overlay a host-provided primary/accent color (e.g. the active VS Code
|
|
60
|
+
* theme's accent) onto a base palette. Only the accent-adjacent entries
|
|
61
|
+
* change — accent, button background/hover, focus stroke, and links — plus a
|
|
62
|
+
* luminance-picked readable on-accent foreground. Every other entry (surfaces,
|
|
63
|
+
* text, fills, diff) keeps its base light/dark value, so any theme is
|
|
64
|
+
* supported without enumerating its full token set.
|
|
65
|
+
*
|
|
66
|
+
* Returns the base palette unchanged when `primary` isn't a hex color we can
|
|
67
|
+
* parse, keeping behaviour identical to hosts that only report a theme `kind`.
|
|
68
|
+
*/
|
|
69
|
+
export declare function applyPrimaryColor(palette: CanvasPalette, primary: string): CanvasPalette;
|
|
70
|
+
export interface CanvasPalette {
|
|
71
|
+
readonly foreground: string;
|
|
72
|
+
readonly foregroundSecondary: string;
|
|
73
|
+
readonly foregroundTertiary: string;
|
|
74
|
+
readonly foregroundQuaternary: string;
|
|
75
|
+
readonly editor: string;
|
|
76
|
+
readonly chrome: string;
|
|
77
|
+
readonly sidebar: string;
|
|
78
|
+
readonly elevated: string;
|
|
79
|
+
readonly fillPrimary: string;
|
|
80
|
+
readonly fillSecondary: string;
|
|
81
|
+
readonly fillTertiary: string;
|
|
82
|
+
readonly fillQuaternary: string;
|
|
83
|
+
readonly strokePrimary: string;
|
|
84
|
+
readonly strokeSecondary: string;
|
|
85
|
+
readonly strokeTertiary: string;
|
|
86
|
+
readonly strokeFocused: string;
|
|
87
|
+
readonly accent: string;
|
|
88
|
+
readonly buttonBackground: string;
|
|
89
|
+
readonly buttonForeground: string;
|
|
90
|
+
readonly buttonHoverBackground: string;
|
|
91
|
+
readonly link: string;
|
|
92
|
+
readonly diffInsertedLine: string;
|
|
93
|
+
readonly diffRemovedLine: string;
|
|
94
|
+
readonly diffStripAdded: string;
|
|
95
|
+
readonly diffStripRemoved: string;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Chart color palette — distilled from portal-website analytics charts.
|
|
99
|
+
* 88% opacity (E0) softens vibrancy without dulling; palette maximizes
|
|
100
|
+
* hue + luminosity spread for distinguishable multi-series charts.
|
|
101
|
+
*/
|
|
102
|
+
export declare const chartPalette: {
|
|
103
|
+
readonly green: "#1F8A65E8";
|
|
104
|
+
readonly darkGreen: "#0D855AE0";
|
|
105
|
+
readonly lightGreen: "#52B896E0";
|
|
106
|
+
readonly mintGreen: "#7DCAB0E0";
|
|
107
|
+
readonly blue: "#2E79B5E0";
|
|
108
|
+
readonly lightBlue: "#70B0D8E0";
|
|
109
|
+
readonly indigo: "#5A6CC0F0";
|
|
110
|
+
readonly lightIndigo: "#9AAADCE0";
|
|
111
|
+
readonly purple: "#7B64B8F0";
|
|
112
|
+
readonly lightPurple: "#AA98D8E0";
|
|
113
|
+
readonly warmPink: "#C85898E0";
|
|
114
|
+
readonly lightPink: "#E8A0C4E0";
|
|
115
|
+
readonly brightOrange: "#F0A040E0";
|
|
116
|
+
readonly deepOrange: "#C06028E0";
|
|
117
|
+
readonly goldenYellow: "#E8C030E0";
|
|
118
|
+
readonly darkAmber: "#C04848E0";
|
|
119
|
+
readonly warmPeach: "#F0A088E0";
|
|
120
|
+
readonly vibrantTeal: "#2A9A8AE0";
|
|
121
|
+
readonly muted: "#8888A8E0";
|
|
122
|
+
readonly neutralLine: "#888899D0";
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Shared category palette for canvas primitives that show categorical tints
|
|
126
|
+
* (`Swatch`, `UsageBar` segments, etc.). Hexes mirror the cursor core hues
|
|
127
|
+
* from `packages/ui/src/tokens/themes/cursor-core/{dark,light}.ts` (via the
|
|
128
|
+
* `text-{hue}-primary` semantic tokens); `gray` reuses the palette's
|
|
129
|
+
* `foregroundTertiary` (= `text-tertiary`, `mixTransparent base 60%`).
|
|
130
|
+
* `orange` is mixed 70/30 with red to keep
|
|
131
|
+
* Conversation distinct from Skills' yellow in light mode while staying warm.
|
|
132
|
+
*
|
|
133
|
+
* The insertion order here is the canonical category order — primitives
|
|
134
|
+
* that auto-assign colors (e.g. `UsageBar` segments without an explicit
|
|
135
|
+
* `color`) cycle through these keys in order.
|
|
136
|
+
*/
|
|
137
|
+
export type Color = "gray" | "purple" | "green" | "yellow" | "cyan" | "pink" | "blue" | "orange" | "red";
|
|
138
|
+
export type CategoryPalette = Readonly<Record<Color, string>>;
|
|
139
|
+
export declare const categoryPaletteDark: CategoryPalette;
|
|
140
|
+
export declare const categoryPaletteLight: CategoryPalette;
|
|
141
|
+
export declare const categoryPaletteGrokDark: CategoryPalette;
|
|
142
|
+
export declare const categoryPaletteGrokLight: CategoryPalette;
|
|
143
|
+
/** Legacy `colorPalette` name kept for back-compat; per-theme tables are `categoryPalette{Dark,Light}`. React consumers should read `useHostTheme().category` so the color flips with the host theme. */
|
|
144
|
+
export declare const colorPalette: CategoryPalette;
|
|
145
|
+
/**
|
|
146
|
+
* Auto-color rotation for `UsageBar` segments without an explicit `color`.
|
|
147
|
+
* Decoupled from `colorPalette`'s declaration order so the palette can grow
|
|
148
|
+
* or be reordered without changing how unspecified segments cycle.
|
|
149
|
+
*
|
|
150
|
+
* Matches the original `packages/ui` `ContextUsageTray` order so the same
|
|
151
|
+
* segment index lands on the same hue as the source.
|
|
152
|
+
*/
|
|
153
|
+
export declare const usageColorSequence: readonly Color[];
|
|
154
|
+
/**
|
|
155
|
+
* Ordered array for automatic series coloring — alternates dark/light across
|
|
156
|
+
* distinct hue families for maximum perceptual separation.
|
|
157
|
+
*/
|
|
158
|
+
export declare const chartColorSequence: readonly string[];
|
|
159
|
+
/**
|
|
160
|
+
* Sand data-categorical hues. Same key set as {@link chartPalette} so
|
|
161
|
+
* tone maps (`success` / `danger` / …) stay typed; the lead series colors
|
|
162
|
+
* are Sand blue / orange / purple.
|
|
163
|
+
*/
|
|
164
|
+
export declare const chartPaletteGrok: {
|
|
165
|
+
readonly green: "#00C972E8";
|
|
166
|
+
readonly darkGreen: "#009957E0";
|
|
167
|
+
readonly lightGreen: "#38D591E0";
|
|
168
|
+
readonly mintGreen: "#78E2B4E0";
|
|
169
|
+
readonly blue: "#1084FEE0";
|
|
170
|
+
readonly lightBlue: "#459FFEE0";
|
|
171
|
+
readonly indigo: "#0C64C1F0";
|
|
172
|
+
readonly lightIndigo: "#80BEFEE0";
|
|
173
|
+
readonly purple: "#9159FEF0";
|
|
174
|
+
readonly lightPurple: "#A97EFEE0";
|
|
175
|
+
readonly warmPink: "#FF309BE0";
|
|
176
|
+
readonly lightPink: "#FF5EB1E0";
|
|
177
|
+
readonly brightOrange: "#FF6700E0";
|
|
178
|
+
readonly deepOrange: "#C24E00E0";
|
|
179
|
+
readonly goldenYellow: "#FF9800E0";
|
|
180
|
+
readonly darkAmber: "#FF263CE0";
|
|
181
|
+
readonly warmPeach: "#FF8838E0";
|
|
182
|
+
readonly vibrantTeal: "#00BCA6E0";
|
|
183
|
+
readonly muted: "#777777E0";
|
|
184
|
+
readonly neutralLine: "#777777D0";
|
|
185
|
+
};
|
|
186
|
+
export declare const chartColorSequenceGrok: readonly string[];
|
|
187
|
+
export type ChartPalette = {
|
|
188
|
+
readonly [K in keyof typeof chartPalette]: string;
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* Semantic colors for components (spacing and radius live in `theme.ts`).
|
|
192
|
+
* There is no `colors` bag — `theme.colors.bg.primary` is not a path.
|
|
193
|
+
* Use `theme.bg.editor`, `theme.fill.primary`, `theme.text.primary`,
|
|
194
|
+
* `theme.stroke.secondary`, `theme.accent.primary`.
|
|
195
|
+
*/
|
|
196
|
+
export interface CanvasTokens {
|
|
197
|
+
bg: {
|
|
198
|
+
editor: string;
|
|
199
|
+
chrome: string;
|
|
200
|
+
elevated: string;
|
|
201
|
+
};
|
|
202
|
+
text: {
|
|
203
|
+
primary: string;
|
|
204
|
+
secondary: string;
|
|
205
|
+
tertiary: string;
|
|
206
|
+
quaternary: string;
|
|
207
|
+
link: string;
|
|
208
|
+
onAccent: string;
|
|
209
|
+
};
|
|
210
|
+
stroke: {
|
|
211
|
+
primary: string;
|
|
212
|
+
secondary: string;
|
|
213
|
+
tertiary: string;
|
|
214
|
+
focused: string;
|
|
215
|
+
};
|
|
216
|
+
fill: {
|
|
217
|
+
primary: string;
|
|
218
|
+
secondary: string;
|
|
219
|
+
tertiary: string;
|
|
220
|
+
quaternary: string;
|
|
221
|
+
};
|
|
222
|
+
accent: {
|
|
223
|
+
primary: string;
|
|
224
|
+
control: string;
|
|
225
|
+
controlHover: string;
|
|
226
|
+
};
|
|
227
|
+
diff: {
|
|
228
|
+
insertedLine: string;
|
|
229
|
+
removedLine: string;
|
|
230
|
+
stripAdded: string;
|
|
231
|
+
stripRemoved: string;
|
|
232
|
+
};
|
|
233
|
+
category: CategoryPalette;
|
|
234
|
+
}
|
|
235
|
+
export declare const canvasTokens: CanvasTokens;
|
|
236
|
+
export declare const canvasTokensLight: CanvasTokens;
|
|
237
|
+
/**
|
|
238
|
+
* Resolve the full token set for a host theme `kind`, optionally overlaying
|
|
239
|
+
* the active editor's primary/accent color via {@link applyPrimaryColor}.
|
|
240
|
+
*
|
|
241
|
+
* Light kinds (`light`, `hc-light`) use the light palette/categories; every
|
|
242
|
+
* other kind uses the dark ones. Centralizing the palette + category choice
|
|
243
|
+
* here keeps `useHostTheme` a thin reader of host state.
|
|
244
|
+
*
|
|
245
|
+
* Grok skips the host `primary` overlay: Grok owns ink accents
|
|
246
|
+
* (`#FAFAFA` / `#070707`). Hosts like Sand and VS Code always send
|
|
247
|
+
* `primary` (workbench `button.background`) and would otherwise wipe
|
|
248
|
+
* those inks. Workbench surfaces (`editorBackground` /
|
|
249
|
+
* `editorForeground`) still apply.
|
|
250
|
+
*/
|
|
251
|
+
export declare function buildHostTokens(kind: string, overrides?: CanvasHostThemeOverrides): {
|
|
252
|
+
tokens: CanvasTokens;
|
|
253
|
+
palette: CanvasPalette;
|
|
254
|
+
brand: CanvasHostThemeBrand;
|
|
255
|
+
};
|
|
256
|
+
export declare function chartThemeForBrand(brand: CanvasHostThemeBrand): {
|
|
257
|
+
palette: ChartPalette;
|
|
258
|
+
sequence: readonly string[];
|
|
259
|
+
};
|