# How to use shapes in the Markup Editor

Shapes are used in the [Annotate](../../plugins/annotate/), [Decorate](../../plugins/decorate/), and the [Sticker](../../plugins/sticker/) plugins, they're also used to render image overlays in the [willRenderCanvas](../../ui/properties/#willrendercanvas) hook of the editor.

The editor also uses shapes internally to draw parts of the user interface.

* [Working with Shapes](#working-with-shapes)  
  * [Manipulating shapes](#manipulating-shapes)
  * [Creating templates with shapes](#creating-templates-with-shapes)
* [Types](#types)
* [Styles](#styles)  
  * [Shared](#shared)
  * [Eraser](#eraser)
  * [Rectangle](#rectangle)
  * [Ellipse](#ellipse)
  * [Line](#line)
  * [Text](#text)
  * [Path](#path)
* [State](#state)
* [Rights](#right-management)
* [Colors](#colors)

## Working with Shapes

In the examples below we'll interact with the `imageAnnotation` property. In the same manner we can update the `imageDecoration` property and `imageRedaction` property.

### Manipulating shapes

We can set the `imageAnnotation` property to an array of shapes and the editor will draw the shapes to the screen.

This example will draw a red square in the top left corner of the image.

* [ ![](/pintura/static/assets/technologies-mono/javascript.svg)JavaScript](#javascript-panel-0)
* [ ![](/pintura/static/assets/technologies-mono/react.svg)React](#react-panel-0)
* [ ![](/pintura/static/assets/technologies-mono/vue.svg)Vue](#vue-panel-0)
* [ ![](/pintura/static/assets/technologies-mono/svelte.svg)Svelte](#svelte-panel-0)
* [ ![](/pintura/static/assets/technologies-mono/angular.svg)Angular](#angular-panel-0)
* [ ![](/pintura/static/assets/technologies-mono/jquery.svg)jQuery](#jquery-panel-0)

* [index.html](#index-html-panel-0)

`<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageAnnotation: [
            // a red square
            {
                x: 0,
                y: 0,
                width: 128,
                height: 128,
                backgroundColor: [1, 0, 0],
            },
        ],
    });
</script>
`

* [App.jsx](#App-jsx-panel-0)
* [App.css](#App-css-panel-0)

`import '@pqina/pintura/pintura.css';
import './App.css';
import { PinturaEditor } from '@pqina/react-pintura';
import { getEditorDefaults } from '@pqina/pintura';

const editorDefaults = getEditorDefaults();

function App() {
    return (
        <div className="App">
            <PinturaEditor
                {...editorDefaults}
                src={'image.jpeg'}
                imageAnnotation={[
                    // a red square
                    {
                        x: 0,
                        y: 0,
                        width: 128,
                        height: 128,
                        backgroundColor: [1, 0, 0],
                    },
                ]}
            />
        </div>
    );
}

export default App;
`

```css
.pintura-editor {
    height: 600px;
}

```

* [App.vue](#App-vue-panel-0)

`<template>
    <div>
        <PinturaEditor
            v-bind="editorDefaults"
            src="image.jpeg"
            :imageAnnotation="imageAnnotation"
        />
    </div>
</template>
<script>
import { PinturaEditor } from '@pqina/vue-pintura';
import { getEditorDefaults } from '@pqina/pintura';

export default {
    name: 'App',

    components: {
        PinturaEditor,
    },

    data() {
        return {
            editorDefaults: getEditorDefaults(),

            imageAnnotation: [
                // a red square
                {
                    x: 0,
                    y: 0,
                    width: 128,
                    height: 128,
                    backgroundColor: [1, 0, 0],
                },
            ],
        };
    },

    methods: {},
};
</script>
<style>
@import '@pqina/pintura/pintura.css';

.pintura-editor {
    height: 600px;
}
</style>
`

* [App.svelte](#App-svelte-panel-0)

`<script>
    import { PinturaEditor } from '@pqina/svelte-pintura';
    import { getEditorDefaults } from '@pqina/pintura';
    import '@pqina/pintura/pintura.css';

    let editorDefaults = getEditorDefaults();
</script>

<div>
    <PinturaEditor
        {...editorDefaults}
        src={'image.jpeg'}
        imageAnnotation={[
            // a red square
            {
                x: 0,
                y: 0,
                width: 128,
                height: 128,
                backgroundColor: [1, 0, 0],
            },
        ]}
    />
</div>

<style>
    div :global(.pintura-editor) {
        height: 600px;
    }
</style>
`

* [app.component.ts](#app-component-ts-panel-0)
* [app.component.html](#app-component-html-panel-0)
* [app.component.css](#app-component-css-panel-0)
* [app.module.ts](#app-module-ts-panel-0)

`import { Component } from '@angular/core';

import { getEditorDefaults } from '@pqina/pintura';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
})
export class AppComponent {
    editorDefaults: any = getEditorDefaults();

    imageAnnotation: any = [
        // a red square
        {
            x: 0,
            y: 0,
            width: 128,
            height: 128,
            backgroundColor: [1, 0, 0],
        },
    ];
}
`

`<pintura-editor
    [options]="editorDefaults"
    src="image.jpeg"
    [imageAnnotation]="imageAnnotation"
></pintura-editor>
`

```css
::ng-deep .pintura-editor {
    height: 600px;
}

```

```javascript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularPinturaModule } from '@pqina/angular-pintura';

@NgModule({
    declarations: [AppComponent],
    imports: [BrowserModule, AngularPinturaModule],
    exports: [AppComponent],
    providers: [],
    bootstrap: [AppComponent],
})
export class AppModule {}

```

* [index.html](#index-html-panel-0)

`<!DOCTYPE html>
<head>
    <link rel="stylesheet" href="./pintura/pintura.css" />
</head>

<script src="./jquery.js"></script>
<script src="./jquery-pintura/useEditorWithJQuery-iife.js"></script>
<script src="./pintura/pintura-iife.js"></script>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script>
    useEditorWithJQuery(jQuery, pintura);

    $(function () {
        var editor = $('#editor').pinturaDefault({
            src: 'image.jpeg',
            imageAnnotation: [
                // a red square
                {
                    x: 0,
                    y: 0,
                    width: 128,
                    height: 128,
                    backgroundColor: [1, 0, 0],
                },
            ],
        });
    });
</script>
`

Let's add a green circle to the view.

* [ ![](/pintura/static/assets/technologies-mono/javascript.svg)JavaScript](#javascript-panel-1)
* [ ![](/pintura/static/assets/technologies-mono/react.svg)React](#react-panel-1)
* [ ![](/pintura/static/assets/technologies-mono/vue.svg)Vue](#vue-panel-1)
* [ ![](/pintura/static/assets/technologies-mono/svelte.svg)Svelte](#svelte-panel-1)
* [ ![](/pintura/static/assets/technologies-mono/angular.svg)Angular](#angular-panel-1)
* [ ![](/pintura/static/assets/technologies-mono/jquery.svg)jQuery](#jquery-panel-1)

* [index.html](#index-html-panel-1)

```html
<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<button type="button" id="buttonAddShape">Add green circle</button>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const buttonAddShape = document.querySelector('#buttonAddShape');

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageAnnotation: [
            // a red square
            {
                x: 0,
                y: 0,
                width: 128,
                height: 128,
                backgroundColor: [1, 0, 0],
            },
        ],
    });

    buttonAddShape.addEventListener('click', () => {
        // we merge our new circle shape with the existing list of shapes
        // it's added at the end of the list, so it will be drawn on top
        const updatedAnnotationList = [
            ...editor.imageAnnotation,
            {
                id: 'circle',
                x: 64,
                y: 64,
                rx: 128,
                ry: 128,
                backgroundColor: [0, 1, 0],
            },
        ];

        editor.imageAnnotation = updatedAnnotationList;
    });
</script>

```

* [App.jsx](#App-jsx-panel-1)
* [App.css](#App-css-panel-1)

```jsx
import '@pqina/pintura/pintura.css';
import './App.css';
import { useRef } from 'react';
import { PinturaEditor } from '@pqina/react-pintura';
import { getEditorDefaults } from '@pqina/pintura';

const editorDefaults = getEditorDefaults();

function App() {
    const editorRef = useRef(null);

    const handleButtonClick = () => {
        // we merge our new circle shape with the existing list of shapes
        // it's added at the end of the list, so it will be drawn on top
        const updatedAnnotationList = [
            ...editorRef.current.editor.imageAnnotation,
            {
                id: 'circle',
                x: 64,
                y: 64,
                rx: 128,
                ry: 128,
                backgroundColor: [0, 1, 0],
            },
        ];

        editorRef.current.editor.imageAnnotation = updatedAnnotationList;
    };

    return (
        <div className="App">
            <button type="button" onClick={handleButtonClick}>
                Add green circle
            </button>

            <PinturaEditor
                ref={editorRef}
                {...editorDefaults}
                src={'image.jpeg'}
                imageAnnotation={[
                    // a red square
                    {
                        x: 0,
                        y: 0,
                        width: 128,
                        height: 128,
                        backgroundColor: [1, 0, 0],
                    },
                ]}
            />
        </div>
    );
}

export default App;

```

```css
.pintura-editor {
    height: 600px;
}

```

* [App.vue](#App-vue-panel-1)

```html
<template>
    <div>
        <button type="button" v-on:click="handleButtonClick($event)">
            Add green circle
        </button>

        <PinturaEditor
            ref="editor"
            v-bind="editorDefaults"
            src="image.jpeg"
            :imageAnnotation="imageAnnotation"
        />
    </div>
</template>
<script>
import { PinturaEditor } from '@pqina/vue-pintura';
import { getEditorDefaults } from '@pqina/pintura';

export default {
    name: 'App',

    components: {
        PinturaEditor,
    },

    data() {
        return {
            editorDefaults: getEditorDefaults(),

            imageAnnotation: [
                // a red square
                {
                    x: 0,
                    y: 0,
                    width: 128,
                    height: 128,
                    backgroundColor: [1, 0, 0],
                },
            ],
        };
    },

    methods: {
        handleButtonClick: function () {
            // we merge our new circle shape with the existing list of shapes
            // it's added at the end of the list, so it will be drawn on top
            const updatedAnnotationList = [
                ...this.$refs.editor.editor.imageAnnotation,
                {
                    id: 'circle',
                    x: 64,
                    y: 64,
                    rx: 128,
                    ry: 128,
                    backgroundColor: [0, 1, 0],
                },
            ];

            this.$refs.editor.editor.imageAnnotation = updatedAnnotationList;
        },
    },
};
</script>
<style>
@import '@pqina/pintura/pintura.css';

.pintura-editor {
    height: 600px;
}
</style>

```

* [App.svelte](#App-svelte-panel-1)

```svelte
<script>
    import { PinturaEditor } from '@pqina/svelte-pintura';
    import { getEditorDefaults } from '@pqina/pintura';
    import '@pqina/pintura/pintura.css';

    let editorDefaults = getEditorDefaults();

    let editor;

    const handleButtonClick = () => {
        // we merge our new circle shape with the existing list of shapes
        // it's added at the end of the list, so it will be drawn on top
        const updatedAnnotationList = [
            ...editor.imageAnnotation,
            {
                id: 'circle',
                x: 64,
                y: 64,
                rx: 128,
                ry: 128,
                backgroundColor: [0, 1, 0],
            },
        ];

        editor.imageAnnotation = updatedAnnotationList;
    };
</script>

<div>
    <button type="button" on:click={handleButtonClick}>Add green circle</button>

    <PinturaEditor
        bind:this={editor}
        {...editorDefaults}
        src={'image.jpeg'}
        imageAnnotation={[
            // a red square
            {
                x: 0,
                y: 0,
                width: 128,
                height: 128,
                backgroundColor: [1, 0, 0],
            },
        ]}
    />
</div>

<style>
    div :global(.pintura-editor) {
        height: 600px;
    }
</style>

```

* [app.component.ts](#app-component-ts-panel-1)
* [app.component.html](#app-component-html-panel-1)
* [app.component.css](#app-component-css-panel-1)
* [app.module.ts](#app-module-ts-panel-1)

```javascript
import { Component, ViewChild } from '@angular/core';

import { getEditorDefaults } from '@pqina/pintura';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
})
export class AppComponent {
    @ViewChild('buttonAddShape') buttonAddShape?: any;

    @ViewChild('editor') editor?: any;

    editorDefaults: any = getEditorDefaults();

    imageAnnotation: any = [
        // a red square
        {
            x: 0,
            y: 0,
            width: 128,
            height: 128,
            backgroundColor: [1, 0, 0],
        },
    ];

    handleButtonClick(): void {
        // we merge our new circle shape with the existing list of shapes
        // it's added at the end of the list, so it will be drawn on top
        const updatedAnnotationList = [
            ...this.editor.editor.imageAnnotation,
            {
                id: 'circle',
                x: 64,
                y: 64,
                rx: 128,
                ry: 128,
                backgroundColor: [0, 1, 0],
            },
        ];

        this.editor.editor.imageAnnotation = updatedAnnotationList;
    }
}

```

```html
<button #buttonAddShape type="button" (click)="handleButtonClick()">
    Add green circle
</button>

<pintura-editor
    #editor
    [options]="editorDefaults"
    src="image.jpeg"
    [imageAnnotation]="imageAnnotation"
></pintura-editor>

```

```css
::ng-deep .pintura-editor {
    height: 600px;
}

```

```javascript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularPinturaModule } from '@pqina/angular-pintura';

@NgModule({
    declarations: [AppComponent],
    imports: [BrowserModule, AngularPinturaModule],
    exports: [AppComponent],
    providers: [],
    bootstrap: [AppComponent],
})
export class AppModule {}

```

* [index.html](#index-html-panel-1)

```html
<!DOCTYPE html>
<head>
    <link rel="stylesheet" href="./pintura/pintura.css" />
</head>

<script src="./jquery.js"></script>
<script src="./jquery-pintura/useEditorWithJQuery-iife.js"></script>
<script src="./pintura/pintura-iife.js"></script>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<button type="button" id="buttonAddShape">Add green circle</button>

<div id="editor"></div>

<script>
    useEditorWithJQuery(jQuery, pintura);

    $(function () {
        var buttonAddShape = $('#buttonAddShape');

        var editor = $('#editor').pinturaDefault({
            src: 'image.jpeg',
            imageAnnotation: [
                // a red square
                {
                    x: 0,
                    y: 0,
                    width: 128,
                    height: 128,
                    backgroundColor: [1, 0, 0],
                },
            ],
        });

        buttonAddShape.on('click', function () {
            // we merge our new circle shape with the existing list of shapes
            // it's added at the end of the list, so it will be drawn on top
            const updatedAnnotationList = [
                ...editor.imageAnnotation,
                {
                    id: 'circle',
                    x: 64,
                    y: 64,
                    rx: 128,
                    ry: 128,
                    backgroundColor: [0, 1, 0],
                },
            ];
            $(editor).pintura('imageAnnotation', updatedAnnotationList);
        });
    });
</script>

```

Now let's change the color of the red square to blue.

* [ ![](/pintura/static/assets/technologies-mono/javascript.svg)JavaScript](#javascript-panel-2)
* [ ![](/pintura/static/assets/technologies-mono/react.svg)React](#react-panel-2)
* [ ![](/pintura/static/assets/technologies-mono/vue.svg)Vue](#vue-panel-2)
* [ ![](/pintura/static/assets/technologies-mono/svelte.svg)Svelte](#svelte-panel-2)
* [ ![](/pintura/static/assets/technologies-mono/angular.svg)Angular](#angular-panel-2)
* [ ![](/pintura/static/assets/technologies-mono/jquery.svg)jQuery](#jquery-panel-2)

* [index.html](#index-html-panel-2)

```html
<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<button type="button" id="buttonChangeColor">Change color</button>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const buttonChangeColor = document.querySelector('#buttonChangeColor');

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageAnnotation: [
            // a red square
            {
                x: 0,
                y: 0,
                width: 128,
                height: 128,
                backgroundColor: [1, 0, 0],
            },
        ],
    });

    buttonChangeColor.addEventListener('click', () => {
        const updatedAnnotationList = editor.imageAnnotation.map((shape) => {
            // if it's the square, copy and overwrite background color property
            if (shape.id === 'square') {
                return {
                    ...shape,
                    backgroundColor: [0, 0, 1],
                };
            }

            // else return shape
            return shape;
        });

        editor.imageAnnotation = updatedAnnotationList;
    });
</script>

```

* [App.jsx](#App-jsx-panel-2)
* [App.css](#App-css-panel-2)

```jsx
import '@pqina/pintura/pintura.css';
import './App.css';
import { useRef } from 'react';
import { PinturaEditor } from '@pqina/react-pintura';
import { getEditorDefaults } from '@pqina/pintura';

const editorDefaults = getEditorDefaults();

function App() {
    const editorRef = useRef(null);

    const handleButtonClick = () => {
        const updatedAnnotationList =
            editorRef.current.editor.imageAnnotation.map((shape) => {
                // if it's the square, copy and overwrite background color property
                if (shape.id === 'square') {
                    return {
                        ...shape,
                        backgroundColor: [0, 0, 1],
                    };
                }

                // else return shape
                return shape;
            });

        editorRef.current.editor.imageAnnotation = updatedAnnotationList;
    };

    return (
        <div className="App">
            <button type="button" onClick={handleButtonClick}>
                Change color
            </button>

            <PinturaEditor
                ref={editorRef}
                {...editorDefaults}
                src={'image.jpeg'}
                imageAnnotation={[
                    // a red square
                    {
                        x: 0,
                        y: 0,
                        width: 128,
                        height: 128,
                        backgroundColor: [1, 0, 0],
                    },
                ]}
            />
        </div>
    );
}

export default App;

```

```css
.pintura-editor {
    height: 600px;
}

```

* [App.vue](#App-vue-panel-2)

```html
<template>
    <div>
        <button type="button" v-on:click="handleButtonClick($event)">
            Change color
        </button>

        <PinturaEditor
            ref="editor"
            v-bind="editorDefaults"
            src="image.jpeg"
            :imageAnnotation="imageAnnotation"
        />
    </div>
</template>
<script>
import { PinturaEditor } from '@pqina/vue-pintura';
import { getEditorDefaults } from '@pqina/pintura';

export default {
    name: 'App',

    components: {
        PinturaEditor,
    },

    data() {
        return {
            editorDefaults: getEditorDefaults(),

            imageAnnotation: [
                // a red square
                {
                    x: 0,
                    y: 0,
                    width: 128,
                    height: 128,
                    backgroundColor: [1, 0, 0],
                },
            ],
        };
    },

    methods: {
        handleButtonClick: function () {
            const updatedAnnotationList =
                this.$refs.editor.editor.imageAnnotation.map((shape) => {
                    // if it's the square, copy and overwrite background color property
                    if (shape.id === 'square') {
                        return {
                            ...shape,
                            backgroundColor: [0, 0, 1],
                        };
                    }

                    // else return shape
                    return shape;
                });

            this.$refs.editor.editor.imageAnnotation = updatedAnnotationList;
        },
    },
};
</script>
<style>
@import '@pqina/pintura/pintura.css';

.pintura-editor {
    height: 600px;
}
</style>

```

* [App.svelte](#App-svelte-panel-2)

```svelte
<script>
    import { PinturaEditor } from '@pqina/svelte-pintura';
    import { getEditorDefaults } from '@pqina/pintura';
    import '@pqina/pintura/pintura.css';

    let editorDefaults = getEditorDefaults();

    let editor;

    const handleButtonClick = () => {
        const updatedAnnotationList = editor.imageAnnotation.map((shape) => {
            // if it's the square, copy and overwrite background color property
            if (shape.id === 'square') {
                return {
                    ...shape,
                    backgroundColor: [0, 0, 1],
                };
            }

            // else return shape
            return shape;
        });

        editor.imageAnnotation = updatedAnnotationList;
    };
</script>

<div>
    <button type="button" on:click={handleButtonClick}>Change color</button>

    <PinturaEditor
        bind:this={editor}
        {...editorDefaults}
        src={'image.jpeg'}
        imageAnnotation={[
            // a red square
            {
                x: 0,
                y: 0,
                width: 128,
                height: 128,
                backgroundColor: [1, 0, 0],
            },
        ]}
    />
</div>

<style>
    div :global(.pintura-editor) {
        height: 600px;
    }
</style>

```

* [app.component.ts](#app-component-ts-panel-2)
* [app.component.html](#app-component-html-panel-2)
* [app.component.css](#app-component-css-panel-2)
* [app.module.ts](#app-module-ts-panel-2)

```javascript
import { Component, ViewChild } from '@angular/core';

import { getEditorDefaults } from '@pqina/pintura';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
})
export class AppComponent {
    @ViewChild('buttonChangeColor') buttonChangeColor?: any;

    @ViewChild('editor') editor?: any;

    editorDefaults: any = getEditorDefaults();

    imageAnnotation: any = [
        // a red square
        {
            x: 0,
            y: 0,
            width: 128,
            height: 128,
            backgroundColor: [1, 0, 0],
        },
    ];

    handleButtonClick(): void {
        const updatedAnnotationList = this.editor.editor.imageAnnotation.map(
            (shape) => {
                // if it's the square, copy and overwrite background color property
                if (shape.id === 'square') {
                    return {
                        ...shape,
                        backgroundColor: [0, 0, 1],
                    };
                }

                // else return shape
                return shape;
            }
        );

        this.editor.editor.imageAnnotation = updatedAnnotationList;
    }
}

```

```html
<button #buttonChangeColor type="button" (click)="handleButtonClick()">
    Change color
</button>

<pintura-editor
    #editor
    [options]="editorDefaults"
    src="image.jpeg"
    [imageAnnotation]="imageAnnotation"
></pintura-editor>

```

```css
::ng-deep .pintura-editor {
    height: 600px;
}

```

```javascript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularPinturaModule } from '@pqina/angular-pintura';

@NgModule({
    declarations: [AppComponent],
    imports: [BrowserModule, AngularPinturaModule],
    exports: [AppComponent],
    providers: [],
    bootstrap: [AppComponent],
})
export class AppModule {}

```

* [index.html](#index-html-panel-2)

```html
<!DOCTYPE html>
<head>
    <link rel="stylesheet" href="./pintura/pintura.css" />
</head>

<script src="./jquery.js"></script>
<script src="./jquery-pintura/useEditorWithJQuery-iife.js"></script>
<script src="./pintura/pintura-iife.js"></script>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<button type="button" id="buttonChangeColor">Change color</button>

<div id="editor"></div>

<script>
    useEditorWithJQuery(jQuery, pintura);

    $(function () {
        var buttonChangeColor = $('#buttonChangeColor');

        var editor = $('#editor').pinturaDefault({
            src: 'image.jpeg',
            imageAnnotation: [
                // a red square
                {
                    x: 0,
                    y: 0,
                    width: 128,
                    height: 128,
                    backgroundColor: [1, 0, 0],
                },
            ],
        });

        buttonChangeColor.on('click', function () {
            const updatedAnnotationList = editor.imageAnnotation.map(
                (shape) => {
                    // if it's the square, copy and overwrite background color property
                    if (shape.id === 'square') {
                        return {
                            ...shape,
                            backgroundColor: [0, 0, 1],
                        };
                    }

                    // else return shape
                    return shape;
                }
            );
            $(editor).pintura('imageAnnotation', updatedAnnotationList);
        });
    });
</script>

```

Now let's remove the red square

* [ ![](/pintura/static/assets/technologies-mono/javascript.svg)JavaScript](#javascript-panel-3)
* [ ![](/pintura/static/assets/technologies-mono/react.svg)React](#react-panel-3)
* [ ![](/pintura/static/assets/technologies-mono/vue.svg)Vue](#vue-panel-3)
* [ ![](/pintura/static/assets/technologies-mono/svelte.svg)Svelte](#svelte-panel-3)
* [ ![](/pintura/static/assets/technologies-mono/angular.svg)Angular](#angular-panel-3)
* [ ![](/pintura/static/assets/technologies-mono/jquery.svg)jQuery](#jquery-panel-3)

* [index.html](#index-html-panel-3)

```html
<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<button type="button" id="buttonRemoveShape">Remove red square</button>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const buttonRemoveShape = document.querySelector('#buttonRemoveShape');

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageAnnotation: [
            // a red square
            {
                x: 0,
                y: 0,
                width: 128,
                height: 128,
                backgroundColor: [1, 0, 0],
            },
            // a green circle
            {
                id: 'circle',
                x: 64,
                y: 64,
                rx: 128,
                ry: 128,
                backgroundColor: [0, 1, 0],
            },
        ],
    });

    buttonRemoveShape.addEventListener('click', () => {
        // this filters out the red square from the shapes list
        const updatedAnnotationList = editor.imageAnnotation.filter(
            (shape) => shape.id !== 'square'
        );

        editor.imageAnnotation = updatedAnnotationList;
    });
</script>

```

* [App.jsx](#App-jsx-panel-3)
* [App.css](#App-css-panel-3)

```jsx
import '@pqina/pintura/pintura.css';
import './App.css';
import { useRef } from 'react';
import { PinturaEditor } from '@pqina/react-pintura';
import { getEditorDefaults } from '@pqina/pintura';

const editorDefaults = getEditorDefaults();

function App() {
    const editorRef = useRef(null);

    const handleButtonClick = () => {
        // this filters out the red square from the shapes list
        const updatedAnnotationList =
            editorRef.current.editor.imageAnnotation.filter(
                (shape) => shape.id !== 'square'
            );

        editorRef.current.editor.imageAnnotation = updatedAnnotationList;
    };

    return (
        <div className="App">
            <button type="button" onClick={handleButtonClick}>
                Remove red square
            </button>

            <PinturaEditor
                ref={editorRef}
                {...editorDefaults}
                src={'image.jpeg'}
                imageAnnotation={[
                    // a red square
                    {
                        x: 0,
                        y: 0,
                        width: 128,
                        height: 128,
                        backgroundColor: [1, 0, 0],
                    },
                    // a green circle
                    {
                        id: 'circle',
                        x: 64,
                        y: 64,
                        rx: 128,
                        ry: 128,
                        backgroundColor: [0, 1, 0],
                    },
                ]}
            />
        </div>
    );
}

export default App;

```

```css
.pintura-editor {
    height: 600px;
}

```

* [App.vue](#App-vue-panel-3)

```html
<template>
    <div>
        <button type="button" v-on:click="handleButtonClick($event)">
            Remove red square
        </button>

        <PinturaEditor
            ref="editor"
            v-bind="editorDefaults"
            src="image.jpeg"
            :imageAnnotation="imageAnnotation"
        />
    </div>
</template>
<script>
import { PinturaEditor } from '@pqina/vue-pintura';
import { getEditorDefaults } from '@pqina/pintura';

export default {
    name: 'App',

    components: {
        PinturaEditor,
    },

    data() {
        return {
            editorDefaults: getEditorDefaults(),

            imageAnnotation: [
                // a red square
                {
                    x: 0,
                    y: 0,
                    width: 128,
                    height: 128,
                    backgroundColor: [1, 0, 0],
                },
                // a green circle
                {
                    id: 'circle',
                    x: 64,
                    y: 64,
                    rx: 128,
                    ry: 128,
                    backgroundColor: [0, 1, 0],
                },
            ],
        };
    },

    methods: {
        handleButtonClick: function () {
            // this filters out the red square from the shapes list
            const updatedAnnotationList =
                this.$refs.editor.editor.imageAnnotation.filter(
                    (shape) => shape.id !== 'square'
                );

            this.$refs.editor.editor.imageAnnotation = updatedAnnotationList;
        },
    },
};
</script>
<style>
@import '@pqina/pintura/pintura.css';

.pintura-editor {
    height: 600px;
}
</style>

```

* [App.svelte](#App-svelte-panel-3)

```svelte
<script>
    import { PinturaEditor } from '@pqina/svelte-pintura';
    import { getEditorDefaults } from '@pqina/pintura';
    import '@pqina/pintura/pintura.css';

    let editorDefaults = getEditorDefaults();

    let editor;

    const handleButtonClick = () => {
        // this filters out the red square from the shapes list
        const updatedAnnotationList = editor.imageAnnotation.filter(
            (shape) => shape.id !== 'square'
        );

        editor.imageAnnotation = updatedAnnotationList;
    };
</script>

<div>
    <button type="button" on:click={handleButtonClick}>Remove red square</button
    >

    <PinturaEditor
        bind:this={editor}
        {...editorDefaults}
        src={'image.jpeg'}
        imageAnnotation={[
            // a red square
            {
                x: 0,
                y: 0,
                width: 128,
                height: 128,
                backgroundColor: [1, 0, 0],
            },
            // a green circle
            {
                id: 'circle',
                x: 64,
                y: 64,
                rx: 128,
                ry: 128,
                backgroundColor: [0, 1, 0],
            },
        ]}
    />
</div>

<style>
    div :global(.pintura-editor) {
        height: 600px;
    }
</style>

```

* [app.component.ts](#app-component-ts-panel-3)
* [app.component.html](#app-component-html-panel-3)
* [app.component.css](#app-component-css-panel-3)
* [app.module.ts](#app-module-ts-panel-3)

```javascript
import { Component, ViewChild } from '@angular/core';

import { getEditorDefaults } from '@pqina/pintura';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
})
export class AppComponent {
    @ViewChild('buttonRemoveShape') buttonRemoveShape?: any;

    @ViewChild('editor') editor?: any;

    editorDefaults: any = getEditorDefaults();

    imageAnnotation: any = [
        // a red square
        {
            x: 0,
            y: 0,
            width: 128,
            height: 128,
            backgroundColor: [1, 0, 0],
        },
        // a green circle
        {
            id: 'circle',
            x: 64,
            y: 64,
            rx: 128,
            ry: 128,
            backgroundColor: [0, 1, 0],
        },
    ];

    handleButtonClick(): void {
        // this filters out the red square from the shapes list
        const updatedAnnotationList = this.editor.editor.imageAnnotation.filter(
            (shape) => shape.id !== 'square'
        );

        this.editor.editor.imageAnnotation = updatedAnnotationList;
    }
}

```

```html
<button #buttonRemoveShape type="button" (click)="handleButtonClick()">
    Remove red square
</button>

<pintura-editor
    #editor
    [options]="editorDefaults"
    src="image.jpeg"
    [imageAnnotation]="imageAnnotation"
></pintura-editor>

```

```css
::ng-deep .pintura-editor {
    height: 600px;
}

```

```javascript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularPinturaModule } from '@pqina/angular-pintura';

@NgModule({
    declarations: [AppComponent],
    imports: [BrowserModule, AngularPinturaModule],
    exports: [AppComponent],
    providers: [],
    bootstrap: [AppComponent],
})
export class AppModule {}

```

* [index.html](#index-html-panel-3)

```html
<!DOCTYPE html>
<head>
    <link rel="stylesheet" href="./pintura/pintura.css" />
</head>

<script src="./jquery.js"></script>
<script src="./jquery-pintura/useEditorWithJQuery-iife.js"></script>
<script src="./pintura/pintura-iife.js"></script>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<button type="button" id="buttonRemoveShape">Remove red square</button>

<div id="editor"></div>

<script>
    useEditorWithJQuery(jQuery, pintura);

    $(function () {
        var buttonRemoveShape = $('#buttonRemoveShape');

        var editor = $('#editor').pinturaDefault({
            src: 'image.jpeg',
            imageAnnotation: [
                // a red square
                {
                    x: 0,
                    y: 0,
                    width: 128,
                    height: 128,
                    backgroundColor: [1, 0, 0],
                },
                // a green circle
                {
                    id: 'circle',
                    x: 64,
                    y: 64,
                    rx: 128,
                    ry: 128,
                    backgroundColor: [0, 1, 0],
                },
            ],
        });

        buttonRemoveShape.on('click', function () {
            // this filters out the red square from the shapes list
            const updatedAnnotationList = editor.imageAnnotation.filter(
                (shape) => shape.id !== 'square'
            );
            $(editor).pintura('imageAnnotation', updatedAnnotationList);
        });
    });
</script>

```

### Creating templates with shapes

We can use shapes to pre-define templates for the user to edit. Anytime we update the `imageDecoration` array the changes are reflected in the editor.

By assigning rights to our shapes we can lock shapes in place and control what the end user can change.

* [ ![](/pintura/static/assets/technologies-mono/javascript.svg)JavaScript](#javascript-panel-4)
* [ ![](/pintura/static/assets/technologies-mono/react.svg)React](#react-panel-4)
* [ ![](/pintura/static/assets/technologies-mono/vue.svg)Vue](#vue-panel-4)
* [ ![](/pintura/static/assets/technologies-mono/svelte.svg)Svelte](#svelte-panel-4)
* [ ![](/pintura/static/assets/technologies-mono/angular.svg)Angular](#angular-panel-4)
* [ ![](/pintura/static/assets/technologies-mono/jquery.svg)jQuery](#jquery-panel-4)

* [index.html](#index-html-panel-4)

`<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        util: 'decorate',
        imageDecoration: [
            // a title
            {
                x: 64,
                y: 64,
                fontSize: 128,
                fontWeight: 'bold',
                text: 'Title',
                color: [0, 0, 0],

                // initially selected
                isSelected: true,

                // prevent adjusting these styles
                disableStyle: ['fontSize', 'fontWeight', 'lineHeight'],

                // prevent these shape manipulations
                disableRemove: true,
                disableMove: true,
                disableFlip: true,
                disableRotate: true,
                disableTextLayout: true,
                disableReorder: true,
            },

            // a line
            {
                x: 0,
                y: 280,
                width: '100%',
                height: 2,
                backgroundColor: [0, 0, 0],
            },

            // a paragraph that resizes with the crop
            {
                top: 344,
                left: 64,
                right: 64,
                height: 512,
                fontSize: 48,
                fontStyle: 'italic',
                text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eget neque eu nisl convallis eleifend et at neque. Sed eleifend tellus ante, id hendrerit turpis molestie id.',
                color: [1, 1, 1],

                // prevent adjusting these styles
                disableStyle: ['fontSize', 'fontWeight', 'lineHeight'],

                // prevent these shape manipulations
                disableRemove: true,
                disableMove: true,
                disableFlip: true,
                disableRotate: true,
                disableTextLayout: true,
                disableReorder: true,
            },
        ],
    });
</script>
`

* [App.jsx](#App-jsx-panel-4)
* [App.css](#App-css-panel-4)

`import '@pqina/pintura/pintura.css';
import './App.css';
import { PinturaEditor } from '@pqina/react-pintura';
import { getEditorDefaults } from '@pqina/pintura';

const editorDefaults = getEditorDefaults();

function App() {
    return (
        <div className="App">
            <PinturaEditor
                {...editorDefaults}
                src={'image.jpeg'}
                util={'decorate'}
                imageDecoration={[
                    // a title
                    {
                        x: 64,
                        y: 64,
                        fontSize: 128,
                        fontWeight: 'bold',
                        text: 'Title',
                        color: [0, 0, 0],

                        // initially selected
                        isSelected: true,

                        // prevent adjusting these styles
                        disableStyle: ['fontSize', 'fontWeight', 'lineHeight'],

                        // prevent these shape manipulations
                        disableRemove: true,
                        disableMove: true,
                        disableFlip: true,
                        disableRotate: true,
                        disableTextLayout: true,
                        disableReorder: true,
                    },

                    // a line
                    {
                        x: 0,
                        y: 280,
                        width: '100%',
                        height: 2,
                        backgroundColor: [0, 0, 0],
                    },

                    // a paragraph that resizes with the crop
                    {
                        top: 344,
                        left: 64,
                        right: 64,
                        height: 512,
                        fontSize: 48,
                        fontStyle: 'italic',
                        text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eget neque eu nisl convallis eleifend et at neque. Sed eleifend tellus ante, id hendrerit turpis molestie id.',
                        color: [1, 1, 1],

                        // prevent adjusting these styles
                        disableStyle: ['fontSize', 'fontWeight', 'lineHeight'],

                        // prevent these shape manipulations
                        disableRemove: true,
                        disableMove: true,
                        disableFlip: true,
                        disableRotate: true,
                        disableTextLayout: true,
                        disableReorder: true,
                    },
                ]}
            />
        </div>
    );
}

export default App;
`

```css
.pintura-editor {
    height: 600px;
}

```

* [App.vue](#App-vue-panel-4)

`<template>
    <div>
        <PinturaEditor
            v-bind="editorDefaults"
            src="image.jpeg"
            util="decorate"
            :imageDecoration="imageDecoration"
        />
    </div>
</template>
<script>
import { PinturaEditor } from '@pqina/vue-pintura';
import { getEditorDefaults } from '@pqina/pintura';

export default {
    name: 'App',

    components: {
        PinturaEditor,
    },

    data() {
        return {
            editorDefaults: getEditorDefaults(),

            imageDecoration: [
                // a title
                {
                    x: 64,
                    y: 64,
                    fontSize: 128,
                    fontWeight: 'bold',
                    text: 'Title',
                    color: [0, 0, 0],

                    // initially selected
                    isSelected: true,

                    // prevent adjusting these styles
                    disableStyle: ['fontSize', 'fontWeight', 'lineHeight'],

                    // prevent these shape manipulations
                    disableRemove: true,
                    disableMove: true,
                    disableFlip: true,
                    disableRotate: true,
                    disableTextLayout: true,
                    disableReorder: true,
                },

                // a line
                {
                    x: 0,
                    y: 280,
                    width: '100%',
                    height: 2,
                    backgroundColor: [0, 0, 0],
                },

                // a paragraph that resizes with the crop
                {
                    top: 344,
                    left: 64,
                    right: 64,
                    height: 512,
                    fontSize: 48,
                    fontStyle: 'italic',
                    text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eget neque eu nisl convallis eleifend et at neque. Sed eleifend tellus ante, id hendrerit turpis molestie id.',
                    color: [1, 1, 1],

                    // prevent adjusting these styles
                    disableStyle: ['fontSize', 'fontWeight', 'lineHeight'],

                    // prevent these shape manipulations
                    disableRemove: true,
                    disableMove: true,
                    disableFlip: true,
                    disableRotate: true,
                    disableTextLayout: true,
                    disableReorder: true,
                },
            ],
        };
    },

    methods: {},
};
</script>
<style>
@import '@pqina/pintura/pintura.css';

.pintura-editor {
    height: 600px;
}
</style>
`

* [App.svelte](#App-svelte-panel-4)

`<script>
    import { PinturaEditor } from '@pqina/svelte-pintura';
    import { getEditorDefaults } from '@pqina/pintura';
    import '@pqina/pintura/pintura.css';

    let editorDefaults = getEditorDefaults();
</script>

<div>
    <PinturaEditor
        {...editorDefaults}
        src={'image.jpeg'}
        util={'decorate'}
        imageDecoration={[
            // a title
            {
                x: 64,
                y: 64,
                fontSize: 128,
                fontWeight: 'bold',
                text: 'Title',
                color: [0, 0, 0],

                // initially selected
                isSelected: true,

                // prevent adjusting these styles
                disableStyle: ['fontSize', 'fontWeight', 'lineHeight'],

                // prevent these shape manipulations
                disableRemove: true,
                disableMove: true,
                disableFlip: true,
                disableRotate: true,
                disableTextLayout: true,
                disableReorder: true,
            },

            // a line
            {
                x: 0,
                y: 280,
                width: '100%',
                height: 2,
                backgroundColor: [0, 0, 0],
            },

            // a paragraph that resizes with the crop
            {
                top: 344,
                left: 64,
                right: 64,
                height: 512,
                fontSize: 48,
                fontStyle: 'italic',
                text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eget neque eu nisl convallis eleifend et at neque. Sed eleifend tellus ante, id hendrerit turpis molestie id.',
                color: [1, 1, 1],

                // prevent adjusting these styles
                disableStyle: ['fontSize', 'fontWeight', 'lineHeight'],

                // prevent these shape manipulations
                disableRemove: true,
                disableMove: true,
                disableFlip: true,
                disableRotate: true,
                disableTextLayout: true,
                disableReorder: true,
            },
        ]}
    />
</div>

<style>
    div :global(.pintura-editor) {
        height: 600px;
    }
</style>
`

* [app.component.ts](#app-component-ts-panel-4)
* [app.component.html](#app-component-html-panel-4)
* [app.component.css](#app-component-css-panel-4)
* [app.module.ts](#app-module-ts-panel-4)

`import { Component } from '@angular/core';

import { getEditorDefaults } from '@pqina/pintura';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
})
export class AppComponent {
    editorDefaults: any = getEditorDefaults();

    imageDecoration: any = [
        // a title
        {
            x: 64,
            y: 64,
            fontSize: 128,
            fontWeight: 'bold',
            text: 'Title',
            color: [0, 0, 0],

            // initially selected
            isSelected: true,

            // prevent adjusting these styles
            disableStyle: ['fontSize', 'fontWeight', 'lineHeight'],

            // prevent these shape manipulations
            disableRemove: true,
            disableMove: true,
            disableFlip: true,
            disableRotate: true,
            disableTextLayout: true,
            disableReorder: true,
        },

        // a line
        {
            x: 0,
            y: 280,
            width: '100%',
            height: 2,
            backgroundColor: [0, 0, 0],
        },

        // a paragraph that resizes with the crop
        {
            top: 344,
            left: 64,
            right: 64,
            height: 512,
            fontSize: 48,
            fontStyle: 'italic',
            text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eget neque eu nisl convallis eleifend et at neque. Sed eleifend tellus ante, id hendrerit turpis molestie id.',
            color: [1, 1, 1],

            // prevent adjusting these styles
            disableStyle: ['fontSize', 'fontWeight', 'lineHeight'],

            // prevent these shape manipulations
            disableRemove: true,
            disableMove: true,
            disableFlip: true,
            disableRotate: true,
            disableTextLayout: true,
            disableReorder: true,
        },
    ];
}
`

`<pintura-editor
    [options]="editorDefaults"
    src="image.jpeg"
    util="decorate"
    [imageDecoration]="imageDecoration"
></pintura-editor>
`

```css
::ng-deep .pintura-editor {
    height: 600px;
}

```

```javascript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularPinturaModule } from '@pqina/angular-pintura';

@NgModule({
    declarations: [AppComponent],
    imports: [BrowserModule, AngularPinturaModule],
    exports: [AppComponent],
    providers: [],
    bootstrap: [AppComponent],
})
export class AppModule {}

```

* [index.html](#index-html-panel-4)

`<!DOCTYPE html>
<head>
    <link rel="stylesheet" href="./pintura/pintura.css" />
</head>

<script src="./jquery.js"></script>
<script src="./jquery-pintura/useEditorWithJQuery-iife.js"></script>
<script src="./pintura/pintura-iife.js"></script>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script>
    useEditorWithJQuery(jQuery, pintura);

    $(function () {
        var editor = $('#editor').pinturaDefault({
            src: 'image.jpeg',
            util: 'decorate',
            imageDecoration: [
                // a title
                {
                    x: 64,
                    y: 64,
                    fontSize: 128,
                    fontWeight: 'bold',
                    text: 'Title',
                    color: [0, 0, 0],

                    // initially selected
                    isSelected: true,

                    // prevent adjusting these styles
                    disableStyle: ['fontSize', 'fontWeight', 'lineHeight'],

                    // prevent these shape manipulations
                    disableRemove: true,
                    disableMove: true,
                    disableFlip: true,
                    disableRotate: true,
                    disableTextLayout: true,
                    disableReorder: true,
                },

                // a line
                {
                    x: 0,
                    y: 280,
                    width: '100%',
                    height: 2,
                    backgroundColor: [0, 0, 0],
                },

                // a paragraph that resizes with the crop
                {
                    top: 344,
                    left: 64,
                    right: 64,
                    height: 512,
                    fontSize: 48,
                    fontStyle: 'italic',
                    text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eget neque eu nisl convallis eleifend et at neque. Sed eleifend tellus ante, id hendrerit turpis molestie id.',
                    color: [1, 1, 1],

                    // prevent adjusting these styles
                    disableStyle: ['fontSize', 'fontWeight', 'lineHeight'],

                    // prevent these shape manipulations
                    disableRemove: true,
                    disableMove: true,
                    disableFlip: true,
                    disableRotate: true,
                    disableTextLayout: true,
                    disableReorder: true,
                },
            ],
        });
    });
</script>
`

## Types

Pintura Image Editor determines the type of a shape (and how to draw and interact with it) based on the defined props on the shape.

| Name                     | Requirements                                                                                                                      |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| [Path ](#path)           | Has points property.                                                                                                              |
| [Line ](#line)           | Has x1, y1, x2, and y2 property.                                                                                                  |
| [Rectangle ](#rectangle) | Has width, height properties. Or a width and height can be derived from the bounds properties x, y, top, right, bottom, and left. |
| [Ellipse ](#ellipse)     | Has rx and ry property.                                                                                                           |
| [Text ](#text)           | Has text property.                                                                                                                |
| Triangle                 | Has x1, y1, x2, y2, x3, and y3 property. This shape is deprecated and is replaced with Path.                                      |

## Styles

Layout related styles can be defined in pixels or in percentages.

When defined in percentages the Pintura Image Editor will calculate the pixel value automatically relative to the shape parent context.

When annotating an image the parent context is the image itself, when decorating a crop, the parent context is the crop selection.

```js
const absoluteShape = {
    x: 0,
    y: 0,
    // ...other styles
};

const relativeShape = {
    x: '10%',
    y: '15%',
    // ...other styles
};
```

### Shared

| Property                    | Description                                                                                          |
| --------------------------- | ---------------------------------------------------------------------------------------------------- |
| x                           | The x position of the shape. Either in pixels or a percentage.                                       |
| y                           | The y position of the shape. Either in pixels or a percentage.                                       |
| [rotation](#rotation)       | Shape rotation in radians.                                                                           |
| [backgroundColor](#colors)  | Array of 3 or 4 color values ranging between 0 and 1.                                                |
| opacity                     | The opacity of the shape. Value between 0 and 1                                                      |
| [alwaysOnTop](#alwaysontop) | If set to true the shape will be sorted to appear above other shapes.                                |
| [aboveFrame](#aboveframe)   | If set to true the shape will be drawn on top of the frame.                                          |
| selectionStyle              | The outline style to use when selected, set to 'hook' for hook style or undefined for default style. |

#### rotation

The rotation of the shape in radians.

```js
const shape = {
    rotation: Math.PI / 4, // 45 degrees
    // ...other styles
};
```

If you want to set the rotation in degrees you can use the `degToRad` method.

```js
import { degToRad } from './pintura.js';

const shape = {
    rotation: degToRad(45),
    // ...other styles
};
```

#### alwaysOnTop

If set to `true` the shape will be sorted to appear above other shapes.

When multiple shapes have this property set to `true` the order of the shapes in the shape array is retained.

Shape draw order runs from top to bottom. In the shape list below the green circle is drawn first, then the blue square and then the red square.

```js
const shapes = [
    // 2. a blue square
    {
        id: 'square',
        x: 32,
        y: 32,
        width: 128,
        height: 128,
        backgroundColor: [0, 0, 1],
        alwaysOnTop: true,
    },
    // 3. a red square
    {
        id: 'square',
        x: 0,
        y: 0,
        width: 128,
        height: 128,
        backgroundColor: [1, 0, 0],
        alwaysOnTop: true,
    },
    // 1. a green circle
    {
        id: 'circle',
        x: 64,
        y: 64,
        rx: 128,
        ry: 128,
        backgroundColor: [0, 1, 0],
    },
];
```

#### aboveFrame

When set to `true` the shape will be drawn on top of the frame, useful for example to draw annotations on a Polaroid.

### Eraser

```js
const shape = {
    eraseRadius: 0,
};
```

| Property    | Description                                                                                                  |
| ----------- | ------------------------------------------------------------------------------------------------------------ |
| eraseRadius | The radius around the erase position to remove shapes in. Increase to make it easier to remove small shapes. |

### Rectangle

A rectangle or square shape. Stickers drawn with rectangle shapes that have a `backgroundImage` applied.

```js
const shape = {
    x: 0,
    y: 0,
    width: 128,
    height: 128,
    backgroundColor: [1, 0, 0],
};
```

| Property                                  | Description                                                                                                                                                          |
| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| width                                     | The width of the rectangle.                                                                                                                                          |
| height                                    | The height of the rectangle.                                                                                                                                         |
| left                                      | The position of the rectangle relative to the left of its context.                                                                                                   |
| top                                       | The position of the rectangle relative to the top of its context.                                                                                                    |
| right                                     | The position of the rectangle relative to the right of its context.                                                                                                  |
| bottom                                    | The position of the rectangle relative to the bottom of its context.                                                                                                 |
| cornerRadius                              | The rectangle corner radius.                                                                                                                                         |
| [backgroundImage](#backgroundimage)       | The resource to use as a background image for this shape.                                                                                                            |
| [backgroundSize](#backgroundsize)         | How the image is fitted in the rectangle, either undefined, 'contain', 'cover', or a size in pixels { width: 128, height: 128 }.                                     |
| [backgroundPosition](#backgroundposition) | How the image is positioned in the rectangle, either undefined, or a position in pixels { x: 128, y: 128 }.                                                          |
| [backgroundRepeat](#backgroundrepeat)     | Set to 'repeat' to use the backgroundImage as a background pattern, set to undefined to stretch image to fit shape.                                                  |
| aspectRatio                               | The aspect ratio the rectangle should adhere to.                                                                                                                     |
| [strokeColor](#colors)                    | Array of 3 or 4 color values ranging between 0 and 1\.                                                                                                               |
| strokeWidth                               | The width of the stroke to use for the rectangle.                                                                                                                    |
| feather                                   | The feather radius around the edges of the shape, useful to blend shapes with their background.                                                                      |
| status                                    | Set to 'error' to show error state, set to 'loading' to show loading state, set to 'complete' to not automatically show loading state while loading backgroundImage. |

#### backgroundImage

The `backgroundImage` to apply to the rectangle.

#### backgroundSize

When set to `undefined` the shape will be forced to match the `backgroundImage` aspect ratio.

Set the value to `'contain'` to center the `backgroundImage` in the rectangle.

Setting the value to `'cover'` will cover the rectangle with the `backgroundImage`.

Setting the value to `'force'` will skew the `backgroundImage` to fit the shape.

Settings the value to `{ width: 128, height: 128 }` will resize the background to that size.

#### backgroundPosition

Sets the position of the background, defaults to `undefined`.

Settings the value to `{ x: 128, y: 128 }` will offset the background to that position.

#### backgroundRepeat

By default a background will stretch to fill the shape. We can set the `backgroundRepeat` property to `'repeat'` to have the background repeat to fill the shape.

We can adjust the size of the `backgroundImage` using the `backgroundSize` property.

### Ellipse

Used to draw circles and ellipses.

```js
const shape = {
    x: 32,
    y: 32,
    rx: 64,
    ry: 64,
    backgroundColor: [1, 0, 0],
};
```

| Property               | Description                                            |
| ---------------------- | ------------------------------------------------------ |
| rx                     | The radius of the ellipse on the x axis.               |
| ry                     | The radius of the ellipse on the y axis.               |
| [strokeColor](#colors) | Array of 3 or 4 color values ranging between 0 and 1\. |
| strokeWidth            | The width of the stroke to use for the ellipse.        |

### Line

The Line shape is used to draw lines and arrows. An arrow is a line with a `lineStart` and/or `lineEnd` style.

```js
const shape = {
    x1: 0,
    y1: 0,
    x2: 128,
    y2: 128,
    strokeColor: [1, 0, 0],
};
```

| Property               | Description                                                                                        |
| ---------------------- | -------------------------------------------------------------------------------------------------- |
| x1                     | The start position of the line on the x axis.                                                      |
| y1                     | The start position of the line on the y axis.                                                      |
| x2                     | The end position of the line on the x axis.                                                        |
| y2                     | The end position of the line on the y axis.                                                        |
| [strokeColor](#colors) | Array of 3 or 4 color values ranging between 0 and 1\.                                             |
| strokeWidth            | The width of the stroke to use for the line.                                                       |
| lineStart              | The decorative shape to use for the start of the line.                                             |
| lineEnd                | The decorative shape to use for the end of the line.                                               |
| lineEndScalar          | The scale factor to use when drawing the decorative shape at the ends of the line, defaults to 5.  |
| lineStartScalar        | The scale factor to use when drawing the decorative shape at the start of the line, defaults to 5. |

If we're not using one of the default editor factory methods we need to set set the [shapePreprocessor](../../image-editor/properties/#shapepreprocessor) property to render `lineStart` and `lineEnd` styles.

For the possible `lineStart` and `lineEnd` values see [lineStart and lineEnd styles](../exports/#createdefaultlineendstyleoptions)

### Text

Draw text and emoji with the Text shape.

If the text shape doesn't have `width`, it'll automatically expand. If it does have a `width` property it'll wrap. If it has a `width` and `height` property it'll render a resizable text box.

Set the `disableTextScale` property to `false` to allow scaling/resizing auto-width text shapes.

```js
const shape = {
    x: 0,
    y: 0,
    width: 128,
    height: 128,
    text: 'Hello World',
    fontWeight: 'bold',
    color: [1, 0, 0],
};
```

| Property         | Description                                                                                                                                 |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| format           | Defaults to text, set to 'html' to enable rich text controls.                                                                               |
| fontSize         | The font size to use for the text.                                                                                                          |
| fontFamily       | The font family to use for the text.                                                                                                        |
| fontWeight       | The font weight to use for the text.                                                                                                        |
| fontStyle        | The font style to use for the text.                                                                                                         |
| fontVariant      | The font variant to use for the text.                                                                                                       |
| lineHeight       | The line height of the text.                                                                                                                |
| [color](#colors) | Array of 3 or 4 color values ranging between 0 and 1.                                                                                       |
| backgroundColor  | Background color of the text box. Set to a default value like \[0, 0, 0, 0\] to enable background color control.                            |
| textAlign        | Alignment of the text, "left", "center", or "right", defaults to "left".                                                                    |
| textOutline      | Outine around text, defaults to undefined. Set to a default value like \['0%', \[1, 1, 1\]\] to enable text outline control.                |
| textShadow       | Shadow behind text, defaults to undefined. Set to a default value like \['0%', '0%', '0%', \[0, 0, 0, .5\]\] to enable text shadow control. |
| letterSpacing    | Spacing between letters, defaults to undefined.                                                                                             |
| text             | The text to show.                                                                                                                           |

The following list of styles isn't enabled on the default text shape.

* `backgroundColor`
* `textOutline`
* `textShadow`

We can enable these styles and add additional features to the default text field like by updating the `markupEditorToolStyles` property.

* [ ![](/pintura/static/assets/technologies-mono/javascript.svg)JavaScript](#javascript-panel-14)
* [ ![](/pintura/static/assets/technologies-mono/react.svg)React](#react-panel-14)
* [ ![](/pintura/static/assets/technologies-mono/vue.svg)Vue](#vue-panel-14)
* [ ![](/pintura/static/assets/technologies-mono/svelte.svg)Svelte](#svelte-panel-14)
* [ ![](/pintura/static/assets/technologies-mono/angular.svg)Angular](#angular-panel-14)
* [ ![](/pintura/static/assets/technologies-mono/jquery.svg)jQuery](#jquery-panel-14)

* [index.html](#index-html-panel-14)

```html
<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import {
        appendDefaultEditor,
        createMarkupEditorToolStyle,
        createMarkupEditorToolStyles,
    } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        markupEditorToolStyles: createMarkupEditorToolStyles({
            text: createMarkupEditorToolStyle('text', {
                // Set default text shape background to transparent
                backgroundColor: [0, 0, 0, 0],

                // Set default text shape outline to 0 width and white
                textOutline: ['0%', [1, 1, 1]],

                // Set default text shadow, shadow will not be drawn if x, y, and blur are 0.
                textShadow: ['0%', '0%', '0%', [0, 0, 0, 0.5]],

                // Allow newlines in inline text
                disableNewline: false,

                // Align to left by default, this triggers always showing the text align control
                textAlign: 'left',

                // Enable text formatting
                format: 'html',
            }),
        }),
    });
</script>

```

* [App.jsx](#App-jsx-panel-14)
* [App.css](#App-css-panel-14)

```jsx
import '@pqina/pintura/pintura.css';
import './App.css';
import { PinturaEditor } from '@pqina/react-pintura';
import {
    getEditorDefaults,
    createMarkupEditorToolStyle,
    createMarkupEditorToolStyles,
} from '@pqina/pintura';

const editorDefaults = getEditorDefaults();

function App() {
    return (
        <div className="App">
            <PinturaEditor
                {...editorDefaults}
                src={'image.jpeg'}
                markupEditorToolStyles={createMarkupEditorToolStyles({
                    text: createMarkupEditorToolStyle('text', {
                        // Set default text shape background to transparent
                        backgroundColor: [0, 0, 0, 0],

                        // Set default text shape outline to 0 width and white
                        textOutline: ['0%', [1, 1, 1]],

                        // Set default text shadow, shadow will not be drawn if x, y, and blur are 0.
                        textShadow: ['0%', '0%', '0%', [0, 0, 0, 0.5]],

                        // Allow newlines in inline text
                        disableNewline: false,

                        // Align to left by default, this triggers always showing the text align control
                        textAlign: 'left',

                        // Enable text formatting
                        format: 'html',
                    }),
                })}
            />
        </div>
    );
}

export default App;

```

```css
.pintura-editor {
    height: 600px;
}

```

* [App.vue](#App-vue-panel-14)

```html
<template>
    <div>
        <PinturaEditor
            v-bind="editorDefaults"
            src="image.jpeg"
            :markupEditorToolStyles="markupEditorToolStyles"
        />
    </div>
</template>
<script>
import { PinturaEditor } from '@pqina/vue-pintura';
import {
    getEditorDefaults,
    createMarkupEditorToolStyle,
    createMarkupEditorToolStyles,
} from '@pqina/pintura';

export default {
    name: 'App',

    components: {
        PinturaEditor,
    },

    data() {
        return {
            editorDefaults: getEditorDefaults(),

            markupEditorToolStyles: createMarkupEditorToolStyles({
                text: createMarkupEditorToolStyle('text', {
                    // Set default text shape background to transparent
                    backgroundColor: [0, 0, 0, 0],

                    // Set default text shape outline to 0 width and white
                    textOutline: ['0%', [1, 1, 1]],

                    // Set default text shadow, shadow will not be drawn if x, y, and blur are 0.
                    textShadow: ['0%', '0%', '0%', [0, 0, 0, 0.5]],

                    // Allow newlines in inline text
                    disableNewline: false,

                    // Align to left by default, this triggers always showing the text align control
                    textAlign: 'left',

                    // Enable text formatting
                    format: 'html',
                }),
            }),
        };
    },

    methods: {},
};
</script>
<style>
@import '@pqina/pintura/pintura.css';

.pintura-editor {
    height: 600px;
}
</style>

```

* [App.svelte](#App-svelte-panel-14)

```svelte
<script>
    import { PinturaEditor } from '@pqina/svelte-pintura';
    import {
        getEditorDefaults,
        createMarkupEditorToolStyle,
        createMarkupEditorToolStyles,
    } from '@pqina/pintura';
    import '@pqina/pintura/pintura.css';

    let editorDefaults = getEditorDefaults();
</script>

<div>
    <PinturaEditor
        {...editorDefaults}
        src={'image.jpeg'}
        markupEditorToolStyles={createMarkupEditorToolStyles({
            text: createMarkupEditorToolStyle('text', {
                // Set default text shape background to transparent
                backgroundColor: [0, 0, 0, 0],

                // Set default text shape outline to 0 width and white
                textOutline: ['0%', [1, 1, 1]],

                // Set default text shadow, shadow will not be drawn if x, y, and blur are 0.
                textShadow: ['0%', '0%', '0%', [0, 0, 0, 0.5]],

                // Allow newlines in inline text
                disableNewline: false,

                // Align to left by default, this triggers always showing the text align control
                textAlign: 'left',

                // Enable text formatting
                format: 'html',
            }),
        })}
    />
</div>

<style>
    div :global(.pintura-editor) {
        height: 600px;
    }
</style>

```

* [app.component.ts](#app-component-ts-panel-14)
* [app.component.html](#app-component-html-panel-14)
* [app.component.css](#app-component-css-panel-14)
* [app.module.ts](#app-module-ts-panel-14)

```javascript
import { Component } from '@angular/core';

import {
    getEditorDefaults,
    createMarkupEditorToolStyle,
    createMarkupEditorToolStyles,
} from '@pqina/pintura';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
})
export class AppComponent {
    editorDefaults: any = getEditorDefaults();

    markupEditorToolStyles: any = createMarkupEditorToolStyles({
        text: createMarkupEditorToolStyle('text', {
            // Set default text shape background to transparent
            backgroundColor: [0, 0, 0, 0],

            // Set default text shape outline to 0 width and white
            textOutline: ['0%', [1, 1, 1]],

            // Set default text shadow, shadow will not be drawn if x, y, and blur are 0.
            textShadow: ['0%', '0%', '0%', [0, 0, 0, 0.5]],

            // Allow newlines in inline text
            disableNewline: false,

            // Align to left by default, this triggers always showing the text align control
            textAlign: 'left',

            // Enable text formatting
            format: 'html',
        }),
    });
}

```

```html
<pintura-editor
    [options]="editorDefaults"
    src="image.jpeg"
    [markupEditorToolStyles]="markupEditorToolStyles"
></pintura-editor>

```

```css
::ng-deep .pintura-editor {
    height: 600px;
}

```

```javascript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularPinturaModule } from '@pqina/angular-pintura';

@NgModule({
    declarations: [AppComponent],
    imports: [BrowserModule, AngularPinturaModule],
    exports: [AppComponent],
    providers: [],
    bootstrap: [AppComponent],
})
export class AppModule {}

```

* [index.html](#index-html-panel-14)

```html
<!DOCTYPE html>
<head>
    <link rel="stylesheet" href="./pintura/pintura.css" />
</head>

<script src="./jquery.js"></script>
<script src="./jquery-pintura/useEditorWithJQuery-iife.js"></script>
<script src="./pintura/pintura-iife.js"></script>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script>
    useEditorWithJQuery(jQuery, pintura);

    $(function () {
        var { createMarkupEditorToolStyle, createMarkupEditorToolStyles } =
            $.fn.pintura;

        var editor = $('#editor').pinturaDefault({
            src: 'image.jpeg',
            markupEditorToolStyles: createMarkupEditorToolStyles({
                text: createMarkupEditorToolStyle('text', {
                    // Set default text shape background to transparent
                    backgroundColor: [0, 0, 0, 0],

                    // Set default text shape outline to 0 width and white
                    textOutline: ['0%', [1, 1, 1]],

                    // Set default text shadow, shadow will not be drawn if x, y, and blur are 0.
                    textShadow: ['0%', '0%', '0%', [0, 0, 0, 0.5]],

                    // Allow newlines in inline text
                    disableNewline: false,

                    // Align to left by default, this triggers always showing the text align control
                    textAlign: 'left',

                    // Enable text formatting
                    format: 'html',
                }),
            }),
        });
    });
</script>

```

```js
const myMarkupEditorToolStyles = createMarkupEditorToolStyles({
    text: createMarkupEditorToolStyle('text', {
        // Set default text shape background to transparent
        backgroundColor: [0, 0, 0, 0],

        // Set default text shape outline to 0 width and white
        textOutline: ['0%', [1, 1, 1]],

        // Set default text shadow to transparent
        textShadow: ['0%', '0%', '0%', [0, 0, 0, 0]],

        // Allow newlines in inline text
        disableNewline: false,

        // Align to left by default, this triggers always showing the text align control
        textAlign: 'left',

        // Enable text formatting
        format: 'html',
    }),
});
```

### Path

Draw paths using the Path shape. Paths can be closed with the `pathClose` property.

If the Path `bitmap` property is set to `true` the path is drawn as a canvas element and can receive additional styles like `strokeJoin`, `strokeCap`, and `strokeDash`.

```js
const shape = {
    points: [
        {
            x: 0,
            y: 0,
        },
        {
            x: 128,
            y: 0,
        },
        {
            x: 128,
            y: 128,
        },
        {
            x: 0,
            y: 128,
        },
    ],
    strokeColor: [1, 0, 0],
    pathClose: false,
};
```

| Property                  | Description                                                                                                                                         |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| [points](#points)         | Array of { x, y } coordinates.                                                                                                                      |
| [strokeColor](#colors)    | Array of 3 or 4 color values ranging between 0 and 1.                                                                                               |
| strokeWidth               | The width of the stroke to use for the path.                                                                                                        |
| pathClose                 | This will draw a line between the first and last point in the points array.                                                                         |
| cursorStyle               | The style of the cursor, defaults to undefined, can be set to 'ellipse'.                                                                            |
| cursorSize                | When the cursor style is 'ellipse' this determines the size. Can be set to a fixed value or to a the name of a property, for example 'strokeWidth'. |
| bitmap                    | When set to true the path will be rendered with a bitmap shape resulting in a better look at some performance cost.                                 |
| [strokeJoin](#strokejoin) | When bitmap is set to true we can set strokeJoin to either 'miter', 'bevel', or 'round'                                                             |
| [strokeCap](#strokecap)   | When bitmap is set to true we can set strokeCap to either 'miter', 'bevel', or 'round'                                                              |
| [strokeDash](#strokedash) | When bitmap is set to true we can set this to an array of numbers or percentages to draw dashed lines, for example \[10,10\].                       |
| selectedPoint             | The index of the currently selected point.                                                                                                          |

### points

The array of points that describe the polygon shape to draw.

```js
const shape = {
    points: [
        { x: 0, y: 0 },
        { x: 128, y: 128 },
        { x: 256, y: 128 },
    ];
}
```

### strokeJoin

When `bitmap` is set to `true` we can set `strokeJoin` to either `'miter'`, `'bevel'`, or `'round'`

### strokeCap

When `bitmap` is set to `true` we can set `strokeCap` to either `'miter'`, `'bevel'`, or `'round'`

### strokeDash

When `bitmap` is set to `true` we can set this to an array of numbers or percentages to draw dashed lines, for example `[10,10]`.

## State

Shape state properties give information on the current state of the shape.

| Property    | Description                                                                |
| ----------- | -------------------------------------------------------------------------- |
| isSelected  | The shape is currently selected.                                           |
| isDraft     | The shape is in draft state, this is true when the shape is being created. |
| isComplete  | Is true when all shape resources have loaded.                              |
| isError     | Something went wrong while loading shape resources.                        |
| isLoading   | Currently loading shape resources.                                         |
| isEditing   | Currently editing this shape.                                              |
| isFormatted | The shape has been formatted by Pintura Image Editor.                      |

## Right management

The shape right management properties can be used for templating. Among other thigns we can control which styles the user can set, if shapes can be removed, selected, rotated, or erased.

| Property                                | Description                                                                      |
| --------------------------------------- | -------------------------------------------------------------------------------- |
| [disableStyle](#disablestyle)           | Prevents changing the styles of the shape or disables a selection of styles.     |
| [disableErase](#disableerase)           | Prevents erasing the shape with eraser.                                          |
| [disableSelect](#disableselect)         | Prevents selecting the shape.                                                    |
| [disableRemove](#disableremove)         | Prevents removing the shape.                                                     |
| [disableDuplicate](#disableduplicate)   | Prevents duplicating the shape.                                                  |
| disableReorder                          | Prevents changing the position of the shape in the shapes list.                  |
| disableFlip                             | Prevents flipping the shape.                                                     |
| [disableInput](#disableinput)           | Prevents updating the text of the shape or filters the text input.               |
| [disableTextLayout](#disabletextlayout) | Prevents switching text layout.                                                  |
| [disableTextScale](#disabletextscale)   | Prevents scaling auto width text.                                                |
| [disableNewline](#disablenewline)       | Prevents inserting new line.                                                     |
| disableManipulate                       | Prevents manipulating the shape in any way.                                      |
| disableMove                             | Prevents moving the shape.                                                       |
| disableResize                           | Prevents resizing the shape.                                                     |
| disableRotate                           | Prevents rotating the shape.                                                     |
| disableAddPoints                        | Prevents adding and removing points from a path.                                 |
| disableShowPoints                       | Disables drawing the corner points of a path.                                    |
| [disableAcceptSnap](#disableacceptsnap) | Removes shape from snap targets list, other shapes no longer snap to this shape. |

### disableSelect

When set to `true` prevents the user from selecting the shape.

### disableRemove

Set to `true` to prevent the user from removing this shape.

### disableDuplicate

When set to `true` this prevents duplicating the shape.

### disableErase

When set to `true` this prevents erasing the shape with the eraser tool.

### disableManipulate

Prevents manipulating the shape in any way.

### disableMove

Prevents moving the shape.

### disableResize

Prevents resizing the shape.

### disableRotate

Prevents rotating the shape.

### disableTextLayout

If set to `true` all text layout options are locked. Set to an array to block specific layout options. Valid values are `'fixed-size'`, `'auto-width'`, and `'auto-height'`

This example prevents the text layout from being set to auto height.

```js
const shape = {
    x: 0,
    y: 0,
    width: 128,
    height: 128,
    text: 'Hello World',
    disableTextLayout: ['auto-height'],
};
```

### disableTextScale

Prevents scaling auto width text boxes. Defaults to `true`, set to `false` on default text shape style to allow scaling text shapes.

### disableStyle

If set to `true` all styles are locked.

Alternatively it can be set to an array of disabled style names.

```js
const shape = {
    x: 0,
    y: 0,
    width: 128,
    height: 128,
    backgroundColor: [1, 0, 0],
    strokeColor: [1, 1, 1],
    strokeWidth: 20,
    disableStyle: ['strokeWidth', 'strokeColor'],
};
```

### disableInput

Only applies to Text shapes. If set to `true` will prevent the user from updating the `text` value.

Can alternatively be set to a `function` in which case the function receives a `string` and can return a formatted string. In the example below we disallow any numeric input.

```js
const shape = {
    x: 0,
    y: 0,
    width: 128,
    height: 128,
    text: 'Hello World',
    disableInput: (text) => text.replace(/[0-9]/g, ''),
};
```

### disableAcceptSnap

Removes shape from snap targets list, other shapes no longer snap to this shape.

## Colors

Shape colors are defined with an array of 3 or 4 color values.

The array format is `[R, G, B]` or `[R ,G ,B ,A]` each value ranges between `0` and `1`.

Setting the color red using the `RGB` array.

```js
const shape = {
    // red
    backgroundColor: [1, 0, 0],
    // ...other styles
};
```

Setting an `RGBA` value.

```js
// red with 50% opacity
const shape = {
    backgroundColor: [1, 0, 0, 0.5],
    // ...other styles
};
```

We can automatically create these arrays from more familiar CSS color values by using the [colorStringToColorArray](../../ui/exports/#colorstringtocolorarray) method exported by the editor.