Implemented types.stringLiteral(.., {as})
This commit is contained in:
parent
97ce94d52a
commit
a4f83e0f84
8 changed files with 180 additions and 34 deletions
|
@ -293,21 +293,33 @@ const editorSheetObjectConfig = types.compound({
|
||||||
showAxes: types.boolean(true),
|
showAxes: types.boolean(true),
|
||||||
showGrid: types.boolean(true),
|
showGrid: types.boolean(true),
|
||||||
showOverlayIcons: types.boolean(false),
|
showOverlayIcons: types.boolean(false),
|
||||||
transformControlsMode: types.stringLiteral('translate', {
|
transformControlsMode: types.stringLiteral(
|
||||||
translate: 'Translate',
|
'translate',
|
||||||
rotate: 'Rotate',
|
{
|
||||||
scale: 'Scale',
|
translate: 'Translate',
|
||||||
}),
|
rotate: 'Rotate',
|
||||||
transformControlsSpace: types.stringLiteral('world', {
|
scale: 'Scale',
|
||||||
local: 'Local',
|
},
|
||||||
world: 'World',
|
{as: 'switch'},
|
||||||
}),
|
),
|
||||||
viewportShading: types.stringLiteral('rendered', {
|
transformControlsSpace: types.stringLiteral(
|
||||||
flat: 'Flat',
|
'world',
|
||||||
rendered: 'Rendered',
|
{
|
||||||
solid: 'Solid',
|
local: 'Local',
|
||||||
wireframe: 'Wireframe',
|
world: 'World',
|
||||||
}),
|
},
|
||||||
|
{as: 'switch'},
|
||||||
|
),
|
||||||
|
viewportShading: types.stringLiteral(
|
||||||
|
'rendered',
|
||||||
|
{
|
||||||
|
flat: 'Flat',
|
||||||
|
rendered: 'Rendered',
|
||||||
|
solid: 'Solid',
|
||||||
|
wireframe: 'Wireframe',
|
||||||
|
},
|
||||||
|
{as: 'menu'},
|
||||||
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const bindToCanvas: BindFunction = ({
|
export const bindToCanvas: BindFunction = ({
|
||||||
|
|
|
@ -62,11 +62,13 @@ export interface PropTypeConfig_StringLiteral<T extends string>
|
||||||
type: 'stringLiteral'
|
type: 'stringLiteral'
|
||||||
default: T
|
default: T
|
||||||
options: Record<T, string>
|
options: Record<T, string>
|
||||||
|
as: 'menu' | 'switch'
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stringLiteral<Opts extends {[key in string]: string}>(
|
export function stringLiteral<Opts extends {[key in string]: string}>(
|
||||||
defaultValue: Extract<keyof Opts, string>,
|
defaultValue: Extract<keyof Opts, string>,
|
||||||
options: Opts,
|
options: Opts,
|
||||||
|
extras?: {as?: 'menu' | 'switch'},
|
||||||
): PropTypeConfig_StringLiteral<Extract<keyof Opts, string>> {
|
): PropTypeConfig_StringLiteral<Extract<keyof Opts, string>> {
|
||||||
return {
|
return {
|
||||||
type: 'stringLiteral',
|
type: 'stringLiteral',
|
||||||
|
@ -74,6 +76,7 @@ export function stringLiteral<Opts extends {[key in string]: string}>(
|
||||||
options: {...options},
|
options: {...options},
|
||||||
[s]: 'TheatrePropType',
|
[s]: 'TheatrePropType',
|
||||||
valueType: null as $IntentionalAny,
|
valueType: null as $IntentionalAny,
|
||||||
|
as: extras?.as ?? 'menu',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,11 @@ const Label = styled.div`
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const Body = styled.div`
|
const Body = styled.label`
|
||||||
cursor: ew-resize;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
width: 140px;
|
width: 140px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
|
@ -76,12 +78,6 @@ const BooleanPropEditor: React.FC<{
|
||||||
{stuff.controlIndicators}
|
{stuff.controlIndicators}
|
||||||
<Body>
|
<Body>
|
||||||
<input type="checkbox" checked={stuff.value} onChange={onChange} />
|
<input type="checkbox" checked={stuff.value} onChange={onChange} />
|
||||||
{/* <BasicNumberEditor
|
|
||||||
value={stuff.value}
|
|
||||||
temporarilySetValue={stuff.temporarilySetValue}
|
|
||||||
discardTemporaryValue={stuff.discardTemporaryValue}
|
|
||||||
permenantlySetValue={stuff.permenantlySetValue}
|
|
||||||
/> */}
|
|
||||||
</Body>
|
</Body>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type {PropTypeConfig_Number} from '@theatre/core/propTypes'
|
import type {PropTypeConfig_Number} from '@theatre/core/propTypes'
|
||||||
import type SheetObject from '@theatre/core/sheetObjects/SheetObject'
|
import type SheetObject from '@theatre/core/sheetObjects/SheetObject'
|
||||||
import BasicNumberEditor from '@theatre/studio/uiComponents/BasicNumberEditor'
|
import BasicNumberEditor from '@theatre/studio/uiComponents/form/BasicNumberEditor'
|
||||||
import useContextMenu from '@theatre/studio/uiComponents/simpleContextMenu/useContextMenu'
|
import useContextMenu from '@theatre/studio/uiComponents/simpleContextMenu/useContextMenu'
|
||||||
import useRefAndState from '@theatre/studio/utils/useRefAndState'
|
import useRefAndState from '@theatre/studio/utils/useRefAndState'
|
||||||
import {getPointerParts} from '@theatre/dataverse'
|
import {getPointerParts} from '@theatre/dataverse'
|
||||||
|
|
|
@ -11,6 +11,8 @@ import {
|
||||||
useEditingToolsForPrimitiveProp,
|
useEditingToolsForPrimitiveProp,
|
||||||
} from './useEditingToolsForPrimitiveProp'
|
} from './useEditingToolsForPrimitiveProp'
|
||||||
import type {$IntentionalAny} from '@theatre/shared/utils/types'
|
import type {$IntentionalAny} from '@theatre/shared/utils/types'
|
||||||
|
import BasicSwitchEditor from '@theatre/studio/uiComponents/form/BasicSwitchEditor'
|
||||||
|
import BasicSelectEditor from '@theatre/studio/uiComponents/form/BasicSelectEditor'
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -62,8 +64,8 @@ const StringLiteralPropEditor: React.FC<{
|
||||||
})
|
})
|
||||||
|
|
||||||
const onChange = useCallback(
|
const onChange = useCallback(
|
||||||
(el: React.ChangeEvent<HTMLSelectElement>) => {
|
(val: string) => {
|
||||||
stuff.permenantlySetValue(String(el.target.value))
|
stuff.permenantlySetValue(val)
|
||||||
},
|
},
|
||||||
[propConfig, pointerToProp, obj],
|
[propConfig, pointerToProp, obj],
|
||||||
)
|
)
|
||||||
|
@ -76,13 +78,19 @@ const StringLiteralPropEditor: React.FC<{
|
||||||
<Label ref={labelRef}>{label}</Label>
|
<Label ref={labelRef}>{label}</Label>
|
||||||
{stuff.controlIndicators}
|
{stuff.controlIndicators}
|
||||||
<Body>
|
<Body>
|
||||||
<select value={stuff.value} onChange={onChange}>
|
{propConfig.as === 'menu' ? (
|
||||||
{Object.keys(propConfig.options).map((key, i) => (
|
<BasicSelectEditor
|
||||||
<option key={'option-' + i} value={key}>
|
value={stuff.value}
|
||||||
{propConfig.options[key]}
|
onChange={onChange}
|
||||||
</option>
|
options={propConfig.options}
|
||||||
))}
|
/>
|
||||||
</select>
|
) : (
|
||||||
|
<BasicSwitchEditor
|
||||||
|
value={stuff.value}
|
||||||
|
onChange={onChange}
|
||||||
|
options={propConfig.options}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Body>
|
</Body>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {isInteger, round} from 'lodash-es'
|
||||||
import {darken, lighten} from 'polished'
|
import {darken, lighten} from 'polished'
|
||||||
import React, {useMemo, useRef, useState} from 'react'
|
import React, {useMemo, useRef, useState} from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import DraggableArea from './DraggableArea'
|
import DraggableArea from '@theatre/studio/uiComponents/DraggableArea'
|
||||||
|
|
||||||
type IMode = IState['mode']
|
type IMode = IState['mode']
|
||||||
|
|
48
theatre/studio/src/uiComponents/form/BasicSelectEditor.tsx
Normal file
48
theatre/studio/src/uiComponents/form/BasicSelectEditor.tsx
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import {theme} from '@theatre/studio/css'
|
||||||
|
import {darken, lighten} from 'polished'
|
||||||
|
import React, {useCallback} from 'react'
|
||||||
|
import styled from 'styled-components'
|
||||||
|
|
||||||
|
const Select = styled.select`
|
||||||
|
background: transparent;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
padding: 1px 6px;
|
||||||
|
font: inherit;
|
||||||
|
outline: none;
|
||||||
|
text-align: left;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 4px);
|
||||||
|
border-radius: 2px;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background: ${darken(0.9, theme.panel.bg)};
|
||||||
|
border: 1px solid ${lighten(0.1, theme.panel.bg)};
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const BasicSelectEditor: React.FC<{
|
||||||
|
value: string
|
||||||
|
onChange: (val: string) => void
|
||||||
|
options: Record<string, string>
|
||||||
|
}> = ({value, onChange, options}) => {
|
||||||
|
const _onChange = useCallback(
|
||||||
|
(el: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
|
onChange(String(el.target.value))
|
||||||
|
},
|
||||||
|
[onChange],
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
<Select value={value} onChange={_onChange}>
|
||||||
|
{Object.keys(options).map((key, i) => (
|
||||||
|
<option key={'option-' + i} value={key}>
|
||||||
|
{options[key]}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BasicSelectEditor
|
79
theatre/studio/src/uiComponents/form/BasicSwitchEditor.tsx
Normal file
79
theatre/studio/src/uiComponents/form/BasicSwitchEditor.tsx
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import {darken} from 'polished'
|
||||||
|
import React, {useCallback} from 'react'
|
||||||
|
import styled from 'styled-components'
|
||||||
|
|
||||||
|
const Container = styled.form`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: stretch;
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 24px;
|
||||||
|
`
|
||||||
|
const Label = styled.label`
|
||||||
|
padding: 0 0.5em;
|
||||||
|
background: transparent;
|
||||||
|
/* background: #373748; */
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #a7a7a7;
|
||||||
|
border: 1px solid #1c2123;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-right-width: 0px;
|
||||||
|
|
||||||
|
& + &:last-child {
|
||||||
|
border-right-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
${Container}:hover > & {
|
||||||
|
/* background-color: #373748; */
|
||||||
|
/* color: ${darken(0.1, 'white')}; */
|
||||||
|
}
|
||||||
|
|
||||||
|
&&:hover {
|
||||||
|
background-color: #464654;
|
||||||
|
}
|
||||||
|
|
||||||
|
&&[data-checked='true'] {
|
||||||
|
color: white;
|
||||||
|
background: #3f3f4c;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const Input = styled.input`
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
`
|
||||||
|
|
||||||
|
const BasicSwitchEditor: React.FC<{
|
||||||
|
value: string
|
||||||
|
onChange: (val: string) => void
|
||||||
|
options: Record<string, string>
|
||||||
|
}> = ({value, onChange, options}) => {
|
||||||
|
const _onChange = useCallback(
|
||||||
|
(el: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
onChange(String(el.target.value))
|
||||||
|
},
|
||||||
|
[onChange],
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
<Container role="radiogroup">
|
||||||
|
{Object.keys(options).map((key, i) => (
|
||||||
|
<Label key={'label-' + i} data-checked={value === key}>
|
||||||
|
{options[key]}
|
||||||
|
<Input
|
||||||
|
type="radio"
|
||||||
|
checked={value === key}
|
||||||
|
value={key}
|
||||||
|
onChange={_onChange}
|
||||||
|
name="switchbox"
|
||||||
|
/>
|
||||||
|
</Label>
|
||||||
|
))}
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BasicSwitchEditor
|
Loading…
Reference in a new issue