feat(text): fix text focus and text wrap

previously the text elements werent relieving their focus up until actually clicking another element
on the page. This now allows cilcking anywhere on the page regardless of element, relieving the
focus and shifting focus to another text element if one is clicked. This also fixes the persistant
text wrapping, replacing the <br> tags with
 chars and wrapping the text wth a pre tag to maintain
all new lines
This commit is contained in:
Triston Armstrong 2024-10-11 13:56:45 -04:00
parent 4869efa8f8
commit 0cc0d388b4
Signed by: tristonarmstrong
GPG Key ID: A23B48AE45EB6EFE
2 changed files with 47 additions and 11 deletions

View File

@ -101,8 +101,9 @@ export function TextItem({ key: itemKey, data: item }: TextItem.TextCardProps) {
} }
function _handleContentInput(e: InputEvent) { function _handleContentInput(e: InputEvent) {
console.log("event: ", e) const el = e.target as HTMLParagraphElement & Pick<HTMLInputElement, 'oninput'>
texts.updateTextProperty(itemKey, 'contents', (e.target as any).textContent) const val = el.innerHTML.split('<br>').join('\n')
texts.updateTextProperty(itemKey, 'contents', val)
updateLocalStorage() updateLocalStorage()
} }
@ -111,25 +112,57 @@ export function TextItem({ key: itemKey, data: item }: TextItem.TextCardProps) {
pRef.current.textContent = item.contents pRef.current.textContent = item.contents
}, []) }, [])
useEffect(() => {
function _handleClick(e: MouseEvent) {
const target = e.target as HTMLElement
if (target === elRef.current) return
if (elRef.current?.contains(target)) return
const classes = '.text-container, .text-p, .text-pre, .text-close'
if (target.closest(classes)) return
if (target.matches(classes)) return
focusedItem.value = null
document.removeEventListener('mousedown', _handleClick)
}
if (focusedItem.value !== itemKey) return
document.addEventListener('mousedown', _handleClick)
return () => {
document.removeEventListener('mousedown', _handleClick)
}
}, [focusedItem.value])
const outline = `${focusedItem.value === item.id ? '1px solid' : ''}`
const fontSize = `${item.fontSize / 6}px`
const zIndex = `${focusedItem.value == itemKey ? LayerEnum.CARD_ELEVATED : LayerEnum.CARD}`
return ( return (
<div <div
ref={elRef} ref={elRef}
onmousedown={_handleMouseDown} onmousedown={_handleMouseDown}
className="transition flex flex-col justify-stretch rounded absolute" className="text-container transition flex flex-col justify-stretch rounded absolute"
style={{ style={{
outline: `${focusedItem.value === item.id ? '1px solid' : ''}`, outline: outline,
fontSize: `${item.fontSize / 6}px`, fontSize: fontSize,
zIndex: `${focusedItem.value == itemKey ? LayerEnum.CARD_ELEVATED : LayerEnum.CARD}`, zIndex: zIndex,
top: `${item.position.y}px`, top: `${item.position.y}px`,
left: `${item.position.x}px`, left: `${item.position.x}px`,
userSelect: focusedItem.value === itemKey ? 'text' : 'none',
}} }}
> >
<div className={'px-2 w-full select-none drop-shadow relative'}> <pre
className={'text-pre px-2 w-full select-none drop-shadow relative'}
>
<p <p
ref={pRef} ref={pRef}
//@ts-expect-error
oninput={_handleContentInput} contentEditable className={'inline-block px-2 w-full select-none drop-shadow relative'}></p> oninput={_handleContentInput}
</div> contentEditable
className={'text-p inline-block px-2 w-full select-none drop-shadow relative'}>
</p>
</pre>
<CloseIcon cb={_handleClose} item={item} /> <CloseIcon cb={_handleClose} item={item} />
<ExpandIcon cb={_handleResizeMouseDown} item={item} /> <ExpandIcon cb={_handleResizeMouseDown} item={item} />
@ -158,7 +191,7 @@ function CloseIcon({ item, cb }: CloseIcon.Props) {
stroke-width="2" stroke-width="2"
stroke-linecap="round" stroke-linecap="round"
stroke-linejoin="round" stroke-linejoin="round"
className="cursor-pointer w-4 h-4 absolute top-[-8px] right-[-8px]" className="text-close cursor-pointer w-4 h-4 absolute top-[-8px] right-[-8px]"
style={{ style={{
display: focusedItem.value === item.id ? 'unset' : 'none' display: focusedItem.value === item.id ? 'unset' : 'none'
}} }}

View File

@ -11,6 +11,9 @@
margin: 0; margin: 0;
padding: 0; padding: 0;
box-sizing: border-box; box-sizing: border-box;
:focus {
outline: none;
}
} }
html { html {