diff options
author | Lieuwe Rooijakkers <lieuwerooijakkers@gmail.com> | 2025-01-19 22:21:32 +0100 |
---|---|---|
committer | Lieuwe Rooijakkers <lieuwerooijakkers@gmail.com> | 2025-01-19 22:21:46 +0100 |
commit | 93552152be180766fda08b1bd7ccefc4d26065ff (patch) | |
tree | f9f1e19372995729adc7e1c79f16c27acd9625be /client/src/components/entry.jsx | |
parent | 6841765fcbfadbd4e3006f5fbcea45194c92e5a1 (diff) |
client advancements
Diffstat (limited to 'client/src/components/entry.jsx')
-rw-r--r-- | client/src/components/entry.jsx | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/client/src/components/entry.jsx b/client/src/components/entry.jsx new file mode 100644 index 0000000..637a696 --- /dev/null +++ b/client/src/components/entry.jsx @@ -0,0 +1,76 @@ +import {createElement, useLayoutEffect, useRef, useState} from 'react'; + +import './entry.css'; + +function TextField({ item, onEnter, onSelect, onRemove, ref }) { + const onKeyDown = e => { + if (e.keyCode === 38) { // up + onSelect(-1); + e.preventDefault(); + return; + } else if (e.keyCode === 40) { // down + onSelect(+1); + e.preventDefault(); + return; + } else if (e.keyCode === 8 && e.target.innerText.length === 0) { // backspace + onRemove(); + e.preventDefault(); + return; + } + + if (e.keyCode !== 13) { + return; + } else if (e.shiftKey) { + return; + } + + e.preventDefault(); + + onEnter(e.ctrlKey ? 'todo' : 'plain'); + }; + + useLayoutEffect(() => { + if (ref.current == null) { + return; + } + + ref.current.innerText = item.text; + }, [item.text]); + + return <div ref={ref} className='text' contentEditable="true" onKeyDown={onKeyDown} onClick={() => onSelect(0)}></div>; +} + +function Plain({ item, onEnter, onSelect, onRemove, ref }) { + return <TextField item={item} onEnter={onEnter} onSelect={onSelect} onRemove={onRemove} ref={ref} />; +} + +function Todo({ item, onEnter, onSelect, onRemove, ref }) { + return <> + <input type="checkbox" /> + <TextField item={item} onEnter={onEnter} onSelect={onSelect} onRemove={onRemove} ref={ref} /> + </>; +} + +export default function Entry({ item, onEnter, onSelect, onRemove, isFocused }) { + const ref = useRef(null); + useLayoutEffect(() => { + if (isFocused && ref.current != null && document.activeElement !== ref.current) { + ref.current.focus(); + document.execCommand('selectAll', false, null); + document.getSelection().collapseToEnd(); + } + }, [isFocused]); + + const child = createElement(item.type === 'plain' ? Plain : Todo, { + ref, + item, + onEnter, + onSelect, + onRemove: () => onRemove(true), + }); + + return <div className={`entry ${isFocused ? 'focus' : ''}`}> + <button onClick={() => onRemove(false)}>X</button> + {child} + </div> +} |