From 3d343cc59e9be7693ba491c070110078a5287cc3 Mon Sep 17 00:00:00 2001 From: Colin Duffy Date: Mon, 23 Jan 2023 13:16:38 -0800 Subject: [PATCH] Feat/studio extension dropdowns (#379) --- .../shared/hello-world-extension/index.tsx | 26 ++++++ theatre/studio/src/TheatreStudio.ts | 28 ++++-- .../src/toolbars/ExtensionToolbar/Toolset.tsx | 2 + .../ExtensionToolbar/tools/Downdown.tsx | 85 +++++++++++++++++++ .../ExtensionToolbar/tools/Switch.tsx | 4 +- 5 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 theatre/studio/src/toolbars/ExtensionToolbar/tools/Downdown.tsx diff --git a/packages/playground/src/shared/hello-world-extension/index.tsx b/packages/playground/src/shared/hello-world-extension/index.tsx index 752b0e5..b9ffc48 100644 --- a/packages/playground/src/shared/hello-world-extension/index.tsx +++ b/packages/playground/src/shared/hello-world-extension/index.tsx @@ -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() diff --git a/theatre/studio/src/TheatreStudio.ts b/theatre/studio/src/TheatreStudio.ts index 7a2d741..b7f5f25 100644 --- a/theatre/studio/src/TheatreStudio.ts +++ b/theatre/studio/src/TheatreStudio.ts @@ -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 diff --git a/theatre/studio/src/toolbars/ExtensionToolbar/Toolset.tsx b/theatre/studio/src/toolbars/ExtensionToolbar/Toolset.tsx index b99fc9c..755cc70 100644 --- a/theatre/studio/src/toolbars/ExtensionToolbar/Toolset.tsx +++ b/theatre/studio/src/toolbars/ExtensionToolbar/Toolset.tsx @@ -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( diff --git a/theatre/studio/src/toolbars/ExtensionToolbar/tools/Downdown.tsx b/theatre/studio/src/toolbars/ExtensionToolbar/tools/Downdown.tsx new file mode 100644 index 0000000..d47117e --- /dev/null +++ b/theatre/studio/src/toolbars/ExtensionToolbar/tools/Downdown.tsx @@ -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 ( + + + {config.svgSource} + + {showOptions && ( +
    + {config.options.map( + (option: ToolConfigDowndownOption, index: number) => ( + + selectOption(index, option)} + className={index === currentIndex ? 'selected' : ''} + > + {option.label} + + + ), + )} +
+ )} +
+ ) +} + +export default Downdown diff --git a/theatre/studio/src/toolbars/ExtensionToolbar/tools/Switch.tsx b/theatre/studio/src/toolbars/ExtensionToolbar/tools/Switch.tsx index bcdd993..b97b998 100644 --- a/theatre/studio/src/toolbars/ExtensionToolbar/tools/Switch.tsx +++ b/theatre/studio/src/toolbars/ExtensionToolbar/tools/Switch.tsx @@ -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