@codecanvas-ide/engine 0.2.0 → 0.4.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.
@@ -54,7 +54,15 @@ export interface CodeCanvasOptions {
54
54
  onSelect?(block: Block | null): void;
55
55
  /** The user picked a block in another file, e.g. in the references list. */
56
56
  onOpenBlock?(path: string, blockId: string): void;
57
+ /** Show the block's code in a text editor ("Open code" on a selected block). Without it, the action is hidden. */
58
+ onOpenCode?(block: Block): void;
59
+ /** Ask an assistant about the block ("Ask" on a selected block). Without it, the action is hidden. */
60
+ onAsk?(block: Block): void;
61
+ /** Show the minimap in the bottom right corner (default true). Hosts can move it with `--cc-minimap-right` and `--cc-minimap-bottom`. */
62
+ minimap?: boolean;
57
63
  }
64
+ /** What dragging on the canvas does: select and move blocks, or pan the view. */
65
+ export type CanvasTool = 'select' | 'pan';
58
66
  export type LayoutChangeReason = 'user' | 'automatic';
59
67
  /** Another file changed by the same canvas action, e.g. usages renamed there. */
60
68
  export interface OtherFileChange {
@@ -75,7 +83,14 @@ export declare class CodeCanvas {
75
83
  private frameEl;
76
84
  private blocksEl;
77
85
  private svg;
86
+ /** The dock at the bottom. */
78
87
  private bar;
88
+ private selectionBar;
89
+ private menuEl;
90
+ private minimapEl;
91
+ private minimapScale;
92
+ private zoomLabel;
93
+ private tool;
79
94
  private refsEl;
80
95
  private banner;
81
96
  private toastEl;
@@ -248,6 +263,22 @@ export declare class CodeCanvas {
248
263
  restoreCamera?: boolean;
249
264
  }): void;
250
265
  private renderBar;
266
+ /** The dock at the bottom: tools, file actions, zoom and the language. */
267
+ private renderDock;
268
+ /** The bar above the selected block: what it uses and what uses it, and actions on it. */
269
+ private renderSelectionBar;
270
+ private moreButton;
271
+ /** The block's actions as a menu, from ⋯ or a right-click. */
272
+ private openBlockMenu;
273
+ private closeMenu;
274
+ /** Keep the selection bar right above the selected block (below it when there is no room). */
275
+ private placeSelectionBar;
276
+ private setTool;
277
+ /** The whole file in small, in a corner; the visible part outlined. A click moves there. */
278
+ private renderMinimap;
279
+ private placeMinimapView;
280
+ private moveToMinimapPoint;
281
+ private languageLabelParts;
251
282
  private toggleRefs;
252
283
  private showErrorsOf;
253
284
  private diagnosticsInside;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * One line of a block's code preview as HTML, with simple syntax colors: keywords, strings,
3
+ * comments, numbers, CONSTANTS and Types. It reads one line at a time, so a comment or string that
4
+ * spans lines is only colored where it starts.
5
+ */
6
+ export declare function highlightLine(line: string): string;
@@ -1 +1,3 @@
1
1
  export declare function setHTML(element: Element, html: string): void;
2
+ /** Text made safe to put in HTML. */
3
+ export declare function esc(s: string): string;
@@ -29,7 +29,7 @@ export interface StackRule {
29
29
  export declare const STACK_RULES: StackRule[];
30
30
  /** What a block knows about its siblings, read from its own code. */
31
31
  export interface SiblingFacts {
32
- /** Sibling functions it calls, in the order of their first call. */
32
+ /** Sibling functions it calls and components it renders, in the order of their first use. */
33
33
  calls: string[];
34
34
  /** Every sibling it names (calls included). */
35
35
  uses: Set<string>;
@@ -23,6 +23,7 @@ export declare function detectIndentUnit(text: string): string;
23
23
  declare class Builder {
24
24
  private sf;
25
25
  private text;
26
+ private isReact;
26
27
  roots: Block[];
27
28
  byId: Map<string, Block>;
28
29
  /**
@@ -34,13 +35,17 @@ declare class Builder {
34
35
  private rangeToBlock;
35
36
  /** Every name a usage could resolve to. Other identifiers skip the (slow) checker. */
36
37
  readonly names: Set<string>;
37
- constructor(sf: ts.SourceFile, text: string);
38
+ /** Setters of React state (`setCount`), keyed like `declToBlock`: using one writes the state. */
39
+ private stateSetters;
40
+ constructor(sf: ts.SourceFile, text: string, isReact: boolean);
38
41
  collectStatements(stmts: readonly ts.Statement[], parent: Block | null, depth: number, declarationsOnly?: boolean): void;
39
42
  private addImport;
40
43
  private addFunctionLike;
41
44
  private addClass;
42
45
  private collectMembers;
43
46
  private addVariableStatement;
47
+ /** `const [count, setCount] = useState(0)`: a state block named `count`; using `setCount` writes it. */
48
+ private addState;
44
49
  private addVariable;
45
50
  private add;
46
51
  /** Include doc comments directly above the node (no blank line in between). */
@@ -0,0 +1,30 @@
1
+ import ts from 'typescript';
2
+ import type { FileLanguage } from './types.js';
3
+ /**
4
+ * JavaScript or TypeScript, and whether React mode is on: a `.jsx`/`.tsx` file, a file with JSX in
5
+ * it, or a file that imports React.
6
+ */
7
+ export declare function fileLanguageOf(path: string, sf: ts.SourceFile): FileLanguage;
8
+ export declare function isJsx(node: ts.Node): boolean;
9
+ type FunctionNode = ts.FunctionDeclaration | ts.FunctionExpression | ts.ArrowFunction;
10
+ /** React only treats capitalized names as components: `<cart />` is an HTML tag. */
11
+ export declare const isComponentName: (name: string) => boolean;
12
+ /** A function that returns JSX from its own body (not from a callback inside it). */
13
+ export declare function returnsJsx(fn: ts.FunctionLikeDeclaration): boolean;
14
+ /**
15
+ * The function of a component assigned to a variable: an arrow or function that returns JSX, or
16
+ * the function inside `memo(…)` / `forwardRef(…)`, also nested.
17
+ */
18
+ export declare function componentFunctionOf(initializer: ts.Expression): FunctionNode | undefined;
19
+ /** `class Cart extends Component`, `extends React.PureComponent<Props>` */
20
+ export declare function isComponentClass(cls: ts.ClassLikeDeclaration): boolean;
21
+ /** `const [count, setCount] = useState(0)`: the hook call and the declarations of the value and its setter. */
22
+ export interface StateHook {
23
+ call: ts.CallExpression;
24
+ value?: ts.BindingElement | ts.VariableDeclaration;
25
+ setter?: ts.BindingElement;
26
+ }
27
+ export declare function stateHookOf(declaration: ts.VariableDeclaration): StateHook | undefined;
28
+ /** `useCart`, `useLocalStorage`: React runs functions named like this as hooks. */
29
+ export declare const isHookName: (name: string) => boolean;
30
+ export {};
@@ -1,3 +1,3 @@
1
1
  /** Canvas styles. Injected once. Hosts can override the CSS variables on `.cc-root`. */
2
- export declare const CSS = "\n.cc-root {\n --cc-bg: #15171c;\n --cc-dot: rgba(255,255,255,.07);\n --cc-frame-bg: rgba(255,255,255,.025);\n --cc-frame-border: rgba(255,255,255,.10);\n --cc-text: #e8eaee;\n --cc-muted: #9aa1ad;\n --cc-faint: #c4cad4;\n --cc-panel: #1f2229;\n --cc-panel-border: rgba(255,255,255,.12);\n --cc-accent: #7aa2ff;\n --cc-danger: #ff6b6b;\n --cc-shadow: 0 10px 30px rgba(0,0,0,.45);\n\n --k-import: #6b7280; --k-import-head: #3b3f46; --k-import-bg: #25272c;\n --k-class: #34b27a; --k-class-head: #1d6b4a; --k-class-bg: rgba(52,178,122,.08);\n --k-function: #ec5fa5; --k-function-head: #8f2f62; --k-function-bg: rgba(236,95,165,.09);\n --k-variable: #4b8ef7; --k-variable-head: #23508f; --k-variable-bg: rgba(75,142,247,.09);\n --k-type: #d4a92a; --k-type-head: #6e5714; --k-type-bg: rgba(212,169,42,.08);\n --k-namespace: #9b8cf8; --k-namespace-head: #4d4291; --k-namespace-bg: rgba(155,140,248,.08);\n --k-statement: #7c8799; --k-statement-head: #39414f; --k-statement-bg: rgba(124,135,153,.08);\n\n position: relative; overflow: hidden; width: 100%; height: 100%;\n background-color: var(--cc-bg);\n background-image: radial-gradient(var(--cc-dot) 1.2px, transparent 1.3px);\n color: var(--cc-text);\n font: 13px/1.3 ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif;\n touch-action: none; user-select: none; -webkit-user-select: none; outline: none;\n -webkit-tap-highlight-color: transparent;\n}\n.cc-root[data-theme=\"light\"] {\n --cc-bg: #f6f7f9; --cc-dot: rgba(0,0,0,.09);\n --cc-frame-bg: rgba(255,255,255,.7); --cc-frame-border: rgba(0,0,0,.12);\n --cc-text: #1d2129; --cc-muted: #5d6573; --cc-faint: #39404c;\n --cc-panel: #ffffff; --cc-panel-border: rgba(0,0,0,.12); --cc-accent: #3366e6;\n --cc-shadow: 0 10px 30px rgba(20,30,50,.18);\n --k-import: #6b7280; --k-import-head: #4b5058; --k-import-bg: #eceef1;\n --k-class: #1f9963; --k-class-head: #1f9963; --k-class-bg: rgba(31,153,99,.07);\n --k-function: #d63e8c; --k-function-head: #d63e8c; --k-function-bg: rgba(214,62,140,.07);\n --k-variable: #2f6fe0; --k-variable-head: #2f6fe0; --k-variable-bg: rgba(47,111,224,.07);\n --k-type: #b58a0c; --k-type-head: #a87f08; --k-type-bg: rgba(181,138,12,.08);\n --k-namespace: #6f5ce6; --k-namespace-head: #6f5ce6; --k-namespace-bg: rgba(111,92,230,.07);\n --k-statement: #64708a; --k-statement-head: #64708a; --k-statement-bg: rgba(100,112,138,.07);\n}\n.cc-world { position: absolute; left: 0; top: 0; transform-origin: 0 0; }\n.cc-root.cc-moving .cc-world { will-change: transform; }\n.cc-frame { position: absolute; border: 1px solid var(--cc-frame-border); background: var(--cc-frame-bg); border-radius: 18px; }\n.cc-frame-title { position: absolute; left: 20px; top: 12px; font: 600 15px/20px var(--cc-font, \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); color: var(--cc-muted); white-space: nowrap; }\n.cc-empty { position: absolute; font-size: 15px; color: var(--cc-muted); white-space: nowrap; }\n\n.cc-block {\n position: absolute; left: 0; top: 0; box-sizing: border-box; border-radius: 10px;\n border: 1.5px solid var(--k); background: var(--kbg); overflow: hidden; contain: layout style;\n cursor: default;\n}\n.cc-block.k-import { --k: var(--k-import); --kh: var(--k-import-head); --kbg: var(--k-import-bg); }\n.cc-block.k-class { --k: var(--k-class); --kh: var(--k-class-head); --kbg: var(--k-class-bg); }\n.cc-block.k-function { --k: var(--k-function); --kh: var(--k-function-head); --kbg: var(--k-function-bg); }\n.cc-block.k-variable { --k: var(--k-variable); --kh: var(--k-variable-head); --kbg: var(--k-variable-bg); }\n.cc-block.k-type { --k: var(--k-type); --kh: var(--k-type-head); --kbg: var(--k-type-bg); }\n.cc-block.k-namespace { --k: var(--k-namespace); --kh: var(--k-namespace-head); --kbg: var(--k-namespace-bg); }\n.cc-block.k-statement { --k: var(--k-statement); --kh: var(--k-statement-head); --kbg: var(--k-statement-bg); }\n.cc-block.k-import, .cc-root:not([data-theme=\"light\"]) .cc-block.k-import { border-color: #555a63; }\n\n.cc-head {\n display: flex; align-items: center; gap: 7px; height: 32px; padding: 0 10px; box-sizing: border-box;\n background: var(--kh); color: #fff; white-space: nowrap; overflow: hidden;\n font: 13px/32px var(--cc-font, \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);\n}\n.cc-kind { font-size: 10px; text-transform: uppercase; letter-spacing: .06em; opacity: .75; flex: none; }\n.cc-name { font-weight: 700; flex: none; max-width: 70%; overflow: hidden; text-overflow: ellipsis; }\n.cc-detail { opacity: .8; overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 1 1 auto; }\n.cc-tags { font-size: 10px; opacity: .7; flex: none; }\n.cc-exp { width: 6px; height: 6px; border-radius: 50%; background: #fff; opacity: .8; flex: none; }\n.cc-fold {\n flex: none; margin-left: auto; width: 22px; height: 22px; border: 0; border-radius: 6px; padding: 0;\n background: rgba(255,255,255,.14); color: #fff; font-size: 12px; line-height: 22px; cursor: pointer;\n}\n.cc-fold:hover { background: rgba(255,255,255,.28); }\n.cc-prev {\n margin: 0; padding: 5px 12px 0; white-space: pre; overflow: hidden; color: var(--cc-faint); opacity: .5;\n font: 11px/15px var(--cc-font, \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);\n}\n.cc-more { opacity: .7; font-style: italic; }\n.cc-mini { position: relative; margin: 6px 12px 0; height: 34px; opacity: .45; }\n.cc-mini > i { position: absolute; border-radius: 2px; border: 1px solid var(--cc-faint); background: rgba(255,255,255,.06); }\n.cc-mini > i.k-class { border-color: var(--k-class); } .cc-mini > i.k-function { border-color: var(--k-function); }\n.cc-mini > i.k-variable { border-color: var(--k-variable); } .cc-mini > i.k-type { border-color: var(--k-type); }\n\n.cc-err {\n flex: none; min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box; border-radius: 9px;\n background: var(--cc-danger); color: #fff; font: 700 11px/18px ui-sans-serif, system-ui, sans-serif; text-align: center;\n}\n.cc-block.cc-has-error { border-color: var(--cc-danger); }\n.cc-root.lod-2 .cc-err { min-width: 34px; height: 34px; border-radius: 17px; font-size: 22px; line-height: 34px; }\n.cc-rename {\n font: inherit; font-weight: 700; color: #fff; background: rgba(0,0,0,.35); border: 1px solid var(--cc-accent);\n border-radius: 4px; padding: 0 4px; height: 22px; outline: none; user-select: text; -webkit-user-select: text; max-width: 100%;\n}\n.cc-rename.invalid { border-color: var(--cc-danger); }\n.cc-name:has(.cc-rename) { max-width: none; overflow: visible; }\n\n/* merge conflicts */\n.cc-block.cc-conflict { border-color: #f0883e; box-shadow: 0 0 0 2px rgba(240, 136, 62, .35); }\n.cc-conflict-chip {\n flex: none; min-width: 18px; height: 18px; border-radius: 9px; background: #f0883e; color: #1b1300;\n font: 900 13px/18px ui-sans-serif, system-ui, sans-serif; text-align: center;\n}\n.cc-root.lod-2 .cc-conflict-chip { min-width: 34px; height: 34px; border-radius: 17px; font-size: 24px; line-height: 34px; }\n.cc-block.cc-conflict-incoming {\n --k: #f0883e; --kh: #8a4a17; --kbg: rgba(240, 136, 62, .08);\n border-style: dashed; pointer-events: none; opacity: .9;\n}\n.cc-diff-chip.incoming { background: #f0883e; }\n.cc-banner.cc-banner-conflicts { border-color: #f0883e; }\n\n/* changes against a base version (setDiffBase) */\n.cc-block.cc-diff-unchanged { filter: saturate(.3) brightness(.92); }\n.cc-diff-chip {\n flex: none; min-width: 18px; height: 18px; padding: 0 4px; box-sizing: border-box; border-radius: 5px;\n font: 800 13px/18px ui-sans-serif, system-ui, sans-serif; text-align: center; color: #fff;\n}\n.cc-diff-chip.added { background: #2ea043; }\n.cc-diff-chip.changed { background: #d29922; }\n.cc-diff-chip.removed { background: var(--cc-danger); }\n.cc-root.lod-2 .cc-diff-chip { min-width: 34px; height: 34px; border-radius: 8px; font-size: 24px; line-height: 34px; }\n.cc-block.cc-diff-removed {\n --k: var(--cc-danger); --kh: #9c2f2f; --kbg: rgba(255, 107, 107, .10);\n border-style: dashed; pointer-events: none; opacity: .9;\n}\n.cc-root[data-theme=\"light\"] .cc-block.cc-diff-removed { --kh: #d64545; --kbg: rgba(214, 69, 69, .08); }\n.cc-prev.cc-diff-prev { opacity: .95; }\n.cc-diff-prev > span { display: block; margin: 0 -12px; padding: 0 12px; }\n.cc-diff-prev .cc-line-same { opacity: .5; }\n.cc-diff-prev .cc-line-added { background: rgba(46, 160, 67, .30); }\n.cc-diff-prev .cc-line-removed { background: rgba(248, 81, 73, .26); text-decoration: line-through; text-decoration-color: rgba(248, 81, 73, .7); }\n.cc-diff-summary { padding: 0 8px; font-size: 12px; color: var(--cc-muted); white-space: nowrap; }\n\n.cc-block.cc-sel { box-shadow: 0 0 0 2px var(--cc-bg), 0 0 0 4px var(--k); }\n.cc-block.cc-editing { box-shadow: 0 0 0 2px var(--cc-bg), 0 0 0 4px var(--cc-accent); }\n.cc-block.cc-dragging { box-shadow: var(--cc-shadow); opacity: .92; z-index: 9999 !important; }\n.cc-root.has-hl .cc-block.cc-linked { box-shadow: 0 0 0 2px var(--k); }\n\n.cc-edges { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }\n.cc-edge { fill: none; stroke-width: 1.5; opacity: .22; }\n.cc-edge.u-type { stroke-dasharray: 4 4; }\n.cc-root.has-hl .cc-edge { opacity: .07; }\n.cc-root.has-hl .cc-edge.hl { opacity: .95; stroke-width: 2.5; }\n\n/* level of detail when zoomed out */\n.cc-root.lod-1 .cc-tags { visibility: hidden; }\n.cc-root.lod-2 .cc-prev, .cc-root.lod-2 .cc-detail, .cc-root.lod-2 .cc-mini { visibility: hidden; }\n.cc-root.lod-2 .cc-head { font-size: 26px; }\n.cc-root.lod-2 .cc-kind, .cc-root.lod-2 .cc-fold { display: none; }\n.cc-root.lod-2 .cc-frame-title { font-size: 40px; line-height: 44px; top: -8px; }\n\n/* overlays (screen space) */\n.cc-banner {\n position: absolute; left: 50%; top: 12px; transform: translateX(-50%); z-index: 20; display: flex; gap: 10px; align-items: center;\n padding: 8px 12px; border-radius: 10px; background: var(--cc-panel); border: 1px solid var(--cc-danger); box-shadow: var(--cc-shadow);\n font-size: 13px; max-width: calc(100% - 32px);\n}\n.cc-banner[hidden], .cc-bar[hidden], .cc-refs[hidden] { display: none; }\n.cc-toast {\n position: absolute; left: 50%; bottom: 76px; transform: translateX(-50%); z-index: 30; padding: 8px 14px; border-radius: 10px;\n background: var(--cc-panel); border: 1px solid var(--cc-panel-border); box-shadow: var(--cc-shadow); font-size: 13px;\n transition: opacity .2s; pointer-events: none; max-width: calc(100% - 32px);\n}\n.cc-bar {\n position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%); z-index: 20; display: flex; align-items: center; gap: 4px;\n padding: 5px; border-radius: 12px; background: var(--cc-panel); border: 1px solid var(--cc-panel-border); box-shadow: var(--cc-shadow);\n width: max-content; max-width: calc(100% - 24px); box-sizing: border-box; flex-wrap: wrap; justify-content: center;\n}\n.cc-bar .cc-chip { padding: 0 10px 0 6px; font: 600 12px/30px var(--cc-font, \"JetBrains Mono\", ui-monospace, Menlo, monospace); white-space: nowrap; display: flex; align-items: center; gap: 6px; max-width: 220px; overflow: hidden; text-overflow: ellipsis; }\n.cc-bar .cc-chip i { width: 10px; height: 10px; border-radius: 3px; background: var(--k); flex: none; }\n.cc-btn {\n border: 0; background: transparent; color: var(--cc-text); font: 500 13px/30px inherit; font-family: inherit; padding: 0 10px; border-radius: 8px;\n cursor: pointer; white-space: nowrap; min-height: 32px;\n}\n.cc-btn:hover { background: rgba(127,127,127,.16); }\n.cc-btn.danger { color: var(--cc-danger); }\n.cc-btn.primary { background: var(--cc-accent); color: #fff; }\n.cc-sep { width: 1px; height: 20px; background: var(--cc-panel-border); margin: 0 2px; flex: none; }\n.cc-refs {\n position: absolute; left: 50%; bottom: 64px; transform: translateX(-50%); z-index: 21; width: min(360px, calc(100% - 24px)); max-height: 45%;\n overflow: auto; border-radius: 12px; background: var(--cc-panel); border: 1px solid var(--cc-panel-border); box-shadow: var(--cc-shadow); padding: 6px;\n}\n.cc-refs h4 { margin: 8px 8px 4px; font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--cc-muted); }\n.cc-refs button {\n display: flex; width: 100%; align-items: center; gap: 8px; border: 0; background: transparent; color: var(--cc-text); text-align: left;\n padding: 6px 8px; border-radius: 8px; cursor: pointer; font: 12px/18px var(--cc-font, \"JetBrains Mono\", ui-monospace, Menlo, monospace);\n}\n.cc-refs button:hover { background: rgba(127,127,127,.16); }\n.cc-refs button i { width: 10px; height: 10px; border-radius: 3px; background: var(--k); flex: none; }\n.cc-refs button span:last-child { margin-left: auto; color: var(--cc-muted); }\n.cc-refs button:disabled { cursor: default; opacity: .7; }\n.cc-refs button:disabled:hover { background: transparent; }\n.cc-refs .cc-file { color: var(--cc-muted); }\n.cc-refs .cc-error-row { --k: var(--cc-danger); align-items: flex-start; }\n.cc-refs .cc-error-row i { border-radius: 50%; margin-top: 4px; }\n.cc-refs .cc-error-row span:nth-child(2) { white-space: pre-wrap; font-family: ui-sans-serif, system-ui, sans-serif; }\n.cc-refs .cc-error-row span:last-child { white-space: nowrap; }\n.cc-refs .none { padding: 4px 8px 8px; color: var(--cc-muted); font-size: 12px; }\n\n.cc-editor {\n position: absolute; z-index: 25; display: flex; flex-direction: column; border-radius: 12px; overflow: hidden;\n background: var(--cc-panel); border: 1px solid var(--cc-panel-border); box-shadow: var(--cc-shadow);\n}\n.cc-editor-head { display: flex; align-items: center; gap: 8px; padding: 4px 6px 4px 12px; border-bottom: 1px solid var(--cc-panel-border); }\n.cc-editor-head .cc-chip { flex: 1; min-width: 0; font: 600 12px/30px var(--cc-font, \"JetBrains Mono\", ui-monospace, Menlo, monospace); display: flex; align-items: center; gap: 6px; overflow: hidden; white-space: nowrap; }\n.cc-editor-head .cc-chip i { width: 10px; height: 10px; border-radius: 3px; background: var(--k); flex: none; }\n.cc-editor-body { flex: 1; min-height: 0; overflow: auto; user-select: text; -webkit-user-select: text; touch-action: auto; }\n.cc-editor-hint { font-size: 11px; color: var(--cc-muted); white-space: nowrap; }\n@media (max-width: 640px) { .cc-editor-hint { display: none; } }\n";
2
+ export declare const CSS = "\n.cc-root {\n --cc-bg: #0c0d0f;\n --cc-dot: #25272c;\n --cc-frame-bg: rgba(255,255,255,.015);\n --cc-frame-border: #2e3036;\n --cc-node-bg: #16171a;\n --cc-node-border: #2b2d33;\n --cc-node-head-border: #24262b;\n --cc-text: #e6e7ea;\n --cc-strong: #f2f2f3;\n --cc-muted: #a9adb6;\n --cc-faint: #8b8f98;\n --cc-faintest: #6e727b;\n --cc-code: #c9ccd2;\n --cc-panel: #16171a;\n --cc-surface2: #1c1d21;\n --cc-raised: #2a2c31;\n --cc-panel-border: #26282d;\n --cc-accent: #e8c27a;\n --cc-ink: #e8c27a;\n --cc-on-accent: #1a1408;\n --cc-danger: #f2877d;\n --cc-shadow: 0 10px 30px rgba(0,0,0,.35);\n --cc-shadow-sm: 0 1px 0 rgba(0,0,0,.2);\n --cc-shadow-lg: 0 24px 60px rgba(0,0,0,.55);\n --cc-syn-kw: #c3a6f0;\n --cc-syn-str: #9fd3ec;\n --cc-syn-type: #b8c4ff;\n --cc-syn-com: #7d828c;\n --cc-syn-con: #7cc4e8;\n --cc-ui-font: Inter, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif;\n\n --k-import: #b4b9c2;\n --k-variable: #7cc4e8;\n --k-function: #e8c27a;\n --k-class: #8fd0a5;\n --k-type: #b8b0f0;\n --k-component: #5fd1b5;\n --k-state: #f0a36a;\n --k-namespace: #9aa6bd;\n --k-statement: #8b8f98;\n\n position: relative; overflow: hidden; width: 100%; height: 100%;\n background-color: var(--cc-bg);\n background-image: radial-gradient(circle, var(--cc-dot) 1px, transparent 1.4px);\n color: var(--cc-text);\n font: 13px/1.3 var(--cc-ui-font);\n touch-action: none; user-select: none; -webkit-user-select: none; outline: none;\n -webkit-tap-highlight-color: transparent;\n}\n.cc-root[data-theme=\"light\"] {\n --cc-bg: #f3f3f1; --cc-dot: #d4d4cf;\n --cc-frame-bg: rgba(255,255,255,.5); --cc-frame-border: #cfcfc9;\n --cc-node-bg: #ffffff; --cc-node-border: #dadad4; --cc-node-head-border: #edede9;\n --cc-text: #1f2023; --cc-strong: #0f1012; --cc-muted: #4a4d55; --cc-faint: #5f626a; --cc-faintest: #8a8d94; --cc-code: #2e3036;\n --cc-panel: #ffffff; --cc-surface2: #f5f5f3; --cc-raised: #ececE8; --cc-panel-border: #e1e1dc;\n --cc-ink: #8a5d0e; --cc-danger: #b4362b;\n --cc-shadow: 0 8px 24px rgba(20,20,10,.08); --cc-shadow-sm: 0 1px 2px rgba(20,20,10,.06); --cc-shadow-lg: 0 24px 60px rgba(20,20,10,.18);\n --cc-syn-kw: #7a3fc0; --cc-syn-str: #1d6a92; --cc-syn-type: #3b4fb0; --cc-syn-com: #6f737b; --cc-syn-con: #1d6a92;\n --k-import: #555a63; --k-variable: #1d6a92; --k-function: #8a5d0e; --k-class: #2f7a4a; --k-type: #5a4bb0;\n --k-component: #11756a; --k-state: #a8521a; --k-namespace: #4f5b73; --k-statement: #5f626a;\n}\n.cc-world { position: absolute; left: 0; top: 0; transform-origin: 0 0; }\n.cc-root.cc-moving .cc-world { will-change: transform; }\n.cc-root.cc-tool-pan, .cc-root.cc-tool-pan .cc-block { cursor: grab; }\n.cc-mono { font-family: var(--cc-font, \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); }\n.cc-frame { position: absolute; border: 1px dashed var(--cc-frame-border); background: var(--cc-frame-bg); border-radius: 18px; }\n.cc-frame-title {\n position: absolute; left: 20px; top: 14px; display: flex; align-items: center; gap: 8px; white-space: nowrap;\n font: 12px/18px var(--cc-font, \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);\n}\n.cc-frame-folder { color: var(--cc-faint); }\n.cc-frame-file { color: var(--cc-text); font-weight: 500; }\n.cc-frame-count { padding: 2px 6px; border-radius: 5px; background: var(--cc-surface2); color: var(--cc-faint); font-size: 10.5px; line-height: 14px; }\n.cc-frame-count:empty { display: none; }\n.cc-empty { position: absolute; font-size: 15px; color: var(--cc-muted); white-space: nowrap; }\n\n.cc-block {\n --kglyph: color-mix(in srgb, var(--k) 16%, transparent);\n position: absolute; left: 0; top: 0; box-sizing: border-box; border-radius: 12px;\n border: 1px solid var(--cc-node-border); background: var(--cc-node-bg); overflow: hidden; contain: layout style;\n box-shadow: var(--cc-shadow-sm); cursor: default; transition: opacity 160ms ease, box-shadow 160ms ease;\n}\n.cc-root[data-theme=\"light\"] .cc-block { --kglyph: color-mix(in srgb, var(--k) 10%, transparent); }\n.cc-block.k-import { --k: var(--k-import); }\n.cc-block.k-class { --k: var(--k-class); }\n.cc-block.k-function { --k: var(--k-function); }\n.cc-block.k-component { --k: var(--k-component); }\n.cc-block.k-state { --k: var(--k-state); }\n.cc-block.k-variable { --k: var(--k-variable); }\n.cc-block.k-type { --k: var(--k-type); }\n.cc-block.k-namespace { --k: var(--k-namespace); }\n.cc-block.k-statement { --k: var(--k-statement); }\n\n.cc-head {\n display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 10px; box-sizing: border-box;\n border-bottom: 1px solid var(--cc-node-head-border); color: var(--cc-strong); white-space: nowrap; overflow: hidden;\n font: 12.5px/34px var(--cc-font, \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);\n}\n.cc-glyph {\n flex: none; width: 18px; min-width: 18px; height: 18px; padding: 0 2px; box-sizing: border-box; border-radius: 5px;\n background: var(--kglyph); color: var(--k); display: flex; align-items: center; justify-content: center;\n font: 600 10.5px/18px var(--cc-font, \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); letter-spacing: -.04em;\n}\n.k-component > .cc-head .cc-glyph, .k-namespace > .cc-head .cc-glyph { width: auto; }\n.cc-name { font-weight: 600; flex: none; max-width: 70%; overflow: hidden; text-overflow: ellipsis; }\n.cc-detail { font-size: 11.5px; color: var(--cc-faint); overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 1 1 auto; }\n.cc-tag {\n flex: none; padding: 0 7px; border-radius: 6px; background: var(--kglyph); color: var(--k);\n font: 500 10.5px/18px var(--cc-ui-font);\n}\n.cc-exp { width: 5px; height: 5px; border-radius: 50%; background: var(--cc-faint); flex: none; }\n.cc-fold {\n flex: none; margin-left: auto; width: 22px; height: 22px; border: 0; border-radius: 6px; padding: 0;\n background: transparent; color: var(--cc-faint); font-size: 12px; line-height: 22px; cursor: pointer;\n}\n.cc-fold:hover { background: var(--cc-raised); color: var(--cc-strong); }\n.cc-prev {\n margin: 0; padding: 7px 12px 9px; white-space: pre; overflow: hidden; color: var(--cc-code);\n font: 11.5px/19px var(--cc-font, \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);\n}\n.cc-prev .s-kw { color: var(--cc-syn-kw); }\n.cc-prev .s-str { color: var(--cc-syn-str); }\n.cc-prev .s-type { color: var(--cc-syn-type); }\n.cc-prev .s-com { color: var(--cc-syn-com); }\n.cc-prev .s-con { color: var(--cc-syn-con); }\n.k-import > .cc-prev { color: var(--cc-muted); }\n.cc-more { color: var(--cc-faintest); font-style: italic; }\n.cc-mini { position: relative; margin: 6px 12px 0; height: 34px; opacity: .55; }\n.cc-mini > i { position: absolute; border-radius: 2px; border: 1px solid var(--cc-faint); background: transparent; }\n.cc-mini > i.k-class { border-color: var(--k-class); } .cc-mini > i.k-function { border-color: var(--k-function); }\n.cc-mini > i.k-component { border-color: var(--k-component); } .cc-mini > i.k-state { border-color: var(--k-state); }\n.cc-mini > i.k-variable { border-color: var(--k-variable); } .cc-mini > i.k-type { border-color: var(--k-type); }\n\n.cc-err {\n flex: none; min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box; border-radius: 9px;\n background: var(--cc-danger); color: #fff; font: 700 11px/18px ui-sans-serif, system-ui, sans-serif; text-align: center;\n}\n.cc-block.cc-has-error { border-color: var(--cc-danger); }\n.cc-err { color: #1a0d0b; }\n.cc-root.lod-2 .cc-err { min-width: 34px; height: 34px; border-radius: 17px; font-size: 22px; line-height: 34px; }\n.cc-rename {\n font: inherit; font-weight: 600; color: var(--cc-strong); background: var(--cc-raised); border: 1px solid var(--cc-ink);\n border-radius: 4px; padding: 0 4px; height: 22px; outline: none; user-select: text; -webkit-user-select: text; max-width: 100%;\n}\n.cc-rename.invalid { border-color: var(--cc-danger); }\n.cc-name:has(.cc-rename) { max-width: none; overflow: visible; }\n\n/* merge conflicts */\n.cc-block.cc-conflict { border-color: #f0883e; box-shadow: 0 0 0 2px rgba(240, 136, 62, .35); }\n.cc-conflict-chip {\n flex: none; min-width: 18px; height: 18px; border-radius: 9px; background: #f0883e; color: #1b1300;\n font: 900 13px/18px ui-sans-serif, system-ui, sans-serif; text-align: center;\n}\n.cc-root.lod-2 .cc-conflict-chip { min-width: 34px; height: 34px; border-radius: 17px; font-size: 24px; line-height: 34px; }\n.cc-block.cc-conflict-incoming { --k: #f0883e; border: 1px dashed #f0883e; pointer-events: none; opacity: .9; }\n.cc-diff-chip.incoming { background: #f0883e; }\n.cc-banner.cc-banner-conflicts { border-color: #f0883e; }\n\n/* changes against a base version (setDiffBase) */\n.cc-block.cc-diff-unchanged { filter: saturate(.3) brightness(.92); }\n.cc-diff-chip {\n flex: none; min-width: 18px; height: 18px; padding: 0 4px; box-sizing: border-box; border-radius: 5px;\n font: 800 13px/18px ui-sans-serif, system-ui, sans-serif; text-align: center; color: #fff;\n}\n.cc-diff-chip.added { background: #2ea043; }\n.cc-diff-chip.changed { background: #d29922; }\n.cc-diff-chip.removed { background: var(--cc-danger); }\n.cc-root.lod-2 .cc-diff-chip { min-width: 34px; height: 34px; border-radius: 8px; font-size: 24px; line-height: 34px; }\n.cc-block.cc-diff-removed {\n --k: var(--cc-danger); border: 1px dashed var(--cc-danger); background: color-mix(in srgb, var(--cc-danger) 8%, var(--cc-node-bg));\n pointer-events: none; opacity: .9;\n}\n.cc-prev.cc-diff-prev { opacity: .95; }\n.cc-diff-prev > span { display: block; margin: 0 -12px; padding: 0 12px; }\n.cc-diff-prev .cc-line-same { opacity: .5; }\n.cc-diff-prev .cc-line-added { background: rgba(46, 160, 67, .30); }\n.cc-diff-prev .cc-line-removed { background: rgba(248, 81, 73, .26); text-decoration: line-through; text-decoration-color: rgba(248, 81, 73, .7); }\n.cc-diff-summary { padding: 0 8px; font-size: 12px; color: var(--cc-muted); white-space: nowrap; }\n\n.cc-block.cc-sel { box-shadow: 0 0 0 2px var(--cc-ink), var(--cc-shadow-lg); }\n.cc-block.cc-editing { box-shadow: 0 0 0 2px var(--cc-ink), var(--cc-shadow-lg); }\n.cc-block.cc-dragging { box-shadow: var(--cc-shadow-lg); opacity: .92; z-index: 9999 !important; }\n.cc-root.has-sel .cc-block:not(.cc-related) { opacity: .38; }\n\n.cc-edges { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }\n.cc-edge { fill: none; stroke: var(--edge); stroke-width: 1.5; opacity: .5; }\n.cc-edge.to-import, .cc-edge.u-type { stroke-dasharray: 3 4; }\n.cc-root.has-hl .cc-edge { opacity: .18; }\n.cc-root.has-hl .cc-edge.hl { stroke: var(--cc-ink); opacity: .95; stroke-width: 2; }\n\n/* level of detail when zoomed out */\n.cc-root.lod-1 .cc-tag { visibility: hidden; }\n.cc-root.lod-2 .cc-prev, .cc-root.lod-2 .cc-detail, .cc-root.lod-2 .cc-mini { visibility: hidden; }\n.cc-root.lod-2 .cc-head { font-size: 26px; }\n.cc-root.lod-2 .cc-glyph, .cc-root.lod-2 .cc-fold, .cc-root.lod-2 .cc-tag { display: none; }\n.cc-root.lod-2 .cc-frame-title { font-size: 40px; line-height: 44px; top: -8px; }\n.cc-root.lod-2 .cc-frame-count { font-size: 28px; line-height: 36px; padding: 2px 12px; border-radius: 10px; }\n\n/* overlays (screen space) */\n.cc-banner {\n position: absolute; left: 50%; top: 12px; transform: translateX(-50%); z-index: 20; display: flex; gap: 10px; align-items: center;\n padding: 8px 12px; border-radius: 10px; background: var(--cc-panel); border: 1px solid var(--cc-danger); box-shadow: var(--cc-shadow);\n font-size: 13px; max-width: calc(100% - 32px);\n}\n.cc-banner[hidden], .cc-bar[hidden], .cc-refs[hidden], .cc-selbar[hidden], .cc-menu[hidden] { display: none; }\n.cc-toast {\n position: absolute; left: 50%; bottom: 76px; transform: translateX(-50%); z-index: 30; padding: 8px 14px; border-radius: 10px;\n background: var(--cc-panel); border: 1px solid var(--cc-panel-border); box-shadow: var(--cc-shadow); font-size: 13px;\n transition: opacity .2s; pointer-events: none; max-width: calc(100% - 32px);\n}\n.cc-bar {\n position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%); z-index: 20; display: flex; align-items: center; gap: 2px;\n padding: 4px; border-radius: 12px; background: var(--cc-panel); border: 1px solid var(--cc-panel-border); box-shadow: var(--cc-shadow);\n width: max-content; max-width: calc(100% - 24px); box-sizing: border-box; flex-wrap: wrap; justify-content: center;\n}\n.cc-btn {\n display: inline-flex; align-items: center; justify-content: center; border: 0; background: transparent; color: var(--cc-muted);\n font: 400 13px/32px var(--cc-ui-font); padding: 0 12px; border-radius: 8px; cursor: pointer; white-space: nowrap; height: 32px; box-sizing: border-box;\n}\n.cc-btn:hover { background: var(--cc-raised); color: var(--cc-strong); }\n.cc-btn:focus-visible { outline: 2px solid var(--cc-ink); outline-offset: -2px; }\n.cc-btn.strong { color: var(--cc-strong); font-weight: 500; }\n.cc-btn.square { padding: 0; min-width: 30px; }\n.cc-btn.on { background: var(--cc-raised); color: var(--cc-strong); }\n.cc-btn.danger { color: var(--cc-danger); }\n.cc-btn.primary { background: var(--cc-accent); color: var(--cc-on-accent); font-weight: 600; }\n.cc-btn.primary:hover { filter: brightness(1.06); }\n.cc-zoom { min-width: 44px; text-align: center; font: 12px/32px var(--cc-font, \"JetBrains Mono\", ui-monospace, Menlo, monospace); color: var(--cc-muted); }\n.cc-language { padding: 0 8px; font: 500 11px/32px var(--cc-font, \"JetBrains Mono\", ui-monospace, Menlo, monospace); color: var(--cc-faint); white-space: nowrap; }\n.cc-sep { width: 1px; height: 20px; background: var(--cc-panel-border); margin: 0 4px; flex: none; }\n.cc-selbar {\n position: absolute; z-index: 19; display: flex; align-items: center; gap: 2px; padding: 3px; border-radius: 10px; white-space: nowrap;\n background: var(--cc-panel); border: 1px solid var(--cc-panel-border); box-shadow: var(--cc-shadow);\n}\n.cc-selbar .cc-btn { height: 26px; line-height: 26px; padding: 0 9px; border-radius: 7px; font-size: 12px; color: var(--cc-strong); }\n.cc-selbar .cc-btn.square { padding: 0; min-width: 26px; color: var(--cc-faint); }\n.cc-selbar .cc-btn.meta { color: var(--cc-faint); font-size: 11.5px; padding: 0 8px; }\n.cc-selbar .cc-btn.danger { color: var(--cc-danger); }\n.cc-selbar .cc-btn.primary { color: var(--cc-on-accent); }\n.cc-selbar .cc-sep { height: 16px; margin: 0 2px; }\n.cc-menu {\n position: absolute; z-index: 40; display: flex; flex-direction: column; min-width: 168px; padding: 4px; border-radius: 10px;\n background: var(--cc-panel); border: 1px solid var(--cc-panel-border); box-shadow: var(--cc-shadow-lg);\n}\n.cc-menu .cc-btn { justify-content: flex-start; height: 30px; line-height: 30px; padding: 0 10px; border-radius: 7px; font-size: 12.5px; color: var(--cc-text); }\n.cc-menu .cc-btn.danger { color: var(--cc-danger); }\n.cc-minimap {\n position: absolute; right: var(--cc-minimap-right, 12px); bottom: var(--cc-minimap-bottom, 12px); z-index: 18; width: 148px; height: 92px;\n box-sizing: border-box; border-radius: 10px; overflow: hidden; background: var(--cc-panel); border: 1px solid var(--cc-panel-border); cursor: pointer;\n}\n.cc-minimap-blocks { position: absolute; left: 10px; top: 13px; width: 128px; height: 66px; }\n.cc-minimap-blocks > i { position: absolute; border-radius: 2px; background: var(--k); opacity: .55; }\n.cc-minimap-view { position: absolute; left: 10px; top: 13px; box-sizing: border-box; border: 1.5px solid var(--cc-ink); border-radius: 6px; margin: 13px 0 0 10px; pointer-events: none; }\n@media (max-width: 640px) { .cc-minimap { display: none; } }\n.cc-refs {\n position: absolute; left: 50%; bottom: 64px; transform: translateX(-50%); z-index: 21; width: min(360px, calc(100% - 24px)); max-height: 45%;\n overflow: auto; border-radius: 12px; background: var(--cc-panel); border: 1px solid var(--cc-panel-border); box-shadow: var(--cc-shadow); padding: 6px;\n}\n.cc-refs h4 { margin: 8px 8px 4px; font: 600 11px/16px var(--cc-ui-font); text-transform: uppercase; letter-spacing: .06em; color: var(--cc-faint); }\n.cc-refs button {\n display: flex; width: 100%; align-items: center; gap: 8px; border: 0; background: transparent; color: var(--cc-text); text-align: left;\n padding: 6px 8px; border-radius: 8px; cursor: pointer; font: 12px/18px var(--cc-font, \"JetBrains Mono\", ui-monospace, Menlo, monospace);\n}\n.cc-refs button:hover { background: var(--cc-raised); }\n.cc-refs button i { width: 10px; height: 10px; border-radius: 3px; background: var(--k); flex: none; }\n.cc-refs button span:last-child { margin-left: auto; color: var(--cc-muted); }\n.cc-refs button:disabled { cursor: default; opacity: .7; }\n.cc-refs button:disabled:hover { background: transparent; }\n.cc-refs .cc-file { color: var(--cc-muted); }\n.cc-refs .cc-error-row { --k: var(--cc-danger); align-items: flex-start; }\n.cc-refs .cc-error-row i { border-radius: 50%; margin-top: 4px; }\n.cc-refs .cc-error-row span:nth-child(2) { white-space: pre-wrap; font-family: ui-sans-serif, system-ui, sans-serif; }\n.cc-refs .cc-error-row span:last-child { white-space: nowrap; }\n.cc-refs .none { padding: 4px 8px 8px; color: var(--cc-muted); font-size: 12px; }\n\n.cc-editor {\n position: absolute; z-index: 25; display: flex; flex-direction: column; border-radius: 12px; overflow: hidden;\n background: var(--cc-panel); border: 1px solid var(--cc-panel-border); box-shadow: var(--cc-shadow);\n}\n.cc-editor-head { display: flex; align-items: center; gap: 8px; padding: 4px 6px 4px 12px; border-bottom: 1px solid var(--cc-panel-border); }\n.cc-editor-head .cc-chip { flex: 1; min-width: 0; font: 600 12px/30px var(--cc-font, \"JetBrains Mono\", ui-monospace, Menlo, monospace); display: flex; align-items: center; gap: 6px; overflow: hidden; white-space: nowrap; }\n.cc-editor-head .cc-chip i { width: 10px; height: 10px; border-radius: 3px; background: var(--k); flex: none; }\n.cc-editor-body { flex: 1; min-height: 0; overflow: auto; user-select: text; -webkit-user-select: text; touch-action: auto; }\n.cc-editor-hint { font-size: 11px; color: var(--cc-muted); white-space: nowrap; }\n@media (max-width: 640px) { .cc-editor-hint { display: none; } }\n";
3
3
  export declare function injectStyles(doc?: Document): void;
@@ -0,0 +1,3 @@
1
+ import ts from 'typescript';
2
+ /** The expression inside parentheses and type assertions: `(x as Y)` → `x`. */
3
+ export declare function unwrap(e: ts.Expression): ts.Expression;
@@ -1,5 +1,5 @@
1
1
  /** What a block represents. Each kind has its own color on the canvas. */
2
- export type BlockKind = 'import' | 'class' | 'function' | 'variable' | 'type' | 'namespace' | 'statement';
2
+ export type BlockKind = 'import' | 'class' | 'function' | 'component' | 'state' | 'variable' | 'type' | 'namespace' | 'statement';
3
3
  /** Where new child code goes when a block is used as a container. */
4
4
  export type InsertStyle = 'class' | 'body' | null;
5
5
  export interface Block {
@@ -32,7 +32,8 @@ export interface Block {
32
32
  /** Indentation of the line the block starts on. */
33
33
  indent: string;
34
34
  }
35
- export type UsageKind = 'call' | 'read' | 'write' | 'type';
35
+ /** `render`: a component used as a JSX tag, `<Cart />`. */
36
+ export type UsageKind = 'call' | 'render' | 'read' | 'write' | 'type';
36
37
  /** A line on the canvas: code in `from` uses the declaration in `to`. */
37
38
  export interface Usage {
38
39
  from: string;
@@ -75,6 +76,18 @@ export interface FileModel {
75
76
  diagnostics: CodeDiagnostic[];
76
77
  /** Indentation unit detected in the file. */
77
78
  indentUnit: string;
79
+ language: FileLanguage;
80
+ }
81
+ export type LanguageLabel = 'JS' | 'TS' | 'React JS' | 'React TS' | 'React JSX' | 'React TSX';
82
+ /** What the file is written in. React mode recognizes components, state and render links. */
83
+ export interface FileLanguage {
84
+ script: 'js' | 'ts';
85
+ /** A `.jsx`/`.tsx` file, or a file with JSX in it. */
86
+ hasJsx: boolean;
87
+ /** React mode: the file has JSX or imports `react`, `react-dom` or `react-native`. */
88
+ isReact: boolean;
89
+ /** Shown on the canvas toolbar. */
90
+ label: LanguageLabel;
78
91
  }
79
92
  export interface Point {
80
93
  x: number;
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@codecanvas-ide/engine",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "The canvas of CodeCanvas: TypeScript and JavaScript files as an editable diagram of blocks, with usage links, references across files, rename, errors, diffs and merge conflicts.",
5
5
  "keywords": [
6
6
  "typescript",
7
7
  "javascript",
8
+ "react",
8
9
  "code-visualization",
9
10
  "diagram",
10
11
  "canvas",