* Add toolbar buttons for text-to-cad and prompt-to-edit Resolves #4890 * A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores) * A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores) * A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores) * A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores) * A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores) * A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores) * A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-macos-8-cores) * `preventDefault` on <kbd>Enter</kbd> with textarea input so buttons aren't clicked as well * A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores) * Trigger CI --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Pierre Jacquier <pierre@zoo.dev>
115 lines
3.7 KiB
TypeScript
115 lines
3.7 KiB
TypeScript
import { useCommandsContext } from 'hooks/useCommandsContext'
|
|
import { CommandArgument } from 'lib/commandTypes'
|
|
import { RefObject, useEffect, useRef } from 'react'
|
|
import { useHotkeys } from 'react-hotkeys-hook'
|
|
|
|
function CommandBarTextareaInput({
|
|
arg,
|
|
stepBack,
|
|
onSubmit,
|
|
}: {
|
|
arg: CommandArgument<unknown> & {
|
|
inputType: 'text'
|
|
name: string
|
|
}
|
|
stepBack: () => void
|
|
onSubmit: (event: unknown) => void
|
|
}) {
|
|
const { commandBarSend, commandBarState } = useCommandsContext()
|
|
useHotkeys('mod + k, mod + /', () => commandBarSend({ type: 'Close' }))
|
|
const formRef = useRef<HTMLFormElement>(null)
|
|
const inputRef = useRef<HTMLTextAreaElement>(null)
|
|
useTextareaAutoGrow(inputRef)
|
|
|
|
useEffect(() => {
|
|
if (inputRef.current) {
|
|
inputRef.current.focus()
|
|
inputRef.current.select()
|
|
}
|
|
}, [arg, inputRef])
|
|
|
|
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
|
|
e.preventDefault()
|
|
onSubmit(inputRef.current?.value)
|
|
}
|
|
|
|
return (
|
|
<form id="arg-form" onSubmit={handleSubmit} ref={formRef}>
|
|
<label className="flex items-start rounded mx-4 my-4 border border-chalkboard-100 dark:border-chalkboard-80">
|
|
<span
|
|
data-testid="cmd-bar-arg-name"
|
|
className="capitalize px-2 py-1 rounded-br bg-chalkboard-100 dark:bg-chalkboard-80 text-chalkboard-10 border-b border-b-chalkboard-100 dark:border-b-chalkboard-80"
|
|
>
|
|
{arg.name}
|
|
</span>
|
|
<textarea
|
|
data-testid="cmd-bar-arg-value"
|
|
id="arg-form"
|
|
name={arg.inputType}
|
|
ref={inputRef}
|
|
required
|
|
className="flex-grow mx-2 my-1 !bg-transparent focus:outline-none min-h-12"
|
|
placeholder="Enter a value"
|
|
defaultValue={
|
|
(commandBarState.context.argumentsToSubmit[arg.name] as
|
|
| string
|
|
| undefined) || (arg.defaultValue as string)
|
|
}
|
|
onKeyDown={(event) => {
|
|
if (event.key === 'Backspace' && !event.currentTarget.value) {
|
|
stepBack()
|
|
} else if (
|
|
event.key === 'Enter' &&
|
|
(event.metaKey || event.shiftKey)
|
|
) {
|
|
// Insert a newline
|
|
event.preventDefault()
|
|
const target = event.currentTarget
|
|
const value = target.value
|
|
const selectionStart = target.selectionStart
|
|
const selectionEnd = target.selectionEnd
|
|
target.value =
|
|
value.substring(0, selectionStart) +
|
|
'\n' +
|
|
value.substring(selectionEnd)
|
|
target.selectionStart = selectionStart + 1
|
|
target.selectionEnd = selectionStart + 1
|
|
} else if (event.key === 'Enter') {
|
|
event.preventDefault()
|
|
formRef.current?.dispatchEvent(
|
|
new Event('submit', { bubbles: true })
|
|
)
|
|
}
|
|
}}
|
|
autoFocus
|
|
/>
|
|
</label>
|
|
</form>
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Modified from https://www.reddit.com/r/reactjs/comments/twmild/comment/i3jf330/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button
|
|
* Thank you to @sidkh for the original code
|
|
*/
|
|
const useTextareaAutoGrow = (ref: RefObject<HTMLTextAreaElement>) => {
|
|
useEffect(() => {
|
|
const listener = () => {
|
|
if (ref.current === null) return
|
|
ref.current.style.padding = '0px'
|
|
ref.current.style.height = ref.current.scrollHeight + 'px'
|
|
ref.current.style.removeProperty('padding')
|
|
}
|
|
|
|
if (ref.current === null) return
|
|
ref.current.addEventListener('input', listener)
|
|
|
|
return () => {
|
|
if (ref.current === null) return
|
|
ref.current.removeEventListener('input', listener)
|
|
}
|
|
}, [ref.current])
|
|
}
|
|
|
|
export default CommandBarTextareaInput
|