diff --git a/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/AggregatedKeyframeTrack/AggregateKeyframeEditor/AggregateKeyframeDot.tsx b/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/AggregatedKeyframeTrack/AggregateKeyframeEditor/AggregateKeyframeDot.tsx
index 388682b..1e6241e 100644
--- a/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/AggregatedKeyframeTrack/AggregateKeyframeEditor/AggregateKeyframeDot.tsx
+++ b/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/AggregatedKeyframeTrack/AggregateKeyframeEditor/AggregateKeyframeDot.tsx
@@ -17,7 +17,11 @@ import type {KeyframeWithPathToPropFromCommonRoot} from '@theatre/studio/store/t
import {commonRootOfPathsToProps} from '@theatre/shared/utils/addresses'
import type {ILogger} from '@theatre/shared/logger'
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 type {
SequenceEditorTree_PrimitiveProp,
@@ -31,17 +35,22 @@ type IAggregateKeyframeDotProps = {
utils: IAggregateKeyframeEditorUtils
}
+const isOptionsTreeNodeNotNull = (
+ a: PropWithChildrenEditingOptionsTree | PrimitivePropEditingOptions | null,
+): a is PropWithChildrenEditingOptionsTree | PrimitivePropEditingOptions =>
+ a !== null
+
function sheetObjectBuild(
viewModel: SequenceEditorTree_SheetObject,
keyframes: KeyframeWithTrack[],
-): EditingOptionsTree | null {
+): SheetObjectEditingOptionsTree | null {
const children = viewModel.children
.map((a) =>
a.type === 'propWithChildren'
? propWithChildrenBuild(a, keyframes)
: primitivePropBuild(a, keyframes),
)
- .filter((a): a is EditingOptionsTree => a !== null)
+ .filter(isOptionsTreeNodeNotNull)
if (children.length === 0) return null
return {
type: 'sheetObject',
@@ -52,14 +61,14 @@ function sheetObjectBuild(
function propWithChildrenBuild(
viewModel: SequenceEditorTree_PropWithChildren,
keyframes: KeyframeWithTrack[],
-): EditingOptionsTree | null {
+): PropWithChildrenEditingOptionsTree | null {
const children = viewModel.children
.map((a) =>
a.type === 'propWithChildren'
? propWithChildrenBuild(a, keyframes)
: primitivePropBuild(a, keyframes),
)
- .filter((a): a is EditingOptionsTree => a !== null)
+ .filter(isOptionsTreeNodeNotNull)
if (children.length === 0) return null
return {
type: 'propWithChildren',
@@ -71,7 +80,7 @@ function propWithChildrenBuild(
function primitivePropBuild(
viewModelLeaf: SequenceEditorTree_PrimitiveProp,
keyframes: KeyframeWithTrack[],
-): EditingOptionsTree | null {
+): PrimitivePropEditingOptions | null {
const keyframe = keyframes.find((kf) => kf.track.id === viewModelLeaf.trackId)
if (!keyframe) return null
return {
@@ -94,7 +103,9 @@ export function AggregateKeyframeDot(
useKeyframeInlineEditorPopover(
props.editorProps.viewModel.type === 'sheetObject'
? 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)
diff --git a/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/DeterminePropEditorForSingleKeyframe.tsx b/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/DeterminePropEditorForSingleKeyframe.tsx
index 9880737..009ecf4 100644
--- a/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/DeterminePropEditorForSingleKeyframe.tsx
+++ b/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/DeterminePropEditorForSingleKeyframe.tsx
@@ -4,8 +4,6 @@ import styled from 'styled-components'
import type {PropTypeConfig_AllSimples} from '@theatre/core/propTypes'
import type {ISimplePropEditorReactProps} from '@theatre/studio/propEditors/simpleEditors/ISimplePropEditorReactProps'
import {simplePropEditorByPropType} from '@theatre/studio/propEditors/simpleEditors/simplePropEditorByPropType'
-
-import SingleKeyframeSimplePropEditor from './DeterminePropEditorForSingleKeyframe/SingleKeyframeSimplePropEditor'
import type {
EditingOptionsTree,
PrimitivePropEditingOptions,
@@ -33,7 +31,7 @@ const SingleKeyframePropLabel = styled.div`
color: #919191;
`
-const IndentedThing = styled.div`
+const Indent = styled.div`
margin-left: 24px;
`
@@ -47,18 +45,24 @@ const IndentedThing = styled.div`
*
* @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') {
return (
<>
{p.sheetObject.address.objectKey}
-
+
{p.children.map((c, i) => (
-
+
))}
-
+
>
)
} else if (p.type === 'propWithChildren') {
@@ -66,19 +70,31 @@ export function DeterminePropEditorForKeyframeTree(p: EditingOptionsTree) {
return (
<>
{label}
-
+
{p.children.map((c, i) => (
-
+
))}
-
+
>
)
} else {
- return
+ return
}
}
-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 editingTools = useEditingToolsForKeyframeEditorPopover(p)
@@ -92,12 +108,14 @@ function BeepBoop(p: PrimitivePropEditingOptions) {
return (
{label}
-
+
+
+
)
}
diff --git a/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/DeterminePropEditorForSingleKeyframe/SingleKeyframeSimplePropEditor.tsx b/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/DeterminePropEditorForSingleKeyframe/SingleKeyframeSimplePropEditor.tsx
deleted file mode 100644
index 9354d58..0000000
--- a/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/DeterminePropEditorForSingleKeyframe/SingleKeyframeSimplePropEditor.tsx
+++ /dev/null
@@ -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
- keyframeValue: TPropTypeConfig['valueType']
- SimpleEditorComponent: React.VFC>
-}
-
-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) {
- return (
-
-
-
- )
-}
-
-export default SingleKeyframeSimplePropEditor
diff --git a/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/SingleKeyframeDot.tsx b/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/SingleKeyframeDot.tsx
index 312f231..7274f8c 100644
--- a/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/SingleKeyframeDot.tsx
+++ b/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/SingleKeyframeDot.tsx
@@ -102,38 +102,39 @@ const SingleKeyframeDot: React.VFC = (props) => {
const [contextMenu] = useSingleKeyframeContextMenu(node, logger, props)
const [inlineEditorPopover, openEditor, _, isInlineEditorPopoverOpen] =
- useKeyframeInlineEditorPopover({
- type: 'primitiveProp',
- keyframe: props.keyframe,
- pathToProp: props.leaf.pathToProp,
- propConfig: props.leaf.propConf,
- sheetObject: props.leaf.sheetObject,
- trackId: props.leaf.trackId,
- })
- const [isDragging] = useDragForSingleKeyframeDot(node, props, {
- onClickFromDrag(dragStartEvent) {
- openEditor(dragStartEvent, ref.current!)
+ useKeyframeInlineEditorPopover([
+ {
+ type: 'primitiveProp',
+ keyframe: props.keyframe,
+ pathToProp: props.leaf.pathToProp,
+ propConfig: props.leaf.propConf,
+ sheetObject: props.leaf.sheetObject,
+ trackId: props.leaf.trackId,
},
- })
+ ])
+ const [isDragging] = useDragForSingleKeyframeDot(node, props, {
+ onClickFromDrag(dragStartEvent) {
+ openEditor(dragStartEvent, ref.current!)
+ },
+ })
- return (
- <>
-
-
- {inlineEditorPopover}
- {contextMenu}
- >
- )
- },
-)
+ return (
+ <>
+
+
+ {inlineEditorPopover}
+ {contextMenu}
+ >
+ )
+}
export default SingleKeyframeDot
diff --git a/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/useSingleKeyframeInlineEditorPopover.tsx b/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/useSingleKeyframeInlineEditorPopover.tsx
index 270d8c0..29991de 100644
--- a/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/useSingleKeyframeInlineEditorPopover.tsx
+++ b/theatre/studio/src/panels/SequenceEditorPanel/DopeSheet/Right/BasicKeyframedTrack/KeyframeEditor/useSingleKeyframeInlineEditorPopover.tsx
@@ -15,13 +15,19 @@ import type {UnknownValidCompoundProps} from '@theatre/core/propTypes/internals'
/** The editor that pops up when directly clicking a Keyframe. */
export function useKeyframeInlineEditorPopover(
- props: EditingOptionsTree | null,
+ props: EditingOptionsTree[] | null,
) {
return usePopover({debugName: 'useKeyframeInlineEditorPopover'}, () => (
- {props === null ? undefined : (
-
- )}
+ {!Array.isArray(props)
+ ? undefined
+ : props.map((prop, i) => (
+
+ ))}
))
}
@@ -30,12 +36,12 @@ export type EditingOptionsTree =
| SheetObjectEditingOptionsTree
| PropWithChildrenEditingOptionsTree
| PrimitivePropEditingOptions
-type SheetObjectEditingOptionsTree = {
+export type SheetObjectEditingOptionsTree = {
type: 'sheetObject'
sheetObject: SheetObject
children: EditingOptionsTree[]
}
-type PropWithChildrenEditingOptionsTree = {
+export type PropWithChildrenEditingOptionsTree = {
type: 'propWithChildren'
propConfig: PropTypeConfig_Compound
pathToProp: PathToProp
diff --git a/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/KeyframeEditor/GraphEditorDotNonScalar.tsx b/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/KeyframeEditor/GraphEditorDotNonScalar.tsx
index 805de39..2d92a3e 100644
--- a/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/KeyframeEditor/GraphEditorDotNonScalar.tsx
+++ b/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/KeyframeEditor/GraphEditorDotNonScalar.tsx
@@ -71,13 +71,16 @@ const GraphEditorDotNonScalar: React.VFC = (props) => {
const curValue = props.which === 'left' ? 0 : 1
const [inlineEditorPopover, openEditor, _, _isInlineEditorPopoverOpen] =
- useKeyframeInlineEditorPopover({
- keyframe: props.keyframe,
- pathToProp: props.pathToProp,
- propConf: props.propConfig,
- sheetObject: props.sheetObject,
- trackId: props.trackId,
- })
+ useKeyframeInlineEditorPopover([
+ {
+ type: 'primitiveProp',
+ keyframe: props.keyframe,
+ pathToProp: props.pathToProp,
+ propConfig: props.propConfig,
+ sheetObject: props.sheetObject,
+ trackId: props.trackId,
+ },
+ ])
const isDragging = useDragKeyframe({
node,
diff --git a/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/KeyframeEditor/GraphEditorDotScalar.tsx b/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/KeyframeEditor/GraphEditorDotScalar.tsx
index fccccc9..1e37624 100644
--- a/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/KeyframeEditor/GraphEditorDotScalar.tsx
+++ b/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/KeyframeEditor/GraphEditorDotScalar.tsx
@@ -71,13 +71,16 @@ const GraphEditorDotScalar: React.VFC = (props) => {
const cyInExtremumSpace = props.extremumSpace.fromValueSpace(curValue)
const [inlineEditorPopover, openEditor, _, _isInlineEditorPopoverOpen] =
- useKeyframeInlineEditorPopover({
- keyframe: props.keyframe,
- pathToProp: props.pathToProp,
- propConf: props.propConfig,
- sheetObject: props.sheetObject,
- trackId: props.trackId,
- })
+ useKeyframeInlineEditorPopover([
+ {
+ type: 'primitiveProp',
+ keyframe: props.keyframe,
+ pathToProp: props.pathToProp,
+ propConfig: props.propConfig,
+ sheetObject: props.sheetObject,
+ trackId: props.trackId,
+ },
+ ])
const isDragging = useDragKeyframe({
node,
diff --git a/theatre/studio/src/propEditors/simpleEditors/BooleanPropEditor.tsx b/theatre/studio/src/propEditors/simpleEditors/BooleanPropEditor.tsx
index 787cd44..ff460c1 100644
--- a/theatre/studio/src/propEditors/simpleEditors/BooleanPropEditor.tsx
+++ b/theatre/studio/src/propEditors/simpleEditors/BooleanPropEditor.tsx
@@ -6,12 +6,17 @@ import type {ISimplePropEditorReactProps} from './ISimplePropEditorReactProps'
const Input = styled(BasicCheckbox)`
margin-left: 6px;
+
+ :focus {
+ outline: 1px solid #555;
+ }
`
function BooleanPropEditor({
propConfig,
editingTools,
value,
+ autoFocus,
}: ISimplePropEditorReactProps) {
const onChange = useCallback(
(el: React.ChangeEvent) => {
@@ -20,7 +25,7 @@ function BooleanPropEditor({
[propConfig, editingTools],
)
- return
+ return
}
export default BooleanPropEditor
diff --git a/theatre/studio/src/propEditors/simpleEditors/ISimplePropEditorReactProps.ts b/theatre/studio/src/propEditors/simpleEditors/ISimplePropEditorReactProps.ts
index c49aa12..0cbe098 100644
--- a/theatre/studio/src/propEditors/simpleEditors/ISimplePropEditorReactProps.ts
+++ b/theatre/studio/src/propEditors/simpleEditors/ISimplePropEditorReactProps.ts
@@ -8,4 +8,5 @@ export type ISimplePropEditorReactProps<
propConfig: TPropTypeConfig
editingTools: IEditingTools
value: TPropTypeConfig['valueType']
+ autoFocus?: boolean
}
diff --git a/theatre/studio/src/propEditors/simpleEditors/NumberPropEditor.tsx b/theatre/studio/src/propEditors/simpleEditors/NumberPropEditor.tsx
index eff8b46..9682066 100644
--- a/theatre/studio/src/propEditors/simpleEditors/NumberPropEditor.tsx
+++ b/theatre/studio/src/propEditors/simpleEditors/NumberPropEditor.tsx
@@ -7,6 +7,7 @@ function NumberPropEditor({
propConfig,
editingTools,
value,
+ autoFocus,
}: ISimplePropEditorReactProps) {
const nudge = useCallback(
(params: {deltaX: number; deltaFraction: number; magnitude: number}) => {
@@ -23,6 +24,7 @@ function NumberPropEditor({
permanentlySetValue={editingTools.permanentlySetValue}
range={propConfig.range}
nudge={nudge}
+ autoFocus={autoFocus}
/>
)
}
diff --git a/theatre/studio/src/propEditors/simpleEditors/RgbaPropEditor.tsx b/theatre/studio/src/propEditors/simpleEditors/RgbaPropEditor.tsx
index ad98d9f..f9a5e26 100644
--- a/theatre/studio/src/propEditors/simpleEditors/RgbaPropEditor.tsx
+++ b/theatre/studio/src/propEditors/simpleEditors/RgbaPropEditor.tsx
@@ -63,6 +63,7 @@ const RgbaPopover = styled.div`
function RgbaPropEditor({
editingTools,
value,
+ autoFocus,
}: ISimplePropEditorReactProps) {
const containerRef = useRef(null!)
@@ -116,6 +117,7 @@ function RgbaPropEditor({
discardTemporaryValue={noop}
permanentlySetValue={onChange}
isValid={(v) => !!v.match(validHexRegExp)}
+ autoFocus={autoFocus}
/>
{popoverNode}
diff --git a/theatre/studio/src/propEditors/simpleEditors/StringLiteralPropEditor.tsx b/theatre/studio/src/propEditors/simpleEditors/StringLiteralPropEditor.tsx
index 4648a26..57356e7 100644
--- a/theatre/studio/src/propEditors/simpleEditors/StringLiteralPropEditor.tsx
+++ b/theatre/studio/src/propEditors/simpleEditors/StringLiteralPropEditor.tsx
@@ -8,6 +8,7 @@ function StringLiteralPropEditor({
propConfig,
editingTools,
value,
+ autoFocus,
}: ISimplePropEditorReactProps>) {
const onChange = useCallback(
(val: TLiteralOptions) => {
@@ -21,12 +22,14 @@ function StringLiteralPropEditor({
value={value}
onChange={onChange}
options={propConfig.valuesAndLabels}
+ autoFocus={autoFocus}
/>
) : (
)
}
diff --git a/theatre/studio/src/propEditors/simpleEditors/StringPropEditor.tsx b/theatre/studio/src/propEditors/simpleEditors/StringPropEditor.tsx
index f01d854..a72a104 100644
--- a/theatre/studio/src/propEditors/simpleEditors/StringPropEditor.tsx
+++ b/theatre/studio/src/propEditors/simpleEditors/StringPropEditor.tsx
@@ -6,6 +6,7 @@ import type {ISimplePropEditorReactProps} from './ISimplePropEditorReactProps'
function StringPropEditor({
editingTools,
value,
+ autoFocus,
}: ISimplePropEditorReactProps) {
return (
)
}
diff --git a/theatre/studio/src/uiComponents/form/BasicNumberInput.tsx b/theatre/studio/src/uiComponents/form/BasicNumberInput.tsx
index 6e1bb62..70feb91 100644
--- a/theatre/studio/src/uiComponents/form/BasicNumberInput.tsx
+++ b/theatre/studio/src/uiComponents/form/BasicNumberInput.tsx
@@ -115,6 +115,7 @@ const BasicNumberInput: React.FC<{
*/
onBlur?: () => void
nudge: BasicNumberInputNudgeFn
+ autoFocus?: boolean
}> = (propsA) => {
const [stateRef] = useRefAndState({mode: 'noFocus'})
const isValid = propsA.isValid ?? alwaysValid
@@ -307,6 +308,7 @@ const BasicNumberInput: React.FC<{
e.preventDefault()
e.stopPropagation()
}}
+ autoFocus={propsA.autoFocus}
/>
)
diff --git a/theatre/studio/src/uiComponents/form/BasicSelect.tsx b/theatre/studio/src/uiComponents/form/BasicSelect.tsx
index dde9280..abfec78 100644
--- a/theatre/studio/src/uiComponents/form/BasicSelect.tsx
+++ b/theatre/studio/src/uiComponents/form/BasicSelect.tsx
@@ -55,11 +55,13 @@ function BasicSelect({
onChange,
options,
className,
+ autoFocus,
}: {
value: TLiteralOptions
onChange: (val: TLiteralOptions) => void
options: Record
className?: string
+ autoFocus?: boolean
}) {
const _onChange = useCallback(
(el: React.ChangeEvent) => {
@@ -70,7 +72,12 @@ function BasicSelect({
return (
-