restores code editor
This commit is contained in:
parent
badda0bb1c
commit
059d704404
23 changed files with 1944 additions and 129 deletions
|
@ -1,11 +1,9 @@
|
|||
// This is the code library.
|
||||
|
||||
export default `
|
||||
new Circle({
|
||||
point: [200, 200],
|
||||
})
|
||||
|
||||
new Rectangle({
|
||||
point: [400, 300],
|
||||
})
|
||||
class Circle {
|
||||
greet(): string {
|
||||
return "Hello!"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
|
|
@ -2,10 +2,15 @@ import Editor, { Monaco } from '@monaco-editor/react'
|
|||
import useTheme from 'hooks/useTheme'
|
||||
import prettier from 'prettier/standalone'
|
||||
import parserTypeScript from 'prettier/parser-typescript'
|
||||
import codeAsString from './code-as-string'
|
||||
// import codeAsString from './code-as-string'
|
||||
import typesImport from './types-import'
|
||||
import React, { useCallback, useEffect, useRef } from 'react'
|
||||
import styled from 'styles'
|
||||
import { IMonaco, IMonacoEditor } from 'types'
|
||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'
|
||||
|
||||
export type IMonaco = typeof monaco
|
||||
|
||||
export type IMonacoEditor = monaco.editor.IStandaloneCodeEditor
|
||||
|
||||
interface Props {
|
||||
value: string
|
||||
|
@ -54,22 +59,27 @@ export default function CodeEditor({
|
|||
})
|
||||
|
||||
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true)
|
||||
|
||||
monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true)
|
||||
|
||||
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
|
||||
noSemanticValidation: true,
|
||||
noSyntaxValidation: true,
|
||||
// noSemanticValidation: true,
|
||||
// noSyntaxValidation: true,
|
||||
})
|
||||
|
||||
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
|
||||
noSemanticValidation: true,
|
||||
noSyntaxValidation: true,
|
||||
// noSemanticValidation: true,
|
||||
// noSyntaxValidation: true,
|
||||
})
|
||||
|
||||
monaco.languages.typescript.javascriptDefaults.addExtraLib(codeAsString)
|
||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(
|
||||
typesImport.content
|
||||
)
|
||||
|
||||
monaco.languages.registerDocumentFormattingEditProvider('javascript', {
|
||||
monaco.languages.typescript.javascriptDefaults.addExtraLib(
|
||||
typesImport.content
|
||||
)
|
||||
|
||||
monaco.languages.registerDocumentFormattingEditProvider('typescript', {
|
||||
async provideDocumentFormattingEdits(model) {
|
||||
const text = prettier.format(model.getValue(), {
|
||||
parser: 'typescript',
|
||||
|
@ -192,7 +202,7 @@ export default function CodeEditor({
|
|||
<EditorContainer onKeyDown={handleKeydown} onKeyUp={handleKeyUp}>
|
||||
<Editor
|
||||
height="100%"
|
||||
language="javascript"
|
||||
language="typescript"
|
||||
value={value}
|
||||
theme={theme === 'dark' ? 'vs-dark' : 'light'}
|
||||
beforeMount={handleBeforeMount}
|
||||
|
|
1615
components/code-panel/types-import.ts
Normal file
1615
components/code-panel/types-import.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -6,22 +6,15 @@ import ToolsPanel from './tools-panel/tools-panel'
|
|||
import StylePanel from './style-panel/style-panel'
|
||||
import styled from 'styles'
|
||||
import PagePanel from './page-panel/page-panel'
|
||||
// import dynamic from 'next/dynamic'
|
||||
// import ControlsPanel from './controls-panel/controls-panel'
|
||||
// import { useSelector } from 'state'
|
||||
// const CodePanel = dynamic(() => import('./code-panel/code-panel'))
|
||||
import CodePanel from './code-panel/code-panel'
|
||||
|
||||
export default function Editor(): JSX.Element {
|
||||
useKeyboardEvents()
|
||||
useLoadOnMount()
|
||||
|
||||
// const hasControls = useSelector(
|
||||
// (s) => Object.keys(s.data.codeControls).length > 0
|
||||
// )
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
{/* <CodePanel /> */}
|
||||
<CodePanel />
|
||||
<PagePanel />
|
||||
<Spacer />
|
||||
<StylePanel />
|
||||
|
|
|
@ -38,7 +38,7 @@ export const Root = styled('div', {
|
|||
left: 8,
|
||||
right: 8,
|
||||
bottom: 48,
|
||||
maxWidth: 720,
|
||||
maxWidth: 680,
|
||||
zIndex: 1000,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"format": "prettier --write .",
|
||||
"lint": "eslint . --ext ts --ext tsx --ext js",
|
||||
"test": "jest",
|
||||
"scripts": "node scripts/type-gen",
|
||||
"test:watch": "jest --watchAll",
|
||||
"test:update": "jest --updateSnapshot",
|
||||
"test-all": "yarn lint && yarn type-check && yarn test"
|
||||
|
@ -89,4 +90,4 @@
|
|||
"tabWidth": 2,
|
||||
"useTabs": false
|
||||
}
|
||||
}
|
||||
}
|
56
scripts/type-gen.js
Normal file
56
scripts/type-gen.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
// @ts-check
|
||||
|
||||
/*
|
||||
Type gen script
|
||||
|
||||
This script will generate TypeScript declarations for the code editor. It reads
|
||||
the global types, as well as all of the code classes, and writes them into a
|
||||
single file as a string. This string is fed into the Monaco editor as an extraLib.
|
||||
*/
|
||||
|
||||
const fs = require("fs/promises")
|
||||
|
||||
async function copyTypesToFile() {
|
||||
const types = await fs.readFile(__dirname + "/../types.ts", 'utf8')
|
||||
const codeIndex = await fs.readFile(__dirname + "/../state/code/index.ts", 'utf8')
|
||||
const codeDot = await fs.readFile(__dirname + "/../state/code/dot.ts", 'utf8')
|
||||
const codeEllipse = await fs.readFile(__dirname + "/../state/code/ellipse.ts", 'utf8')
|
||||
const codeLine = await fs.readFile(__dirname + "/../state/code/line.ts", 'utf8')
|
||||
const codePolyline = await fs.readFile(__dirname + "/../state/code/polyline.ts", 'utf8')
|
||||
const codeRay = await fs.readFile(__dirname + "/../state/code/ray.ts", 'utf8')
|
||||
const codeArrow = await fs.readFile(__dirname + "/../state/code/arrow.ts", 'utf8')
|
||||
const codeDraw = await fs.readFile(__dirname + "/../state/code/draw.ts", 'utf8')
|
||||
const codeRectangle = await fs.readFile(__dirname + "/../state/code/rectangle.ts", 'utf8')
|
||||
const codeVector = await fs.readFile(__dirname + "/../utils/vec.ts", 'utf8')
|
||||
const codeUtils = await fs.readFile(__dirname + "/../state/code/utils.ts", 'utf8')
|
||||
|
||||
const content = `
|
||||
// HEY! DO NOT MODIFY THIS FILE. THE CONTENTS OF THIS FILE
|
||||
// ARE AUTO-GENERATED BY A SCRIPT AT: /scripts/type-gen.js
|
||||
// ANY CHANGES WILL BE LOST WHEN THE SCRIPT RUNS AGAIN!
|
||||
|
||||
export default {` + `
|
||||
name: "types.ts",
|
||||
content: \`
|
||||
|
||||
${types}
|
||||
|
||||
${codeIndex.match(/export default(.|\n)*$/g)[0]}
|
||||
${codeDot.match(/\/\*\*(.|\n)*$/g)[0]}
|
||||
${codeEllipse.match(/\/\*\*(.|\n)*$/g)[0]}
|
||||
${codeLine.match(/\/\*\*(.|\n)*$/g)[0]}
|
||||
${codePolyline.match(/\/\*\*(.|\n)*$/g)[0]}
|
||||
${codeRay.match(/\/\*\*(.|\n)*$/g)[0]}
|
||||
${codeRectangle.match(/\/\*\*(.|\n)*$/g)[0]}
|
||||
${codeArrow.match(/\/\*\*(.|\n)*$/g)[0]}
|
||||
${codeDraw.match(/\/\*\*(.|\n)*$/g)[0]}
|
||||
${codeUtils.match(/\/\*\*(.|\n)*$/g)[0]}
|
||||
${codeVector}
|
||||
\`
|
||||
}`.replaceAll("export default", "").replaceAll("export ", "")
|
||||
|
||||
await fs.writeFile(__dirname + "/../components/code-panel/types-import.ts", content)
|
||||
}
|
||||
|
||||
// Kickoff
|
||||
copyTypesToFile()
|
101
state/code/arrow.ts
Normal file
101
state/code/arrow.ts
Normal file
|
@ -0,0 +1,101 @@
|
|||
import CodeShape from './index'
|
||||
import { uniqueId } from 'utils/utils'
|
||||
import { ArrowShape, Decoration, ShapeStyles, ShapeType } from 'types'
|
||||
import { defaultStyle } from 'state/shape-styles'
|
||||
import { getShapeUtils } from 'state/shape-utils'
|
||||
import Vec from 'utils/vec'
|
||||
|
||||
/**
|
||||
* ## Draw
|
||||
*/
|
||||
export default class Arrow extends CodeShape<ArrowShape> {
|
||||
constructor(
|
||||
props = {} as Partial<ArrowShape> &
|
||||
Partial<ShapeStyles> & { start?: number[]; end?: number[] }
|
||||
) {
|
||||
const { start = [0, 0], end = [0, 0] } = props
|
||||
|
||||
const {
|
||||
point = [0, 0],
|
||||
handles = {
|
||||
start: {
|
||||
id: 'start',
|
||||
index: 0,
|
||||
point: start,
|
||||
},
|
||||
end: {
|
||||
id: 'end',
|
||||
index: 1,
|
||||
point: end,
|
||||
},
|
||||
bend: {
|
||||
id: 'bend',
|
||||
index: 2,
|
||||
point: Vec.med(start, end),
|
||||
},
|
||||
},
|
||||
} = props
|
||||
|
||||
super({
|
||||
id: uniqueId(),
|
||||
seed: Math.random(),
|
||||
type: ShapeType.Arrow,
|
||||
isGenerated: false,
|
||||
name: 'Arrow',
|
||||
parentId: 'page1',
|
||||
childIndex: 0,
|
||||
point,
|
||||
rotation: 0,
|
||||
isAspectRatioLocked: false,
|
||||
isLocked: false,
|
||||
isHidden: false,
|
||||
bend: 0,
|
||||
handles,
|
||||
decorations: {
|
||||
start: null,
|
||||
middle: null,
|
||||
end: Decoration.Arrow,
|
||||
},
|
||||
...props,
|
||||
style: {
|
||||
...defaultStyle,
|
||||
...props.style,
|
||||
isFilled: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
get start(): number[] {
|
||||
return this.shape.handles.start.point
|
||||
}
|
||||
|
||||
set start(point: number[]) {
|
||||
getShapeUtils(this.shape).onHandleChange(this.shape, {
|
||||
start: { ...this.shape.handles.start, point },
|
||||
})
|
||||
}
|
||||
|
||||
get middle(): number[] {
|
||||
return this.shape.handles.bend.point
|
||||
}
|
||||
|
||||
set middle(point: number[]) {
|
||||
getShapeUtils(this.shape).onHandleChange(this.shape, {
|
||||
bend: { ...this.shape.handles.bend, point },
|
||||
})
|
||||
}
|
||||
|
||||
get end(): number[] {
|
||||
return this.shape.handles.end.point
|
||||
}
|
||||
|
||||
set end(point: number[]) {
|
||||
getShapeUtils(this.shape).onHandleChange(this.shape, {
|
||||
end: { ...this.shape.handles.end, point },
|
||||
})
|
||||
}
|
||||
|
||||
get bend(): number {
|
||||
return this.shape.bend
|
||||
}
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
import CodeShape from './index'
|
||||
import { uniqueId } from 'utils/utils'
|
||||
import { DotShape, ShapeType } from 'types'
|
||||
import { DotShape, ShapeStyles, ShapeType } from 'types'
|
||||
import { defaultStyle } from 'state/shape-styles'
|
||||
import Utils from './utils'
|
||||
|
||||
/**
|
||||
* ## Dot
|
||||
*/
|
||||
export default class Dot extends CodeShape<DotShape> {
|
||||
constructor(props = {} as Partial<DotShape>) {
|
||||
props.point = Utils.vectorToPoint(props.point)
|
||||
|
||||
constructor(props = {} as Partial<DotShape> & Partial<ShapeStyles>) {
|
||||
super({
|
||||
id: uniqueId(),
|
||||
seed: Math.random(),
|
||||
|
@ -29,12 +29,4 @@ export default class Dot extends CodeShape<DotShape> {
|
|||
},
|
||||
})
|
||||
}
|
||||
|
||||
export(): DotShape {
|
||||
const shape = { ...this.shape }
|
||||
|
||||
shape.point = Utils.vectorToPoint(shape.point)
|
||||
|
||||
return shape
|
||||
}
|
||||
}
|
||||
|
|
32
state/code/draw.ts
Normal file
32
state/code/draw.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import CodeShape from './index'
|
||||
import { uniqueId } from 'utils/utils'
|
||||
import { DrawShape, ShapeType } from 'types'
|
||||
import { defaultStyle } from 'state/shape-styles'
|
||||
|
||||
/**
|
||||
* ## Draw
|
||||
*/
|
||||
export default class Draw extends CodeShape<DrawShape> {
|
||||
constructor(props = {} as Partial<DrawShape>) {
|
||||
super({
|
||||
id: uniqueId(),
|
||||
seed: Math.random(),
|
||||
type: ShapeType.Draw,
|
||||
isGenerated: false,
|
||||
name: 'Draw',
|
||||
parentId: 'page1',
|
||||
childIndex: 0,
|
||||
point: [0, 0],
|
||||
points: [],
|
||||
rotation: 0,
|
||||
isAspectRatioLocked: false,
|
||||
isLocked: false,
|
||||
isHidden: false,
|
||||
...props,
|
||||
style: {
|
||||
...defaultStyle,
|
||||
...props.style,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
import CodeShape from './index'
|
||||
import { uniqueId } from 'utils/utils'
|
||||
import { EllipseShape, ShapeType } from 'types'
|
||||
import Utils from './utils'
|
||||
import { EllipseShape, ShapeStyles, ShapeType } from 'types'
|
||||
import { defaultStyle } from 'state/shape-styles'
|
||||
|
||||
/**
|
||||
* ## Ellipse
|
||||
*/
|
||||
export default class Ellipse extends CodeShape<EllipseShape> {
|
||||
constructor(props = {} as Partial<EllipseShape>) {
|
||||
props.point = Utils.vectorToPoint(props.point)
|
||||
|
||||
constructor(props = {} as Partial<EllipseShape> & Partial<ShapeStyles>) {
|
||||
super({
|
||||
id: uniqueId(),
|
||||
seed: Math.random(),
|
||||
|
@ -17,8 +17,8 @@ export default class Ellipse extends CodeShape<EllipseShape> {
|
|||
name: 'Ellipse',
|
||||
childIndex: 0,
|
||||
point: [0, 0],
|
||||
radiusX: 20,
|
||||
radiusY: 20,
|
||||
radiusX: 50,
|
||||
radiusY: 50,
|
||||
rotation: 0,
|
||||
isAspectRatioLocked: false,
|
||||
isLocked: false,
|
||||
|
@ -28,14 +28,6 @@ export default class Ellipse extends CodeShape<EllipseShape> {
|
|||
})
|
||||
}
|
||||
|
||||
export(): EllipseShape {
|
||||
const shape = { ...this.shape }
|
||||
|
||||
shape.point = Utils.vectorToPoint(shape.point)
|
||||
|
||||
return shape
|
||||
}
|
||||
|
||||
get radiusX(): number {
|
||||
return this.shape.radiusX
|
||||
}
|
||||
|
|
|
@ -4,11 +4,14 @@ import Polyline from './polyline'
|
|||
import Dot from './dot'
|
||||
import Ray from './ray'
|
||||
import Line from './line'
|
||||
import Vector from './vector'
|
||||
import Arrow from './arrow'
|
||||
import Draw from './draw'
|
||||
import Utils from './utils'
|
||||
import Vec from 'utils/vec'
|
||||
import { NumberControl, VectorControl, codeControls, controls } from './control'
|
||||
import { codeShapes } from './index'
|
||||
import { CodeControl, Data, Shape } from 'types'
|
||||
import { getPage } from 'utils/utils'
|
||||
|
||||
const baseScope = {
|
||||
Dot,
|
||||
|
@ -17,8 +20,10 @@ const baseScope = {
|
|||
Line,
|
||||
Polyline,
|
||||
Rectangle,
|
||||
Vector,
|
||||
Vec,
|
||||
Utils,
|
||||
Arrow,
|
||||
Draw,
|
||||
VectorControl,
|
||||
NumberControl,
|
||||
}
|
||||
|
@ -45,9 +50,11 @@ export function generateFromCode(
|
|||
|
||||
new Function(...Object.keys(scope), `${code}`)(...Object.values(scope))
|
||||
|
||||
const generatedShapes = Array.from(codeShapes.values()).map(
|
||||
(instance) => instance.shape
|
||||
)
|
||||
const generatedShapes = Array.from(codeShapes.values()).map((instance) => ({
|
||||
...instance.shape,
|
||||
isGenerated: true,
|
||||
parentId: getPage(data).id,
|
||||
}))
|
||||
|
||||
const generatedControls = Array.from(codeControls.values())
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import { Mutable, Shape, ShapeUtility } from 'types'
|
||||
import { createShape, getShapeUtils } from 'state/shape-utils'
|
||||
import vec from 'utils/vec'
|
||||
import Vector from './vector'
|
||||
import Utils from './utils'
|
||||
|
||||
export const codeShapes = new Set<CodeShape<Shape>>([])
|
||||
|
||||
|
@ -20,20 +18,24 @@ export default class CodeShape<T extends Shape> {
|
|||
codeShapes.add(this)
|
||||
}
|
||||
|
||||
export(): Mutable<T> {
|
||||
return { ...this._shape }
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
codeShapes.delete(this)
|
||||
}
|
||||
|
||||
moveTo(point: Vector): CodeShape<T> {
|
||||
this.utils.setProperty(this._shape, 'point', Utils.vectorToPoint(point))
|
||||
moveTo(point: number[]): CodeShape<T> {
|
||||
this.utils.setProperty(this._shape, 'point', point)
|
||||
return this
|
||||
}
|
||||
|
||||
translate(delta: Vector): CodeShape<T> {
|
||||
translate(delta: number[]): CodeShape<T> {
|
||||
this.utils.setProperty(
|
||||
this._shape,
|
||||
'point',
|
||||
vec.add(this._shape.point, Utils.vectorToPoint(delta))
|
||||
vec.add(this._shape.point, delta)
|
||||
)
|
||||
return this
|
||||
}
|
||||
|
@ -48,8 +50,8 @@ export default class CodeShape<T extends Shape> {
|
|||
return this
|
||||
}
|
||||
|
||||
hitTest(point: Vector): CodeShape<T> {
|
||||
this.utils.hitTest(this.shape, Utils.vectorToPoint(point))
|
||||
hitTest(point: number[]): CodeShape<T> {
|
||||
this.utils.hitTest(this.shape, point)
|
||||
return this
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import CodeShape from './index'
|
||||
import { uniqueId } from 'utils/utils'
|
||||
import { LineShape, ShapeType } from 'types'
|
||||
import { LineShape, ShapeStyles, ShapeType } from 'types'
|
||||
import { defaultStyle } from 'state/shape-styles'
|
||||
import Utils from './utils'
|
||||
|
||||
/**
|
||||
* ## Line
|
||||
*/
|
||||
export default class Line extends CodeShape<LineShape> {
|
||||
constructor(props = {} as Partial<LineShape>) {
|
||||
props.point = Utils.vectorToPoint(props.point)
|
||||
props.direction = Utils.vectorToPoint(props.direction)
|
||||
|
||||
constructor(props = {} as Partial<LineShape> & Partial<ShapeStyles>) {
|
||||
super({
|
||||
id: uniqueId(),
|
||||
seed: Math.random(),
|
||||
|
@ -32,15 +31,6 @@ export default class Line extends CodeShape<LineShape> {
|
|||
})
|
||||
}
|
||||
|
||||
export(): LineShape {
|
||||
const shape = { ...this.shape }
|
||||
|
||||
shape.point = Utils.vectorToPoint(shape.point)
|
||||
shape.direction = Utils.vectorToPoint(shape.direction)
|
||||
|
||||
return shape
|
||||
}
|
||||
|
||||
get direction(): number[] {
|
||||
return this.shape.direction
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import CodeShape from './index'
|
||||
import { uniqueId } from 'utils/utils'
|
||||
import { PolylineShape, ShapeType } from 'types'
|
||||
import { PolylineShape, ShapeStyles, ShapeType } from 'types'
|
||||
import { defaultStyle } from 'state/shape-styles'
|
||||
import Utils from './utils'
|
||||
|
||||
/**
|
||||
* ## Polyline
|
||||
*/
|
||||
export default class Polyline extends CodeShape<PolylineShape> {
|
||||
constructor(props = {} as Partial<PolylineShape>) {
|
||||
props.point = Utils.vectorToPoint(props.point)
|
||||
props.points = props.points.map(Utils.vectorToPoint)
|
||||
|
||||
constructor(props = {} as Partial<PolylineShape> & Partial<ShapeStyles>) {
|
||||
super({
|
||||
id: uniqueId(),
|
||||
seed: Math.random(),
|
||||
|
@ -28,15 +27,6 @@ export default class Polyline extends CodeShape<PolylineShape> {
|
|||
})
|
||||
}
|
||||
|
||||
export(): PolylineShape {
|
||||
const shape = { ...this.shape }
|
||||
|
||||
shape.point = Utils.vectorToPoint(shape.point)
|
||||
shape.points = shape.points.map(Utils.vectorToPoint)
|
||||
|
||||
return shape
|
||||
}
|
||||
|
||||
get points(): number[][] {
|
||||
return this.shape.points
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import CodeShape from './index'
|
||||
import { uniqueId } from 'utils/utils'
|
||||
import { RayShape, ShapeType } from 'types'
|
||||
import { RayShape, ShapeStyles, ShapeType } from 'types'
|
||||
import { defaultStyle } from 'state/shape-styles'
|
||||
import Utils from './utils'
|
||||
|
||||
/**
|
||||
* ## Ray
|
||||
*/
|
||||
export default class Ray extends CodeShape<RayShape> {
|
||||
constructor(props = {} as Partial<RayShape>) {
|
||||
props.point = Utils.vectorToPoint(props.point)
|
||||
props.direction = Utils.vectorToPoint(props.direction)
|
||||
|
||||
constructor(props = {} as Partial<RayShape> & Partial<ShapeStyles>) {
|
||||
super({
|
||||
id: uniqueId(),
|
||||
seed: Math.random(),
|
||||
|
@ -32,15 +31,6 @@ export default class Ray extends CodeShape<RayShape> {
|
|||
})
|
||||
}
|
||||
|
||||
export(): RayShape {
|
||||
const shape = { ...this.shape }
|
||||
|
||||
shape.point = Utils.vectorToPoint(shape.point)
|
||||
shape.direction = Utils.vectorToPoint(shape.direction)
|
||||
|
||||
return shape
|
||||
}
|
||||
|
||||
get direction(): number[] {
|
||||
return this.shape.direction
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import CodeShape from './index'
|
||||
import { uniqueId } from 'utils/utils'
|
||||
import { RectangleShape, ShapeType } from 'types'
|
||||
import Utils from './utils'
|
||||
import { RectangleShape, ShapeStyles, ShapeType } from 'types'
|
||||
import { defaultStyle } from 'state/shape-styles'
|
||||
|
||||
/**
|
||||
* ## Rectangle
|
||||
*/
|
||||
export default class Rectangle extends CodeShape<RectangleShape> {
|
||||
constructor(props = {} as Partial<RectangleShape>) {
|
||||
props.point = Utils.vectorToPoint(props.point)
|
||||
props.size = Utils.vectorToPoint(props.size)
|
||||
|
||||
constructor(props = {} as Partial<RectangleShape> & Partial<ShapeStyles>) {
|
||||
super({
|
||||
id: uniqueId(),
|
||||
seed: Math.random(),
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { Bounds } from 'types'
|
||||
import Vector, { Point } from './vector'
|
||||
|
||||
/**
|
||||
* ## Utils
|
||||
*/
|
||||
export default class Utils {
|
||||
static vectorToPoint(point: number[] | Vector | undefined): number[] {
|
||||
if (typeof point === 'undefined') {
|
||||
|
|
|
@ -8,6 +8,9 @@ export interface Point {
|
|||
y: number
|
||||
}
|
||||
|
||||
/**
|
||||
* ## Vector
|
||||
*/
|
||||
export default class Vector {
|
||||
x = 0
|
||||
y = 0
|
||||
|
|
|
@ -60,6 +60,7 @@ export default function pasteCommand(data: Data, initialShapes: Shape[]): void {
|
|||
parentId: oldSelectedIds[shape.parentId] || data.currentPageId,
|
||||
childIndex: childIndex++,
|
||||
point: vec.add(topLeft, topLeftOffset),
|
||||
isGenerated: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Data, GroupShape, ShapeType } from 'types'
|
||||
import { Data, GroupShape, Shape, ShapeType } from 'types'
|
||||
import vec from 'utils/vec'
|
||||
import BaseSession from './base-session'
|
||||
import commands from 'state/commands'
|
||||
|
@ -217,12 +217,13 @@ export function getTranslateSnapshot(data: Data) {
|
|||
clones: selectedShapes
|
||||
.filter((shape) => shape.type !== ShapeType.Group)
|
||||
.flatMap((shape) => {
|
||||
const clone = {
|
||||
const clone: Shape = {
|
||||
...shape,
|
||||
id: uniqueId(),
|
||||
seed: Math.random(),
|
||||
parentId: shape.parentId,
|
||||
childIndex: getChildIndexAbove(cData, shape.id),
|
||||
isGenerated: false,
|
||||
}
|
||||
|
||||
return clone
|
||||
|
|
|
@ -93,7 +93,52 @@ const initialData: Data = {
|
|||
file0: {
|
||||
id: 'file0',
|
||||
name: 'index.ts',
|
||||
code: ``,
|
||||
code: `
|
||||
const draw = new Draw({
|
||||
points: [
|
||||
[0, 0],
|
||||
[0, 50],
|
||||
[20, 80],
|
||||
[56, 56],
|
||||
[52, 52],
|
||||
[80, 20],
|
||||
[90, 90],
|
||||
[100, 100],
|
||||
],
|
||||
})
|
||||
|
||||
const rectangle = new Rectangle({
|
||||
point: [200, 0],
|
||||
style: {
|
||||
color: ColorStyle.Blue,
|
||||
},
|
||||
})
|
||||
|
||||
const ellipse = new Ellipse({
|
||||
point: [400, 0],
|
||||
})
|
||||
|
||||
const arrow = new Arrow({
|
||||
start: [600, 0],
|
||||
end: [700, 100],
|
||||
})
|
||||
|
||||
const radius = 1000
|
||||
const count = 100
|
||||
const center = [350, 50]
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const point = Vec.rotWith(
|
||||
Vec.add(center, [radius, 0]),
|
||||
center,
|
||||
(Math.PI * 2 * i) / count
|
||||
)
|
||||
|
||||
const dot = new Dot({
|
||||
point,
|
||||
})
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
6
types.ts
6
types.ts
|
@ -1,5 +1,3 @@
|
|||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Client State */
|
||||
/* -------------------------------------------------- */
|
||||
|
@ -355,10 +353,6 @@ export enum DistributeType {
|
|||
/* Code Editor */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export type IMonaco = typeof monaco
|
||||
|
||||
export type IMonacoEditor = monaco.editor.IStandaloneCodeEditor
|
||||
|
||||
export enum ControlType {
|
||||
Number = 'number',
|
||||
Vector = 'vector',
|
||||
|
|
Loading…
Reference in a new issue