Skip to content

Commit

Permalink
wip: omni-text (ui for adding text on canvas)
Browse files Browse the repository at this point in the history
  • Loading branch information
zenkyuv committed Jan 10, 2024
1 parent c48d4da commit 171f2de
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 0 deletions.
87 changes: 87 additions & 0 deletions s/components/omni-text/component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import {html} from "@benev/slate"

import {styles} from "./styles.js"
import {shadow_component} from "../../context/slate.js"
import boldSvg from "../../icons/remix-icon/bold.svg.js"
import italicSvg from "../../icons/remix-icon/italic.svg.js"
import alignLeftSvg from "../../icons/remix-icon/align-left.svg.js"
import alignRightSvg from "../../icons/remix-icon/align-right.svg.js"
import alignCenterSvg from "../../icons/remix-icon/align-center.svg.js"
import {Font, FontStyle, TextAlign, TextEffectProps} from "../../context/controllers/timeline/types.js"

Check failure on line 10 in s/components/omni-text/component.ts

View workflow job for this annotation

GitHub Actions / build

Module '"../../context/controllers/timeline/types.js"' has no exported member 'Font'.

Check failure on line 10 in s/components/omni-text/component.ts

View workflow job for this annotation

GitHub Actions / build

Module '"../../context/controllers/timeline/types.js"' has no exported member 'FontStyle'.

Check failure on line 10 in s/components/omni-text/component.ts

View workflow job for this annotation

GitHub Actions / build

Module '"../../context/controllers/timeline/types.js"' has no exported member 'TextAlign'.

Check failure on line 10 in s/components/omni-text/component.ts

View workflow job for this annotation

GitHub Actions / build

'"../../context/controllers/timeline/types.js"' has no exported member named 'TextEffectProps'. Did you mean 'TextEffect'?

export const OmniText = shadow_component({styles}, use => {
use.watch(() => use.context.state.timeline)
const actions = use.context.actions
const {canvas, ctx} = use.context.controllers.compositor

Check failure on line 15 in s/components/omni-text/component.ts

View workflow job for this annotation

GitHub Actions / build

Property 'compositor' does not exist on type '{ timeline: Timeline; }'.
const selected_effect = use.context.state.timeline.selected_effect?.kind === "text"

Check failure on line 16 in s/components/omni-text/component.ts

View workflow job for this annotation

GitHub Actions / build

Property 'selected_effect' does not exist on type 'XTimeline'.
? use.context.state.timeline.selected_effect

Check failure on line 17 in s/components/omni-text/component.ts

View workflow job for this annotation

GitHub Actions / build

Property 'selected_effect' does not exist on type 'XTimeline'.
: null

const [
text,
setTextEffectProps
] = use.state<TextEffectProps>({
size: selected_effect?.size ?? 38,
content: selected_effect?.content ?? "example",
style: selected_effect?.style ?? "normal",
font: selected_effect?.font ?? "Lato",
color: selected_effect?.color ?? "blue",
align: selected_effect?.align ?? "center",
rect: {
position_on_canvas: {
x: canvas.width/2,
y: canvas.height/2,
},
width: measure_text_width(),
height: measure_text_height(),
rotation: 0
}
})

function measure_text_width () {
ctx!.font = `${selected_effect?.size ?? 38}px ${selected_effect?.font ?? "Lato"}`;
ctx!.fillStyle = selected_effect?.color ?? "blue";
return ctx?.measureText(selected_effect?.content ?? "example").width!
}

function measure_text_height() {
return ctx?.measureText(selected_effect?.content ?? "example").actualBoundingBoxAscent! + ctx?.measureText(selected_effect?.content ?? "example").actualBoundingBoxDescent!
}

const set_font = (e: Event) => setTextEffectProps({...text, font: (e.target! as HTMLSelectElement).value as Font})
const set_font_size = (e: InputEvent) => setTextEffectProps({...text, size: +(e.target as HTMLInputElement).value})
const set_font_style = (style: FontStyle) => setTextEffectProps({...text, style: text.style === style ? "normal" : style})
const set_text_align = (align: TextAlign) => setTextEffectProps({...text, align})

return html`
<div class="text-selector">
<label for="font-select">Font</label>
<div class="flex-hover">
<select @change=${set_font} name="fonts" id="font-select">
<option value="Arial">Arial</option>
</select>
<input @change=${set_font_size} class="font-size" value=${text.size} />
</div>
<div class=flex-hover>
<div ?data-selected=${text.style === "bold"} @click=${() => set_font_style("bold")} class="bold">${boldSvg}</div>
<div ?data-selected=${text.style === "italic"} @click=${() => set_font_style("italic")} class="italic">${italicSvg}</div>
</div>
<div class=flex-hover>
<div ?data-selected=${text.align === "left"} @click=${() => set_text_align("left")} class="align">${alignLeftSvg}</div>
<div ?data-selected=${text.align === "center"} @click=${() => set_text_align("center")} class="align">${alignCenterSvg}</div>
<div ?data-selected=${text.align === "right"} @click=${() => set_text_align("right")} class="align">${alignRightSvg}</div>
</div>
<div class="color-picker flex"><span>${text.color}</span><div class="picker"></div></div>
${selected_effect
? html`
<button class="add-text" @click=${() => {
actions.timeline_actions.update_text_effect(text, selected_effect.id)

Check failure on line 78 in s/components/omni-text/component.ts

View workflow job for this annotation

GitHub Actions / build

Property 'update_text_effect' does not exist on type 'Callable<{ add_text_effect: (state: OmniState) => () => void; set_effect_track: (state: OmniState) => (effect: AnyEffect, track: number) => void; set_effect_duration: (state: OmniState) => ({ id }: AnyEffect, duration: number) => void; ... 7 more ...; toggle_is_playing: (state: OmniState) => () => void; }>'. Did you mean 'add_text_effect'?
use.context.controllers.compositor.set_currently_played_effects(use.context.state.timeline)

Check failure on line 79 in s/components/omni-text/component.ts

View workflow job for this annotation

GitHub Actions / build

Property 'compositor' does not exist on type '{ timeline: Timeline; }'.
use.context.controllers.compositor.draw_effects(true)

Check failure on line 80 in s/components/omni-text/component.ts

View workflow job for this annotation

GitHub Actions / build

Property 'compositor' does not exist on type '{ timeline: Timeline; }'.
}}>
Update text
</button>`
: html`<button class="add-text" @click=${() => actions.timeline_actions.add_text_effect(text)}>Add text</button>`}
</div>
`
})
14 changes: 14 additions & 0 deletions s/components/omni-text/panel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {svg, html} from "@benev/slate"
import {standard_panel_styles as styles, panel} from "@benev/construct"

