From ed273d816a6c2a13b02e71baf1ec1922bf3622c7 Mon Sep 17 00:00:00 2001 From: Gui Seek Date: Mon, 26 Aug 2024 17:51:56 -0300 Subject: [PATCH] feat: fill canvas color --- src/constants/icon.ts | 3 ++- src/features/canvas/canvas.ts | 15 +++++++++++++++ src/features/forms/events.ts | 3 +++ src/features/forms/handlers/index.ts | 1 + .../forms/handlers/on-form-fill-submit.ts | 7 +++++++ src/features/toolbar/events.ts | 3 +++ src/features/toolbar/handlers/index.ts | 1 + .../handlers/on-toolbar-select-fill.ts | 19 +++++++++++++++++++ .../toolbar/handlers/on-toolbar-selected.ts | 4 ++++ src/features/toolbar/toolbar.ts | 1 + src/styles/_forms.scss | 1 + src/styles/_toolbar.scss | 7 +++++-- src/vite-env.d.ts | 8 +++++++- 13 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 src/features/forms/handlers/on-form-fill-submit.ts create mode 100644 src/features/toolbar/handlers/on-toolbar-select-fill.ts diff --git a/src/constants/icon.ts b/src/constants/icon.ts index 9171ce4..81bd98f 100644 --- a/src/constants/icon.ts +++ b/src/constants/icon.ts @@ -5,5 +5,6 @@ export const icon = { edit: ` `, delete: ` `, bringToFront: ` `, - sendToBack: ` ` + sendToBack: ` `, + fill: ` ` } diff --git a/src/features/canvas/canvas.ts b/src/features/canvas/canvas.ts index 6105bae..fe229af 100644 --- a/src/features/canvas/canvas.ts +++ b/src/features/canvas/canvas.ts @@ -15,6 +15,16 @@ class Canvas extends HTMLCanvasElement implements CanvasLike { #isContextMenu = false + #fill = '' + + get fill() { + return this.#fill + } + + setFill(fill: string) { + this.#fill = fill + } + constructor() { super() this.context = this.getContext('2d') @@ -44,6 +54,11 @@ class Canvas extends HTMLCanvasElement implements CanvasLike { if (!this.offscreenContext || !this.context) return this.offscreenContext.clearRect(0, 0, this.width, this.height) + + if (this.fill) { + this.offscreenContext.fillStyle = this.fill + this.offscreenContext.fillRect(0, 0, this.width, this.height) + } const layers = this.#layers .filter((layer) => layer.active) diff --git a/src/features/forms/events.ts b/src/features/forms/events.ts index 7ed15d7..c96a7a2 100644 --- a/src/features/forms/events.ts +++ b/src/features/forms/events.ts @@ -2,3 +2,6 @@ import {createEvent, createListener} from '@websqnl/event-flow' export const formTextSubmit = createEvent('form.text.submit') export const onFormTextSubmit = createListener('form.text.submit') + +export const formFillSubmit = createEvent('form.fill.submit') +export const onFormFillSubmit = createListener('form.fill.submit') diff --git a/src/features/forms/handlers/index.ts b/src/features/forms/handlers/index.ts index 4cf556d..d0e1978 100644 --- a/src/features/forms/handlers/index.ts +++ b/src/features/forms/handlers/index.ts @@ -1 +1,2 @@ +export * from './on-form-fill-submit'; export * from './on-form-text-submit'; diff --git a/src/features/forms/handlers/on-form-fill-submit.ts b/src/features/forms/handlers/on-form-fill-submit.ts new file mode 100644 index 0000000..6123f93 --- /dev/null +++ b/src/features/forms/handlers/on-form-fill-submit.ts @@ -0,0 +1,7 @@ +import {onFormFillSubmit} from '../events' +import {canvas} from '@features/canvas' + +onFormFillSubmit((value) => { + canvas.setFill(value.color) + canvas.render().then() +}) diff --git a/src/features/toolbar/events.ts b/src/features/toolbar/events.ts index 12f1572..4ee2f9a 100644 --- a/src/features/toolbar/events.ts +++ b/src/features/toolbar/events.ts @@ -8,3 +8,6 @@ export const onToolbarSelectImage = createListener('toolbar.select.image') export const toolbarSelectText = createEvent('toolbar.select.text') export const onToolbarSelectText = createListener('toolbar.select.text') + +export const toolbarSelectFill = createEvent('toolbar.select.fill') +export const onToolbarSelectFill = createListener('toolbar.select.fill') diff --git a/src/features/toolbar/handlers/index.ts b/src/features/toolbar/handlers/index.ts index 9afeb9b..e5d6780 100644 --- a/src/features/toolbar/handlers/index.ts +++ b/src/features/toolbar/handlers/index.ts @@ -1,3 +1,4 @@ +export * from './on-toolbar-select-fill'; export * from './on-toolbar-select-image'; export * from './on-toolbar-select-text'; export * from './on-toolbar-selected'; diff --git a/src/features/toolbar/handlers/on-toolbar-select-fill.ts b/src/features/toolbar/handlers/on-toolbar-select-fill.ts new file mode 100644 index 0000000..f0a6933 --- /dev/null +++ b/src/features/toolbar/handlers/on-toolbar-select-fill.ts @@ -0,0 +1,19 @@ +import {FormDialog, formFillSubmit} from '@features/forms' +import {onToolbarSelectFill} from '../events' +import {Input} from '@websqnl/elements' + +onToolbarSelectFill(() => { + const color = new Input({ + type: 'color', + name: 'color', + value: '#000000', + }) + + const controls = {color} + + const dialog = new FormDialog(controls, formFillSubmit) + + document.body.insertAdjacentElement('beforeend', dialog) + + dialog.showModal() +}) diff --git a/src/features/toolbar/handlers/on-toolbar-selected.ts b/src/features/toolbar/handlers/on-toolbar-selected.ts index 452d477..a37f7f5 100644 --- a/src/features/toolbar/handlers/on-toolbar-selected.ts +++ b/src/features/toolbar/handlers/on-toolbar-selected.ts @@ -1,5 +1,6 @@ import { onToolbarSelected, + toolbarSelectFill, toolbarSelectImage, toolbarSelectText, } from '../events' @@ -13,5 +14,8 @@ onToolbarSelected((action) => { case 'text': { return dispatch(toolbarSelectText()) } + case 'fill': { + return dispatch(toolbarSelectFill()) + } } }) diff --git a/src/features/toolbar/toolbar.ts b/src/features/toolbar/toolbar.ts index ec09df1..00e6943 100644 --- a/src/features/toolbar/toolbar.ts +++ b/src/features/toolbar/toolbar.ts @@ -10,6 +10,7 @@ export class Toolbar extends HTMLMenuElement { buttons = { image: this.#button(icon.image, 'image', 'Select image'), text: this.#button(icon.text, 'text', 'Write text'), + fill: this.#button(icon.fill, 'fill', 'Format color fill'), } connectedCallback() { diff --git a/src/styles/_forms.scss b/src/styles/_forms.scss index f1991f7..c07a316 100644 --- a/src/styles/_forms.scss +++ b/src/styles/_forms.scss @@ -46,6 +46,7 @@ dialog { footer { flex: 1; + gap: 0.6em; display: flex; flex-direction: row-reverse; justify-content: space-between; diff --git a/src/styles/_toolbar.scss b/src/styles/_toolbar.scss index 2213168..6a867c9 100644 --- a/src/styles/_toolbar.scss +++ b/src/styles/_toolbar.scss @@ -1,8 +1,7 @@ menu.cf-toolbar { display: flex; - flex-flow: row wrap; + flex-direction: column; gap: 0.2em; - max-width: 6em; background-color: #dadada; margin: 0; @@ -27,4 +26,8 @@ menu.cf-toolbar { color: rgb(var(--cf-onsurface-rgb)); } } + + @media (max-width: 640px) { + flex-direction: row; + } } diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index ed45a0a..8d36ffb 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -21,7 +21,7 @@ interface RectLike { h: number } -type LayerType = 'image' | 'text' +type LayerType = 'image' | 'text' | 'fill' type TextWeight = 'bold' | 'normal' @@ -106,8 +106,13 @@ interface TextForm { bold: boolean } +interface FillForm { + color: string +} + interface StateEventMap { 'form.text.submit': TextForm + 'form.fill.submit': FillForm 'canvas.render.request': void 'canvas.update.size': CanvasSize @@ -118,6 +123,7 @@ interface StateEventMap { 'toolbar.select.image': void 'toolbar.select.text': void + 'toolbar.select.fill': void 'toolbar.selected': LayerType 'context.open': ContextOpenEvent