Improves code editor types, adds es5 lib

This commit is contained in:
Steve Ruiz 2021-06-27 12:58:08 +01:00
parent 9d63160521
commit 61399fb9d0
12 changed files with 6219 additions and 114 deletions

View file

@ -1,5 +1,6 @@
import Editor, { Monaco } from '@monaco-editor/react'
import useTheme from 'hooks/useTheme'
import libImport from './es5-lib'
import typesImport from './types-import'
import React, { useCallback, useEffect, useRef } from 'react'
import styled from 'styles'
@ -46,17 +47,10 @@ export default function CodeEditor({
if (monacoRef) {
monacoRef.current = monaco
}
rMonaco.current = monaco
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
allowJs: true,
checkJs: false,
strict: false,
noLib: true,
lib: ['es6'],
target: monaco.languages.typescript.ScriptTarget.ES2016,
allowNonTsExtensions: true,
})
// Set the compiler options.
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
allowJs: true,
@ -68,27 +62,31 @@ export default function CodeEditor({
allowNonTsExtensions: true,
})
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true)
monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true)
// Sync the intellisense on load.
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
noSemanticValidation: false,
noSyntaxValidation: false,
})
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true)
// Run both semantic and syntax validation.
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
noSemanticValidation: false,
noSyntaxValidation: false,
})
// Add custom types
monaco.languages.typescript.typescriptDefaults.addExtraLib(
typesImport.content
)
monaco.languages.typescript.javascriptDefaults.addExtraLib(
typesImport.content
// Add es5 library types
monaco.languages.typescript.typescriptDefaults.addExtraLib(
libImport.content
)
// Use prettier as a formatter
monaco.languages.registerDocumentFormattingEditProvider('typescript', {
async provideDocumentFormattingEdits(model) {
try {
@ -223,6 +221,7 @@ export default function CodeEditor({
beforeMount={handleBeforeMount}
onMount={handleMount}
onChange={handleChange}
defaultPath="index.ts"
/>
</EditorContainer>
)

File diff suppressed because it is too large Load diff

View file

@ -8,10 +8,6 @@ export default {
name: 'types.ts',
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> = {
[P in keyof T]?: DeepPartial<T[P]>;
};
@ -141,7 +137,6 @@ interface TextShape extends BaseShape {
type: ShapeType.Text
text: string
scale: number
fontSize: FontSize
}
interface GroupShape extends BaseShape {
@ -187,12 +182,6 @@ type Shape = Readonly<MutableShape>
type ShapeByType<T extends ShapeType> = Shapes[T]
interface CodeFile {
id: string
name: string
code: string
}
enum Decoration {
Arrow = 'Arrow',
}
@ -209,6 +198,24 @@ interface ShapeHandle {
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 */
/* -------------------------------------------------- */
@ -548,7 +555,11 @@ interface ShapeUtility<K extends Shape> {
// Test whether bounds collide with or contain a shape.
hitTestBounds(this: ShapeUtility<K>, shape: K, bounds: Bounds): boolean
// Get whether the shape should delete
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> {
private _shape: Mutable<T>
private utils: ShapeUtility<T>
protected utils: ShapeUtility<T>
constructor(props: T) {
this._shape = createShape(props.type, props) as Mutable<T>
@ -1833,79 +1844,130 @@ interface ShapeUtility<K extends Shape> {
codeShapes.add(this)
}
export(): Mutable<T> {
return { ...this._shape }
}
/**
* Destroy the shape.
*
* \`\`\`ts
* shape.destroy()
* \`\`\`
*/
destroy(): void {
destroy = (): void => {
codeShapes.delete(this)
}
/**
* 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)
}
/**
* 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)
return this
}
/**
* 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)
return this
}
/**
* 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)
return this
}
/**
* 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)
return this
}
/**
* Get the shape's bounding box.
*
* \`\`\`ts
* const bounds = shape.getBounds()
* \`\`\`
*/
getBounds(): CodeShape<T> {
getBounds = (): CodeShape<T> => {
this.utils.getBounds(this.shape)
return this
}
/**
* 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)
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()
if (sorted.length <= 1) return
@ -1922,8 +1984,12 @@ interface ShapeUtility<K extends Shape> {
/**
* Move the shape to the top of the painting order.
*
* \`\`\`ts
* shape.moveToFront()
* \`\`\`
*/
moveToFront(): CodeShape<T> {
moveToFront = (): CodeShape<T> => {
const sorted = getOrderedShapes()
if (sorted.length <= 1) return
@ -1941,8 +2007,12 @@ interface ShapeUtility<K extends Shape> {
/**
* Move the shape backward in the painting order.
*
* \`\`\`ts
* shape.moveBackward()
* \`\`\`
*/
moveBackward(): CodeShape<T> {
moveBackward = (): CodeShape<T> => {
const sorted = getOrderedShapes()
if (sorted.length <= 1) return
@ -1963,8 +2033,12 @@ interface ShapeUtility<K extends Shape> {
/**
* Move the shape forward in the painting order.
*
* \`\`\`ts
* shape.moveForward()
* \`\`\`
*/
moveForward(): CodeShape<T> {
moveForward = (): CodeShape<T> => {
const sorted = getOrderedShapes()
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
}
/**
* The shape's current point.
*
* \`\`\`ts
* const shapePoint = shape.point()
* \`\`\`
*/
get point(): number[] {
return [...this.shape.point]
}
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.
*
* \`\`\`ts
* const shapeRotation = shape.rotation
*
* shape.rotation = Math.PI / 2
* \`\`\`
*/
get rotation(): number {
return this.shape.rotation
}
set rotation(rotation: number) {
getShapeUtils(this.shape).rotateTo(
this._shape,
rotation,
rotation - this.shape.rotation
)
this.utils.rotateTo(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 {
return this.shape.style.color
}
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 {
return this.shape.style.dash
}
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
}
set strokeWidth(size: SizeStyle) {
getShapeUtils(this.shape).applyStyles(this._shape, { size })
set size(size: SizeStyle) {
this.utils.applyStyles(this._shape, { size })
}
/**
* The shape's index in the painting order.
*
* \`\`\`ts
* const shapeChildIndex = shape.childIndex
*
* shape.childIndex = 10
* \`\`\`
*/
get childIndex(): number {
return this.shape.childIndex
}
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 {
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 {
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[] {
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[][] {
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[] {
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[] {
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[] {
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[] {
return this.shape.handles.end.point
}
@ -2366,7 +2629,6 @@ interface ShapeUtility<K extends Shape> {
isHidden: false,
text: 'Text',
scale: 1,
fontSize: FontSize.Medium,
...props,
style: {
...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,
])
}
}

View file

@ -25,6 +25,7 @@ async function inlineFileContents(path) {
/\/\* ----------------- Start Copy Here ---------------- \*\/(.|\n)*$/g
)[0]
.replaceAll('/* ----------------- Start Copy Here ---------------- */', '')
.replaceAll('```', '\\`\\`\\`')
.replaceAll('export default', '')
.replaceAll('export ', '')
.replaceAll('vec.', 'Vec.')
@ -46,16 +47,14 @@ async function copyTypesToFile() {
name: "types.ts",
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> = {
[P in keyof T]?: DeepPartial<T[P]>;
};
${await inlineFileContents('/types.ts')}
${await inlineFileContents('/types.ts')}
${await inlineFileContents('/utils/vec.ts')}
${await inlineFileContents('/state/code/utils.ts')}

View file

@ -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[] {
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[] {
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[] {
return this.shape.handles.end.point
}

View file

@ -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 {
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 {
return this.shape.radiusY
}
set radiusY(radiusY: number) {
this.utils.setProperty(this.shape, 'radiusY', radiusY)
}
}

View file

@ -7,7 +7,8 @@ import {
SizeStyle,
} from 'types'
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>>([])
@ -26,7 +27,7 @@ function getOrderedShapes() {
export default class CodeShape<T extends Shape> {
private _shape: Mutable<T>
private utils: ShapeUtility<T>
protected utils: ShapeUtility<T>
constructor(props: T) {
this._shape = createShape(props.type, props) as Mutable<T>
@ -34,79 +35,130 @@ export default class CodeShape<T extends Shape> {
codeShapes.add(this)
}
export(): Mutable<T> {
return { ...this._shape }
}
/**
* Destroy the shape.
*
* ```ts
* shape.destroy()
* ```
*/
destroy(): void {
destroy = (): void => {
codeShapes.delete(this)
}
/**
* 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)
}
/**
* 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)
return this
}
/**
* 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)
return this
}
/**
* 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)
return this
}
/**
* 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)
return this
}
/**
* Get the shape's bounding box.
*
* ```ts
* const bounds = shape.getBounds()
* ```
*/
getBounds(): CodeShape<T> {
getBounds = (): CodeShape<T> => {
this.utils.getBounds(this.shape)
return this
}
/**
* 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)
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()
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.
*
* ```ts
* shape.moveToFront()
* ```
*/
moveToFront(): CodeShape<T> {
moveToFront = (): CodeShape<T> => {
const sorted = getOrderedShapes()
if (sorted.length <= 1) return
@ -142,8 +198,12 @@ export default class CodeShape<T extends Shape> {
/**
* Move the shape backward in the painting order.
*
* ```ts
* shape.moveBackward()
* ```
*/
moveBackward(): CodeShape<T> {
moveBackward = (): CodeShape<T> => {
const sorted = getOrderedShapes()
if (sorted.length <= 1) return
@ -164,8 +224,12 @@ export default class CodeShape<T extends Shape> {
/**
* Move the shape forward in the painting order.
*
* ```ts
* shape.moveForward()
* ```
*/
moveForward(): CodeShape<T> {
moveForward = (): CodeShape<T> => {
const sorted = getOrderedShapes()
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
}
/**
* The shape's current point.
*
* ```ts
* const shapePoint = shape.point()
* ```
*/
get point(): number[] {
return [...this.shape.point]
}
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.
*
* ```ts
* const shapeRotation = shape.rotation
*
* shape.rotation = Math.PI / 2
* ```
*/
get rotation(): number {
return this.shape.rotation
}
set rotation(rotation: number) {
getShapeUtils(this.shape).rotateTo(
this._shape,
rotation,
rotation - this.shape.rotation
)
this.utils.rotateTo(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 {
return this.shape.style.color
}
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 {
return this.shape.style.dash
}
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
}
set strokeWidth(size: SizeStyle) {
getShapeUtils(this.shape).applyStyles(this._shape, { size })
set size(size: SizeStyle) {
this.utils.applyStyles(this._shape, { size })
}
/**
* The shape's index in the painting order.
*
* ```ts
* const shapeChildIndex = shape.childIndex
*
* shape.childIndex = 10
* ```
*/
get childIndex(): number {
return this.shape.childIndex
}
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)
}
}

View file

@ -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[] {
return this.shape.direction
}
set direction(direction: number[]) {
this.utils.setProperty(this.shape, 'direction', direction)
}
}

View file

@ -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[][] {
return this.shape.points
}
set points(points: number[][]) {
this.utils.setProperty(this.shape, 'points', points)
}
}

View file

@ -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[] {
return this.shape.direction
}
set direction(direction: number[]) {
this.utils.setProperty(this.shape, 'direction', direction)
}
}

View file

@ -2,6 +2,7 @@ import CodeShape from './index'
import { uniqueId } from 'utils'
import { RectangleShape, ShapeProps, ShapeType } from 'types'
import { defaultStyle } from 'state/shape-styles'
import { getShapeUtils } from 'state/shape-utils'
/* ----------------- 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,
])
}
}

View file

@ -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 {
return this.shape.scale
}