import {shadow_view} from "../../context/slate.js"

export const TextPanel = panel({
label: "text",
icon: svg``,
view: shadow_view({name: "text", styles}, _use => ({}: any) => {
return html`
<omni-text></omni-text>
`
}),
})
103 changes: 103 additions & 0 deletions s/components/omni-text/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {css} from "@benev/slate"

export const styles = css`
:host {}
.text-selector {
display: flex;
flex-direction: column;
gap: 0.3em;
padding: 0.3em;
& [data-selected] {
background: rgb(32, 31, 31);
}
& .flex-column {
display: flex;
flex-direction: column;
gap: 0.3em;
}
& .flex {
display: flex;
align-items: center;
}
& .flex-hover {
display: flex;
gap: 0.3em;
& > * {
display: flex;
padding: 0.2em;
border-radius: 5px;
cursor: pointer;
&:hover {
outline: 1px solid #FFFFFF88;
}
}
}
& label {
font-weight: bold;
}
& select {
background: rgb(32, 31, 31);
border: none;
padding: 0.5em;
border-radius: 5px;
color: inherit;
width: 80%;
cursor: pointer;
}
& svg {
padding: 0.2em;
width: 30px;
height: 30px;
}
& .font-size {
background: rgb(32, 31, 31);
border: none;
border-radius: 5px;
padding: 0.5em;
color: inherit;
width: 20%;
text-align: center;
}
& .add-text {
padding: 0.5em;
background: rgb(32, 31, 31);
margin-top: 1em;
cursor: pointer;
transition: all 0.3s ease;
font-weight: bold;
&:hover {
opacity: 0.7;
color: white;
}
}
& .color-picker {
display: flex;
gap: 0.5em;
& span {
font-weight: bold;
}
& .picker {
width: 40px;
height: 40px;
border: 1px solid gray;
border-radius: 5px;
background: blue;
}
}
}
`

0 comments on commit 171f2de

Please sign in to comment.