Feat/studio extension dropdowns (#379)

This commit is contained in:
Colin Duffy 2023-01-23 13:16:38 -08:00 committed by GitHub
parent 8470b67d4b
commit 3d343cc59e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 137 additions and 8 deletions

View file

@ -40,6 +40,32 @@ studio.extend({
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()

View file

@ -89,18 +89,34 @@ export type ToolConfigIcon = {
onClick: () => void
}
export type ToolConfigOption = {
value: string
label: string
svgSource: string
}
export type ToolConfigSwitch = {
type: 'Switch'
value: string
onChange: (value: string) => void
options: {
value: string
label: string
svgSource: string
}[]
options: ToolConfigOption[]
}
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>

View file

@ -5,6 +5,7 @@ import type {ToolConfig, ToolsetConfig} from '@theatre/studio/TheatreStudio'
import React from 'react'
import IconButton from './tools/IconButton'
import Switch from './tools/Switch'
import Downdown from './tools/Downdown'
const Toolset: React.FC<{
config: ToolsetConfig
@ -25,6 +26,7 @@ const toolByType: {
} = {
Icon: IconButton,
Switch: Switch,
Downdown: Downdown,
}
function getToolByType<Type extends ToolConfig['type']>(

View file

@ -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

View file

@ -13,7 +13,7 @@ const IconContainer = styled.div`
}
`
const IconButton: React.FC<{
const Switch: React.FC<{
config: ToolConfigSwitch
}> = ({config}) => {
return (
@ -29,4 +29,4 @@ const IconButton: React.FC<{
)
}
export default IconButton
export default Switch