Improves code editor types, adds es5 lib
This commit is contained in:
parent
9d63160521
commit
61399fb9d0
12 changed files with 6219 additions and 114 deletions
|
@ -1,5 +1,6 @@
|
||||||
import Editor, { Monaco } from '@monaco-editor/react'
|
import Editor, { Monaco } from '@monaco-editor/react'
|
||||||
import useTheme from 'hooks/useTheme'
|
import useTheme from 'hooks/useTheme'
|
||||||
|
import libImport from './es5-lib'
|
||||||
import typesImport from './types-import'
|
import typesImport from './types-import'
|
||||||
import React, { useCallback, useEffect, useRef } from 'react'
|
import React, { useCallback, useEffect, useRef } from 'react'
|
||||||
import styled from 'styles'
|
import styled from 'styles'
|
||||||
|
@ -46,17 +47,10 @@ export default function CodeEditor({
|
||||||
if (monacoRef) {
|
if (monacoRef) {
|
||||||
monacoRef.current = monaco
|
monacoRef.current = monaco
|
||||||
}
|
}
|
||||||
|
|
||||||
rMonaco.current = monaco
|
rMonaco.current = monaco
|
||||||
|
|
||||||
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
|
// Set the compiler options.
|
||||||
allowJs: true,
|
|
||||||
checkJs: false,
|
|
||||||
strict: false,
|
|
||||||
noLib: true,
|
|
||||||
lib: ['es6'],
|
|
||||||
target: monaco.languages.typescript.ScriptTarget.ES2016,
|
|
||||||
allowNonTsExtensions: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
|
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
|
||||||
allowJs: true,
|
allowJs: true,
|
||||||
|
@ -68,27 +62,31 @@ export default function CodeEditor({
|
||||||
allowNonTsExtensions: true,
|
allowNonTsExtensions: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true)
|
// Sync the intellisense on load.
|
||||||
monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true)
|
|
||||||
|
|
||||||
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
|
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true)
|
||||||
noSemanticValidation: false,
|
|
||||||
noSyntaxValidation: false,
|
// Run both semantic and syntax validation.
|
||||||
})
|
|
||||||
|
|
||||||
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
|
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
|
||||||
noSemanticValidation: false,
|
noSemanticValidation: false,
|
||||||
noSyntaxValidation: false,
|
noSyntaxValidation: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Add custom types
|
||||||
|
|
||||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(
|
monaco.languages.typescript.typescriptDefaults.addExtraLib(
|
||||||
typesImport.content
|
typesImport.content
|
||||||
)
|
)
|
||||||
|
|
||||||
monaco.languages.typescript.javascriptDefaults.addExtraLib(
|
// Add es5 library types
|
||||||
typesImport.content
|
|
||||||
|
monaco.languages.typescript.typescriptDefaults.addExtraLib(
|
||||||
|
libImport.content
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Use prettier as a formatter
|
||||||
|
|
||||||
monaco.languages.registerDocumentFormattingEditProvider('typescript', {
|
monaco.languages.registerDocumentFormattingEditProvider('typescript', {
|
||||||
async provideDocumentFormattingEdits(model) {
|
async provideDocumentFormattingEdits(model) {
|
||||||
try {
|
try {
|
||||||
|
@ -223,6 +221,7 @@ export default function CodeEditor({
|
||||||
beforeMount={handleBeforeMount}
|
beforeMount={handleBeforeMount}
|
||||||
onMount={handleMount}
|
onMount={handleMount}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
defaultPath="index.ts"
|
||||||
/>
|
/>
|
||||||
</EditorContainer>
|
</EditorContainer>
|
||||||
)
|
)
|
||||||
|
|
5459
components/code-panel/es5-lib.ts
Normal file
5459
components/code-panel/es5-lib.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -8,10 +8,6 @@ export default {
|
||||||
name: 'types.ts',
|
name: 'types.ts',
|
||||||
content: `
|
content: `
|
||||||
|
|
||||||
type Partial<T> = { [P in keyof T]?: T[P]; };
|
|
||||||
|
|
||||||
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
|
|
||||||
|
|
||||||
type DeepPartial<T> = {
|
type DeepPartial<T> = {
|
||||||
[P in keyof T]?: DeepPartial<T[P]>;
|
[P in keyof T]?: DeepPartial<T[P]>;
|
||||||
};
|
};
|
||||||
|
@ -141,7 +137,6 @@ interface TextShape extends BaseShape {
|
||||||
type: ShapeType.Text
|
type: ShapeType.Text
|
||||||
text: string
|
text: string
|
||||||
scale: number
|
scale: number
|
||||||
fontSize: FontSize
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GroupShape extends BaseShape {
|
interface GroupShape extends BaseShape {
|
||||||
|
@ -187,12 +182,6 @@ type Shape = Readonly<MutableShape>
|
||||||
|
|
||||||
type ShapeByType<T extends ShapeType> = Shapes[T]
|
type ShapeByType<T extends ShapeType> = Shapes[T]
|
||||||
|
|
||||||
interface CodeFile {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
code: string
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Decoration {
|
enum Decoration {
|
||||||
Arrow = 'Arrow',
|
Arrow = 'Arrow',
|
||||||
}
|
}
|
||||||
|
@ -209,6 +198,24 @@ interface ShapeHandle {
|
||||||
point: number[]
|
point: number[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CodeFile {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
code: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CodeError {
|
||||||
|
message: string
|
||||||
|
line: number
|
||||||
|
column: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CodeResult {
|
||||||
|
shapes: Shape[]
|
||||||
|
controls: CodeControl[]
|
||||||
|
error: CodeError
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------- */
|
/* -------------------------------------------------- */
|
||||||
/* Editor UI */
|
/* Editor UI */
|
||||||
/* -------------------------------------------------- */
|
/* -------------------------------------------------- */
|
||||||
|
@ -548,7 +555,11 @@ interface ShapeUtility<K extends Shape> {
|
||||||
// Test whether bounds collide with or contain a shape.
|
// Test whether bounds collide with or contain a shape.
|
||||||
hitTestBounds(this: ShapeUtility<K>, shape: K, bounds: Bounds): boolean
|
hitTestBounds(this: ShapeUtility<K>, shape: K, bounds: Bounds): boolean
|
||||||
|
|
||||||
|
// Get whether the shape should delete
|
||||||
shouldDelete(this: ShapeUtility<K>, shape: K): boolean
|
shouldDelete(this: ShapeUtility<K>, shape: K): boolean
|
||||||
|
|
||||||
|
// Get whether the shape should render
|
||||||
|
shouldRender(this: ShapeUtility<K>, shape: K, previous: K): boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1825,7 +1836,7 @@ interface ShapeUtility<K extends Shape> {
|
||||||
|
|
||||||
class CodeShape<T extends Shape> {
|
class CodeShape<T extends Shape> {
|
||||||
private _shape: Mutable<T>
|
private _shape: Mutable<T>
|
||||||
private utils: ShapeUtility<T>
|
protected utils: ShapeUtility<T>
|
||||||
|
|
||||||
constructor(props: T) {
|
constructor(props: T) {
|
||||||
this._shape = createShape(props.type, props) as Mutable<T>
|
this._shape = createShape(props.type, props) as Mutable<T>
|
||||||
|
@ -1833,79 +1844,130 @@ interface ShapeUtility<K extends Shape> {
|
||||||
codeShapes.add(this)
|
codeShapes.add(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
export(): Mutable<T> {
|
|
||||||
return { ...this._shape }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy the shape.
|
* Destroy the shape.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* shape.destroy()
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
destroy(): void {
|
destroy = (): void => {
|
||||||
codeShapes.delete(this)
|
codeShapes.delete(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape to a point.
|
* Move the shape to a point.
|
||||||
* @param delta
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* shape.moveTo(100,100)
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
moveTo(point: number[]): CodeShape<T> {
|
moveTo = (point: number[]): CodeShape<T> => {
|
||||||
return this.translateTo(point)
|
return this.translateTo(point)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape to a point.
|
* Move the shape to a point.
|
||||||
* @param delta
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* shape.translateTo([100,100])
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
translateTo(point: number[]): CodeShape<T> {
|
translateTo = (point: number[]): CodeShape<T> => {
|
||||||
this.utils.translateTo(this._shape, point)
|
this.utils.translateTo(this._shape, point)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape by a delta.
|
* Move the shape by a delta.
|
||||||
* @param delta
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* shape.translateBy([100,100])
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
translateBy(delta: number[]): CodeShape<T> {
|
translateBy = (delta: number[]): CodeShape<T> => {
|
||||||
this.utils.translateTo(this._shape, delta)
|
this.utils.translateTo(this._shape, delta)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotate the shape.
|
* Rotate the shape.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* shape.rotateTo(Math.PI / 2)
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
rotateTo(rotation: number): CodeShape<T> {
|
rotateTo = (rotation: number): CodeShape<T> => {
|
||||||
this.utils.rotateTo(this._shape, rotation, this.shape.rotation - rotation)
|
this.utils.rotateTo(this._shape, rotation, this.shape.rotation - rotation)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotate the shape by a delta.
|
* Rotate the shape by a delta.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* shape.rotateBy(Math.PI / 2)
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
rotateBy(rotation: number): CodeShape<T> {
|
rotateBy = (rotation: number): CodeShape<T> => {
|
||||||
this.utils.rotateBy(this._shape, rotation)
|
this.utils.rotateBy(this._shape, rotation)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the shape's bounding box.
|
* Get the shape's bounding box.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const bounds = shape.getBounds()
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
getBounds(): CodeShape<T> {
|
getBounds = (): CodeShape<T> => {
|
||||||
this.utils.getBounds(this.shape)
|
this.utils.getBounds(this.shape)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether a point is inside of the shape.
|
* Test whether a point is inside of the shape.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const isHit = shape.hitTest()
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
hitTest(point: number[]): CodeShape<T> {
|
hitTest = (point: number[]): CodeShape<T> => {
|
||||||
this.utils.hitTest(this.shape, point)
|
this.utils.hitTest(this.shape, point)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape to the back of the painting order.
|
* Duplicate this shape.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeB = shape.duplicate()
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
moveToBack(): CodeShape<T> {
|
duplicate = (): CodeShape<T> => {
|
||||||
|
const duplicate = Object.assign(
|
||||||
|
Object.create(Object.getPrototypeOf(this)),
|
||||||
|
this
|
||||||
|
)
|
||||||
|
|
||||||
|
duplicate._shape = createShape(this._shape.type, {
|
||||||
|
...this._shape,
|
||||||
|
id: uniqueId(),
|
||||||
|
} as any)
|
||||||
|
|
||||||
|
codeShapes.add(duplicate)
|
||||||
|
return duplicate
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the shape to the back of the painting order.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* shape.moveToBack()
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
|
moveToBack = (): CodeShape<T> => {
|
||||||
const sorted = getOrderedShapes()
|
const sorted = getOrderedShapes()
|
||||||
|
|
||||||
if (sorted.length <= 1) return
|
if (sorted.length <= 1) return
|
||||||
|
@ -1922,8 +1984,12 @@ interface ShapeUtility<K extends Shape> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape to the top of the painting order.
|
* Move the shape to the top of the painting order.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* shape.moveToFront()
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
moveToFront(): CodeShape<T> {
|
moveToFront = (): CodeShape<T> => {
|
||||||
const sorted = getOrderedShapes()
|
const sorted = getOrderedShapes()
|
||||||
|
|
||||||
if (sorted.length <= 1) return
|
if (sorted.length <= 1) return
|
||||||
|
@ -1941,8 +2007,12 @@ interface ShapeUtility<K extends Shape> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape backward in the painting order.
|
* Move the shape backward in the painting order.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* shape.moveBackward()
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
moveBackward(): CodeShape<T> {
|
moveBackward = (): CodeShape<T> => {
|
||||||
const sorted = getOrderedShapes()
|
const sorted = getOrderedShapes()
|
||||||
|
|
||||||
if (sorted.length <= 1) return
|
if (sorted.length <= 1) return
|
||||||
|
@ -1963,8 +2033,12 @@ interface ShapeUtility<K extends Shape> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape forward in the painting order.
|
* Move the shape forward in the painting order.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* shape.moveForward()
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
moveForward(): CodeShape<T> {
|
moveForward = (): CodeShape<T> => {
|
||||||
const sorted = getOrderedShapes()
|
const sorted = getOrderedShapes()
|
||||||
|
|
||||||
if (sorted.length <= 1) return
|
if (sorted.length <= 1) return
|
||||||
|
@ -1988,80 +2062,167 @@ interface ShapeUtility<K extends Shape> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's underlying shape.
|
* The shape's underlying shape (readonly).
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const underlyingShape = shape.shape
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
get shape(): T {
|
get shape(): Readonly<T> {
|
||||||
return this._shape
|
return this._shape
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's current point.
|
* The shape's current point.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapePoint = shape.point()
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
get point(): number[] {
|
get point(): number[] {
|
||||||
return [...this.shape.point]
|
return [...this.shape.point]
|
||||||
}
|
}
|
||||||
|
|
||||||
set point(point: number[]) {
|
set point(point: number[]) {
|
||||||
getShapeUtils(this.shape).translateTo(this._shape, point)
|
this.utils.translateTo(this._shape, point)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shape's current x position.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeX = shape.x
|
||||||
|
*
|
||||||
|
* shape.x = 100
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
|
get x(): number {
|
||||||
|
return this.point[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
set x(x: number) {
|
||||||
|
this.utils.translateTo(this._shape, [x, this.y])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shape's current y position.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeY = shape.y
|
||||||
|
*
|
||||||
|
* shape.y = 100
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
|
get y(): number {
|
||||||
|
return this.point[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
set y(y: number) {
|
||||||
|
this.utils.translateTo(this._shape, [this.x, y])
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's rotation.
|
* The shape's rotation.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeRotation = shape.rotation
|
||||||
|
*
|
||||||
|
* shape.rotation = Math.PI / 2
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
get rotation(): number {
|
get rotation(): number {
|
||||||
return this.shape.rotation
|
return this.shape.rotation
|
||||||
}
|
}
|
||||||
|
|
||||||
set rotation(rotation: number) {
|
set rotation(rotation: number) {
|
||||||
getShapeUtils(this.shape).rotateTo(
|
this.utils.rotateTo(this._shape, rotation, rotation - this.shape.rotation)
|
||||||
this._shape,
|
|
||||||
rotation,
|
|
||||||
rotation - this.shape.rotation
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's color style.
|
* The shape's color style (ColorStyle).
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeColor = shape.color
|
||||||
|
*
|
||||||
|
* shape.color = ColorStyle.Red
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
get color(): ColorStyle {
|
get color(): ColorStyle {
|
||||||
return this.shape.style.color
|
return this.shape.style.color
|
||||||
}
|
}
|
||||||
|
|
||||||
set color(color: ColorStyle) {
|
set color(color: ColorStyle) {
|
||||||
getShapeUtils(this.shape).applyStyles(this._shape, { color })
|
this.utils.applyStyles(this._shape, { color })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's dash style.
|
* The shape's dash style (DashStyle).
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeDash = shape.dash
|
||||||
|
*
|
||||||
|
* shape.dash = DashStyle.Dotted
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
get dash(): DashStyle {
|
get dash(): DashStyle {
|
||||||
return this.shape.style.dash
|
return this.shape.style.dash
|
||||||
}
|
}
|
||||||
|
|
||||||
set dash(dash: DashStyle) {
|
set dash(dash: DashStyle) {
|
||||||
getShapeUtils(this.shape).applyStyles(this._shape, { dash })
|
this.utils.applyStyles(this._shape, { dash })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's stroke width.
|
* The shape's size (SizeStyle).
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeSize = shape.size
|
||||||
|
*
|
||||||
|
* shape.size = SizeStyle.Large
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
get strokeWidth(): SizeStyle {
|
get size(): SizeStyle {
|
||||||
return this.shape.style.size
|
return this.shape.style.size
|
||||||
}
|
}
|
||||||
|
|
||||||
set strokeWidth(size: SizeStyle) {
|
set size(size: SizeStyle) {
|
||||||
getShapeUtils(this.shape).applyStyles(this._shape, { size })
|
this.utils.applyStyles(this._shape, { size })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's index in the painting order.
|
* The shape's index in the painting order.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeChildIndex = shape.childIndex
|
||||||
|
*
|
||||||
|
* shape.childIndex = 10
|
||||||
|
* \`\`\`
|
||||||
*/
|
*/
|
||||||
get childIndex(): number {
|
get childIndex(): number {
|
||||||
return this.shape.childIndex
|
return this.shape.childIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
set childIndex(childIndex: number) {
|
set childIndex(childIndex: number) {
|
||||||
getShapeUtils(this.shape).setProperty(this._shape, 'childIndex', childIndex)
|
this.utils.setProperty(this._shape, 'childIndex', childIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shape's center.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeCenter = shape.center
|
||||||
|
*
|
||||||
|
* shape.center = [100, 100]
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
|
get center(): number[] {
|
||||||
|
return this.utils.getCenter(this.shape)
|
||||||
|
}
|
||||||
|
|
||||||
|
set center(center: number[]) {
|
||||||
|
const oldCenter = this.utils.getCenter(this.shape)
|
||||||
|
const delta = Vec.sub(center, oldCenter)
|
||||||
|
this.translateBy(delta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2117,13 +2278,39 @@ interface ShapeUtility<K extends Shape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ellipse's x radius.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeRadiusX = shape.radiusX
|
||||||
|
*
|
||||||
|
* shape.radiusX = 100
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
get radiusX(): number {
|
get radiusX(): number {
|
||||||
return this.shape.radiusX
|
return this.shape.radiusX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set radiusX(radiusX: number) {
|
||||||
|
this.utils.setProperty(this.shape, 'radiusX', radiusX)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ellipse's y radius.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeRadiusY = shape.radiusY
|
||||||
|
*
|
||||||
|
* shape.radiusY = 100
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
get radiusY(): number {
|
get radiusY(): number {
|
||||||
return this.shape.radiusY
|
return this.shape.radiusY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set radiusY(radiusY: number) {
|
||||||
|
this.utils.setProperty(this.shape, 'radiusY', radiusY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2154,9 +2341,21 @@ interface ShapeUtility<K extends Shape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The line's direction.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeDirection = shape.direction
|
||||||
|
*
|
||||||
|
* shape.direction = [0,0]
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
get direction(): number[] {
|
get direction(): number[] {
|
||||||
return this.shape.direction
|
return this.shape.direction
|
||||||
}
|
}
|
||||||
|
set direction(direction: number[]) {
|
||||||
|
this.utils.setProperty(this.shape, 'direction', direction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2186,9 +2385,34 @@ interface ShapeUtility<K extends Shape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a point to the polyline's points.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* shape.addPoint([100,100])
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
|
addPoint(point: number[]): CodeShape<PolylineShape> {
|
||||||
|
this.utils.setProperty(this.shape, 'points', [...this.points, point])
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The polyline's points.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapePoints = shape.points
|
||||||
|
*
|
||||||
|
* shape.points = [[0,0], [100,100], [100,200]]
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
get points(): number[][] {
|
get points(): number[][] {
|
||||||
return this.shape.points
|
return this.shape.points
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set points(points: number[][]) {
|
||||||
|
this.utils.setProperty(this.shape, 'points', points)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2219,9 +2443,21 @@ interface ShapeUtility<K extends Shape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ray's direction.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeDirection = shape.direction
|
||||||
|
*
|
||||||
|
* shape.direction = [0,0]
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
get direction(): number[] {
|
get direction(): number[] {
|
||||||
return this.shape.direction
|
return this.shape.direction
|
||||||
}
|
}
|
||||||
|
set direction(direction: number[]) {
|
||||||
|
this.utils.setProperty(this.shape, 'direction', direction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2283,6 +2519,15 @@ interface ShapeUtility<K extends Shape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arrow's start point.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const startPoint = shape.start
|
||||||
|
*
|
||||||
|
* shape.start = [100, 100]
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
get start(): number[] {
|
get start(): number[] {
|
||||||
return this.shape.handles.start.point
|
return this.shape.handles.start.point
|
||||||
}
|
}
|
||||||
|
@ -2293,6 +2538,15 @@ interface ShapeUtility<K extends Shape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arrow's middle point.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const middlePoint = shape.middle
|
||||||
|
*
|
||||||
|
* shape.middle = [100, 100]
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
get middle(): number[] {
|
get middle(): number[] {
|
||||||
return this.shape.handles.bend.point
|
return this.shape.handles.bend.point
|
||||||
}
|
}
|
||||||
|
@ -2303,6 +2557,15 @@ interface ShapeUtility<K extends Shape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arrow's end point.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const endPoint = shape.end
|
||||||
|
*
|
||||||
|
* shape.end = [100, 100]
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
get end(): number[] {
|
get end(): number[] {
|
||||||
return this.shape.handles.end.point
|
return this.shape.handles.end.point
|
||||||
}
|
}
|
||||||
|
@ -2366,7 +2629,6 @@ interface ShapeUtility<K extends Shape> {
|
||||||
isHidden: false,
|
isHidden: false,
|
||||||
text: 'Text',
|
text: 'Text',
|
||||||
scale: 1,
|
scale: 1,
|
||||||
fontSize: FontSize.Medium,
|
|
||||||
...props,
|
...props,
|
||||||
style: {
|
style: {
|
||||||
...defaultStyle,
|
...defaultStyle,
|
||||||
|
@ -2374,6 +2636,40 @@ interface ShapeUtility<K extends Shape> {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The text shape's text content.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeText = shape.text
|
||||||
|
*
|
||||||
|
* shape.text = "Hello world!"
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
|
get text(): string {
|
||||||
|
return this.shape.text
|
||||||
|
}
|
||||||
|
|
||||||
|
set text(text: string) {
|
||||||
|
getShapeUtils(this.shape).setProperty(this.shape, 'text', text)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The text's scale.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeScale = shape.scale
|
||||||
|
*
|
||||||
|
* shape.scale = 2
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
|
get scale(): number {
|
||||||
|
return this.shape.scale
|
||||||
|
}
|
||||||
|
|
||||||
|
set scale(scale: number) {
|
||||||
|
getShapeUtils(this.shape).setProperty(this.shape, 'scale', scale)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2404,8 +2700,44 @@ interface ShapeUtility<K extends Shape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
get size(): number[] {
|
/**
|
||||||
return this.shape.size
|
* The rectangle's width.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeWidth = shape.width
|
||||||
|
*
|
||||||
|
* shape.width = 100
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
|
get width(): number {
|
||||||
|
return this.shape.size[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
set width(width: number) {
|
||||||
|
getShapeUtils(this.shape).setProperty(this.shape, 'size', [
|
||||||
|
width,
|
||||||
|
this.height,
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rectangle's height.
|
||||||
|
*
|
||||||
|
* \`\`\`ts
|
||||||
|
* const shapeHeight = shape.height
|
||||||
|
*
|
||||||
|
* shape.height = 100
|
||||||
|
* \`\`\`
|
||||||
|
*/
|
||||||
|
get height(): number {
|
||||||
|
return this.shape.size[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
set height(height: number) {
|
||||||
|
getShapeUtils(this.shape).setProperty(this.shape, 'size', [
|
||||||
|
this.width,
|
||||||
|
height,
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ async function inlineFileContents(path) {
|
||||||
/\/\* ----------------- Start Copy Here ---------------- \*\/(.|\n)*$/g
|
/\/\* ----------------- Start Copy Here ---------------- \*\/(.|\n)*$/g
|
||||||
)[0]
|
)[0]
|
||||||
.replaceAll('/* ----------------- Start Copy Here ---------------- */', '')
|
.replaceAll('/* ----------------- Start Copy Here ---------------- */', '')
|
||||||
|
.replaceAll('```', '\\`\\`\\`')
|
||||||
.replaceAll('export default', '')
|
.replaceAll('export default', '')
|
||||||
.replaceAll('export ', '')
|
.replaceAll('export ', '')
|
||||||
.replaceAll('vec.', 'Vec.')
|
.replaceAll('vec.', 'Vec.')
|
||||||
|
@ -46,16 +47,14 @@ async function copyTypesToFile() {
|
||||||
name: "types.ts",
|
name: "types.ts",
|
||||||
content: \`
|
content: \`
|
||||||
|
|
||||||
type Partial<T> = { [P in keyof T]?: T[P]; };
|
|
||||||
|
|
||||||
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
|
|
||||||
|
|
||||||
type DeepPartial<T> = {
|
type DeepPartial<T> = {
|
||||||
[P in keyof T]?: DeepPartial<T[P]>;
|
[P in keyof T]?: DeepPartial<T[P]>;
|
||||||
};
|
};
|
||||||
|
|
||||||
${await inlineFileContents('/types.ts')}
|
${await inlineFileContents('/types.ts')}
|
||||||
|
|
||||||
|
${await inlineFileContents('/types.ts')}
|
||||||
|
|
||||||
${await inlineFileContents('/utils/vec.ts')}
|
${await inlineFileContents('/utils/vec.ts')}
|
||||||
|
|
||||||
${await inlineFileContents('/state/code/utils.ts')}
|
${await inlineFileContents('/state/code/utils.ts')}
|
||||||
|
|
|
@ -63,6 +63,15 @@ export default class Arrow extends CodeShape<ArrowShape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arrow's start point.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const startPoint = shape.start
|
||||||
|
*
|
||||||
|
* shape.start = [100, 100]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
get start(): number[] {
|
get start(): number[] {
|
||||||
return this.shape.handles.start.point
|
return this.shape.handles.start.point
|
||||||
}
|
}
|
||||||
|
@ -73,6 +82,15 @@ export default class Arrow extends CodeShape<ArrowShape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arrow's middle point.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const middlePoint = shape.middle
|
||||||
|
*
|
||||||
|
* shape.middle = [100, 100]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
get middle(): number[] {
|
get middle(): number[] {
|
||||||
return this.shape.handles.bend.point
|
return this.shape.handles.bend.point
|
||||||
}
|
}
|
||||||
|
@ -83,6 +101,15 @@ export default class Arrow extends CodeShape<ArrowShape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arrow's end point.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const endPoint = shape.end
|
||||||
|
*
|
||||||
|
* shape.end = [100, 100]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
get end(): number[] {
|
get end(): number[] {
|
||||||
return this.shape.handles.end.point
|
return this.shape.handles.end.point
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,11 +26,37 @@ export default class Ellipse extends CodeShape<EllipseShape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ellipse's x radius.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeRadiusX = shape.radiusX
|
||||||
|
*
|
||||||
|
* shape.radiusX = 100
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
get radiusX(): number {
|
get radiusX(): number {
|
||||||
return this.shape.radiusX
|
return this.shape.radiusX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set radiusX(radiusX: number) {
|
||||||
|
this.utils.setProperty(this.shape, 'radiusX', radiusX)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ellipse's y radius.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeRadiusY = shape.radiusY
|
||||||
|
*
|
||||||
|
* shape.radiusY = 100
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
get radiusY(): number {
|
get radiusY(): number {
|
||||||
return this.shape.radiusY
|
return this.shape.radiusY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set radiusY(radiusY: number) {
|
||||||
|
this.utils.setProperty(this.shape, 'radiusY', radiusY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,8 @@ import {
|
||||||
SizeStyle,
|
SizeStyle,
|
||||||
} from 'types'
|
} from 'types'
|
||||||
import { createShape, getShapeUtils } from 'state/shape-utils'
|
import { createShape, getShapeUtils } from 'state/shape-utils'
|
||||||
import { setToArray } from 'utils'
|
import { setToArray, uniqueId } from 'utils'
|
||||||
|
import Vec from 'utils/vec'
|
||||||
|
|
||||||
export const codeShapes = new Set<CodeShape<Shape>>([])
|
export const codeShapes = new Set<CodeShape<Shape>>([])
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ function getOrderedShapes() {
|
||||||
|
|
||||||
export default class CodeShape<T extends Shape> {
|
export default class CodeShape<T extends Shape> {
|
||||||
private _shape: Mutable<T>
|
private _shape: Mutable<T>
|
||||||
private utils: ShapeUtility<T>
|
protected utils: ShapeUtility<T>
|
||||||
|
|
||||||
constructor(props: T) {
|
constructor(props: T) {
|
||||||
this._shape = createShape(props.type, props) as Mutable<T>
|
this._shape = createShape(props.type, props) as Mutable<T>
|
||||||
|
@ -34,79 +35,130 @@ export default class CodeShape<T extends Shape> {
|
||||||
codeShapes.add(this)
|
codeShapes.add(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
export(): Mutable<T> {
|
|
||||||
return { ...this._shape }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy the shape.
|
* Destroy the shape.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* shape.destroy()
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
destroy(): void {
|
destroy = (): void => {
|
||||||
codeShapes.delete(this)
|
codeShapes.delete(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape to a point.
|
* Move the shape to a point.
|
||||||
* @param delta
|
*
|
||||||
|
* ```ts
|
||||||
|
* shape.moveTo(100,100)
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
moveTo(point: number[]): CodeShape<T> {
|
moveTo = (point: number[]): CodeShape<T> => {
|
||||||
return this.translateTo(point)
|
return this.translateTo(point)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape to a point.
|
* Move the shape to a point.
|
||||||
* @param delta
|
*
|
||||||
|
* ```ts
|
||||||
|
* shape.translateTo([100,100])
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
translateTo(point: number[]): CodeShape<T> {
|
translateTo = (point: number[]): CodeShape<T> => {
|
||||||
this.utils.translateTo(this._shape, point)
|
this.utils.translateTo(this._shape, point)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape by a delta.
|
* Move the shape by a delta.
|
||||||
* @param delta
|
*
|
||||||
|
* ```ts
|
||||||
|
* shape.translateBy([100,100])
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
translateBy(delta: number[]): CodeShape<T> {
|
translateBy = (delta: number[]): CodeShape<T> => {
|
||||||
this.utils.translateTo(this._shape, delta)
|
this.utils.translateTo(this._shape, delta)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotate the shape.
|
* Rotate the shape.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* shape.rotateTo(Math.PI / 2)
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
rotateTo(rotation: number): CodeShape<T> {
|
rotateTo = (rotation: number): CodeShape<T> => {
|
||||||
this.utils.rotateTo(this._shape, rotation, this.shape.rotation - rotation)
|
this.utils.rotateTo(this._shape, rotation, this.shape.rotation - rotation)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotate the shape by a delta.
|
* Rotate the shape by a delta.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* shape.rotateBy(Math.PI / 2)
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
rotateBy(rotation: number): CodeShape<T> {
|
rotateBy = (rotation: number): CodeShape<T> => {
|
||||||
this.utils.rotateBy(this._shape, rotation)
|
this.utils.rotateBy(this._shape, rotation)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the shape's bounding box.
|
* Get the shape's bounding box.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const bounds = shape.getBounds()
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
getBounds(): CodeShape<T> {
|
getBounds = (): CodeShape<T> => {
|
||||||
this.utils.getBounds(this.shape)
|
this.utils.getBounds(this.shape)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether a point is inside of the shape.
|
* Test whether a point is inside of the shape.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const isHit = shape.hitTest()
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
hitTest(point: number[]): CodeShape<T> {
|
hitTest = (point: number[]): CodeShape<T> => {
|
||||||
this.utils.hitTest(this.shape, point)
|
this.utils.hitTest(this.shape, point)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape to the back of the painting order.
|
* Duplicate this shape.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeB = shape.duplicate()
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
moveToBack(): CodeShape<T> {
|
duplicate = (): CodeShape<T> => {
|
||||||
|
const duplicate = Object.assign(
|
||||||
|
Object.create(Object.getPrototypeOf(this)),
|
||||||
|
this
|
||||||
|
)
|
||||||
|
|
||||||
|
duplicate._shape = createShape(this._shape.type, {
|
||||||
|
...this._shape,
|
||||||
|
id: uniqueId(),
|
||||||
|
} as any)
|
||||||
|
|
||||||
|
codeShapes.add(duplicate)
|
||||||
|
return duplicate
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the shape to the back of the painting order.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* shape.moveToBack()
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
moveToBack = (): CodeShape<T> => {
|
||||||
const sorted = getOrderedShapes()
|
const sorted = getOrderedShapes()
|
||||||
|
|
||||||
if (sorted.length <= 1) return
|
if (sorted.length <= 1) return
|
||||||
|
@ -123,8 +175,12 @@ export default class CodeShape<T extends Shape> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape to the top of the painting order.
|
* Move the shape to the top of the painting order.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* shape.moveToFront()
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
moveToFront(): CodeShape<T> {
|
moveToFront = (): CodeShape<T> => {
|
||||||
const sorted = getOrderedShapes()
|
const sorted = getOrderedShapes()
|
||||||
|
|
||||||
if (sorted.length <= 1) return
|
if (sorted.length <= 1) return
|
||||||
|
@ -142,8 +198,12 @@ export default class CodeShape<T extends Shape> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape backward in the painting order.
|
* Move the shape backward in the painting order.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* shape.moveBackward()
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
moveBackward(): CodeShape<T> {
|
moveBackward = (): CodeShape<T> => {
|
||||||
const sorted = getOrderedShapes()
|
const sorted = getOrderedShapes()
|
||||||
|
|
||||||
if (sorted.length <= 1) return
|
if (sorted.length <= 1) return
|
||||||
|
@ -164,8 +224,12 @@ export default class CodeShape<T extends Shape> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the shape forward in the painting order.
|
* Move the shape forward in the painting order.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* shape.moveForward()
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
moveForward(): CodeShape<T> {
|
moveForward = (): CodeShape<T> => {
|
||||||
const sorted = getOrderedShapes()
|
const sorted = getOrderedShapes()
|
||||||
|
|
||||||
if (sorted.length <= 1) return
|
if (sorted.length <= 1) return
|
||||||
|
@ -189,79 +253,166 @@ export default class CodeShape<T extends Shape> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's underlying shape.
|
* The shape's underlying shape (readonly).
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const underlyingShape = shape.shape
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
get shape(): T {
|
get shape(): Readonly<T> {
|
||||||
return this._shape
|
return this._shape
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's current point.
|
* The shape's current point.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapePoint = shape.point()
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
get point(): number[] {
|
get point(): number[] {
|
||||||
return [...this.shape.point]
|
return [...this.shape.point]
|
||||||
}
|
}
|
||||||
|
|
||||||
set point(point: number[]) {
|
set point(point: number[]) {
|
||||||
getShapeUtils(this.shape).translateTo(this._shape, point)
|
this.utils.translateTo(this._shape, point)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shape's current x position.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeX = shape.x
|
||||||
|
*
|
||||||
|
* shape.x = 100
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
get x(): number {
|
||||||
|
return this.point[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
set x(x: number) {
|
||||||
|
this.utils.translateTo(this._shape, [x, this.y])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shape's current y position.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeY = shape.y
|
||||||
|
*
|
||||||
|
* shape.y = 100
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
get y(): number {
|
||||||
|
return this.point[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
set y(y: number) {
|
||||||
|
this.utils.translateTo(this._shape, [this.x, y])
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's rotation.
|
* The shape's rotation.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeRotation = shape.rotation
|
||||||
|
*
|
||||||
|
* shape.rotation = Math.PI / 2
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
get rotation(): number {
|
get rotation(): number {
|
||||||
return this.shape.rotation
|
return this.shape.rotation
|
||||||
}
|
}
|
||||||
|
|
||||||
set rotation(rotation: number) {
|
set rotation(rotation: number) {
|
||||||
getShapeUtils(this.shape).rotateTo(
|
this.utils.rotateTo(this._shape, rotation, rotation - this.shape.rotation)
|
||||||
this._shape,
|
|
||||||
rotation,
|
|
||||||
rotation - this.shape.rotation
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's color style.
|
* The shape's color style (ColorStyle).
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeColor = shape.color
|
||||||
|
*
|
||||||
|
* shape.color = ColorStyle.Red
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
get color(): ColorStyle {
|
get color(): ColorStyle {
|
||||||
return this.shape.style.color
|
return this.shape.style.color
|
||||||
}
|
}
|
||||||
|
|
||||||
set color(color: ColorStyle) {
|
set color(color: ColorStyle) {
|
||||||
getShapeUtils(this.shape).applyStyles(this._shape, { color })
|
this.utils.applyStyles(this._shape, { color })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's dash style.
|
* The shape's dash style (DashStyle).
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeDash = shape.dash
|
||||||
|
*
|
||||||
|
* shape.dash = DashStyle.Dotted
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
get dash(): DashStyle {
|
get dash(): DashStyle {
|
||||||
return this.shape.style.dash
|
return this.shape.style.dash
|
||||||
}
|
}
|
||||||
|
|
||||||
set dash(dash: DashStyle) {
|
set dash(dash: DashStyle) {
|
||||||
getShapeUtils(this.shape).applyStyles(this._shape, { dash })
|
this.utils.applyStyles(this._shape, { dash })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's stroke width.
|
* The shape's size (SizeStyle).
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeSize = shape.size
|
||||||
|
*
|
||||||
|
* shape.size = SizeStyle.Large
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
get strokeWidth(): SizeStyle {
|
get size(): SizeStyle {
|
||||||
return this.shape.style.size
|
return this.shape.style.size
|
||||||
}
|
}
|
||||||
|
|
||||||
set strokeWidth(size: SizeStyle) {
|
set size(size: SizeStyle) {
|
||||||
getShapeUtils(this.shape).applyStyles(this._shape, { size })
|
this.utils.applyStyles(this._shape, { size })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shape's index in the painting order.
|
* The shape's index in the painting order.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeChildIndex = shape.childIndex
|
||||||
|
*
|
||||||
|
* shape.childIndex = 10
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
get childIndex(): number {
|
get childIndex(): number {
|
||||||
return this.shape.childIndex
|
return this.shape.childIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
set childIndex(childIndex: number) {
|
set childIndex(childIndex: number) {
|
||||||
getShapeUtils(this.shape).setProperty(this._shape, 'childIndex', childIndex)
|
this.utils.setProperty(this._shape, 'childIndex', childIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shape's center.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeCenter = shape.center
|
||||||
|
*
|
||||||
|
* shape.center = [100, 100]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
get center(): number[] {
|
||||||
|
return this.utils.getCenter(this.shape)
|
||||||
|
}
|
||||||
|
|
||||||
|
set center(center: number[]) {
|
||||||
|
const oldCenter = this.utils.getCenter(this.shape)
|
||||||
|
const delta = Vec.sub(center, oldCenter)
|
||||||
|
this.translateBy(delta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,19 @@ export default class Line extends CodeShape<LineShape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The line's direction.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeDirection = shape.direction
|
||||||
|
*
|
||||||
|
* shape.direction = [0,0]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
get direction(): number[] {
|
get direction(): number[] {
|
||||||
return this.shape.direction
|
return this.shape.direction
|
||||||
}
|
}
|
||||||
|
set direction(direction: number[]) {
|
||||||
|
this.utils.setProperty(this.shape, 'direction', direction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,32 @@ export default class Polyline extends CodeShape<PolylineShape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a point to the polyline's points.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* shape.addPoint([100,100])
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
addPoint(point: number[]): CodeShape<PolylineShape> {
|
||||||
|
this.utils.setProperty(this.shape, 'points', [...this.points, point])
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The polyline's points.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapePoints = shape.points
|
||||||
|
*
|
||||||
|
* shape.points = [[0,0], [100,100], [100,200]]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
get points(): number[][] {
|
get points(): number[][] {
|
||||||
return this.shape.points
|
return this.shape.points
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set points(points: number[][]) {
|
||||||
|
this.utils.setProperty(this.shape, 'points', points)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,19 @@ export default class Ray extends CodeShape<RayShape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ray's direction.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeDirection = shape.direction
|
||||||
|
*
|
||||||
|
* shape.direction = [0,0]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
get direction(): number[] {
|
get direction(): number[] {
|
||||||
return this.shape.direction
|
return this.shape.direction
|
||||||
}
|
}
|
||||||
|
set direction(direction: number[]) {
|
||||||
|
this.utils.setProperty(this.shape, 'direction', direction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import CodeShape from './index'
|
||||||
import { uniqueId } from 'utils'
|
import { uniqueId } from 'utils'
|
||||||
import { RectangleShape, ShapeProps, ShapeType } from 'types'
|
import { RectangleShape, ShapeProps, ShapeType } from 'types'
|
||||||
import { defaultStyle } from 'state/shape-styles'
|
import { defaultStyle } from 'state/shape-styles'
|
||||||
|
import { getShapeUtils } from 'state/shape-utils'
|
||||||
|
|
||||||
/* ----------------- Start Copy Here ---------------- */
|
/* ----------------- Start Copy Here ---------------- */
|
||||||
|
|
||||||
|
@ -30,7 +31,43 @@ export default class Rectangle extends CodeShape<RectangleShape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
get size(): number[] {
|
/**
|
||||||
return this.shape.size
|
* The rectangle's width.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeWidth = shape.width
|
||||||
|
*
|
||||||
|
* shape.width = 100
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
get width(): number {
|
||||||
|
return this.shape.size[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
set width(width: number) {
|
||||||
|
getShapeUtils(this.shape).setProperty(this.shape, 'size', [
|
||||||
|
width,
|
||||||
|
this.height,
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rectangle's height.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeHeight = shape.height
|
||||||
|
*
|
||||||
|
* shape.height = 100
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
get height(): number {
|
||||||
|
return this.shape.size[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
set height(height: number) {
|
||||||
|
getShapeUtils(this.shape).setProperty(this.shape, 'size', [
|
||||||
|
this.width,
|
||||||
|
height,
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,32 @@ export default class Text extends CodeShape<TextShape> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The text shape's text content.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeText = shape.text
|
||||||
|
*
|
||||||
|
* shape.text = "Hello world!"
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
get text(): string {
|
||||||
|
return this.shape.text
|
||||||
|
}
|
||||||
|
|
||||||
|
set text(text: string) {
|
||||||
|
getShapeUtils(this.shape).setProperty(this.shape, 'text', text)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The text's scale.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const shapeScale = shape.scale
|
||||||
|
*
|
||||||
|
* shape.scale = 2
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
get scale(): number {
|
get scale(): number {
|
||||||
return this.shape.scale
|
return this.shape.scale
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue