From 0fb86de9dbc656b478931cffef4e3db0d078ac4b Mon Sep 17 00:00:00 2001 From: Sean Parsons Date: Fri, 25 Oct 2024 12:44:59 +0100 Subject: [PATCH 1/2] feature(inspector) Increment/Decrement Fractional Grid Tracks - Added `isFR` utility function. - Modified `GridExpressionInput.onKeyDown` to handle arrow up and down but only for fractional values. --- .../components/inspector/common/css-utils.ts | 4 + .../uuiui/inputs/grid-expression-input.tsx | 76 +++++++++++++------ 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/editor/src/components/inspector/common/css-utils.ts b/editor/src/components/inspector/common/css-utils.ts index eb74150ed104..04ffa431427d 100644 --- a/editor/src/components/inspector/common/css-utils.ts +++ b/editor/src/components/inspector/common/css-utils.ts @@ -574,6 +574,10 @@ const CSSNumberUnits: Array = [ '%', ] +export function isFR(unit: CSSNumberUnit): unit is 'fr' { + return unit === 'fr' +} + export interface CSSNumber { value: number unit: CSSNumberUnit | null diff --git a/editor/src/uuiui/inputs/grid-expression-input.tsx b/editor/src/uuiui/inputs/grid-expression-input.tsx index f86e841fd60f..5dbff723c54e 100644 --- a/editor/src/uuiui/inputs/grid-expression-input.tsx +++ b/editor/src/uuiui/inputs/grid-expression-input.tsx @@ -3,9 +3,11 @@ import { jsx } from '@emotion/react' import type { CSSProperties } from 'react' import React from 'react' +import type { CSSNumberUnit } from '../../components/inspector/common/css-utils' import { cssKeyword, gridDimensionsAreEqual, + isFR, isGridCSSNumber, isValidGridDimensionKeyword, parseCSSNumber, @@ -28,6 +30,9 @@ import { Icons, SmallerIcons } from '../icons' import { NO_OP } from '../../core/shared/utils' import { unless } from '../../utils/react-conditionals' import { useColorTheme, UtopiaTheme } from '../styles/theme' +import type { Optic } from '../../core/shared/optics/optics' +import { fromField, fromTypeGuard, notNull } from '../../core/shared/optics/optic-creators' +import { exists, modify } from '../../core/shared/optics/optic-utilities' interface GridExpressionInputProps { testId: string @@ -66,32 +71,53 @@ export const GridExpressionInput = React.memo( const onKeyDown = React.useCallback( (e: React.KeyboardEvent) => { - if (e.key !== 'Enter') { - return + switch (e.key) { + case 'Enter': + if (isValidGridDimensionKeyword(printValue)) { + return onUpdateNumberOrKeyword(cssKeyword(printValue)) + } + + const defaultUnit = isGridCSSNumber(value) ? value.value.unit : 'px' + const maybeNumber = parseCSSNumber(printValue, 'AnyValid', defaultUnit) + if (isRight(maybeNumber)) { + return onUpdateNumberOrKeyword(maybeNumber.value) + } + + const maybeMinmax = parseGridCSSMinmaxOrRepeat(printValue) + if (maybeMinmax != null) { + return onUpdateDimension({ + ...maybeMinmax, + lineName: value.lineName, + } as GridDimension) + } + + if (printValue === '') { + return onUpdateNumberOrKeyword(cssKeyword('auto')) + } + + setPrintValue(stringifyGridDimension(value)) + break + case 'ArrowUp': + case 'ArrowDown': + e.preventDefault() + const gridNumberValueOptic: Optic = fromTypeGuard( + isGridCSSNumber, + ).compose(fromField('value')) + const valueUnitOptic: Optic = gridNumberValueOptic + .compose(fromField('unit')) + .compose(notNull()) + .compose(fromTypeGuard(isFR)) + const gridNumberNumberOptic: Optic = + gridNumberValueOptic.compose(fromField('value')) + if (exists(valueUnitOptic, value)) { + function updateFractional(fractionalValue: number): number { + return fractionalValue + (e.key === 'ArrowUp' ? 0.1 : -0.1) + } + const updatedDimension = modify(gridNumberNumberOptic, updateFractional, value) + onUpdateDimension(updatedDimension) + } + break } - if (isValidGridDimensionKeyword(printValue)) { - return onUpdateNumberOrKeyword(cssKeyword(printValue)) - } - - const defaultUnit = isGridCSSNumber(value) ? value.value.unit : 'px' - const maybeNumber = parseCSSNumber(printValue, 'AnyValid', defaultUnit) - if (isRight(maybeNumber)) { - return onUpdateNumberOrKeyword(maybeNumber.value) - } - - const maybeMinmax = parseGridCSSMinmaxOrRepeat(printValue) - if (maybeMinmax != null) { - return onUpdateDimension({ - ...maybeMinmax, - lineName: value.lineName, - } as GridDimension) - } - - if (printValue === '') { - return onUpdateNumberOrKeyword(cssKeyword('auto')) - } - - setPrintValue(stringifyGridDimension(value)) }, [printValue, onUpdateNumberOrKeyword, onUpdateDimension, value], ) From e567e803385f313187b977aa758da7e5363142b6 Mon Sep 17 00:00:00 2001 From: Sean Parsons Date: Fri, 25 Oct 2024 14:23:18 +0100 Subject: [PATCH 2/2] refactor(editor) Introduced a constant for the increment/decrement amount. --- editor/src/uuiui/inputs/grid-expression-input.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/editor/src/uuiui/inputs/grid-expression-input.tsx b/editor/src/uuiui/inputs/grid-expression-input.tsx index 5dbff723c54e..12a8cbaddcb1 100644 --- a/editor/src/uuiui/inputs/grid-expression-input.tsx +++ b/editor/src/uuiui/inputs/grid-expression-input.tsx @@ -48,6 +48,8 @@ interface GridExpressionInputProps { const DropdownWidth = 25 +const ArrowKeyFractionalIncrement = 0.1 + export const GridExpressionInput = React.memo( ({ testId, @@ -111,7 +113,10 @@ export const GridExpressionInput = React.memo( gridNumberValueOptic.compose(fromField('value')) if (exists(valueUnitOptic, value)) { function updateFractional(fractionalValue: number): number { - return fractionalValue + (e.key === 'ArrowUp' ? 0.1 : -0.1) + return ( + fractionalValue + + (e.key === 'ArrowUp' ? ArrowKeyFractionalIncrement : -ArrowKeyFractionalIncrement) + ) } const updatedDimension = modify(gridNumberNumberOptic, updateFractional, value) onUpdateDimension(updatedDimension)