From dd4cff1717e1d87abaf635b2ee6f9485c3321ffd Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 15 Jul 2024 15:09:50 +0200 Subject: [PATCH 1/4] support labels in grid templates --- .../canvas/controls/grid-controls.tsx | 5 ++ .../store/store-deep-equality-instances.ts | 4 +- .../inspector/common/css-utils.spec.ts | 32 ++++++++++++ .../components/inspector/common/css-utils.ts | 52 +++++++++++++++++-- 4 files changed, 88 insertions(+), 5 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 960b10bbe3c8..ada9bca19e2e 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -229,6 +229,7 @@ export const GridResizingControl = React.memo((props: GridResizingControlProps) justifyContent: 'center', cursor: gridEdgeToCSSCursor(props.axis === 'column' ? 'column-start' : 'row-start'), fontSize: 8, + position: 'relative', }} css={{ opacity: resizing ? 1 : 0.5, @@ -239,6 +240,10 @@ export const GridResizingControl = React.memo((props: GridResizingControlProps) onMouseDown={mouseDownHandler} > {props.axis === 'row' ? '↕' : '↔'} + {when( + props.dimension.label != null, + {props.dimension.label}, + )} {when( resizing, diff --git a/editor/src/components/editor/store/store-deep-equality-instances.ts b/editor/src/components/editor/store/store-deep-equality-instances.ts index 7c0227f6db6d..e9a2bf790014 100644 --- a/editor/src/components/editor/store/store-deep-equality-instances.ts +++ b/editor/src/components/editor/store/store-deep-equality-instances.ts @@ -1970,11 +1970,13 @@ export const CSSNumberKeepDeepEquality: KeepDeepEqualityCall = combin ) export const GridCSSNumberKeepDeepEquality: KeepDeepEqualityCall = - combine2EqualityCalls( + combine3EqualityCalls( (cssNum) => cssNum.value, createCallWithTripleEquals(), (cssNum) => cssNum.unit, nullableDeepEquality(createCallWithTripleEquals()), + (cssNum) => cssNum.label, + nullableDeepEquality(StringKeepDeepEquality), gridCSSNumber, ) diff --git a/editor/src/components/inspector/common/css-utils.spec.ts b/editor/src/components/inspector/common/css-utils.spec.ts index ae3151c0e63e..0f29b2a36d0d 100644 --- a/editor/src/components/inspector/common/css-utils.spec.ts +++ b/editor/src/components/inspector/common/css-utils.spec.ts @@ -71,6 +71,7 @@ import { RegExpLibrary, toggleSimple, toggleStylePropPath, + tokenizeGridTemplate, } from './css-utils' describe('toggleStyleProp', () => { @@ -1807,3 +1808,34 @@ describe('printBackgroundSize', () => { `) }) }) + +describe('tokenizeGridTemplate', () => { + it('tokenizes the grid template strings (no units)', async () => { + expect(tokenizeGridTemplate('123 456 78 9')).toEqual(['123', '456', '78', '9']) + }) + it('tokenizes the grid template strings (with units)', async () => { + expect(tokenizeGridTemplate('123 456px 78 9rem')).toEqual(['123', '456px', '78', '9rem']) + }) + it('tokenizes the grid template strings (with some labels)', async () => { + expect(tokenizeGridTemplate('[foo] 123 456px 78 9rem')).toEqual([ + '[foo] 123', + '456px', + '78', + '9rem', + ]) + expect(tokenizeGridTemplate('123 [foo]456px 78 [bar] 9rem')).toEqual([ + '123', + '[foo] 456px', + '78', + '[bar] 9rem', + ]) + }) + it('tokenizes the grid template strings (with all labels)', async () => { + expect(tokenizeGridTemplate('[foo] 123 [bar]456px [baz] 78 [QUX]9rem')).toEqual([ + '[foo] 123', + '[bar] 456px', + '[baz] 78', + '[QUX] 9rem', + ]) + }) +}) diff --git a/editor/src/components/inspector/common/css-utils.ts b/editor/src/components/inspector/common/css-utils.ts index 4e00df8c85a0..53e5c7e920ec 100644 --- a/editor/src/components/inspector/common/css-utils.ts +++ b/editor/src/components/inspector/common/css-utils.ts @@ -589,12 +589,18 @@ const GridCSSNumberUnits: Array = [...LengthUnits, ...Resolut export interface GridCSSNumber { value: number unit: GridCSSNumberUnit | null + label: string | null } -export function gridCSSNumber(value: number, unit: GridCSSNumberUnit | null): GridCSSNumber { +export function gridCSSNumber( + value: number, + unit: GridCSSNumberUnit | null, + label: string | null, +): GridCSSNumber { return { value, unit, + label, } } @@ -762,7 +768,9 @@ export function printArrayCSSNumber(array: Array): string { return array .map((dimension) => { const printed = printCSSNumber(dimension, null) - return typeof printed === 'string' ? printed : `${printed}` + const label = dimension.label != null ? `[${dimension.label}] ` : '' + const value = typeof printed === 'string' ? printed : `${printed}` + return `${label}${value}` }) .join(' ') } @@ -834,13 +842,30 @@ export const parseCSSUnitlessAsNumber = (input: unknown): Either } } +const gridCSSTemplateNumberRegex = /^\[(.+)\]\s*(.+)$/ + export function parseToCSSGridNumber(input: unknown): Either { + function getParts() { + if (typeof input === 'string') { + const match = input.match(gridCSSTemplateNumberRegex) + if (match != null) { + return { + label: match[1], + inputToParse: match[2], + } + } + } + return { label: null, inputToParse: input } + } + const { label, inputToParse } = getParts() + return mapEither((value) => { return { value: value.value, unit: value.unit as GridCSSNumberUnit | null, + label: label, } - }, parseCSSGrid(input)) + }, parseCSSGrid(inputToParse)) } export const parseCSSNumber = ( @@ -887,6 +912,25 @@ export function parseGridRange(input: unknown): Either { } } +export function tokenizeGridTemplate(str: string): string[] { + let tokens: string[] = [] + let parts = str.replace(/\]/g, '] ').split(/\s+/) + + while (parts.length > 0) { + const part = parts.shift()?.trim() + if (part == null) { + break + } + if (part.match(/^\[.+\]$/) != null && parts.length > 0) { + const withLabel = `${part} ${parts.shift()}` + tokens.push(withLabel) + } else { + tokens.push(part) + } + } + return tokens +} + export function parseGridAutoOrTemplateBase( input: unknown, ): Either { @@ -895,7 +939,7 @@ export function parseGridAutoOrTemplateBase( return leftMapEither(descriptionParseError, result) } if (typeof input === 'string') { - const parsedCSSArray = parseCSSArray([numberParse])(input.split(/ +/)) + const parsedCSSArray = parseCSSArray([numberParse])(tokenizeGridTemplate(input)) return bimapEither( (error) => { if (error.type === 'DESCRIPTION_PARSE_ERROR') { From 366c79da7175f1aacdc7d4e8251c4b9d61d8f287 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 15 Jul 2024 15:15:53 +0200 Subject: [PATCH 2/4] rename --- .../canvas/controls/grid-controls.tsx | 4 +-- .../store/store-deep-equality-instances.ts | 2 +- .../components/inspector/common/css-utils.ts | 30 ++++++++++--------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index ada9bca19e2e..e4ab421f7280 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -241,8 +241,8 @@ export const GridResizingControl = React.memo((props: GridResizingControlProps) > {props.axis === 'row' ? '↕' : '↔'} {when( - props.dimension.label != null, - {props.dimension.label}, + props.dimension.areaName != null, + {props.dimension.areaName}, )} {when( diff --git a/editor/src/components/editor/store/store-deep-equality-instances.ts b/editor/src/components/editor/store/store-deep-equality-instances.ts index e9a2bf790014..68a7ab75d6e3 100644 --- a/editor/src/components/editor/store/store-deep-equality-instances.ts +++ b/editor/src/components/editor/store/store-deep-equality-instances.ts @@ -1975,7 +1975,7 @@ export const GridCSSNumberKeepDeepEquality: KeepDeepEqualityCall createCallWithTripleEquals(), (cssNum) => cssNum.unit, nullableDeepEquality(createCallWithTripleEquals()), - (cssNum) => cssNum.label, + (cssNum) => cssNum.areaName, nullableDeepEquality(StringKeepDeepEquality), gridCSSNumber, ) diff --git a/editor/src/components/inspector/common/css-utils.ts b/editor/src/components/inspector/common/css-utils.ts index 53e5c7e920ec..54d87582806d 100644 --- a/editor/src/components/inspector/common/css-utils.ts +++ b/editor/src/components/inspector/common/css-utils.ts @@ -589,18 +589,18 @@ const GridCSSNumberUnits: Array = [...LengthUnits, ...Resolut export interface GridCSSNumber { value: number unit: GridCSSNumberUnit | null - label: string | null + areaName: string | null } export function gridCSSNumber( value: number, unit: GridCSSNumberUnit | null, - label: string | null, + areaName: string | null, ): GridCSSNumber { return { - value, - unit, - label, + value: value, + unit: unit, + areaName: areaName, } } @@ -768,9 +768,9 @@ export function printArrayCSSNumber(array: Array): string { return array .map((dimension) => { const printed = printCSSNumber(dimension, null) - const label = dimension.label != null ? `[${dimension.label}] ` : '' + const areaName = dimension.areaName != null ? `[${dimension.areaName}] ` : '' const value = typeof printed === 'string' ? printed : `${printed}` - return `${label}${value}` + return `${areaName}${value}` }) .join(' ') } @@ -850,20 +850,20 @@ export function parseToCSSGridNumber(input: unknown): Either { return { value: value.value, unit: value.unit as GridCSSNumberUnit | null, - label: label, + areaName: areaName, } }, parseCSSGrid(inputToParse)) } @@ -912,6 +912,8 @@ export function parseGridRange(input: unknown): Either { } } +const reGridAreaNameBrackets = /^\[.+\]$/ + export function tokenizeGridTemplate(str: string): string[] { let tokens: string[] = [] let parts = str.replace(/\]/g, '] ').split(/\s+/) @@ -921,9 +923,9 @@ export function tokenizeGridTemplate(str: string): string[] { if (part == null) { break } - if (part.match(/^\[.+\]$/) != null && parts.length > 0) { - const withLabel = `${part} ${parts.shift()}` - tokens.push(withLabel) + if (part.match(reGridAreaNameBrackets) != null && parts.length > 0) { + const withAreaName = `${part} ${parts.shift()}` + tokens.push(withAreaName) } else { tokens.push(part) } From 280539c7250e9aeef828fc700941b36b96e681a3 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 15 Jul 2024 15:16:34 +0200 Subject: [PATCH 3/4] rename --- editor/src/components/inspector/common/css-utils.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/src/components/inspector/common/css-utils.spec.ts b/editor/src/components/inspector/common/css-utils.spec.ts index 0f29b2a36d0d..cc0fb96037fa 100644 --- a/editor/src/components/inspector/common/css-utils.spec.ts +++ b/editor/src/components/inspector/common/css-utils.spec.ts @@ -1816,7 +1816,7 @@ describe('tokenizeGridTemplate', () => { it('tokenizes the grid template strings (with units)', async () => { expect(tokenizeGridTemplate('123 456px 78 9rem')).toEqual(['123', '456px', '78', '9rem']) }) - it('tokenizes the grid template strings (with some labels)', async () => { + it('tokenizes the grid template strings (with some area names)', async () => { expect(tokenizeGridTemplate('[foo] 123 456px 78 9rem')).toEqual([ '[foo] 123', '456px', @@ -1830,7 +1830,7 @@ describe('tokenizeGridTemplate', () => { '[bar] 9rem', ]) }) - it('tokenizes the grid template strings (with all labels)', async () => { + it('tokenizes the grid template strings (with all area names)', async () => { expect(tokenizeGridTemplate('[foo] 123 [bar]456px [baz] 78 [QUX]9rem')).toEqual([ '[foo] 123', '[bar] 456px', From f5573860c5356073d009f153df9ea3a60b7b7b9a Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 15 Jul 2024 15:45:37 +0200 Subject: [PATCH 4/4] clean up --- editor/src/components/inspector/common/css-utils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/editor/src/components/inspector/common/css-utils.ts b/editor/src/components/inspector/common/css-utils.ts index 54d87582806d..5d063f951951 100644 --- a/editor/src/components/inspector/common/css-utils.ts +++ b/editor/src/components/inspector/common/css-utils.ts @@ -769,8 +769,7 @@ export function printArrayCSSNumber(array: Array): string { .map((dimension) => { const printed = printCSSNumber(dimension, null) const areaName = dimension.areaName != null ? `[${dimension.areaName}] ` : '' - const value = typeof printed === 'string' ? printed : `${printed}` - return `${areaName}${value}` + return `${areaName}${printed}` }) .join(' ') }