Change DeterminePropEditor... to take an array

- Add autoFocus to prop inputs
This commit is contained in:
vezwork 2022-08-09 16:18:10 -04:00 committed by Elliot
parent 38e6a4ba36
commit 047f01bb45
17 changed files with 148 additions and 122 deletions

View file

@ -17,7 +17,11 @@ import type {KeyframeWithPathToPropFromCommonRoot} from '@theatre/studio/store/t
import {commonRootOfPathsToProps} from '@theatre/shared/utils/addresses' import {commonRootOfPathsToProps} from '@theatre/shared/utils/addresses'
import type {ILogger} from '@theatre/shared/logger' import type {ILogger} from '@theatre/shared/logger'
import DopeSnap from '@theatre/studio/panels/SequenceEditorPanel/RightOverlay/DopeSnap' import DopeSnap from '@theatre/studio/panels/SequenceEditorPanel/RightOverlay/DopeSnap'
import type {EditingOptionsTree} from '@theatre/studio/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/useSingleKeyframeInlineEditorPopover' import type {
PrimitivePropEditingOptions,
PropWithChildrenEditingOptionsTree,
SheetObjectEditingOptionsTree,
} from '@theatre/studio/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/useSingleKeyframeInlineEditorPopover'
import {useKeyframeInlineEditorPopover} from '@theatre/studio/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/useSingleKeyframeInlineEditorPopover' import {useKeyframeInlineEditorPopover} from '@theatre/studio/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/useSingleKeyframeInlineEditorPopover'
import type { import type {
SequenceEditorTree_PrimitiveProp, SequenceEditorTree_PrimitiveProp,
@ -31,17 +35,22 @@ type IAggregateKeyframeDotProps = {
utils: IAggregateKeyframeEditorUtils utils: IAggregateKeyframeEditorUtils
} }
const isOptionsTreeNodeNotNull = (
a: PropWithChildrenEditingOptionsTree | PrimitivePropEditingOptions | null,
): a is PropWithChildrenEditingOptionsTree | PrimitivePropEditingOptions =>
a !== null
function sheetObjectBuild( function sheetObjectBuild(
viewModel: SequenceEditorTree_SheetObject, viewModel: SequenceEditorTree_SheetObject,
keyframes: KeyframeWithTrack[], keyframes: KeyframeWithTrack[],
): EditingOptionsTree | null { ): SheetObjectEditingOptionsTree | null {
const children = viewModel.children const children = viewModel.children
.map((a) => .map((a) =>
a.type === 'propWithChildren' a.type === 'propWithChildren'
? propWithChildrenBuild(a, keyframes) ? propWithChildrenBuild(a, keyframes)
: primitivePropBuild(a, keyframes), : primitivePropBuild(a, keyframes),
) )
.filter((a): a is EditingOptionsTree => a !== null) .filter(isOptionsTreeNodeNotNull)
if (children.length === 0) return null if (children.length === 0) return null
return { return {
type: 'sheetObject', type: 'sheetObject',
@ -52,14 +61,14 @@ function sheetObjectBuild(
function propWithChildrenBuild( function propWithChildrenBuild(
viewModel: SequenceEditorTree_PropWithChildren, viewModel: SequenceEditorTree_PropWithChildren,
keyframes: KeyframeWithTrack[], keyframes: KeyframeWithTrack[],
): EditingOptionsTree | null { ): PropWithChildrenEditingOptionsTree | null {
const children = viewModel.children const children = viewModel.children
.map((a) => .map((a) =>
a.type === 'propWithChildren' a.type === 'propWithChildren'
? propWithChildrenBuild(a, keyframes) ? propWithChildrenBuild(a, keyframes)
: primitivePropBuild(a, keyframes), : primitivePropBuild(a, keyframes),
) )
.filter((a): a is EditingOptionsTree => a !== null) .filter(isOptionsTreeNodeNotNull)
if (children.length === 0) return null if (children.length === 0) return null
return { return {
type: 'propWithChildren', type: 'propWithChildren',
@ -71,7 +80,7 @@ function propWithChildrenBuild(
function primitivePropBuild( function primitivePropBuild(
viewModelLeaf: SequenceEditorTree_PrimitiveProp, viewModelLeaf: SequenceEditorTree_PrimitiveProp,
keyframes: KeyframeWithTrack[], keyframes: KeyframeWithTrack[],
): EditingOptionsTree | null { ): PrimitivePropEditingOptions | null {
const keyframe = keyframes.find((kf) => kf.track.id === viewModelLeaf.trackId) const keyframe = keyframes.find((kf) => kf.track.id === viewModelLeaf.trackId)
if (!keyframe) return null if (!keyframe) return null
return { return {
@ -94,7 +103,9 @@ export function AggregateKeyframeDot(
useKeyframeInlineEditorPopover( useKeyframeInlineEditorPopover(
props.editorProps.viewModel.type === 'sheetObject' props.editorProps.viewModel.type === 'sheetObject'
? sheetObjectBuild(props.editorProps.viewModel, cur.keyframes) ? sheetObjectBuild(props.editorProps.viewModel, cur.keyframes)
: propWithChildrenBuild(props.editorProps.viewModel, cur.keyframes), ?.children ?? null
: propWithChildrenBuild(props.editorProps.viewModel, cur.keyframes)
?.children ?? null,
) )
const presence = usePresence(props.utils.itemKey) const presence = usePresence(props.utils.itemKey)

View file

@ -4,8 +4,6 @@ import styled from 'styled-components'
import type {PropTypeConfig_AllSimples} from '@theatre/core/propTypes' import type {PropTypeConfig_AllSimples} from '@theatre/core/propTypes'
import type {ISimplePropEditorReactProps} from '@theatre/studio/propEditors/simpleEditors/ISimplePropEditorReactProps' import type {ISimplePropEditorReactProps} from '@theatre/studio/propEditors/simpleEditors/ISimplePropEditorReactProps'
import {simplePropEditorByPropType} from '@theatre/studio/propEditors/simpleEditors/simplePropEditorByPropType' import {simplePropEditorByPropType} from '@theatre/studio/propEditors/simpleEditors/simplePropEditorByPropType'
import SingleKeyframeSimplePropEditor from './DeterminePropEditorForSingleKeyframe/SingleKeyframeSimplePropEditor'
import type { import type {
EditingOptionsTree, EditingOptionsTree,
PrimitivePropEditingOptions, PrimitivePropEditingOptions,
@ -33,7 +31,7 @@ const SingleKeyframePropLabel = styled.div`
color: #919191; color: #919191;
` `
const IndentedThing = styled.div` const Indent = styled.div`
margin-left: 24px; margin-left: 24px;
` `
@ -47,18 +45,24 @@ const IndentedThing = styled.div`
* *
* @param p - propConfig object for any type of prop. * @param p - propConfig object for any type of prop.
*/ */
export function DeterminePropEditorForKeyframeTree(p: EditingOptionsTree) { export function DeterminePropEditorForKeyframeTree(
p: EditingOptionsTree & {autoFocusInput?: boolean},
) {
if (p.type === 'sheetObject') { if (p.type === 'sheetObject') {
return ( return (
<> <>
<SingleKeyframePropLabel> <SingleKeyframePropLabel>
{p.sheetObject.address.objectKey} {p.sheetObject.address.objectKey}
</SingleKeyframePropLabel> </SingleKeyframePropLabel>
<IndentedThing> <Indent>
{p.children.map((c, i) => ( {p.children.map((c, i) => (
<DeterminePropEditorForKeyframeTree key={i} {...c} /> <DeterminePropEditorForKeyframeTree
key={i}
{...c}
autoFocusInput={p.autoFocusInput && i === 0}
/>
))} ))}
</IndentedThing> </Indent>
</> </>
) )
} else if (p.type === 'propWithChildren') { } else if (p.type === 'propWithChildren') {
@ -66,19 +70,31 @@ export function DeterminePropEditorForKeyframeTree(p: EditingOptionsTree) {
return ( return (
<> <>
<SingleKeyframePropLabel>{label}</SingleKeyframePropLabel> <SingleKeyframePropLabel>{label}</SingleKeyframePropLabel>
<IndentedThing> <Indent>
{p.children.map((c, i) => ( {p.children.map((c, i) => (
<DeterminePropEditorForKeyframeTree key={i} {...c} /> <DeterminePropEditorForKeyframeTree
key={i}
{...c}
autoFocusInput={p.autoFocusInput && i === 0}
/>
))} ))}
</IndentedThing> </Indent>
</> </>
) )
} else { } else {
return <BeepBoop {...p} /> return <PrimitivePropEditor {...p} autoFocusInput={p.autoFocusInput} />
} }
} }
function BeepBoop(p: PrimitivePropEditingOptions) { const SingleKeyframeSimplePropEditorContainer = styled.div`
padding: 0 6px;
display: flex;
align-items: center;
`
function PrimitivePropEditor(
p: PrimitivePropEditingOptions & {autoFocusInput?: boolean},
) {
const label = p.propConfig.label ?? last(p.pathToProp) const label = p.propConfig.label ?? last(p.pathToProp)
const editingTools = useEditingToolsForKeyframeEditorPopover(p) const editingTools = useEditingToolsForKeyframeEditorPopover(p)
@ -92,12 +108,14 @@ function BeepBoop(p: PrimitivePropEditingOptions) {
return ( return (
<SingleKeyframePropEditorContainer> <SingleKeyframePropEditorContainer>
<SingleKeyframePropLabel>{label}</SingleKeyframePropLabel> <SingleKeyframePropLabel>{label}</SingleKeyframePropLabel>
<SingleKeyframeSimplePropEditor <SingleKeyframeSimplePropEditorContainer>
SimpleEditorComponent={PropEditor} <PropEditor
propConfig={p.propConfig} editingTools={editingTools}
editingTools={editingTools} propConfig={p.propConfig}
keyframeValue={p.keyframe.value} value={p.keyframe.value}
/> autoFocus={p.autoFocusInput}
/>
</SingleKeyframeSimplePropEditorContainer>
</SingleKeyframePropEditorContainer> </SingleKeyframePropEditorContainer>
) )
} }

View file

@ -1,45 +0,0 @@
import React from 'react'
import type {ISimplePropEditorReactProps} from '@theatre/studio/propEditors/simpleEditors/ISimplePropEditorReactProps'
import styled from 'styled-components'
import type {PropTypeConfig_AllSimples} from '@theatre/core/propTypes'
import type {IEditingTools} from '@theatre/studio/propEditors/utils/IEditingTools'
export type ISingleKeyframeSimplePropEditorProps<
TPropTypeConfig extends PropTypeConfig_AllSimples,
> = {
propConfig: TPropTypeConfig
editingTools: IEditingTools<TPropTypeConfig['valueType']>
keyframeValue: TPropTypeConfig['valueType']
SimpleEditorComponent: React.VFC<ISimplePropEditorReactProps<TPropTypeConfig>>
}
const SingleKeyframeSimplePropEditorContainer = styled.div`
padding: 0 6px;
display: flex;
align-items: center;
`
/**
* Initially used for inline keyframe property editor, this editor is attached to the
* functionality of editing a property for a sequence keyframe.
*/
function SingleKeyframeSimplePropEditor<
TPropTypeConfig extends PropTypeConfig_AllSimples,
>({
propConfig,
editingTools,
keyframeValue: value,
SimpleEditorComponent: EditorComponent,
}: ISingleKeyframeSimplePropEditorProps<TPropTypeConfig>) {
return (
<SingleKeyframeSimplePropEditorContainer>
<EditorComponent
editingTools={editingTools}
propConfig={propConfig}
value={value}
/>
</SingleKeyframeSimplePropEditorContainer>
)
}
export default SingleKeyframeSimplePropEditor

View file

@ -102,38 +102,39 @@ const SingleKeyframeDot: React.VFC<ISingleKeyframeDotProps> = (props) => {
const [contextMenu] = useSingleKeyframeContextMenu(node, logger, props) const [contextMenu] = useSingleKeyframeContextMenu(node, logger, props)
const [inlineEditorPopover, openEditor, _, isInlineEditorPopoverOpen] = const [inlineEditorPopover, openEditor, _, isInlineEditorPopoverOpen] =
useKeyframeInlineEditorPopover({ useKeyframeInlineEditorPopover([
type: 'primitiveProp', {
keyframe: props.keyframe, type: 'primitiveProp',
pathToProp: props.leaf.pathToProp, keyframe: props.keyframe,
propConfig: props.leaf.propConf, pathToProp: props.leaf.pathToProp,
sheetObject: props.leaf.sheetObject, propConfig: props.leaf.propConf,
trackId: props.leaf.trackId, sheetObject: props.leaf.sheetObject,
}) trackId: props.leaf.trackId,
const [isDragging] = useDragForSingleKeyframeDot(node, props, {
onClickFromDrag(dragStartEvent) {
openEditor(dragStartEvent, ref.current!)
}, },
}) ])
const [isDragging] = useDragForSingleKeyframeDot(node, props, {
onClickFromDrag(dragStartEvent) {
openEditor(dragStartEvent, ref.current!)
},
})
return ( return (
<> <>
<HitZone <HitZone
ref={ref} ref={ref}
isInlineEditorPopoverOpen={isInlineEditorPopoverOpen} isInlineEditorPopoverOpen={isInlineEditorPopoverOpen}
{...presence.attrs} {...presence.attrs}
/> />
<Diamond <Diamond
isSelected={!!props.selection} isSelected={!!props.selection}
isInlineEditorPopoverOpen={isInlineEditorPopoverOpen} isInlineEditorPopoverOpen={isInlineEditorPopoverOpen}
flag={presence.flag} flag={presence.flag}
/> />
{inlineEditorPopover} {inlineEditorPopover}
{contextMenu} {contextMenu}
</> </>
) )
}, }
)
export default SingleKeyframeDot export default SingleKeyframeDot

View file

@ -15,13 +15,19 @@ import type {UnknownValidCompoundProps} from '@theatre/core/propTypes/internals'
/** The editor that pops up when directly clicking a Keyframe. */ /** The editor that pops up when directly clicking a Keyframe. */
export function useKeyframeInlineEditorPopover( export function useKeyframeInlineEditorPopover(
props: EditingOptionsTree | null, props: EditingOptionsTree[] | null,
) { ) {
return usePopover({debugName: 'useKeyframeInlineEditorPopover'}, () => ( return usePopover({debugName: 'useKeyframeInlineEditorPopover'}, () => (
<BasicPopover showPopoverEdgeTriangle> <BasicPopover showPopoverEdgeTriangle>
{props === null ? undefined : ( {!Array.isArray(props)
<DeterminePropEditorForKeyframeTree {...props} /> ? undefined
)} : props.map((prop, i) => (
<DeterminePropEditorForKeyframeTree
key={i}
{...prop}
autoFocusInput={i === 0}
/>
))}
</BasicPopover> </BasicPopover>
)) ))
} }
@ -30,12 +36,12 @@ export type EditingOptionsTree =
| SheetObjectEditingOptionsTree | SheetObjectEditingOptionsTree
| PropWithChildrenEditingOptionsTree | PropWithChildrenEditingOptionsTree
| PrimitivePropEditingOptions | PrimitivePropEditingOptions
type SheetObjectEditingOptionsTree = { export type SheetObjectEditingOptionsTree = {
type: 'sheetObject' type: 'sheetObject'
sheetObject: SheetObject sheetObject: SheetObject
children: EditingOptionsTree[] children: EditingOptionsTree[]
} }
type PropWithChildrenEditingOptionsTree = { export type PropWithChildrenEditingOptionsTree = {
type: 'propWithChildren' type: 'propWithChildren'
propConfig: PropTypeConfig_Compound<UnknownValidCompoundProps> propConfig: PropTypeConfig_Compound<UnknownValidCompoundProps>
pathToProp: PathToProp pathToProp: PathToProp

View file

@ -71,13 +71,16 @@ const GraphEditorDotNonScalar: React.VFC<IProps> = (props) => {
const curValue = props.which === 'left' ? 0 : 1 const curValue = props.which === 'left' ? 0 : 1
const [inlineEditorPopover, openEditor, _, _isInlineEditorPopoverOpen] = const [inlineEditorPopover, openEditor, _, _isInlineEditorPopoverOpen] =
useKeyframeInlineEditorPopover({ useKeyframeInlineEditorPopover([
keyframe: props.keyframe, {
pathToProp: props.pathToProp, type: 'primitiveProp',
propConf: props.propConfig, keyframe: props.keyframe,
sheetObject: props.sheetObject, pathToProp: props.pathToProp,
trackId: props.trackId, propConfig: props.propConfig,
}) sheetObject: props.sheetObject,
trackId: props.trackId,
},
])
const isDragging = useDragKeyframe({ const isDragging = useDragKeyframe({
node, node,

View file

@ -71,13 +71,16 @@ const GraphEditorDotScalar: React.VFC<IProps> = (props) => {
const cyInExtremumSpace = props.extremumSpace.fromValueSpace(curValue) const cyInExtremumSpace = props.extremumSpace.fromValueSpace(curValue)
const [inlineEditorPopover, openEditor, _, _isInlineEditorPopoverOpen] = const [inlineEditorPopover, openEditor, _, _isInlineEditorPopoverOpen] =
useKeyframeInlineEditorPopover({ useKeyframeInlineEditorPopover([
keyframe: props.keyframe, {
pathToProp: props.pathToProp, type: 'primitiveProp',
propConf: props.propConfig, keyframe: props.keyframe,
sheetObject: props.sheetObject, pathToProp: props.pathToProp,
trackId: props.trackId, propConfig: props.propConfig,
}) sheetObject: props.sheetObject,
trackId: props.trackId,
},
])
const isDragging = useDragKeyframe({ const isDragging = useDragKeyframe({
node, node,

View file

@ -6,12 +6,17 @@ import type {ISimplePropEditorReactProps} from './ISimplePropEditorReactProps'
const Input = styled(BasicCheckbox)` const Input = styled(BasicCheckbox)`
margin-left: 6px; margin-left: 6px;
:focus {
outline: 1px solid #555;
}
` `
function BooleanPropEditor({ function BooleanPropEditor({
propConfig, propConfig,
editingTools, editingTools,
value, value,
autoFocus,
}: ISimplePropEditorReactProps<PropTypeConfig_Boolean>) { }: ISimplePropEditorReactProps<PropTypeConfig_Boolean>) {
const onChange = useCallback( const onChange = useCallback(
(el: React.ChangeEvent<HTMLInputElement>) => { (el: React.ChangeEvent<HTMLInputElement>) => {
@ -20,7 +25,7 @@ function BooleanPropEditor({
[propConfig, editingTools], [propConfig, editingTools],
) )
return <Input checked={value} onChange={onChange} /> return <Input checked={value} onChange={onChange} autoFocus={autoFocus} />
} }
export default BooleanPropEditor export default BooleanPropEditor

View file

@ -8,4 +8,5 @@ export type ISimplePropEditorReactProps<
propConfig: TPropTypeConfig propConfig: TPropTypeConfig
editingTools: IEditingTools<TPropTypeConfig['valueType']> editingTools: IEditingTools<TPropTypeConfig['valueType']>
value: TPropTypeConfig['valueType'] value: TPropTypeConfig['valueType']
autoFocus?: boolean
} }

View file

@ -7,6 +7,7 @@ function NumberPropEditor({
propConfig, propConfig,
editingTools, editingTools,
value, value,
autoFocus,
}: ISimplePropEditorReactProps<PropTypeConfig_Number>) { }: ISimplePropEditorReactProps<PropTypeConfig_Number>) {
const nudge = useCallback( const nudge = useCallback(
(params: {deltaX: number; deltaFraction: number; magnitude: number}) => { (params: {deltaX: number; deltaFraction: number; magnitude: number}) => {
@ -23,6 +24,7 @@ function NumberPropEditor({
permanentlySetValue={editingTools.permanentlySetValue} permanentlySetValue={editingTools.permanentlySetValue}
range={propConfig.range} range={propConfig.range}
nudge={nudge} nudge={nudge}
autoFocus={autoFocus}
/> />
) )
} }

View file

@ -63,6 +63,7 @@ const RgbaPopover = styled.div`
function RgbaPropEditor({ function RgbaPropEditor({
editingTools, editingTools,
value, value,
autoFocus,
}: ISimplePropEditorReactProps<PropTypeConfig_Rgba>) { }: ISimplePropEditorReactProps<PropTypeConfig_Rgba>) {
const containerRef = useRef<HTMLDivElement>(null!) const containerRef = useRef<HTMLDivElement>(null!)
@ -116,6 +117,7 @@ function RgbaPropEditor({
discardTemporaryValue={noop} discardTemporaryValue={noop}
permanentlySetValue={onChange} permanentlySetValue={onChange}
isValid={(v) => !!v.match(validHexRegExp)} isValid={(v) => !!v.match(validHexRegExp)}
autoFocus={autoFocus}
/> />
</RowContainer> </RowContainer>
{popoverNode} {popoverNode}

View file

@ -8,6 +8,7 @@ function StringLiteralPropEditor<TLiteralOptions extends string>({
propConfig, propConfig,
editingTools, editingTools,
value, value,
autoFocus,
}: ISimplePropEditorReactProps<PropTypeConfig_StringLiteral<TLiteralOptions>>) { }: ISimplePropEditorReactProps<PropTypeConfig_StringLiteral<TLiteralOptions>>) {
const onChange = useCallback( const onChange = useCallback(
(val: TLiteralOptions) => { (val: TLiteralOptions) => {
@ -21,12 +22,14 @@ function StringLiteralPropEditor<TLiteralOptions extends string>({
value={value} value={value}
onChange={onChange} onChange={onChange}
options={propConfig.valuesAndLabels} options={propConfig.valuesAndLabels}
autoFocus={autoFocus}
/> />
) : ( ) : (
<BasicSwitch <BasicSwitch
value={value} value={value}
onChange={onChange} onChange={onChange}
options={propConfig.valuesAndLabels} options={propConfig.valuesAndLabels}
autoFocus={autoFocus}
/> />
) )
} }

View file

@ -6,6 +6,7 @@ import type {ISimplePropEditorReactProps} from './ISimplePropEditorReactProps'
function StringPropEditor({ function StringPropEditor({
editingTools, editingTools,
value, value,
autoFocus,
}: ISimplePropEditorReactProps<PropTypeConfig_String>) { }: ISimplePropEditorReactProps<PropTypeConfig_String>) {
return ( return (
<BasicStringInput <BasicStringInput
@ -13,6 +14,7 @@ function StringPropEditor({
temporarilySetValue={editingTools.temporarilySetValue} temporarilySetValue={editingTools.temporarilySetValue}
discardTemporaryValue={editingTools.discardTemporaryValue} discardTemporaryValue={editingTools.discardTemporaryValue}
permanentlySetValue={editingTools.permanentlySetValue} permanentlySetValue={editingTools.permanentlySetValue}
autoFocus={autoFocus}
/> />
) )
} }

View file

@ -115,6 +115,7 @@ const BasicNumberInput: React.FC<{
*/ */
onBlur?: () => void onBlur?: () => void
nudge: BasicNumberInputNudgeFn nudge: BasicNumberInputNudgeFn
autoFocus?: boolean
}> = (propsA) => { }> = (propsA) => {
const [stateRef] = useRefAndState<IState>({mode: 'noFocus'}) const [stateRef] = useRefAndState<IState>({mode: 'noFocus'})
const isValid = propsA.isValid ?? alwaysValid const isValid = propsA.isValid ?? alwaysValid
@ -307,6 +308,7 @@ const BasicNumberInput: React.FC<{
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
}} }}
autoFocus={propsA.autoFocus}
/> />
) )

View file

@ -55,11 +55,13 @@ function BasicSelect<TLiteralOptions extends string>({
onChange, onChange,
options, options,
className, className,
autoFocus,
}: { }: {
value: TLiteralOptions value: TLiteralOptions
onChange: (val: TLiteralOptions) => void onChange: (val: TLiteralOptions) => void
options: Record<TLiteralOptions, string> options: Record<TLiteralOptions, string>
className?: string className?: string
autoFocus?: boolean
}) { }) {
const _onChange = useCallback( const _onChange = useCallback(
(el: React.ChangeEvent<HTMLSelectElement>) => { (el: React.ChangeEvent<HTMLSelectElement>) => {
@ -70,7 +72,12 @@ function BasicSelect<TLiteralOptions extends string>({
return ( return (
<Container> <Container>
<Select className={className} value={value} onChange={_onChange}> <Select
className={className}
value={value}
onChange={_onChange}
autoFocus={autoFocus}
>
{Object.keys(options).map((key, i) => ( {Object.keys(options).map((key, i) => (
<option key={'option-' + i} value={key}> <option key={'option-' + i} value={key}>
{options[key]} {options[key]}

View file

@ -64,6 +64,7 @@ const BasicStringInput: React.FC<{
* before this, so use this for UI purposes such as closing a popover. * before this, so use this for UI purposes such as closing a popover.
*/ */
onBlur?: () => void onBlur?: () => void
autoFocus?: boolean
}> = (props) => { }> = (props) => {
const [stateRef] = useRefAndState<IState>({mode: 'noFocus'}) const [stateRef] = useRefAndState<IState>({mode: 'noFocus'})
const isValid = props.isValid ?? alwaysValid const isValid = props.isValid ?? alwaysValid
@ -195,6 +196,7 @@ const BasicStringInput: React.FC<{
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
}} }}
autoFocus={props.autoFocus}
/> />
) )

View file

@ -56,10 +56,12 @@ function BasicSwitch<TLiteralOptions extends string>({
value, value,
onChange, onChange,
options, options,
autoFocus,
}: { }: {
value: TLiteralOptions value: TLiteralOptions
onChange: (val: TLiteralOptions) => void onChange: (val: TLiteralOptions) => void
options: Record<TLiteralOptions, string> options: Record<TLiteralOptions, string>
autoFocus?: boolean
}) { }) {
const _onChange = useCallback( const _onChange = useCallback(
(el: React.ChangeEvent<HTMLInputElement>) => { (el: React.ChangeEvent<HTMLInputElement>) => {
@ -78,6 +80,7 @@ function BasicSwitch<TLiteralOptions extends string>({
value={key} value={key}
onChange={_onChange} onChange={_onChange}
name="switchbox" name="switchbox"
autoFocus={autoFocus}
/> />
</Label> </Label>
))} ))}