@flesler/cursor-canvas-web 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 thisismydesign
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,212 @@
1
- # Temporary Holding Version
1
+ # cursor-canvas-web
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > **Fork** of [`@thisismydesign/cursor-canvas-web`](https://github.com/thisismydesign/cursor-canvas-web) ([npm](https://www.npmjs.com/package/@thisismydesign/cursor-canvas-web)), published as **`@flesler/cursor-canvas-web`**. We keep the shim aligned with the Cursor IDE `cursor/canvas` SDK (see [`COMPAT.md`](./COMPAT.md), `pnpm test:contract`) and track current stack versions — **Mantine 8** and **Recharts 2 or 3** — instead of the upstream Mantine 7 line.
4
+
5
+ Deploy **Cursor canvases** to the web.
6
+
7
+ A Cursor canvas is a `.tsx` that imports only from `cursor/canvas`. That module isn't an installable package; it's provided by the Cursor IDE at compile time, so a canvas can't build or render anywhere outside the IDE. This project is an open, **Mantine-backed shim** of `cursor/canvas`. A build-time Vite alias swaps the module for the shim, so the same `.tsx` renders in the Cursor IDE and on the web. No converter, no fork of your source.
8
+
9
+ **Upstream demo:** <https://thisismydesign.github.io/cursor-canvas-web/> (this fork uses the same demo canvas; deploy your own `dist/` from `pnpm build`)
10
+
11
+ ![The demo canvas rendered on the web](docs/demo-screenshot.png)
12
+
13
+ ## How it works: a module shim, not a converter
14
+
15
+ Your canvas stays a normal `.tsx` React component that imports only from
16
+ `cursor/canvas`. The only bridge is one module that re-exports that API
17
+ implemented with Mantine. A Vite alias (plus a matching tsconfig path) resolves
18
+ `cursor/canvas` to the shim at build time. There is no parser, AST, or registry,
19
+ and your canvas source never changes.
20
+
21
+ ```
22
+ your.canvas.tsx Vite alias + @flesler/cursor-canvas-web
23
+ imports "cursor/canvas" -> tsconfig paths -> Mantine core + @mantine/charts
24
+ -> Vite build -> any static host
25
+ ```
26
+
27
+ Because the shim mirrors the real SDK API, a canvas that builds here also
28
+ compiles and renders unchanged in the Cursor IDE.
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ pnpm add @flesler/cursor-canvas-web
34
+ # peer deps your app must supply (Mantine 8 + matching charts styles):
35
+ pnpm add react react-dom @mantine/core@^8 @mantine/charts@^8 recharts@^2
36
+ ```
37
+
38
+ The package ships two entry points:
39
+
40
+ | Import | Provides |
41
+ | ------------------------------------------- | --------------------------------------------- |
42
+ | `@flesler/cursor-canvas-web` | The `cursor/canvas` shim (components, hooks). |
43
+ | `@flesler/cursor-canvas-web/runtime` | `CanvasRoot` + `mountCanvas` web host glue. |
44
+
45
+ ## Use it in your project
46
+
47
+ ### 1. Point `cursor/canvas` at the package
48
+
49
+ Two coordinated settings — runtime (Vite) and types (tsconfig) — keep your
50
+ canvas sources pure while resolving the bare specifier to the shim:
51
+
52
+ ```ts
53
+ // vite.config.ts — runtime
54
+ resolve: {
55
+ alias: {
56
+ 'cursor/canvas': '@flesler/cursor-canvas-web',
57
+ },
58
+ }
59
+ ```
60
+
61
+ ```jsonc
62
+ // tsconfig.json — types
63
+ "paths": {
64
+ "cursor/canvas": ["./node_modules/@flesler/cursor-canvas-web"]
65
+ }
66
+ ```
67
+
68
+ ### 2. Mount your canvas
69
+
70
+ Use the `mountCanvas` helper (it wraps `MantineProvider` for you):
71
+
72
+ ```tsx
73
+ // src/main.tsx
74
+ import { mountCanvas } from '@flesler/cursor-canvas-web/runtime';
75
+ import '@mantine/core/styles.css';
76
+ import '@mantine/charts/styles.css';
77
+ import MyCanvas from '../.cursor/canvases/my.canvas';
78
+
79
+ mountCanvas('root', <MyCanvas />);
80
+ ```
81
+
82
+ Or, if you manage your own React root, wrap the tree with `CanvasRoot`:
83
+
84
+ ```tsx
85
+ import { CanvasRoot } from '@flesler/cursor-canvas-web/runtime';
86
+ import '@mantine/core/styles.css';
87
+ import '@mantine/charts/styles.css';
88
+
89
+ createRoot(el).render(
90
+ <CanvasRoot defaultColorScheme="auto">
91
+ <MyCanvas />
92
+ </CanvasRoot>,
93
+ );
94
+ ```
95
+
96
+ The canvas file itself never changes — it still imports only from
97
+ `cursor/canvas`, so it renders identically in the Cursor IDE.
98
+
99
+ ### 3. Deploy
100
+
101
+ The result is a plain Vite app, so `pnpm build` produces a static `dist/` you
102
+ can host anywhere (GitHub Pages, Netlify, Vercel, S3, …). This repo deploys its
103
+ example canvas to GitHub Pages — see [Example deployment](#example-deployment).
104
+
105
+ ## Supported canvas API
106
+
107
+ The shim implements the **full public `cursor/canvas` surface**:
108
+
109
+ - Typography: `H1`, `H2`, `H3`, `Text`, `Code`, `Link`
110
+ - Layout: `Stack`, `Row`, `Spacer`, `Grid`, `Divider`, `mergeStyle`
111
+ - Surfaces: `Card`/`CardHeader`/`CardBody` (incl. `collapsible`)
112
+ - Display & feedback: `Stat`, `Pill`, `Callout`, `Table`
113
+ - Actions: `Button`, `IconButton`
114
+ - Forms: `Select`, `Checkbox`, `Toggle`, `TextInput`, `TextArea`
115
+ - Charts: `LineChart`, `BarChart`, `PieChart`
116
+ - Rich: `Swatch`, `UsageBar`, `CollapsibleSection`, `TodoList`/`TodoListCard`,
117
+ `DiffView`/`DiffStats`, `computeDAGLayout`
118
+ - Hooks: `useCanvasState`, `useHostTheme`, `useCanvasAction` (+ React
119
+ `useState` / `useEffect` / `useRef` / `useMemo` re-exported from the barrel)
120
+ - Tokens: `categoryPalette(Dark|Light)`, `colorPalette`, `usageColorSequence`,
121
+ `canvasTokens(Light)`, `canvasPalette(Dark|Light)`; `useHostTheme()` also
122
+ exposes `category`, `chart.palette` / `chart.sequence`, `radius`, `typography`,
123
+ and `spacing` (see `COMPAT.md` for IDE vs web)
124
+
125
+ Known fidelity gaps (behavior is reproduced, not the exact renderer):
126
+ `DiffView` skips Shiki syntax highlighting (plain-text fallback), and
127
+ `useCanvasAction` is a no-op on the web (IDE-only). Styling approximates the
128
+ Cursor theme rather than matching it pixel-for-pixel.
129
+
130
+ If your canvas needs an export the shim doesn't yet provide, see
131
+ [Extending the shim](#extending-the-shim).
132
+
133
+ ## Example deployment
134
+
135
+ This repo is itself a working example. The canvas at
136
+ [`.cursor/canvases/demo.canvas.tsx`](./.cursor/canvases/demo.canvas.tsx) is the
137
+ single source of truth: the web app imports it directly, and the same file is
138
+ copied into Cursor's managed canvases folder so it renders in the IDE too.
139
+
140
+ The deployed result lives at
141
+ <https://thisismydesign.github.io/cursor-canvas-web/>.
142
+
143
+ `deploy.yml` builds and publishes to GitHub Pages on push to `main` via
144
+ `configure-pages` / `upload-pages-artifact` / `deploy-pages`. The Vite `base`
145
+ defaults to `/cursor-canvas-web/` (project Page); override it with the
146
+ `BASE_PATH` env var if you deploy elsewhere.
147
+
148
+ ## Develop this repo
149
+
150
+ Tool versions (Node, pnpm) are pinned in [`.tool-versions`](./.tool-versions)
151
+ and managed with [mise](https://mise.jdx.dev/).
152
+
153
+ ```bash
154
+ mise install # install Node + pnpm from .tool-versions
155
+ pnpm install
156
+ pnpm dev # start the dev server
157
+ ```
158
+
159
+ Validation gate:
160
+
161
+ ```bash
162
+ pnpm typecheck # tsc --noEmit, strict
163
+ pnpm lint # eslint
164
+ pnpm test # vitest run
165
+ pnpm test:contract # IDE SDK snapshot + export parity + consumer tsc
166
+ pnpm sync:sdk # refresh test/contract/cursor-sdk from ~/.cursor/skills-cursor/canvas/sdk
167
+ pnpm build # typecheck + vite build -> dist/
168
+ ```
169
+
170
+ ### Layout
171
+
172
+ | Path | Role |
173
+ | ---------------------------------- | ----------------------------------------------------- |
174
+ | `.cursor/canvases/demo.canvas.tsx` | The example canvas; imports **only** `cursor/canvas`. |
175
+ | `src/shim/cursor-canvas.tsx` | Mantine implementation matching the real SDK API. |
176
+ | `src/shim/theme.ts` | Tone→color map + host-theme tokens. |
177
+ | `src/runtime/index.tsx` | Web host glue (`CanvasRoot`, `mountCanvas`). |
178
+ | `src/main.tsx` | Mounts React inside `MantineProvider`. |
179
+ | `vite.config.ts` | `resolve.alias` for `cursor/canvas` + Pages base. |
180
+ | `vite.lib.config.ts` | Library build (shim + runtime) for publishing. |
181
+ | `tsconfig.json` | `paths` maps `cursor/canvas` to the shim. |
182
+
183
+ ### Extending the shim
184
+
185
+ To support more of the canvas API:
186
+
187
+ 1. Add the export to `src/shim/cursor-canvas.tsx`, implemented with Mantine.
188
+ 2. Keep prop shapes stable — they are the contract canvases rely on, and they
189
+ must match the official SDK declarations so canvases render unchanged in the
190
+ IDE.
191
+ 3. If it carries semantic color, map `tone` via `toneColor` in
192
+ `src/shim/theme.ts`, using the SDK's tone vocabulary for that primitive
193
+ (`StatTone`, `PillTone`, `CalloutTone`, `ChartTone`).
194
+ 4. Add a test under `src/shim/__tests__/`.
195
+
196
+ The only non-trivial adapter so far is `LineChart`, which reshapes parallel
197
+ `categories` + `series[]` arrays into Mantine's array-of-row-objects `data` and
198
+ maps each series `tone` to a color (`reshapeLineChartData`).
199
+
200
+ ### Publishing
201
+
202
+ `prepublishOnly` runs `typecheck`, `test`, and `build:lib` automatically, so a
203
+ publish only needs:
204
+
205
+ ```bash
206
+ npm login
207
+ npm publish --access public --tag latest
208
+ ```
209
+
210
+ `--access public` is required for the scoped package. Publishing needs 2FA
211
+ (WebAuthn/passkey) on your npm account; `npm publish` opens a browser to
212
+ complete the passkey prompt.
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),u=require("@mantine/core"),y=require("react"),B=require("@mantine/charts"),O={foreground:"#E4E4E4EB",foregroundSecondary:"#E4E4E48D",foregroundTertiary:"#E4E4E45E",foregroundQuaternary:"#E4E4E442",editor:"#181818",chrome:"#141414",sidebar:"#141414",elevated:"#181818",fillPrimary:"#E4E4E430",fillSecondary:"#E4E4E41E",fillTertiary:"#E4E4E411",fillQuaternary:"#E4E4E40A",strokePrimary:"#E4E4E433",strokeSecondary:"#E4E4E41F",strokeTertiary:"#E4E4E414",strokeFocused:"#599CE7",accent:"#599CE7",buttonBackground:"#599CE7",buttonForeground:"#191c22",buttonHoverBackground:"#6AABE9",link:"#87c3ff",diffInsertedLine:"#3FA26633",diffRemovedLine:"#B8004933",diffStripAdded:"#3FA2668F",diffStripRemoved:"#FC6B838F"},G={foreground:"#141414F0",foregroundSecondary:"#141414BD",foregroundTertiary:"#1414148A",foregroundQuaternary:"#1414145C",editor:"#FCFCFC",chrome:"#F8F8F8",sidebar:"#F3F3F3",elevated:"#FCFCFC",fillPrimary:"#14141433",fillSecondary:"#14141424",fillTertiary:"#14141414",fillQuaternary:"#1414140F",strokePrimary:"#14141433",strokeSecondary:"#1414141F",strokeTertiary:"#14141414",strokeFocused:"#3685BF",accent:"#3685BF",buttonBackground:"#3685BF",buttonForeground:"#FCFCFC",buttonHoverBackground:"#2E76AB",link:"#3685BF",diffInsertedLine:"#1F8A651F",diffRemovedLine:"#CF2D5614",diffStripAdded:"#1F8A65CC",diffStripRemoved:"#CF2D56CC"},M={gray:"#8888A8E0",purple:"#7B64B8F0",green:"#1F8A65E8",yellow:"#E8C030E0",cyan:"#2A9A8AE0",pink:"#C85898E0",blue:"#2E79B5E0",orange:"#F0A040E0",red:"#C04848E0"},$={gray:"#8888A8E0",purple:"#7B64B8F0",green:"#1F8A65E8",yellow:"#E8C030E0",cyan:"#2A9A8AE0",pink:"#C85898E0",blue:"#2E79B5E0",orange:"#F0A088E0",red:"#CF2D56E0"};function oe(e,t){return{bg:{editor:e.editor,chrome:e.chrome,elevated:e.elevated},text:{primary:e.foreground,secondary:e.foregroundSecondary,tertiary:e.foregroundTertiary,quaternary:e.foregroundQuaternary,link:e.link,onAccent:e.buttonForeground},stroke:{primary:e.strokePrimary,secondary:e.strokeSecondary,tertiary:e.strokeTertiary,focused:e.strokeFocused},fill:{primary:e.fillPrimary,secondary:e.fillSecondary,tertiary:e.fillTertiary,quaternary:e.fillQuaternary},accent:{primary:e.accent,control:e.buttonBackground,controlHover:e.buttonHoverBackground},diff:{insertedLine:e.diffInsertedLine,removedLine:e.diffRemovedLine,stripAdded:e.diffStripAdded,stripRemoved:e.diffStripRemoved},category:t}}const ae=oe(O,M),se=oe(G,$),ye=M,I=["blue","purple","green","yellow","cyan","pink","orange","red","gray"],me={green:"#1F8A65E8",darkGreen:"#0D855AE0",lightGreen:"#52B896E0",mintGreen:"#7DCAB0E0",blue:"#2E79B5E0",lightBlue:"#70B0D8E0",indigo:"#5A6CC0F0",lightIndigo:"#9AAADCE0",purple:"#7B64B8F0",lightPurple:"#AA98D8E0",warmPink:"#C85898E0",lightPink:"#E8A0C4E0",brightOrange:"#F0A040E0",deepOrange:"#C06028E0",goldenYellow:"#E8C030E0",darkAmber:"#C04848E0",warmPeach:"#F0A088E0",vibrantTeal:"#2A9A8AE0",muted:"#8888A8E0",neutralLine:"#888899D0"},ve={h1:{fontSize:"24px",lineHeight:"30px",fontWeight:590},h2:{fontSize:"18px",lineHeight:"24px",fontWeight:590},h3:{fontSize:"16px",lineHeight:"22px",fontWeight:590},body:{fontSize:"14px",lineHeight:"20px",fontWeight:400},small:{fontSize:"12px",lineHeight:"16px",fontWeight:400}},be={"0.5":2,1:4,"1.5":6,2:8,"2.5":10,3:12,"3.5":14,4:16,"4.5":18,5:20,6:24,7:28,8:32,9:36,10:40},Ee={none:0,xs:2,sm:4,md:6,lg:8,xl:12,full:9999},W=["#1F8A65E8","#70B0D8E0","#5A6CC0F0","#F0A040E0","#C06028E0","#E8C030E0","#C85898E0","#F0A088E0","#7B64B8F0","#7DCAB0E0","#8888A8E0","#2A9A8AE0"],E={success:"#1F8A65",danger:"#CF2D56",warning:"#E8A33D",info:"#2E79B5",neutral:"#8888A8",added:"#1F8A65",deleted:"#CF2D56",renamed:"#5A6CC0"},q={success:"green",danger:"red",warning:"orange",info:"blue",neutral:"gray",added:"green",deleted:"red",renamed:"indigo"};function je(e){const t=e==="dark"?ae:se;return{...t,kind:e,tokens:t,palette:e==="dark"?O:G,category:e==="dark"?M:$,chart:{palette:me,sequence:W},radius:Ee,typography:ve,spacing:be}}function j(){const e=u.useComputedColorScheme("light");return je(e==="dark"?"dark":"light")}function ie(e,t){return e?E[e]:W[t%W.length]}function N(e,t){return e.map((r,s)=>{const i={category:r};for(const o of t)i[o.name]=o.data[s]??0;return i})}function ce(e){return e.map((t,r)=>({name:t.name,color:ie(t.tone,r)}))}function le(e,t){if(!(!e&&!t))return r=>`${t??""}${r}${e??""}`}function ke(e,t){if(e!=null&&e.length)return e.map(r=>({...t?{x:r.value}:{y:r.value},label:r.label,color:r.tone?E[r.tone]:E.neutral}))}function de(e){const t=ke(e.referenceLines,!!e.horizontal);if(e.stacked||e.normalized)return{referenceLines:t};const r=e.beginAtZero!==!1,s=[e.yMin??(r?0:"auto"),e.yMax??"auto"];return e.horizontal?{xAxisProps:{domain:s},referenceLines:t}:{yAxisProps:{domain:s},referenceLines:t}}function Se(e,t,r){return e!==void 0?e:t.length===1&&r.length<=8}function Ce({categories:e,series:t,height:r=240,fill:s,valueSuffix:i,valuePrefix:o,showValues:l,showHoverGuide:f=!0,beginAtZero:d,yMin:c,yMax:h,referenceLines:x,style:v}){const b=N(e,t),F=ce(t),k=de({beginAtZero:d,yMin:c,yMax:h,referenceLines:x,horizontal:!1}),S={h:r,data:b,dataKey:"category",series:F,curveType:"monotone",withLegend:t.length>1,valueFormatter:le(i,o),withPointLabels:l??e.length<=20,tooltipProps:f?void 0:{cursor:!1},...k,style:v};return s?n.jsx(B.AreaChart,{...S}):n.jsx(B.LineChart,{...S})}function Ae({categories:e,series:t,height:r=240,stacked:s,horizontal:i,normalized:o,valueSuffix:l,valuePrefix:f,showValues:d,beginAtZero:c,yMin:h,yMax:x,referenceLines:v,style:b}){const F=N(e,t),k=o?"percent":s?"stacked":"default",S=de({beginAtZero:c,yMin:h,yMax:x,referenceLines:v,horizontal:i,stacked:s,normalized:o}),T=!s&&!o&&Se(d,t,e);return n.jsx(B.BarChart,{h:r,data:F,dataKey:"category",series:ce(t),type:k,orientation:i?"vertical":"horizontal",withLegend:t.length>1,valueFormatter:le(l,f),withBarValueLabel:T,...S,style:b})}function Fe({data:e,size:t=200,donut:r,style:s}){const o={data:e.map((l,f)=>({name:l.label,value:l.value,color:ie(l.tone,f)})),size:t,withTooltip:!0,style:s};return r?n.jsx(B.DonutChart,{...o}):n.jsx(B.PieChart,{...o,withLabelsLine:!1})}function Te(e){const{nodes:t,edges:r,direction:s="vertical",nodeWidth:i=160,nodeHeight:o=40,rankGap:l=64,nodeGap:f=48,padding:d=24}=e,c=t.map(a=>a.id),h=new Set(c),x=new Map;for(const a of c)x.set(a,[]);for(const a of r)h.has(a.from)&&h.has(a.to)&&x.get(a.from).push(a.to);const v=0,b=1,F=2,k=new Map(c.map(a=>[a,v])),S=new Set,T=(a,g)=>`${a}\0${g}`,Q=a=>{k.set(a,b);for(const g of x.get(a)??[]){const p=k.get(g);p===b?S.add(T(a,g)):p===v&&Q(g)}k.set(a,F)};for(const a of c)k.get(a)===v&&Q(a);const he=r.filter(a=>h.has(a.from)&&h.has(a.to)&&!S.has(T(a.from,a.to))),C=new Map(c.map(a=>[a,0])),K=new Map(c.map(a=>[a,[]]));for(const a of he)K.get(a.from).push(a.to),C.set(a.to,(C.get(a.to)??0)+1);const w=new Map(c.map(a=>[a,0])),z=c.filter(a=>(C.get(a)??0)===0);for(;z.length>0;){const a=z.shift(),g=w.get(a);for(const p of K.get(a))w.set(p,Math.max(w.get(p),g+1)),C.set(p,C.get(p)-1),C.get(p)===0&&z.push(p)}const A=new Map;for(const a of c){const g=w.get(a);A.has(g)||A.set(g,[]),A.get(g).push(a)}const L=[...A.keys()].sort((a,g)=>a-g),m=s==="vertical",X=a=>a*(m?i:o)+Math.max(0,a-1)*f,V=Math.max(0,...L.map(a=>X(A.get(a).length))),D=new Map,Y=[];L.forEach((a,g)=>{const p=A.get(a),H=X(p.length),R=d+(V-H)/2,P=d+g*((m?o:i)+l);p.forEach((ee,te)=>{const re=R+te*((m?i:o)+f),pe=m?re:P,xe=m?P:re;D.set(ee,{id:ee,x:pe,y:xe,rank:a,order:te})}),Y.push({rank:a,x:m?R:P,y:m?P:R,width:m?H:i,height:m?o:H,nodeIds:p})});const U=(a,g)=>a?m?{x:a.x+i/2,y:g==="source"?a.y+o:a.y}:{x:g==="source"?a.x+i:a.x,y:a.y+o/2}:{x:0,y:0},ge=r.filter(a=>h.has(a.from)&&h.has(a.to)).map(a=>{const g=U(D.get(a.from),"source"),p=U(D.get(a.to),"target");return{from:a.from,to:a.to,sourceX:g.x,sourceY:g.y,targetX:p.x,targetY:p.y,isBackEdge:S.has(T(a.from,a.to))}}),J=d*2+L.length*(m?o:i)+Math.max(0,L.length-1)*l,Z=d*2+V;return{nodes:[...D.values()],edges:ge,ranks:Y,direction:s,width:m?Z:J,height:m?J:Z}}function Be({additions:e=0,deletions:t=0,style:r}){return e===0&&t===0?null:n.jsxs("span",{style:{display:"inline-flex",gap:8,fontVariantNumeric:"tabular-nums",fontSize:12,fontWeight:600,...r},children:[e>0&&n.jsxs("span",{style:{color:E.added},children:["+",e]}),t>0&&n.jsxs("span",{style:{color:E.deleted},children:["-",t]})]})}const we={added:"+",removed:"-",unchanged:" "};function Le({lines:e,showLineNumbers:t=!0,coloredLineNumbers:r=!0,showAccentStrip:s=!0,style:i}){const o=j(),l=c=>c==="added"?o.diff.insertedLine:c==="removed"?o.diff.removedLine:"transparent",f=c=>c==="added"?o.diff.stripAdded:c==="removed"?o.diff.stripRemoved:"transparent",d=c=>r&&c==="added"?E.added:r&&c==="removed"?E.deleted:o.text.tertiary;return n.jsx("div",{style:{fontFamily:'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Code", monospace',fontSize:12.5,lineHeight:"18px",color:o.text.primary,overflowX:"auto",...i},children:e.map((c,h)=>n.jsxs("div",{style:{display:"flex",alignItems:"stretch",background:l(c.type),borderLeft:s?`3px solid ${f(c.type)}`:void 0},children:[t&&n.jsx("span",{style:{flex:"0 0 auto",width:40,textAlign:"right",paddingRight:10,userSelect:"none",color:d(c.type)},children:c.lineNumber??""}),n.jsx("span",{style:{flex:"0 0 auto",width:14,textAlign:"center",userSelect:"none",color:d(c.type)},children:we[c.type]}),n.jsx("pre",{style:{margin:0,padding:"0 8px",whiteSpace:"pre",fontFamily:"inherit"},children:c.content})]},h))})}function De({status:e}){const t=j(),r=e==="completed"?E.success:e==="in_progress"?t.accent.primary:e==="cancelled"?E.danger:t.text.tertiary;return n.jsxs("svg",{width:14,height:14,viewBox:"0 0 14 14",fill:"none",style:{flex:"0 0 auto",marginTop:3},"aria-hidden":!0,children:[n.jsx("circle",{cx:7,cy:7,r:6,stroke:r,strokeWidth:1.4}),e==="completed"&&n.jsx("path",{d:"M4 7.2l2 2 4-4.4",stroke:r,strokeWidth:1.4,strokeLinecap:"round",strokeLinejoin:"round"}),e==="in_progress"&&n.jsx("circle",{cx:7,cy:7,r:3,fill:r}),e==="cancelled"&&n.jsx("path",{d:"M4.8 4.8l4.4 4.4M9.2 4.8l-4.4 4.4",stroke:r,strokeWidth:1.4,strokeLinecap:"round"})]})}function ue({todos:e,dimmedTodoIds:t,onTodoClick:r,style:s}){const i=j();return e.length===0?null:n.jsx("div",{style:{display:"flex",flexDirection:"column",...s},children:e.map(o=>{const l=t==null?void 0:t.has(o.id);return n.jsxs("button",{type:"button",onClick:()=>r==null?void 0:r(o),style:{display:"flex",gap:8,alignItems:"flex-start",width:"100%",textAlign:"left",padding:"4px 6px",background:"transparent",border:"none",cursor:r?"pointer":"default",color:i.text.primary,fontSize:14,lineHeight:"20px",opacity:l?.45:1},children:[n.jsx(De,{status:o.status}),n.jsx("span",{style:{textDecoration:o.status==="cancelled"?"line-through":void 0,color:o.status==="cancelled"?i.text.tertiary:void 0},children:o.content})]},o.id)})})}function Pe({todos:e,dimmedTodoIds:t,defaultExpanded:r=!1,onTodoClick:s,style:i}){const o=j(),[l,f]=y.useState(r);if(e.length===0)return null;const d=e.filter(c=>c.status==="completed").length;return n.jsxs("div",{style:{border:`1px solid ${o.stroke.primary}`,borderRadius:6,overflow:"hidden",...i},children:[n.jsxs("button",{type:"button",onClick:()=>f(c=>!c),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"6px 10px",background:"transparent",border:"none",cursor:"pointer",color:o.text.secondary,fontSize:12,fontWeight:600},children:[n.jsx("svg",{width:12,height:12,viewBox:"0 0 12 12",fill:"none",style:{transform:l?"rotate(90deg)":"none",transition:"transform 120ms"},"aria-hidden":!0,children:n.jsx("path",{d:"M4 2.5L8 6l-4 3.5",stroke:"currentColor",strokeWidth:1.4,strokeLinecap:"round",strokeLinejoin:"round"})}),n.jsx("span",{children:"Todos"}),n.jsx("span",{style:{flex:1}}),n.jsxs("span",{children:[d," of ",e.length," Done"]})]}),l&&n.jsx("div",{style:{padding:6},children:n.jsx(ue,{todos:e,dimmedTodoIds:t,onTodoClick:s})})]})}function Me(e,t){const r=`canvas:${e}`,[s,i]=y.useState(()=>{if(typeof localStorage>"u")return t;try{const l=localStorage.getItem(r);return l===null?t:JSON.parse(l)}catch{return t}}),o=y.useCallback(l=>{i(f=>{const d=typeof l=="function"?l(f):l;try{localStorage==null||localStorage.setItem(r,JSON.stringify(d))}catch{}return d})},[r]);return[s,o]}function ze(){return y.useCallback(e=>{},[])}function He(e,t){return{...e,...t}}function Re({children:e,style:t}){return n.jsx(u.Title,{order:1,fz:24,lh:"30px",style:t,children:e})}function Ie({children:e,style:t}){return n.jsx(u.Title,{order:2,fz:18,lh:"24px",style:t,children:e})}function We({children:e,style:t}){return n.jsx(u.Title,{order:3,fz:16,lh:"22px",style:t,children:e})}const Oe={normal:400,medium:500,semibold:600,bold:700};function Ge({children:e,tone:t="primary",size:r="body",as:s="p",weight:i="normal",italic:o,truncate:l,style:f}){const d=j();return n.jsx(u.Text,{component:s,size:r==="small"?"xs":"sm",fw:Oe[i],c:t==="primary"?void 0:d.text[t],truncate:l,style:{fontStyle:o?"italic":void 0,...f},children:e})}function $e({children:e,style:t}){return n.jsx("code",{style:{fontFamily:'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Code", monospace',fontSize:"0.92em",background:"var(--mantine-color-default-hover)",borderRadius:4,padding:"1px 4px",...t},children:e})}function qe({children:e,href:t,style:r}){return n.jsx("a",{href:t,target:"_blank",rel:"noreferrer",style:{color:"var(--mantine-color-anchor)",...r},children:e})}function Ne({children:e,gap:t,style:r}){return n.jsx(u.Stack,{gap:t,style:r,children:e})}const ne={start:"flex-start",center:"center",end:"flex-end",stretch:"stretch","space-between":"space-between"};function _e({children:e,gap:t,align:r="center",justify:s="start",wrap:i=!1,style:o}){return n.jsx(u.Group,{gap:t,align:ne[r],justify:ne[s],wrap:i?"wrap":"nowrap",style:o,children:e})}function Qe(){return n.jsx("div",{style:{flex:1}})}function Ke({children:e,columns:t,gap:r=16,align:s,style:i}){const o=typeof t=="number"?`repeat(${t}, minmax(0, 1fr))`:t;return n.jsx("div",{style:{display:"grid",gridTemplateColumns:o,gap:r,alignItems:s,...i},children:e})}function Xe({style:e}){return n.jsx(u.Divider,{style:e})}const _=y.createContext({collapsible:!1,open:!0,toggle:()=>{}});function Ve({children:e,variant:t="default",collapsible:r=!1,defaultOpen:s=!0,open:i,onOpenChange:o,style:l}){const[f,d]=y.useState(s),c=i??f,h=y.useCallback(()=>{const x=!c;i===void 0&&d(x),o==null||o(x)},[c,i,o]);return n.jsx(u.Card,{withBorder:t!=="borderless",radius:"md",padding:0,style:l,children:n.jsx(_.Provider,{value:{collapsible:r,open:c,toggle:h},children:e})})}function Ye({children:e,trailing:t,style:r}){const{collapsible:s,open:i,toggle:o}=y.useContext(_);return n.jsxs("div",{onClick:s?o:void 0,style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,padding:"8px 14px",borderBottom:"1px solid var(--mantine-color-default-border)",fontSize:12,fontWeight:600,color:"var(--mantine-color-dimmed)",cursor:s?"pointer":void 0,userSelect:s?"none":void 0,...r},children:[n.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:6},children:[s&&n.jsx(fe,{expanded:i}),e]}),t!=null&&n.jsx("span",{children:t})]})}function Ue({children:e,style:t}){const{collapsible:r,open:s}=y.useContext(_);return r&&!s?null:n.jsx("div",{style:{padding:14,...t},children:e})}function fe({expanded:e}){return n.jsx("svg",{width:12,height:12,viewBox:"0 0 12 12",fill:"none",style:{transform:e?"rotate(90deg)":"none",transition:"transform 120ms"},"aria-hidden":!0,children:n.jsx("path",{d:"M4 2.5L8 6l-4 3.5",stroke:"currentColor",strokeWidth:1.4,strokeLinecap:"round",strokeLinejoin:"round"})})}function Je({value:e,label:t,tone:r,style:s}){return n.jsxs("div",{style:s,children:[n.jsx(u.Text,{fz:22,fw:700,lh:1.2,c:r?`${q[r]}.6`:void 0,children:e}),n.jsx(u.Text,{fz:12,c:"dimmed",children:t})]})}function Ze({children:e,active:t,tone:r="neutral",size:s="md",leadingContent:i,keyboardHint:o,title:l,style:f,onClick:d}){return n.jsx(u.Badge,{color:q[r],variant:t?"filled":"light",size:s==="sm"?"sm":"md",leftSection:i,rightSection:o,title:l,onClick:d,style:{cursor:d?"pointer":void 0,textTransform:"none",...f},children:e})}function et({children:e,tone:t="neutral",title:r,icon:s,style:i}){return n.jsx(u.Alert,{color:q[t],title:r,icon:s,variant:"light",style:i,children:e})}const tt={success:"rgba(31,138,101,0.12)",danger:"rgba(207,45,86,0.12)",warning:"rgba(232,163,61,0.14)",info:"rgba(46,121,181,0.12)",neutral:"rgba(136,136,168,0.12)"};function rt({headers:e,rows:t,columnAlign:r,rowTone:s,framed:i=!0,striped:o,stickyHeader:l,style:f,emptyMessage:d}){return n.jsxs(u.Table,{withTableBorder:i,withColumnBorders:!1,striped:o,stickyHeader:l,highlightOnHover:!0,style:f,children:[n.jsx(u.Table.Thead,{children:n.jsx(u.Table.Tr,{children:e.map((c,h)=>n.jsx(u.Table.Th,{ta:(r==null?void 0:r[h])??"left",children:c},h))})}),n.jsx(u.Table.Tbody,{children:t.length===0?n.jsx(u.Table.Tr,{children:n.jsx(u.Table.Td,{colSpan:e.length,ta:"center",c:"dimmed",children:d??"No data"})}):t.map((c,h)=>{const x=s==null?void 0:s[h];return n.jsx(u.Table.Tr,{style:x?{background:tt[x]}:void 0,children:e.map((v,b)=>n.jsx(u.Table.Td,{ta:(r==null?void 0:r[b])??"left",children:c[b]},b))},h)})})]})}const nt={primary:"filled",secondary:"default",ghost:"subtle"};function ot({children:e,variant:t="secondary",disabled:r,type:s="button",style:i,onClick:o}){return n.jsx(u.Button,{variant:nt[t],size:"xs",disabled:r,type:s,onClick:o,style:i,children:e})}function at({children:e,onClick:t,disabled:r,title:s,variant:i="default",size:o="md",style:l}){return n.jsx(u.ActionIcon,{variant:i==="circle"?"light":"subtle",radius:i==="circle"?"xl":"sm",size:o==="sm"?"sm":"md",color:"gray",disabled:r,title:s,"aria-label":s,onClick:t,style:l,children:e})}function st({value:e,onChange:t,options:r,placeholder:s,disabled:i,style:o}){return n.jsx(u.Select,{value:e,data:r,placeholder:s,disabled:i,allowDeselect:!1,onChange:l=>{l!==null&&(t==null||t(l))},style:o})}function it({checked:e,onChange:t,disabled:r,label:s,style:i}){return n.jsx(u.Checkbox,{checked:e,disabled:r,label:s,onChange:o=>t==null?void 0:t(o.currentTarget.checked),style:i})}function ct({checked:e,onChange:t,disabled:r,size:s="sm",style:i}){return n.jsx(u.Switch,{checked:e,disabled:r,size:s==="sm"?"sm":"md",onChange:o=>t==null?void 0:t(o.currentTarget.checked),style:i})}function lt({value:e,onChange:t,placeholder:r,disabled:s,type:i,style:o}){return n.jsx(u.TextInput,{value:e,placeholder:r,disabled:s,type:i,onChange:l=>t==null?void 0:t(l.currentTarget.value),style:o})}function dt({value:e,onChange:t,placeholder:r,disabled:s,rows:i=3,style:o}){return n.jsx(u.Textarea,{value:e,placeholder:r,disabled:s,autosize:!0,minRows:i,onChange:l=>t==null?void 0:t(l.currentTarget.value),style:o})}function ut({color:e,style:t}){const r=j();return n.jsx("span",{style:{display:"inline-block",width:14,height:14,borderRadius:4,background:r.category[e],flex:"0 0 auto",...t}})}function ft({segments:e,total:t,topLeftLabel:r,topRightLabel:s,style:i}){const o=j(),l=t>0?t:1,f=e.reduce((c,h)=>c+(Number.isFinite(h.value)&&h.value>0?h.value:0),0),d=Math.max(0,l-f);return n.jsxs("div",{style:i,children:[(r!=null||s!=null)&&n.jsxs("div",{style:{display:"flex",justifyContent:"space-between",fontSize:12,color:o.text.secondary,marginBottom:6},children:[n.jsx("span",{children:r}),n.jsx("span",{children:s})]}),n.jsxs("div",{style:{display:"flex",gap:2,height:8},children:[e.map((c,h)=>{const x=Number.isFinite(c.value)&&c.value>0?c.value:0,v=o.category[c.color??I[h%I.length]];return n.jsx("div",{style:{width:`${x/l*100}%`,background:v,borderRadius:3}},c.id)}),d>0&&n.jsx("div",{style:{width:`${d/l*100}%`,background:o.fill.tertiary,borderRadius:3}})]})]})}function ht({title:e,leading:t,count:r,trailing:s,children:i,defaultOpen:o=!1,style:l}){const f=j(),[d,c]=y.useState(o);return n.jsxs("div",{style:l,children:[n.jsxs("div",{onClick:()=>c(h=>!h),style:{display:"flex",alignItems:"center",gap:6,padding:"4px 0",cursor:"pointer",userSelect:"none",color:f.text.primary,fontSize:14},children:[n.jsx(fe,{expanded:d}),t,n.jsx("span",{style:{fontWeight:500},children:e}),r!=null&&n.jsx("span",{style:{color:f.text.tertiary,fontSize:12},children:r}),n.jsx("span",{style:{flex:1}}),s!=null&&n.jsx("span",{style:{color:f.text.tertiary},children:s})]}),d&&n.jsx("div",{style:{paddingLeft:18,paddingBottom:4},children:i})]})}Object.defineProperty(exports,"useEffect",{enumerable:!0,get:()=>y.useEffect});Object.defineProperty(exports,"useMemo",{enumerable:!0,get:()=>y.useMemo});Object.defineProperty(exports,"useRef",{enumerable:!0,get:()=>y.useRef});Object.defineProperty(exports,"useState",{enumerable:!0,get:()=>y.useState});exports.BarChart=Ae;exports.Button=ot;exports.Callout=et;exports.Card=Ve;exports.CardBody=Ue;exports.CardHeader=Ye;exports.Checkbox=it;exports.Code=$e;exports.CollapsibleSection=ht;exports.DiffStats=Be;exports.DiffView=Le;exports.Divider=Xe;exports.Grid=Ke;exports.H1=Re;exports.H2=Ie;exports.H3=We;exports.IconButton=at;exports.LineChart=Ce;exports.Link=qe;exports.PieChart=Fe;exports.Pill=Ze;exports.Row=_e;exports.Select=st;exports.Spacer=Qe;exports.Stack=Ne;exports.Stat=Je;exports.Swatch=ut;exports.Table=rt;exports.Text=Ge;exports.TextArea=dt;exports.TextInput=lt;exports.TodoList=ue;exports.TodoListCard=Pe;exports.Toggle=ct;exports.UsageBar=ft;exports.canvasPaletteDark=O;exports.canvasPaletteLight=G;exports.canvasTokens=ae;exports.canvasTokensLight=se;exports.categoryPaletteDark=M;exports.categoryPaletteLight=$;exports.colorPalette=ye;exports.computeDAGLayout=Te;exports.mergeStyle=He;exports.reshapeLineChartData=N;exports.usageColorSequence=I;exports.useCanvasAction=ze;exports.useCanvasState=Me;exports.useHostTheme=j;