Feat/studio extension dropdowns (#379)
This commit is contained in:
parent
8470b67d4b
commit
3d343cc59e
5 changed files with 137 additions and 8 deletions
|
@ -40,6 +40,32 @@ studio.extend({
|
||||||
studio.createPane('example')
|
studio.createPane('example')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'Downdown',
|
||||||
|
svgSource: '🫠',
|
||||||
|
onChange: (value: any) => {
|
||||||
|
console.log('Change:', value)
|
||||||
|
},
|
||||||
|
selectable: false,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'Option 1',
|
||||||
|
value: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Option 2',
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Option 3',
|
||||||
|
value: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Option 4',
|
||||||
|
value: 3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
updateToolset()
|
updateToolset()
|
||||||
|
|
|
@ -89,18 +89,34 @@ export type ToolConfigIcon = {
|
||||||
onClick: () => void
|
onClick: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ToolConfigOption = {
|
||||||
|
value: string
|
||||||
|
label: string
|
||||||
|
svgSource: string
|
||||||
|
}
|
||||||
|
|
||||||
export type ToolConfigSwitch = {
|
export type ToolConfigSwitch = {
|
||||||
type: 'Switch'
|
type: 'Switch'
|
||||||
value: string
|
value: string
|
||||||
onChange: (value: string) => void
|
onChange: (value: string) => void
|
||||||
options: {
|
options: ToolConfigOption[]
|
||||||
value: string
|
|
||||||
label: string
|
|
||||||
svgSource: string
|
|
||||||
}[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ToolConfig = ToolConfigIcon | ToolConfigSwitch
|
export type ToolConfigDowndownOption = {
|
||||||
|
label: string
|
||||||
|
value: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ToolConfigDowndown = {
|
||||||
|
type: 'Downdown'
|
||||||
|
index?: number
|
||||||
|
svgSource: string
|
||||||
|
selectable: boolean
|
||||||
|
onChange: (option: ToolConfigDowndownOption | null) => void
|
||||||
|
options: ToolConfigDowndownOption[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ToolConfig = ToolConfigIcon | ToolConfigSwitch | ToolConfigDowndown
|
||||||
|
|
||||||
export type ToolsetConfig = Array<ToolConfig>
|
export type ToolsetConfig = Array<ToolConfig>
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import type {ToolConfig, ToolsetConfig} from '@theatre/studio/TheatreStudio'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import IconButton from './tools/IconButton'
|
import IconButton from './tools/IconButton'
|
||||||
import Switch from './tools/Switch'
|
import Switch from './tools/Switch'
|
||||||
|
import Downdown from './tools/Downdown'
|
||||||
|
|
||||||
const Toolset: React.FC<{
|
const Toolset: React.FC<{
|
||||||
config: ToolsetConfig
|
config: ToolsetConfig
|
||||||
|
@ -25,6 +26,7 @@ const toolByType: {
|
||||||
} = {
|
} = {
|
||||||
Icon: IconButton,
|
Icon: IconButton,
|
||||||
Switch: Switch,
|
Switch: Switch,
|
||||||
|
Downdown: Downdown,
|
||||||
}
|
}
|
||||||
|
|
||||||
function getToolByType<Type extends ToolConfig['type']>(
|
function getToolByType<Type extends ToolConfig['type']>(
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
import React, {useState} from 'react'
|
||||||
|
import styled from 'styled-components'
|
||||||
|
import {pointerEventsAutoInNormalMode} from '@theatre/studio/css'
|
||||||
|
import type {
|
||||||
|
ToolConfigDowndown,
|
||||||
|
ToolConfigDowndownOption,
|
||||||
|
} from '@theatre/studio/TheatreStudio'
|
||||||
|
import ToolbarIconButton from '@theatre/studio/uiComponents/toolbar/ToolbarIconButton'
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
${pointerEventsAutoInNormalMode};
|
||||||
|
& > svg {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const DropdownItem = styled.li`
|
||||||
|
width: max-content;
|
||||||
|
& > button {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
padding: 0 9px;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
& > .selected {
|
||||||
|
border-color: white;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const Downdown: React.FC<{
|
||||||
|
config: ToolConfigDowndown
|
||||||
|
}> = ({config}) => {
|
||||||
|
const [currentIndex, setCurrentIndex] = useState(
|
||||||
|
config.index !== undefined ? config.index : -1,
|
||||||
|
)
|
||||||
|
const [showOptions, setShowOptions] = useState(false)
|
||||||
|
|
||||||
|
const toggleOptions = () => {
|
||||||
|
setShowOptions(!showOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectOption = (index: number, option: ToolConfigDowndownOption) => {
|
||||||
|
if (config.selectable) {
|
||||||
|
if (index !== currentIndex) {
|
||||||
|
config.onChange(option.value)
|
||||||
|
setCurrentIndex(index)
|
||||||
|
} else {
|
||||||
|
config.onChange(null)
|
||||||
|
setCurrentIndex(-1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config.onChange(option.value)
|
||||||
|
}
|
||||||
|
setShowOptions(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<ToolbarIconButton onClick={toggleOptions}>
|
||||||
|
{config.svgSource}
|
||||||
|
</ToolbarIconButton>
|
||||||
|
{showOptions && (
|
||||||
|
<ul>
|
||||||
|
{config.options.map(
|
||||||
|
(option: ToolConfigDowndownOption, index: number) => (
|
||||||
|
<DropdownItem key={index}>
|
||||||
|
<ToolbarIconButton
|
||||||
|
onClick={() => selectOption(index, option)}
|
||||||
|
className={index === currentIndex ? 'selected' : ''}
|
||||||
|
>
|
||||||
|
{option.label}
|
||||||
|
</ToolbarIconButton>
|
||||||
|
</DropdownItem>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Downdown
|
|
@ -13,7 +13,7 @@ const IconContainer = styled.div`
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const IconButton: React.FC<{
|
const Switch: React.FC<{
|
||||||
config: ToolConfigSwitch
|
config: ToolConfigSwitch
|
||||||
}> = ({config}) => {
|
}> = ({config}) => {
|
||||||
return (
|
return (
|
||||||
|
@ -29,4 +29,4 @@ const IconButton: React.FC<{
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default IconButton
|
export default Switch
|
||||||
|
|
Loading…
Reference in a new issue