Change DeterminePropEditor... to take an array
- Add autoFocus to prop inputs
This commit is contained in:
parent
38e6a4ba36
commit
047f01bb45
17 changed files with 148 additions and 122 deletions
|
@ -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)
|
||||
|
|
|
@ -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 (
|
||||
<>
|
||||
<SingleKeyframePropLabel>
|
||||
{p.sheetObject.address.objectKey}
|
||||
</SingleKeyframePropLabel>
|
||||
<IndentedThing>
|
||||
<Indent>
|
||||
{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') {
|
||||
|
@ -66,19 +70,31 @@ export function DeterminePropEditorForKeyframeTree(p: EditingOptionsTree) {
|
|||
return (
|
||||
<>
|
||||
<SingleKeyframePropLabel>{label}</SingleKeyframePropLabel>
|
||||
<IndentedThing>
|
||||
<Indent>
|
||||
{p.children.map((c, i) => (
|
||||
<DeterminePropEditorForKeyframeTree key={i} {...c} />
|
||||
<DeterminePropEditorForKeyframeTree
|
||||
key={i}
|
||||
{...c}
|
||||
autoFocusInput={p.autoFocusInput && i === 0}
|
||||
/>
|
||||
))}
|
||||
</IndentedThing>
|
||||
</Indent>
|
||||
</>
|
||||
)
|
||||
} 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 editingTools = useEditingToolsForKeyframeEditorPopover(p)
|
||||
|
||||
|
@ -92,12 +108,14 @@ function BeepBoop(p: PrimitivePropEditingOptions) {
|
|||
return (
|
||||
<SingleKeyframePropEditorContainer>
|
||||
<SingleKeyframePropLabel>{label}</SingleKeyframePropLabel>
|
||||
<SingleKeyframeSimplePropEditor
|
||||
SimpleEditorComponent={PropEditor}
|
||||
propConfig={p.propConfig}
|
||||
<SingleKeyframeSimplePropEditorContainer>
|
||||
<PropEditor
|
||||
editingTools={editingTools}
|
||||
keyframeValue={p.keyframe.value}
|
||||
propConfig={p.propConfig}
|
||||
value={p.keyframe.value}
|
||||
autoFocus={p.autoFocusInput}
|
||||
/>
|
||||
</SingleKeyframeSimplePropEditorContainer>
|
||||
</SingleKeyframePropEditorContainer>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -102,14 +102,16 @@ const SingleKeyframeDot: React.VFC<ISingleKeyframeDotProps> = (props) => {
|
|||
|
||||
const [contextMenu] = useSingleKeyframeContextMenu(node, logger, props)
|
||||
const [inlineEditorPopover, openEditor, _, isInlineEditorPopoverOpen] =
|
||||
useKeyframeInlineEditorPopover({
|
||||
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!)
|
||||
|
@ -132,8 +134,7 @@ const SingleKeyframeDot: React.VFC<ISingleKeyframeDotProps> = (props) => {
|
|||
{contextMenu}
|
||||
</>
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export default SingleKeyframeDot
|
||||
|
||||
|
|
|
@ -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'}, () => (
|
||||
<BasicPopover showPopoverEdgeTriangle>
|
||||
{props === null ? undefined : (
|
||||
<DeterminePropEditorForKeyframeTree {...props} />
|
||||
)}
|
||||
{!Array.isArray(props)
|
||||
? undefined
|
||||
: props.map((prop, i) => (
|
||||
<DeterminePropEditorForKeyframeTree
|
||||
key={i}
|
||||
{...prop}
|
||||
autoFocusInput={i === 0}
|
||||
/>
|
||||
))}
|
||||
</BasicPopover>
|
||||
))
|
||||
}
|
||||
|
@ -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<UnknownValidCompoundProps>
|
||||
pathToProp: PathToProp
|
||||
|
|
|
@ -71,13 +71,16 @@ const GraphEditorDotNonScalar: React.VFC<IProps> = (props) => {
|
|||
const curValue = props.which === 'left' ? 0 : 1
|
||||
|
||||
const [inlineEditorPopover, openEditor, _, _isInlineEditorPopoverOpen] =
|
||||
useKeyframeInlineEditorPopover({
|
||||
useKeyframeInlineEditorPopover([
|
||||
{
|
||||
type: 'primitiveProp',
|
||||
keyframe: props.keyframe,
|
||||
pathToProp: props.pathToProp,
|
||||
propConf: props.propConfig,
|
||||
propConfig: props.propConfig,
|
||||
sheetObject: props.sheetObject,
|
||||
trackId: props.trackId,
|
||||
})
|
||||
},
|
||||
])
|
||||
|
||||
const isDragging = useDragKeyframe({
|
||||
node,
|
||||
|
|
|
@ -71,13 +71,16 @@ const GraphEditorDotScalar: React.VFC<IProps> = (props) => {
|
|||
|
||||
const cyInExtremumSpace = props.extremumSpace.fromValueSpace(curValue)
|
||||
const [inlineEditorPopover, openEditor, _, _isInlineEditorPopoverOpen] =
|
||||
useKeyframeInlineEditorPopover({
|
||||
useKeyframeInlineEditorPopover([
|
||||
{
|
||||
type: 'primitiveProp',
|
||||
keyframe: props.keyframe,
|
||||
pathToProp: props.pathToProp,
|
||||
propConf: props.propConfig,
|
||||
propConfig: props.propConfig,
|
||||
sheetObject: props.sheetObject,
|
||||
trackId: props.trackId,
|
||||
})
|
||||
},
|
||||
])
|
||||
|
||||
const isDragging = useDragKeyframe({
|
||||
node,
|
||||
|
|
|
@ -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<PropTypeConfig_Boolean>) {
|
||||
const onChange = useCallback(
|
||||
(el: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
@ -20,7 +25,7 @@ function BooleanPropEditor({
|
|||
[propConfig, editingTools],
|
||||
)
|
||||
|
||||
return <Input checked={value} onChange={onChange} />
|
||||
return <Input checked={value} onChange={onChange} autoFocus={autoFocus} />
|
||||
}
|
||||
|
||||
export default BooleanPropEditor
|
||||
|
|
|
@ -8,4 +8,5 @@ export type ISimplePropEditorReactProps<
|
|||
propConfig: TPropTypeConfig
|
||||
editingTools: IEditingTools<TPropTypeConfig['valueType']>
|
||||
value: TPropTypeConfig['valueType']
|
||||
autoFocus?: boolean
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ function NumberPropEditor({
|
|||
propConfig,
|
||||
editingTools,
|
||||
value,
|
||||
autoFocus,
|
||||
}: ISimplePropEditorReactProps<PropTypeConfig_Number>) {
|
||||
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}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ const RgbaPopover = styled.div`
|
|||
function RgbaPropEditor({
|
||||
editingTools,
|
||||
value,
|
||||
autoFocus,
|
||||
}: ISimplePropEditorReactProps<PropTypeConfig_Rgba>) {
|
||||
const containerRef = useRef<HTMLDivElement>(null!)
|
||||
|
||||
|
@ -116,6 +117,7 @@ function RgbaPropEditor({
|
|||
discardTemporaryValue={noop}
|
||||
permanentlySetValue={onChange}
|
||||
isValid={(v) => !!v.match(validHexRegExp)}
|
||||
autoFocus={autoFocus}
|
||||
/>
|
||||
</RowContainer>
|
||||
{popoverNode}
|
||||
|
|
|
@ -8,6 +8,7 @@ function StringLiteralPropEditor<TLiteralOptions extends string>({
|
|||
propConfig,
|
||||
editingTools,
|
||||
value,
|
||||
autoFocus,
|
||||
}: ISimplePropEditorReactProps<PropTypeConfig_StringLiteral<TLiteralOptions>>) {
|
||||
const onChange = useCallback(
|
||||
(val: TLiteralOptions) => {
|
||||
|
@ -21,12 +22,14 @@ function StringLiteralPropEditor<TLiteralOptions extends string>({
|
|||
value={value}
|
||||
onChange={onChange}
|
||||
options={propConfig.valuesAndLabels}
|
||||
autoFocus={autoFocus}
|
||||
/>
|
||||
) : (
|
||||
<BasicSwitch
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
options={propConfig.valuesAndLabels}
|
||||
autoFocus={autoFocus}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import type {ISimplePropEditorReactProps} from './ISimplePropEditorReactProps'
|
|||
function StringPropEditor({
|
||||
editingTools,
|
||||
value,
|
||||
autoFocus,
|
||||
}: ISimplePropEditorReactProps<PropTypeConfig_String>) {
|
||||
return (
|
||||
<BasicStringInput
|
||||
|
@ -13,6 +14,7 @@ function StringPropEditor({
|
|||
temporarilySetValue={editingTools.temporarilySetValue}
|
||||
discardTemporaryValue={editingTools.discardTemporaryValue}
|
||||
permanentlySetValue={editingTools.permanentlySetValue}
|
||||
autoFocus={autoFocus}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -115,6 +115,7 @@ const BasicNumberInput: React.FC<{
|
|||
*/
|
||||
onBlur?: () => void
|
||||
nudge: BasicNumberInputNudgeFn
|
||||
autoFocus?: boolean
|
||||
}> = (propsA) => {
|
||||
const [stateRef] = useRefAndState<IState>({mode: 'noFocus'})
|
||||
const isValid = propsA.isValid ?? alwaysValid
|
||||
|
@ -307,6 +308,7 @@ const BasicNumberInput: React.FC<{
|
|||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}}
|
||||
autoFocus={propsA.autoFocus}
|
||||
/>
|
||||
)
|
||||
|
||||
|
|
|
@ -55,11 +55,13 @@ function BasicSelect<TLiteralOptions extends string>({
|
|||
onChange,
|
||||
options,
|
||||
className,
|
||||
autoFocus,
|
||||
}: {
|
||||
value: TLiteralOptions
|
||||
onChange: (val: TLiteralOptions) => void
|
||||
options: Record<TLiteralOptions, string>
|
||||
className?: string
|
||||
autoFocus?: boolean
|
||||
}) {
|
||||
const _onChange = useCallback(
|
||||
(el: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
|
@ -70,7 +72,12 @@ function BasicSelect<TLiteralOptions extends string>({
|
|||
|
||||
return (
|
||||
<Container>
|
||||
<Select className={className} value={value} onChange={_onChange}>
|
||||
<Select
|
||||
className={className}
|
||||
value={value}
|
||||
onChange={_onChange}
|
||||
autoFocus={autoFocus}
|
||||
>
|
||||
{Object.keys(options).map((key, i) => (
|
||||
<option key={'option-' + i} value={key}>
|
||||
{options[key]}
|
||||
|
|
|
@ -64,6 +64,7 @@ const BasicStringInput: React.FC<{
|
|||
* before this, so use this for UI purposes such as closing a popover.
|
||||
*/
|
||||
onBlur?: () => void
|
||||
autoFocus?: boolean
|
||||
}> = (props) => {
|
||||
const [stateRef] = useRefAndState<IState>({mode: 'noFocus'})
|
||||
const isValid = props.isValid ?? alwaysValid
|
||||
|
@ -195,6 +196,7 @@ const BasicStringInput: React.FC<{
|
|||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}}
|
||||
autoFocus={props.autoFocus}
|
||||
/>
|
||||
)
|
||||
|
||||
|
|
|
@ -56,10 +56,12 @@ function BasicSwitch<TLiteralOptions extends string>({
|
|||
value,
|
||||
onChange,
|
||||
options,
|
||||
autoFocus,
|
||||
}: {
|
||||
value: TLiteralOptions
|
||||
onChange: (val: TLiteralOptions) => void
|
||||
options: Record<TLiteralOptions, string>
|
||||
autoFocus?: boolean
|
||||
}) {
|
||||
const _onChange = useCallback(
|
||||
(el: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
@ -78,6 +80,7 @@ function BasicSwitch<TLiteralOptions extends string>({
|
|||
value={key}
|
||||
onChange={_onChange}
|
||||
name="switchbox"
|
||||
autoFocus={autoFocus}
|
||||
/>
|
||||
</Label>
|
||||
))}
|
||||
|
|
Loading…
Reference in a new issue