Range indicator for the number editor
This commit is contained in:
parent
4e4452f0ad
commit
232ffa7836
4 changed files with 63 additions and 9 deletions
|
@ -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',
|
||||||
{
|
{
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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>
|
||||||
)
|
)
|
||||||
|
|
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue