Range indicator for the number editor

This commit is contained in:
Aria Minaei 2021-07-16 11:08:09 +02:00
parent 4e4452f0ad
commit 232ffa7836
4 changed files with 63 additions and 9 deletions

View file

@ -295,7 +295,10 @@ const editorSheetObjectConfig = types.compound({
showAxes: types.boolean(true, {label: 'Axes'}), showAxes: types.boolean(true, {label: 'Axes'}),
showGrid: types.boolean(true, {label: 'Grid'}), showGrid: types.boolean(true, {label: 'Grid'}),
showOverlayIcons: types.boolean(false, {label: 'Overlay Icons'}), showOverlayIcons: types.boolean(false, {label: 'Overlay Icons'}),
resolution: types.number(1440, {label: 'Resolution'}), resolution: types.number(1440, {
label: 'Resolution',
range: [0, 1000],
}),
shading: types.stringLiteral( shading: types.stringLiteral(
'rendered', 'rendered',
{ {

View file

@ -12,15 +12,12 @@ interface IBasePropType<ValueType> {
export interface PropTypeConfig_Number extends IBasePropType<number> { export interface PropTypeConfig_Number extends IBasePropType<number> {
type: 'number' type: 'number'
default: number default: number
min?: number range?: [min: number, max: number]
max?: number
step?: number
} }
export const number = ( export const number = (
defaultValue: number, defaultValue: number,
opts?: Pick<PropTypeConfig_Number, 'min' | 'max' | 'step'> & opts?: Pick<PropTypeConfig_Number, 'range'> & PropTypeConfigExtras,
PropTypeConfigExtras,
): PropTypeConfig_Number => { ): PropTypeConfig_Number => {
return { return {
type: 'number', type: 'number',

View file

@ -19,6 +19,7 @@ const NumberPropEditor: React.FC<{
temporarilySetValue={stuff.temporarilySetValue} temporarilySetValue={stuff.temporarilySetValue}
discardTemporaryValue={stuff.discardTemporaryValue} discardTemporaryValue={stuff.discardTemporaryValue}
permenantlySetValue={stuff.permenantlySetValue} permenantlySetValue={stuff.permenantlySetValue}
range={propConfig.range}
/> />
</SingleRowPropEditor> </SingleRowPropEditor>
) )

View file

@ -1,5 +1,5 @@
import {theme} from '@theatre/studio/css' import {theme} from '@theatre/studio/css'
import {isInteger, round} from 'lodash-es' import {clamp, 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'
@ -10,6 +10,31 @@ type IMode = IState['mode']
const Container = styled.div` const Container = styled.div`
height: 100%; height: 100%;
width: 100%; width: 100%;
position: relative;
z-index: 0;
box-sizing: border-box;
&:after {
position: absolute;
inset: 1px 0 2px;
display: block;
content: ' ';
background-color: #2525252b;
border: 1px solid #1c2123;
z-index: -2;
box-sizing: border-box;
border-radius: 1px;
}
&:hover,
&.dragging,
&.editingViaKeyboard {
&:after {
background-color: #10101042;
/* background-color: ${darken(0.2, theme.panel.bg)}; */
border-color: #00000059;
}
}
` `
const Input = styled.input` const Input = styled.input`
@ -25,18 +50,32 @@ const Input = styled.input`
height: calc(100% - 4px); height: calc(100% - 4px);
border-radius: 2px; border-radius: 2px;
&:hover, /* &:hover,
&:focus, &:focus,
${Container}.dragging > & { ${Container}.dragging > & {
background: ${darken(0.9, theme.panel.bg)}; background: ${darken(0.9, theme.panel.bg)};
border: 1px solid ${lighten(0.1, theme.panel.bg)}; border: 1px solid ${lighten(0.1, theme.panel.bg)};
} } */
&:focus { &:focus {
cursor: text; cursor: text;
} }
` `
const FillIndicator = styled.div`
position: absolute;
inset: 3px 2px 4px;
transform: scale(var(--percentage), 1);
transform-origin: top left;
background-color: #2d5561;
z-index: -1;
border-radius: 2px;
${Container}.dragging &, ${Container}.noFocus:hover & {
background-color: #338198;
}
`
function isValueAcceptable(s: string) { function isValueAcceptable(s: string) {
const v = parseFloat(s) const v = parseFloat(s)
return !isNaN(v) return !isNaN(v)
@ -66,6 +105,7 @@ const BasicNumberInput: React.FC<{
discardTemporaryValue: () => void discardTemporaryValue: () => void
permenantlySetValue: (v: number) => void permenantlySetValue: (v: number) => void
className?: string className?: string
range?: [min: number, max: number]
}> = (propsA) => { }> = (propsA) => {
const [stateA, setState] = useState<IState>({mode: 'noFocus'}) const [stateA, setState] = useState<IState>({mode: 'noFocus'})
@ -238,6 +278,18 @@ const BasicNumberInput: React.FC<{
/> />
) )
const {range} = propsA
const num = parseFloat(value)
const fillIndicator = range ? (
<FillIndicator
style={{
// @ts-ignore
'--percentage': clamp((num - range[0]) / (range[1] - range[0]), 0, 1),
}}
/>
) : null
return ( return (
<Container className={propsA.className + ' ' + refs.current.state.mode}> <Container className={propsA.className + ' ' + refs.current.state.mode}>
<DraggableArea <DraggableArea
@ -250,6 +302,7 @@ const BasicNumberInput: React.FC<{
> >
{theInput} {theInput}
</DraggableArea> </DraggableArea>
{fillIndicator}
</Container> </Container>
) )
} }